google-protobuf 3.0.0.alpha.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -0,0 +1,597 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2014 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 "protobuf.h"
32
+
33
+ // -----------------------------------------------------------------------------
34
+ // Repeated field container type.
35
+ // -----------------------------------------------------------------------------
36
+
37
+ const rb_data_type_t RepeatedField_type = {
38
+ "Google::Protobuf::RepeatedField",
39
+ { RepeatedField_mark, RepeatedField_free, NULL },
40
+ };
41
+
42
+ VALUE cRepeatedField;
43
+
44
+ RepeatedField* ruby_to_RepeatedField(VALUE _self) {
45
+ RepeatedField* self;
46
+ TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
47
+ return self;
48
+ }
49
+
50
+ /*
51
+ * call-seq:
52
+ * RepeatedField.each(&block)
53
+ *
54
+ * Invokes the block once for each element of the repeated field. RepeatedField
55
+ * also includes Enumerable; combined with this method, the repeated field thus
56
+ * acts like an ordinary Ruby sequence.
57
+ */
58
+ VALUE RepeatedField_each(VALUE _self) {
59
+ RepeatedField* self = ruby_to_RepeatedField(_self);
60
+ upb_fieldtype_t field_type = self->field_type;
61
+ VALUE field_type_class = self->field_type_class;
62
+ int element_size = native_slot_size(field_type);
63
+
64
+ size_t off = 0;
65
+ for (int i = 0; i < self->size; i++, off += element_size) {
66
+ void* memory = (void *) (((uint8_t *)self->elements) + off);
67
+ VALUE val = native_slot_get(field_type, field_type_class, memory);
68
+ rb_yield(val);
69
+ }
70
+ return Qnil;
71
+ }
72
+
73
+ /*
74
+ * call-seq:
75
+ * RepeatedField.[](index) => value
76
+ *
77
+ * Accesses the element at the given index. Throws an exception on out-of-bounds
78
+ * errors.
79
+ */
80
+ VALUE RepeatedField_index(VALUE _self, VALUE _index) {
81
+ RepeatedField* self = ruby_to_RepeatedField(_self);
82
+ int element_size = native_slot_size(self->field_type);
83
+ upb_fieldtype_t field_type = self->field_type;
84
+ VALUE field_type_class = self->field_type_class;
85
+
86
+ int index = NUM2INT(_index);
87
+ if (index < 0 || index >= self->size) {
88
+ rb_raise(rb_eRangeError, "Index out of range");
89
+ }
90
+
91
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
92
+ return native_slot_get(field_type, field_type_class, memory);
93
+ }
94
+
95
+ /*
96
+ * call-seq:
97
+ * RepeatedField.[]=(index, value)
98
+ *
99
+ * Sets the element at the given index. On out-of-bounds assignments, extends
100
+ * the array and fills the hole (if any) with default values.
101
+ */
102
+ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
103
+ RepeatedField* self = ruby_to_RepeatedField(_self);
104
+ upb_fieldtype_t field_type = self->field_type;
105
+ VALUE field_type_class = self->field_type_class;
106
+ int element_size = native_slot_size(field_type);
107
+
108
+ int index = NUM2INT(_index);
109
+ if (index < 0 || index >= (INT_MAX - 1)) {
110
+ rb_raise(rb_eRangeError, "Index out of range");
111
+ }
112
+ if (index >= self->size) {
113
+ RepeatedField_reserve(self, index + 1);
114
+ upb_fieldtype_t field_type = self->field_type;
115
+ int element_size = native_slot_size(field_type);
116
+ for (int i = self->size; i <= index; i++) {
117
+ void* elem = (void *)(((uint8_t *)self->elements) + i * element_size);
118
+ native_slot_init(field_type, elem);
119
+ }
120
+ self->size = index + 1;
121
+ }
122
+
123
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
124
+ native_slot_set(field_type, field_type_class, memory, val);
125
+ return Qnil;
126
+ }
127
+
128
+ static int kInitialSize = 8;
129
+
130
+ void RepeatedField_reserve(RepeatedField* self, int new_size) {
131
+ if (new_size <= self->capacity) {
132
+ return;
133
+ }
134
+ if (self->capacity == 0) {
135
+ self->capacity = kInitialSize;
136
+ }
137
+ while (self->capacity < new_size) {
138
+ self->capacity *= 2;
139
+ }
140
+ void* old_elems = self->elements;
141
+ int elem_size = native_slot_size(self->field_type);
142
+ self->elements = ALLOC_N(uint8_t, elem_size * self->capacity);
143
+ if (old_elems != NULL) {
144
+ memcpy(self->elements, old_elems, self->size * elem_size);
145
+ xfree(old_elems);
146
+ }
147
+ }
148
+
149
+ /*
150
+ * call-seq:
151
+ * RepeatedField.push(value)
152
+ *
153
+ * Adds a new element to the repeated field.
154
+ */
155
+ VALUE RepeatedField_push(VALUE _self, VALUE val) {
156
+ RepeatedField* self = ruby_to_RepeatedField(_self);
157
+ upb_fieldtype_t field_type = self->field_type;
158
+ int element_size = native_slot_size(field_type);
159
+ RepeatedField_reserve(self, self->size + 1);
160
+ int index = self->size;
161
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
162
+ native_slot_set(field_type, self->field_type_class, memory, val);
163
+ // native_slot_set may raise an error; bump index only after set.
164
+ self->size++;
165
+ return _self;
166
+ }
167
+
168
+ // Used by parsing handlers.
169
+ void RepeatedField_push_native(VALUE _self, void* data) {
170
+ RepeatedField* self = ruby_to_RepeatedField(_self);
171
+ upb_fieldtype_t field_type = self->field_type;
172
+ int element_size = native_slot_size(field_type);
173
+ RepeatedField_reserve(self, self->size + 1);
174
+ int index = self->size;
175
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
176
+ memcpy(memory, data, element_size);
177
+ self->size++;
178
+ }
179
+
180
+ void* RepeatedField_index_native(VALUE _self, int index) {
181
+ RepeatedField* self = ruby_to_RepeatedField(_self);
182
+ upb_fieldtype_t field_type = self->field_type;
183
+ int element_size = native_slot_size(field_type);
184
+ return ((uint8_t *)self->elements) + index * element_size;
185
+ }
186
+
187
+ /*
188
+ * call-seq:
189
+ * RepeatedField.pop => value
190
+ *
191
+ * Removes the last element and returns it. Throws an exception if the repeated
192
+ * field is empty.
193
+ */
194
+ VALUE RepeatedField_pop(VALUE _self) {
195
+ RepeatedField* self = ruby_to_RepeatedField(_self);
196
+ upb_fieldtype_t field_type = self->field_type;
197
+ VALUE field_type_class = self->field_type_class;
198
+ int element_size = native_slot_size(field_type);
199
+ if (self->size == 0) {
200
+ rb_raise(rb_eRangeError, "Pop from empty repeated field is not allowed.");
201
+ }
202
+ int index = self->size - 1;
203
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
204
+ VALUE ret = native_slot_get(field_type, field_type_class, memory);
205
+ self->size--;
206
+ return ret;
207
+ }
208
+
209
+ /*
210
+ * call-seq:
211
+ * RepeatedField.insert(*args)
212
+ *
213
+ * Pushes each arg in turn onto the end of the repeated field.
214
+ */
215
+ VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self) {
216
+ for (int i = 0; i < argc; i++) {
217
+ RepeatedField_push(_self, argv[i]);
218
+ }
219
+ return Qnil;
220
+ }
221
+
222
+ /*
223
+ * call-seq:
224
+ * RepeatedField.replace(list)
225
+ *
226
+ * Replaces the contents of the repeated field with the given list of elements.
227
+ */
228
+ VALUE RepeatedField_replace(VALUE _self, VALUE list) {
229
+ RepeatedField* self = ruby_to_RepeatedField(_self);
230
+ Check_Type(list, T_ARRAY);
231
+ self->size = 0;
232
+ for (int i = 0; i < RARRAY_LEN(list); i++) {
233
+ RepeatedField_push(_self, rb_ary_entry(list, i));
234
+ }
235
+ return Qnil;
236
+ }
237
+
238
+ /*
239
+ * call-seq:
240
+ * RepeatedField.clear
241
+ *
242
+ * Clears (removes all elements from) this repeated field.
243
+ */
244
+ VALUE RepeatedField_clear(VALUE _self) {
245
+ RepeatedField* self = ruby_to_RepeatedField(_self);
246
+ self->size = 0;
247
+ return Qnil;
248
+ }
249
+
250
+ /*
251
+ * call-seq:
252
+ * RepeatedField.length
253
+ *
254
+ * Returns the length of this repeated field.
255
+ */
256
+ VALUE RepeatedField_length(VALUE _self) {
257
+ RepeatedField* self = ruby_to_RepeatedField(_self);
258
+ return INT2NUM(self->size);
259
+ }
260
+
261
+ static VALUE RepeatedField_new_this_type(VALUE _self) {
262
+ RepeatedField* self = ruby_to_RepeatedField(_self);
263
+ VALUE new_rptfield = Qnil;
264
+ VALUE element_type = fieldtype_to_ruby(self->field_type);
265
+ if (self->field_type_class != Qnil) {
266
+ new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
267
+ element_type, self->field_type_class);
268
+ } else {
269
+ new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
270
+ element_type);
271
+ }
272
+ return new_rptfield;
273
+ }
274
+
275
+ /*
276
+ * call-seq:
277
+ * RepeatedField.dup => repeated_field
278
+ *
279
+ * Duplicates this repeated field with a shallow copy. References to all
280
+ * non-primitive element objects (e.g., submessages) are shared.
281
+ */
282
+ VALUE RepeatedField_dup(VALUE _self) {
283
+ RepeatedField* self = ruby_to_RepeatedField(_self);
284
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
285
+ RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
286
+ RepeatedField_reserve(new_rptfield_self, self->size);
287
+ upb_fieldtype_t field_type = self->field_type;
288
+ size_t elem_size = native_slot_size(field_type);
289
+ size_t off = 0;
290
+ for (int i = 0; i < self->size; i++, off += elem_size) {
291
+ void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
292
+ void* from_mem = (uint8_t *)self->elements + off;
293
+ native_slot_dup(field_type, to_mem, from_mem);
294
+ new_rptfield_self->size++;
295
+ }
296
+
297
+ return new_rptfield;
298
+ }
299
+
300
+ // Internal only: used by Google::Protobuf.deep_copy.
301
+ VALUE RepeatedField_deep_copy(VALUE _self) {
302
+ RepeatedField* self = ruby_to_RepeatedField(_self);
303
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
304
+ RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
305
+ RepeatedField_reserve(new_rptfield_self, self->size);
306
+ upb_fieldtype_t field_type = self->field_type;
307
+ size_t elem_size = native_slot_size(field_type);
308
+ size_t off = 0;
309
+ for (int i = 0; i < self->size; i++, off += elem_size) {
310
+ void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
311
+ void* from_mem = (uint8_t *)self->elements + off;
312
+ native_slot_deep_copy(field_type, to_mem, from_mem);
313
+ new_rptfield_self->size++;
314
+ }
315
+
316
+ return new_rptfield;
317
+ }
318
+
319
+ /*
320
+ * call-seq:
321
+ * RepeatedField.==(other) => boolean
322
+ *
323
+ * Compares this repeated field to another. Repeated fields are equal if their
324
+ * element types are equal, their lengths are equal, and each element is equal.
325
+ * Elements are compared as per normal Ruby semantics, by calling their :==
326
+ * methods (or performing a more efficient comparison for primitive types).
327
+ */
328
+ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
329
+ if (_self == _other) {
330
+ return Qtrue;
331
+ }
332
+ RepeatedField* self = ruby_to_RepeatedField(_self);
333
+
334
+ // Inefficient but workable: to support comparison to a generic array, we
335
+ // build a temporary RepeatedField of our type.
336
+ if (TYPE(_other) == T_ARRAY) {
337
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
338
+ for (int i = 0; i < RARRAY_LEN(_other); i++) {
339
+ VALUE elem = rb_ary_entry(_other, i);
340
+ RepeatedField_push(new_rptfield, elem);
341
+ }
342
+ _other = new_rptfield;
343
+ }
344
+
345
+ RepeatedField* other = ruby_to_RepeatedField(_other);
346
+ if (self->field_type != other->field_type ||
347
+ self->field_type_class != other->field_type_class ||
348
+ self->size != other->size) {
349
+ return Qfalse;
350
+ }
351
+
352
+ upb_fieldtype_t field_type = self->field_type;
353
+ size_t elem_size = native_slot_size(field_type);
354
+ size_t off = 0;
355
+ for (int i = 0; i < self->size; i++, off += elem_size) {
356
+ void* self_mem = ((uint8_t *)self->elements) + off;
357
+ void* other_mem = ((uint8_t *)other->elements) + off;
358
+ if (!native_slot_eq(field_type, self_mem, other_mem)) {
359
+ return Qfalse;
360
+ }
361
+ }
362
+ return Qtrue;
363
+ }
364
+
365
+ /*
366
+ * call-seq:
367
+ * RepeatedField.hash => hash_value
368
+ *
369
+ * Returns a hash value computed from this repeated field's elements.
370
+ */
371
+ VALUE RepeatedField_hash(VALUE _self) {
372
+ RepeatedField* self = ruby_to_RepeatedField(_self);
373
+
374
+ VALUE hash = LL2NUM(0);
375
+
376
+ upb_fieldtype_t field_type = self->field_type;
377
+ VALUE field_type_class = self->field_type_class;
378
+ size_t elem_size = native_slot_size(field_type);
379
+ size_t off = 0;
380
+ for (int i = 0; i < self->size; i++, off += elem_size) {
381
+ void* mem = ((uint8_t *)self->elements) + off;
382
+ VALUE elem = native_slot_get(field_type, field_type_class, mem);
383
+ hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
384
+ hash = rb_funcall(hash, rb_intern("^"), 1,
385
+ rb_funcall(elem, rb_intern("hash"), 0));
386
+ }
387
+
388
+ return hash;
389
+ }
390
+
391
+ /*
392
+ * call-seq:
393
+ * RepeatedField.inspect => string
394
+ *
395
+ * Returns a string representing this repeated field's elements. It will be
396
+ * formated as "[<element>, <element>, ...]", with each element's string
397
+ * representation computed by its own #inspect method.
398
+ */
399
+ VALUE RepeatedField_inspect(VALUE _self) {
400
+ RepeatedField* self = ruby_to_RepeatedField(_self);
401
+
402
+ VALUE str = rb_str_new2("[");
403
+
404
+ bool first = true;
405
+
406
+ upb_fieldtype_t field_type = self->field_type;
407
+ VALUE field_type_class = self->field_type_class;
408
+ size_t elem_size = native_slot_size(field_type);
409
+ size_t off = 0;
410
+ for (int i = 0; i < self->size; i++, off += elem_size) {
411
+ void* mem = ((uint8_t *)self->elements) + off;
412
+ VALUE elem = native_slot_get(field_type, field_type_class, mem);
413
+ if (!first) {
414
+ str = rb_str_cat2(str, ", ");
415
+ } else {
416
+ first = false;
417
+ }
418
+ str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
419
+ }
420
+
421
+ str = rb_str_cat2(str, "]");
422
+ return str;
423
+ }
424
+
425
+ /*
426
+ * call-seq:
427
+ * RepeatedField.+(other) => repeated field
428
+ *
429
+ * Returns a new repeated field that contains the concatenated list of this
430
+ * repeated field's elements and other's elements. The other (second) list may
431
+ * be either another repeated field or a Ruby array.
432
+ */
433
+ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
434
+ VALUE dupped = RepeatedField_dup(_self);
435
+
436
+ if (TYPE(list) == T_ARRAY) {
437
+ for (int i = 0; i < RARRAY_LEN(list); i++) {
438
+ VALUE elem = rb_ary_entry(list, i);
439
+ RepeatedField_push(dupped, elem);
440
+ }
441
+ } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
442
+ RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
443
+ RepeatedField* self = ruby_to_RepeatedField(_self);
444
+ RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
445
+ if (self->field_type != list_rptfield->field_type ||
446
+ self->field_type_class != list_rptfield->field_type_class) {
447
+ rb_raise(rb_eArgError,
448
+ "Attempt to append RepeatedField with different element type.");
449
+ }
450
+ for (int i = 0; i < list_rptfield->size; i++) {
451
+ void* mem = RepeatedField_index_native(list, i);
452
+ RepeatedField_push_native(dupped, mem);
453
+ }
454
+ } else {
455
+ rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
456
+ }
457
+
458
+ return dupped;
459
+ }
460
+
461
+ static void validate_type_class(upb_fieldtype_t type, VALUE klass) {
462
+ if (rb_iv_get(klass, kDescriptorInstanceVar) == Qnil) {
463
+ rb_raise(rb_eArgError,
464
+ "Type class has no descriptor. Please pass a "
465
+ "class or enum as returned by the DescriptorPool.");
466
+ }
467
+ if (type == UPB_TYPE_MESSAGE) {
468
+ VALUE desc = rb_iv_get(klass, kDescriptorInstanceVar);
469
+ if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
470
+ RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
471
+ rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
472
+ }
473
+ if (rb_get_alloc_func(klass) != &Message_alloc) {
474
+ rb_raise(rb_eArgError,
475
+ "Message class was not returned by the DescriptorPool.");
476
+ }
477
+ } else if (type == UPB_TYPE_ENUM) {
478
+ VALUE enumdesc = rb_iv_get(klass, kDescriptorInstanceVar);
479
+ if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
480
+ RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
481
+ rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
482
+ }
483
+ }
484
+ }
485
+
486
+ void RepeatedField_init_args(int argc, VALUE* argv,
487
+ VALUE _self) {
488
+ RepeatedField* self = ruby_to_RepeatedField(_self);
489
+ VALUE ary = Qnil;
490
+ if (argc < 1) {
491
+ rb_raise(rb_eArgError, "Expected at least 1 argument.");
492
+ }
493
+ self->field_type = ruby_to_fieldtype(argv[0]);
494
+
495
+ if (self->field_type == UPB_TYPE_MESSAGE ||
496
+ self->field_type == UPB_TYPE_ENUM) {
497
+ if (argc < 2) {
498
+ rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
499
+ }
500
+ self->field_type_class = argv[1];
501
+ if (argc > 2) {
502
+ ary = argv[2];
503
+ }
504
+ validate_type_class(self->field_type, self->field_type_class);
505
+ } else {
506
+ if (argc > 2) {
507
+ rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
508
+ }
509
+ if (argc > 1) {
510
+ ary = argv[1];
511
+ }
512
+ }
513
+
514
+ if (ary != Qnil) {
515
+ if (!RB_TYPE_P(ary, T_ARRAY)) {
516
+ rb_raise(rb_eArgError, "Expected array as initialize argument");
517
+ }
518
+ for (int i = 0; i < RARRAY_LEN(ary); i++) {
519
+ RepeatedField_push(_self, rb_ary_entry(ary, i));
520
+ }
521
+ }
522
+ }
523
+
524
+ // Mark, free, alloc, init and class setup functions.
525
+
526
+ void RepeatedField_mark(void* _self) {
527
+ RepeatedField* self = (RepeatedField*)_self;
528
+ rb_gc_mark(self->field_type_class);
529
+ upb_fieldtype_t field_type = self->field_type;
530
+ int element_size = native_slot_size(field_type);
531
+ for (int i = 0; i < self->size; i++) {
532
+ void* memory = (((uint8_t *)self->elements) + i * element_size);
533
+ native_slot_mark(self->field_type, memory);
534
+ }
535
+ }
536
+
537
+ void RepeatedField_free(void* _self) {
538
+ RepeatedField* self = (RepeatedField*)_self;
539
+ xfree(self->elements);
540
+ xfree(self);
541
+ }
542
+
543
+ /*
544
+ * call-seq:
545
+ * RepeatedField.new(type, type_class = nil, initial_elems = [])
546
+ *
547
+ * Creates a new repeated field. The provided type must be a Ruby symbol, and
548
+ * can take on the same values as those accepted by FieldDescriptor#type=. If
549
+ * the type is :message or :enum, type_class must be non-nil, and must be the
550
+ * Ruby class or module returned by Descriptor#msgclass or
551
+ * EnumDescriptor#enummodule, respectively. An initial list of elements may also
552
+ * be provided.
553
+ */
554
+ VALUE RepeatedField_alloc(VALUE klass) {
555
+ RepeatedField* self = ALLOC(RepeatedField);
556
+ self->elements = NULL;
557
+ self->size = 0;
558
+ self->capacity = 0;
559
+ self->field_type = -1;
560
+ self->field_type_class = Qnil;
561
+ VALUE ret = TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
562
+ return ret;
563
+ }
564
+
565
+ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
566
+ RepeatedField_init_args(argc, argv, self);
567
+ return Qnil;
568
+ }
569
+
570
+ void RepeatedField_register(VALUE module) {
571
+ VALUE klass = rb_define_class_under(
572
+ module, "RepeatedField", rb_cObject);
573
+ rb_define_alloc_func(klass, RepeatedField_alloc);
574
+ cRepeatedField = klass;
575
+ rb_gc_register_address(&cRepeatedField);
576
+
577
+ rb_define_method(klass, "initialize",
578
+ RepeatedField_init, -1);
579
+ rb_define_method(klass, "each", RepeatedField_each, 0);
580
+ rb_define_method(klass, "[]", RepeatedField_index, 1);
581
+ rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
582
+ rb_define_method(klass, "push", RepeatedField_push, 1);
583
+ rb_define_method(klass, "<<", RepeatedField_push, 1);
584
+ rb_define_method(klass, "pop", RepeatedField_pop, 0);
585
+ rb_define_method(klass, "insert", RepeatedField_insert, -1);
586
+ rb_define_method(klass, "replace", RepeatedField_replace, 1);
587
+ rb_define_method(klass, "clear", RepeatedField_clear, 0);
588
+ rb_define_method(klass, "length", RepeatedField_length, 0);
589
+ rb_define_method(klass, "dup", RepeatedField_dup, 0);
590
+ // Also define #clone so that we don't inherit Object#clone.
591
+ rb_define_method(klass, "clone", RepeatedField_dup, 0);
592
+ rb_define_method(klass, "==", RepeatedField_eq, 1);
593
+ rb_define_method(klass, "hash", RepeatedField_hash, 0);
594
+ rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
595
+ rb_define_method(klass, "+", RepeatedField_plus, 1);
596
+ rb_include_module(klass, rb_mEnumerable);
597
+ }