• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?php
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// https://developers.google.com/protocol-buffers/
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met:
10//
11//     * Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//     * Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17//     * Neither the name of Google Inc. nor the names of its
18// contributors may be used to endorse or promote products derived from
19// this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33/**
34 * MapField and MapFieldIter are used by generated protocol message classes to
35 * manipulate map fields.
36 */
37
38namespace Google\Protobuf\Internal;
39
40/**
41 * MapField is used by generated protocol message classes to manipulate map
42 * fields. It can be used like native PHP array.
43 */
44class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
45{
46    /**
47     * @ignore
48     */
49    private $container;
50    /**
51     * @ignore
52     */
53    private $key_type;
54    /**
55     * @ignore
56     */
57    private $value_type;
58    /**
59     * @ignore
60     */
61    private $klass;
62    /**
63     * @ignore
64     */
65    private $legacy_klass;
66
67    /**
68     * Constructs an instance of MapField.
69     *
70     * @param long $key_type Type of the stored key element.
71     * @param long $value_type Type of the stored value element.
72     * @param string $klass Message/Enum class name of value instance
73     * (message/enum fields only).
74     * @ignore
75     */
76    public function __construct($key_type, $value_type, $klass = null)
77    {
78        $this->container = [];
79        $this->key_type = $key_type;
80        $this->value_type = $value_type;
81        $this->klass = $klass;
82
83        if ($this->value_type == GPBType::MESSAGE) {
84            $pool = DescriptorPool::getGeneratedPool();
85            $desc = $pool->getDescriptorByClassName($klass);
86            if ($desc == NULL) {
87                new $klass;  // No msg class instance has been created before.
88                $desc = $pool->getDescriptorByClassName($klass);
89            }
90            $this->klass = $desc->getClass();
91            $this->legacy_klass = $desc->getLegacyClass();
92        }
93    }
94
95    /**
96     * @ignore
97     */
98    public function getKeyType()
99    {
100        return $this->key_type;
101    }
102
103    /**
104     * @ignore
105     */
106    public function getValueType()
107    {
108        return $this->value_type;
109    }
110
111    /**
112     * @ignore
113     */
114    public function getValueClass()
115    {
116        return $this->klass;
117    }
118
119    /**
120     * @ignore
121     */
122    public function getLegacyValueClass()
123    {
124        return $this->legacy_klass;
125    }
126
127    /**
128     * Return the element at the given key.
129     *
130     * This will also be called for: $ele = $arr[$key]
131     *
132     * @param object $key The key of the element to be fetched.
133     * @return object The stored element at given key.
134     * @throws \ErrorException Invalid type for index.
135     * @throws \ErrorException Non-existing index.
136     */
137    public function offsetGet($key)
138    {
139        return $this->container[$key];
140    }
141
142    /**
143     * Assign the element at the given key.
144     *
145     * This will also be called for: $arr[$key] = $value
146     *
147     * @param object $key The key of the element to be fetched.
148     * @param object $value The element to be assigned.
149     * @return void
150     * @throws \ErrorException Invalid type for key.
151     * @throws \ErrorException Invalid type for value.
152     * @throws \ErrorException Non-existing key.
153     */
154    public function offsetSet($key, $value)
155    {
156        $this->checkKey($this->key_type, $key);
157
158        switch ($this->value_type) {
159            case GPBType::SFIXED32:
160            case GPBType::SINT32:
161            case GPBType::INT32:
162            case GPBType::ENUM:
163                GPBUtil::checkInt32($value);
164                break;
165            case GPBType::FIXED32:
166            case GPBType::UINT32:
167                GPBUtil::checkUint32($value);
168                break;
169            case GPBType::SFIXED64:
170            case GPBType::SINT64:
171            case GPBType::INT64:
172                GPBUtil::checkInt64($value);
173                break;
174            case GPBType::FIXED64:
175            case GPBType::UINT64:
176                GPBUtil::checkUint64($value);
177                break;
178            case GPBType::FLOAT:
179                GPBUtil::checkFloat($value);
180                break;
181            case GPBType::DOUBLE:
182                GPBUtil::checkDouble($value);
183                break;
184            case GPBType::BOOL:
185                GPBUtil::checkBool($value);
186                break;
187            case GPBType::STRING:
188                GPBUtil::checkString($value, true);
189                break;
190            case GPBType::MESSAGE:
191                if (is_null($value)) {
192                  trigger_error("Map element cannot be null.", E_USER_ERROR);
193                }
194                GPBUtil::checkMessage($value, $this->klass);
195                break;
196            default:
197                break;
198        }
199
200        $this->container[$key] = $value;
201    }
202
203    /**
204     * Remove the element at the given key.
205     *
206     * This will also be called for: unset($arr)
207     *
208     * @param object $key The key of the element to be removed.
209     * @return void
210     * @throws \ErrorException Invalid type for key.
211     */
212    public function offsetUnset($key)
213    {
214        $this->checkKey($this->key_type, $key);
215        unset($this->container[$key]);
216    }
217
218    /**
219     * Check the existence of the element at the given key.
220     *
221     * This will also be called for: isset($arr)
222     *
223     * @param object $key The key of the element to be removed.
224     * @return bool True if the element at the given key exists.
225     * @throws \ErrorException Invalid type for key.
226     */
227    public function offsetExists($key)
228    {
229        $this->checkKey($this->key_type, $key);
230        return isset($this->container[$key]);
231    }
232
233    /**
234     * @ignore
235     */
236    public function getIterator()
237    {
238        return new MapFieldIter($this->container, $this->key_type);
239    }
240
241    /**
242     * Return the number of stored elements.
243     *
244     * This will also be called for: count($arr)
245     *
246     * @return integer The number of stored elements.
247     */
248    public function count()
249    {
250        return count($this->container);
251    }
252
253    /**
254     * @ignore
255     */
256    private function checkKey($key_type, &$key)
257    {
258        switch ($key_type) {
259            case GPBType::SFIXED32:
260            case GPBType::SINT32:
261            case GPBType::INT32:
262                GPBUtil::checkInt32($key);
263                break;
264            case GPBType::FIXED32:
265            case GPBType::UINT32:
266                GPBUtil::checkUint32($key);
267                break;
268            case GPBType::SFIXED64:
269            case GPBType::SINT64:
270            case GPBType::INT64:
271                GPBUtil::checkInt64($key);
272                break;
273            case GPBType::FIXED64:
274            case GPBType::UINT64:
275                GPBUtil::checkUint64($key);
276                break;
277            case GPBType::BOOL:
278                GPBUtil::checkBool($key);
279                break;
280            case GPBType::STRING:
281                GPBUtil::checkString($key, true);
282                break;
283            default:
284                trigger_error(
285                    "Given type cannot be map key.",
286                    E_USER_ERROR);
287                break;
288        }
289    }
290}
291