Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: third_party/protobuf/php/ext/google/protobuf/array.c

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <ext/spl/spl_iterators.h>
32 #include <Zend/zend_API.h>
33 #include <Zend/zend_interfaces.h>
34
35 #include "protobuf.h"
36
37 ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
38 ZEND_ARG_INFO(0, index)
39 ZEND_END_ARG_INFO()
40
41 ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
42 ZEND_ARG_INFO(0, index)
43 ZEND_ARG_INFO(0, newval)
44 ZEND_END_ARG_INFO()
45
46 ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
47 ZEND_END_ARG_INFO()
48
49 static zend_function_entry repeated_field_methods[] = {
50 PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
51 PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
52 PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
53 PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
54 PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
55 PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
56 PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
57 PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
58 ZEND_FE_END
59 };
60
61 static zend_function_entry repeated_field_iter_methods[] = {
62 PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
63 PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
64 PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
65 PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
66 PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
67 ZEND_FE_END
68 };
69
70 // Forward declare static functions.
71
72 static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC);
73 static void repeated_field_free(void *object TSRMLS_DC);
74 static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
75 uint size ZEND_FILE_LINE_DC);
76 static void repeated_field_free_element(void *object);
77 static void repeated_field_write_dimension(zval *object, zval *offset,
78 zval *value TSRMLS_DC);
79 static int repeated_field_has_dimension(zval *object, zval *offset TSRMLS_DC);
80 static HashTable *repeated_field_get_gc(zval *object, zval ***table,
81 int *n TSRMLS_DC);
82
83 static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_ DC);
84 static void repeated_field_iter_free(void *object TSRMLS_DC);
85
86 // -----------------------------------------------------------------------------
87 // RepeatedField creation/desctruction
88 // -----------------------------------------------------------------------------
89
90 zend_class_entry* repeated_field_type;
91 zend_class_entry* repeated_field_iter_type;
92 zend_object_handlers* repeated_field_handlers;
93
94 void repeated_field_init(TSRMLS_D) {
95 zend_class_entry class_type;
96 const char* class_name = "Google\\Protobuf\\Internal\\RepeatedField";
97 INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
98 repeated_field_methods);
99
100 repeated_field_type = zend_register_internal_class(&class_type TSRMLS_CC);
101 repeated_field_type->create_object = repeated_field_create;
102
103 zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
104 zend_ce_aggregate, spl_ce_Countable);
105
106 repeated_field_handlers = PEMALLOC(zend_object_handlers);
107 memcpy(repeated_field_handlers, zend_get_std_object_handlers(),
108 sizeof(zend_object_handlers));
109 repeated_field_handlers->get_gc = repeated_field_get_gc;
110 }
111
112 static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC) {
113 zend_object_value retval = {0};
114 RepeatedField *intern;
115
116 intern = emalloc(sizeof(RepeatedField));
117 memset(intern, 0, sizeof(RepeatedField));
118
119 zend_object_std_init(&intern->std, ce TSRMLS_CC);
120 object_properties_init(&intern->std, ce);
121
122 intern->array = NULL;
123 intern->type = 0;
124 intern->msg_ce = NULL;
125
126 retval.handle = zend_objects_store_put(
127 intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
128 (zend_objects_free_object_storage_t)repeated_field_free, NULL TSRMLS_CC);
129 retval.handlers = repeated_field_handlers;
130
131 return retval;
132 }
133
134 static void repeated_field_free(void *object TSRMLS_DC) {
135 RepeatedField *intern = object;
136 zend_object_std_dtor(&intern->std TSRMLS_CC);
137 zval_ptr_dtor(&intern->array);
138 efree(object);
139 }
140
141 static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
142 uint size ZEND_FILE_LINE_DC) {
143 ALLOC_HASHTABLE(Z_ARRVAL_P(array));
144
145 switch (type) {
146 case UPB_TYPE_STRING:
147 case UPB_TYPE_BYTES:
148 case UPB_TYPE_MESSAGE:
149 zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
150 break;
151 default:
152 zend_hash_init(Z_ARRVAL_P(array), size, NULL, repeated_field_free_element,
153 0);
154 }
155 Z_TYPE_P(array) = IS_ARRAY;
156 return SUCCESS;
157 }
158
159 static void repeated_field_free_element(void *object) {
160 }
161
162 // -----------------------------------------------------------------------------
163 // RepeatedField Handlers
164 // -----------------------------------------------------------------------------
165
166 static void repeated_field_write_dimension(zval *object, zval *offset,
167 zval *value TSRMLS_DC) {
168 uint64_t index;
169
170 RepeatedField *intern = zend_object_store_get_object(object TSRMLS_CC);
171 HashTable *ht = HASH_OF(intern->array);
172 int size = native_slot_size(intern->type);
173
174 unsigned char memory[NATIVE_SLOT_MAX_SIZE];
175 memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
176
177 if (!native_slot_set(intern->type, intern->msg_ce, memory, value TSRMLS_CC)) {
178 return;
179 }
180
181 if (!offset || Z_TYPE_P(offset) == IS_NULL) {
182 index = zend_hash_num_elements(HASH_OF(intern->array));
183 } else {
184 if (protobuf_convert_to_uint64(offset, &index)) {
185 if (!zend_hash_index_exists(ht, index)) {
186 zend_error(E_USER_ERROR, "Element at %llu doesn't exist.\n", index);
187 return;
188 }
189 } else {
190 return;
191 }
192 }
193
194 zend_hash_index_update(ht, index, memory, size, NULL);
195 }
196
197 static HashTable *repeated_field_get_gc(zval *object, zval ***table,
198 int *n TSRMLS_DC) {
199 *table = NULL;
200 *n = 0;
201 RepeatedField *intern = zend_object_store_get_object(object TSRMLS_CC);
202 return HASH_OF(intern->array);
203 }
204
205 // -----------------------------------------------------------------------------
206 // C RepeatedField Utilities
207 // -----------------------------------------------------------------------------
208
209 void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
210 HashTable *ht = HASH_OF(intern->array);
211 void *value;
212
213 if (zend_hash_index_find(ht, index, (void **)&value) == FAILURE) {
214 zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
215 return NULL;
216 }
217
218 return value;
219 }
220
221 void repeated_field_push_native(RepeatedField *intern, void *value TSRMLS_DC) {
222 HashTable *ht = HASH_OF(intern->array);
223 int size = native_slot_size(intern->type);
224 zend_hash_next_index_insert(ht, (void **)value, size, NULL);
225 }
226
227 void repeated_field_create_with_type(zend_class_entry *ce,
228 const upb_fielddef *field,
229 zval **repeated_field TSRMLS_DC) {
230 MAKE_STD_ZVAL(*repeated_field);
231 Z_TYPE_PP(repeated_field) = IS_OBJECT;
232 Z_OBJVAL_PP(repeated_field) =
233 repeated_field_type->create_object(repeated_field_type TSRMLS_CC);
234
235 RepeatedField *intern =
236 zend_object_store_get_object(*repeated_field TSRMLS_CC);
237 intern->type = upb_fielddef_type(field);
238 if (intern->type == UPB_TYPE_MESSAGE) {
239 const upb_msgdef *msg = upb_fielddef_msgsubdef(field);
240 zval *desc_php = get_def_obj(msg);
241 Descriptor *desc = zend_object_store_get_object(desc_php TSRMLS_CC);
242 intern->msg_ce = desc->klass;
243 }
244 MAKE_STD_ZVAL(intern->array);
245 repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
246
247 // TODO(teboring): Link class entry for message and enum
248 }
249
250
251 // -----------------------------------------------------------------------------
252 // PHP RepeatedField Methods
253 // -----------------------------------------------------------------------------
254
255 /**
256 * Constructs an instance of RepeatedField.
257 * @param long Type of the stored element.
258 * @param string Message/Enum class name (message/enum fields only).
259 */
260 PHP_METHOD(RepeatedField, __construct) {
261 long type;
262 zend_class_entry* klass = NULL;
263
264 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) ==
265 FAILURE) {
266 return;
267 }
268
269 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
270 intern->type = to_fieldtype(type);
271 intern->msg_ce = klass;
272
273 MAKE_STD_ZVAL(intern->array);
274 repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
275
276 if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
277 zend_error(E_USER_ERROR, "Message type must have concrete class.");
278 return;
279 }
280
281 // TODO(teboring): Consider enum.
282 }
283
284 /**
285 * Append element to the end of the repeated field.
286 * @param object The element to be added.
287 */
288 PHP_METHOD(RepeatedField, append) {
289 zval *value;
290
291 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==
292 FAILURE) {
293 return;
294 }
295 repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC);
296 }
297
298 /**
299 * Check whether the element at given index exists.
300 * @param long The index to be checked.
301 * @return bool True if the element at the given index exists.
302 */
303 PHP_METHOD(RepeatedField, offsetExists) {
304 long index;
305
306 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
307 FAILURE) {
308 return;
309 }
310
311 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
312
313 RETURN_BOOL(index >= 0 &&
314 index < zend_hash_num_elements(HASH_OF(intern->array)));
315 }
316
317 /**
318 * Return the element at the given index.
319 * This will also be called for: $ele = $arr[0]
320 * @param long The index of the element to be fetched.
321 * @return object The stored element at given index.
322 * @exception Invalid type for index.
323 * @exception Non-existing index.
324 */
325 PHP_METHOD(RepeatedField, offsetGet) {
326 long index;
327 void *memory;
328
329 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
330 FAILURE) {
331 return;
332 }
333
334 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
335 HashTable *table = HASH_OF(intern->array);
336
337 if (zend_hash_index_find(table, index, (void **)&memory) == FAILURE) {
338 zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
339 return;
340 }
341
342 native_slot_get(intern->type, memory, return_value_ptr TSRMLS_CC);
343 }
344
345 /**
346 * Assign the element at the given index.
347 * This will also be called for: $arr []= $ele and $arr[0] = ele
348 * @param long The index of the element to be assigned.
349 * @param object The element to be assigned.
350 * @exception Invalid type for index.
351 * @exception Non-existing index.
352 * @exception Incorrect type of the element.
353 */
354 PHP_METHOD(RepeatedField, offsetSet) {
355 zval *index, *value;
356 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
357 FAILURE) {
358 return;
359 }
360 repeated_field_write_dimension(getThis(), index, value TSRMLS_CC);
361 }
362
363 /**
364 * Remove the element at the given index.
365 * This will also be called for: unset($arr)
366 * @param long The index of the element to be removed.
367 * @exception Invalid type for index.
368 * @exception The element to be removed is not at the end of the RepeatedField.
369 */
370 PHP_METHOD(RepeatedField, offsetUnset) {
371 long index;
372 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
373 FAILURE) {
374 return;
375 }
376
377 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
378
379 // Only the element at the end of the array can be removed.
380 if (index == -1 ||
381 index != (zend_hash_num_elements(HASH_OF(intern->array)) - 1)) {
382 zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index);
383 return;
384 }
385
386 zend_hash_index_del(HASH_OF(intern->array), index);
387 }
388
389 /**
390 * Return the number of stored elements.
391 * This will also be called for: count($arr)
392 * @return long The number of stored elements.
393 */
394 PHP_METHOD(RepeatedField, count) {
395 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
396
397 if (zend_parse_parameters_none() == FAILURE) {
398 return;
399 }
400
401 RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->array)));
402 }
403
404 /**
405 * Return the beginning iterator.
406 * This will also be called for: foreach($arr)
407 * @return object Beginning iterator.
408 */
409 PHP_METHOD(RepeatedField, getIterator) {
410 zval *iter_php = NULL;
411 MAKE_STD_ZVAL(iter_php);
412 Z_TYPE_P(iter_php) = IS_OBJECT;
413 Z_OBJVAL_P(iter_php) = repeated_field_iter_type->create_object(
414 repeated_field_iter_type TSRMLS_CC);
415
416 RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
417 RepeatedFieldIter *iter = zend_object_store_get_object(iter_php TSRMLS_CC);
418 iter->repeated_field = intern;
419 iter->position = 0;
420
421 RETURN_ZVAL(iter_php, 1, 1);
422 }
423
424 // -----------------------------------------------------------------------------
425 // RepeatedFieldIter creation/desctruction
426 // -----------------------------------------------------------------------------
427
428 void repeated_field_iter_init(TSRMLS_D) {
429 zend_class_entry class_type;
430 const char* class_name = "Google\\Protobuf\\Internal\\RepeatedFieldIter";
431 INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
432 repeated_field_iter_methods);
433
434 repeated_field_iter_type =
435 zend_register_internal_class(&class_type TSRMLS_CC);
436 repeated_field_iter_type->create_object = repeated_field_iter_create;
437
438 zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1,
439 zend_ce_iterator);
440 }
441
442 static zend_object_value repeated_field_iter_create(
443 zend_class_entry *ce TSRMLS_DC) {
444 zend_object_value retval = {0};
445 RepeatedFieldIter *intern;
446
447 intern = emalloc(sizeof(RepeatedFieldIter));
448 memset(intern, 0, sizeof(RepeatedFieldIter));
449
450 zend_object_std_init(&intern->std, ce TSRMLS_CC);
451 object_properties_init(&intern->std, ce);
452
453 intern->repeated_field = NULL;
454 intern->position = 0;
455
456 retval.handle = zend_objects_store_put(
457 intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
458 (zend_objects_free_object_storage_t)repeated_field_iter_free,
459 NULL TSRMLS_CC);
460 retval.handlers = zend_get_std_object_handlers();
461
462 return retval;
463 }
464
465 static void repeated_field_iter_free(void *object TSRMLS_DC) {
466 RepeatedFieldIter *intern = object;
467 zend_object_std_dtor(&intern->std TSRMLS_CC);
468 efree(object);
469 }
470
471 // -----------------------------------------------------------------------------
472 // PHP RepeatedFieldIter Methods
473 // -----------------------------------------------------------------------------
474
475 PHP_METHOD(RepeatedFieldIter, rewind) {
476 RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
477 intern->position = 0;
478 }
479
480 PHP_METHOD(RepeatedFieldIter, current) {
481 RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
482 RepeatedField *repeated_field = intern->repeated_field;
483
484 long index;
485 void *memory;
486
487 HashTable *table = HASH_OF(repeated_field->array);
488
489 if (zend_hash_index_find(table, intern->position, (void **)&memory) ==
490 FAILURE) {
491 zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
492 return;
493 }
494 native_slot_get(repeated_field->type, memory, return_value_ptr TSRMLS_CC);
495 }
496
497 PHP_METHOD(RepeatedFieldIter, key) {
498 RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
499 RETURN_LONG(intern->position);
500 }
501
502 PHP_METHOD(RepeatedFieldIter, next) {
503 RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
504 ++intern->position;
505 }
506
507 PHP_METHOD(RepeatedFieldIter, valid) {
508 RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
509 RETURN_BOOL(zend_hash_num_elements(HASH_OF(intern->repeated_field->array)) >
510 intern->position);
511 }
OLDNEW
« no previous file with comments | « third_party/protobuf/php/composer.json ('k') | third_party/protobuf/php/ext/google/protobuf/config.m4 » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698