blob: 461cd7af82042ae208053e150b2d7b041a1aac1b [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/// @file
2/// @addtogroup flatbuffers_javascript_api
3/// @{
4/// @cond FLATBUFFERS_INTERNAL
5
6/**
7 * @fileoverview
8 *
9 * Need to suppress 'global this' error so the Node.js export line doesn't cause
10 * closure compile to error out.
11 * @suppress {globalThis}
12 */
13
14/**
15 * @const
16 * @namespace
17 */
18var flatbuffers = {};
19
20/**
21 * @typedef {number}
22 */
23flatbuffers.Offset;
24
25/**
26 * @typedef {{
27 * bb: flatbuffers.ByteBuffer,
28 * bb_pos: number
29 * }}
30 */
31flatbuffers.Table;
32
33/**
34 * @type {number}
35 * @const
36 */
37flatbuffers.SIZEOF_SHORT = 2;
38
39/**
40 * @type {number}
41 * @const
42 */
43flatbuffers.SIZEOF_INT = 4;
44
45/**
46 * @type {number}
47 * @const
48 */
49flatbuffers.FILE_IDENTIFIER_LENGTH = 4;
50
51/**
52 * @type {number}
53 * @const
54 */
55flatbuffers.SIZE_PREFIX_LENGTH = 4;
56
57/**
58 * @enum {number}
59 */
60flatbuffers.Encoding = {
61 UTF8_BYTES: 1,
62 UTF16_STRING: 2
63};
64
65/**
66 * @type {Int32Array}
67 * @const
68 */
69flatbuffers.int32 = new Int32Array(2);
70
71/**
72 * @type {Float32Array}
73 * @const
74 */
75flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer);
76
77/**
78 * @type {Float64Array}
79 * @const
80 */
81flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer);
82
83/**
84 * @type {boolean}
85 * @const
86 */
87flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
88
89////////////////////////////////////////////////////////////////////////////////
90
91/**
92 * @constructor
93 * @param {number} low
94 * @param {number} high
95 */
96flatbuffers.Long = function(low, high) {
97 /**
98 * @type {number}
99 * @const
100 */
101 this.low = low | 0;
102
103 /**
104 * @type {number}
105 * @const
106 */
107 this.high = high | 0;
108};
109
110/**
111 * @param {number} low
112 * @param {number} high
113 * @returns {flatbuffers.Long}
114 */
115flatbuffers.Long.create = function(low, high) {
116 // Special-case zero to avoid GC overhead for default values
117 return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high);
118};
119
120/**
121 * @returns {number}
122 */
123flatbuffers.Long.prototype.toFloat64 = function() {
124 return (this.low >>> 0) + this.high * 0x100000000;
125};
126
127/**
128 * @param {flatbuffers.Long} other
129 * @returns {boolean}
130 */
131flatbuffers.Long.prototype.equals = function(other) {
132 return this.low == other.low && this.high == other.high;
133};
134
135/**
136 * @type {flatbuffers.Long}
137 * @const
138 */
139flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0);
140
141/// @endcond
142////////////////////////////////////////////////////////////////////////////////
143/**
144 * Create a FlatBufferBuilder.
145 *
146 * @constructor
147 * @param {number=} opt_initial_size
148 */
149flatbuffers.Builder = function(opt_initial_size) {
150 if (!opt_initial_size) {
151 var initial_size = 1024;
152 } else {
153 var initial_size = opt_initial_size;
154 }
155
156 /**
157 * @type {flatbuffers.ByteBuffer}
158 * @private
159 */
160 this.bb = flatbuffers.ByteBuffer.allocate(initial_size);
161
162 /**
163 * Remaining space in the ByteBuffer.
164 *
165 * @type {number}
166 * @private
167 */
168 this.space = initial_size;
169
170 /**
171 * Minimum alignment encountered so far.
172 *
173 * @type {number}
174 * @private
175 */
176 this.minalign = 1;
177
178 /**
179 * The vtable for the current table.
180 *
181 * @type {Array.<number>}
182 * @private
183 */
184 this.vtable = null;
185
186 /**
187 * The amount of fields we're actually using.
188 *
189 * @type {number}
190 * @private
191 */
192 this.vtable_in_use = 0;
193
194 /**
195 * Whether we are currently serializing a table.
196 *
197 * @type {boolean}
198 * @private
199 */
200 this.isNested = false;
201
202 /**
203 * Starting offset of the current struct/table.
204 *
205 * @type {number}
206 * @private
207 */
208 this.object_start = 0;
209
210 /**
211 * List of offsets of all vtables.
212 *
213 * @type {Array.<number>}
214 * @private
215 */
216 this.vtables = [];
217
218 /**
219 * For the current vector being built.
220 *
221 * @type {number}
222 * @private
223 */
224 this.vector_num_elems = 0;
225
226 /**
227 * False omits default values from the serialized data
228 *
229 * @type {boolean}
230 * @private
231 */
232 this.force_defaults = false;
233};
234
235flatbuffers.Builder.prototype.clear = function() {
236 this.bb.clear();
237 this.space = this.bb.capacity();
238 this.minalign = 1;
239 this.vtable = null;
240 this.vtable_in_use = 0;
241 this.isNested = false;
242 this.object_start = 0;
243 this.vtables = [];
244 this.vector_num_elems = 0;
245 this.force_defaults = false;
246};
247
248/**
249 * In order to save space, fields that are set to their default value
250 * don't get serialized into the buffer. Forcing defaults provides a
251 * way to manually disable this optimization.
252 *
253 * @param {boolean} forceDefaults true always serializes default values
254 */
255flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) {
256 this.force_defaults = forceDefaults;
257};
258
259/**
260 * Get the ByteBuffer representing the FlatBuffer. Only call this after you've
261 * called finish(). The actual data starts at the ByteBuffer's current position,
262 * not necessarily at 0.
263 *
264 * @returns {flatbuffers.ByteBuffer}
265 */
266flatbuffers.Builder.prototype.dataBuffer = function() {
267 return this.bb;
268};
269
270/**
271 * Get the bytes representing the FlatBuffer. Only call this after you've
272 * called finish().
273 *
274 * @returns {Uint8Array}
275 */
276flatbuffers.Builder.prototype.asUint8Array = function() {
277 return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset());
278};
279
280/// @cond FLATBUFFERS_INTERNAL
281/**
282 * Prepare to write an element of `size` after `additional_bytes` have been
283 * written, e.g. if you write a string, you need to align such the int length
284 * field is aligned to 4 bytes, and the string data follows it directly. If all
285 * you need to do is alignment, `additional_bytes` will be 0.
286 *
287 * @param {number} size This is the of the new element to write
288 * @param {number} additional_bytes The padding size
289 */
290flatbuffers.Builder.prototype.prep = function(size, additional_bytes) {
291 // Track the biggest thing we've ever aligned to.
292 if (size > this.minalign) {
293 this.minalign = size;
294 }
295
296 // Find the amount of alignment needed such that `size` is properly
297 // aligned after `additional_bytes`
298 var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1);
299
300 // Reallocate the buffer if needed.
301 while (this.space < align_size + size + additional_bytes) {
302 var old_buf_size = this.bb.capacity();
303 this.bb = flatbuffers.Builder.growByteBuffer(this.bb);
304 this.space += this.bb.capacity() - old_buf_size;
305 }
306
307 this.pad(align_size);
308};
309
310/**
311 * @param {number} byte_size
312 */
313flatbuffers.Builder.prototype.pad = function(byte_size) {
314 for (var i = 0; i < byte_size; i++) {
315 this.bb.writeInt8(--this.space, 0);
316 }
317};
318
319/**
320 * @param {number} value
321 */
322flatbuffers.Builder.prototype.writeInt8 = function(value) {
323 this.bb.writeInt8(this.space -= 1, value);
324};
325
326/**
327 * @param {number} value
328 */
329flatbuffers.Builder.prototype.writeInt16 = function(value) {
330 this.bb.writeInt16(this.space -= 2, value);
331};
332
333/**
334 * @param {number} value
335 */
336flatbuffers.Builder.prototype.writeInt32 = function(value) {
337 this.bb.writeInt32(this.space -= 4, value);
338};
339
340/**
341 * @param {flatbuffers.Long} value
342 */
343flatbuffers.Builder.prototype.writeInt64 = function(value) {
344 this.bb.writeInt64(this.space -= 8, value);
345};
346
347/**
348 * @param {number} value
349 */
350flatbuffers.Builder.prototype.writeFloat32 = function(value) {
351 this.bb.writeFloat32(this.space -= 4, value);
352};
353
354/**
355 * @param {number} value
356 */
357flatbuffers.Builder.prototype.writeFloat64 = function(value) {
358 this.bb.writeFloat64(this.space -= 8, value);
359};
360/// @endcond
361
362/**
363 * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary).
364 * @param {number} value The `int8` to add the the buffer.
365 */
366flatbuffers.Builder.prototype.addInt8 = function(value) {
367 this.prep(1, 0);
368 this.writeInt8(value);
369};
370
371/**
372 * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary).
373 * @param {number} value The `int16` to add the the buffer.
374 */
375flatbuffers.Builder.prototype.addInt16 = function(value) {
376 this.prep(2, 0);
377 this.writeInt16(value);
378};
379
380/**
381 * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary).
382 * @param {number} value The `int32` to add the the buffer.
383 */
384flatbuffers.Builder.prototype.addInt32 = function(value) {
385 this.prep(4, 0);
386 this.writeInt32(value);
387};
388
389/**
390 * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary).
391 * @param {flatbuffers.Long} value The `int64` to add the the buffer.
392 */
393flatbuffers.Builder.prototype.addInt64 = function(value) {
394 this.prep(8, 0);
395 this.writeInt64(value);
396};
397
398/**
399 * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary).
400 * @param {number} value The `float32` to add the the buffer.
401 */
402flatbuffers.Builder.prototype.addFloat32 = function(value) {
403 this.prep(4, 0);
404 this.writeFloat32(value);
405};
406
407/**
408 * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary).
409 * @param {number} value The `float64` to add the the buffer.
410 */
411flatbuffers.Builder.prototype.addFloat64 = function(value) {
412 this.prep(8, 0);
413 this.writeFloat64(value);
414};
415
416/// @cond FLATBUFFERS_INTERNAL
417/**
418 * @param {number} voffset
419 * @param {number} value
420 * @param {number} defaultValue
421 */
422flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) {
423 if (this.force_defaults || value != defaultValue) {
424 this.addInt8(value);
425 this.slot(voffset);
426 }
427};
428
429/**
430 * @param {number} voffset
431 * @param {number} value
432 * @param {number} defaultValue
433 */
434flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) {
435 if (this.force_defaults || value != defaultValue) {
436 this.addInt16(value);
437 this.slot(voffset);
438 }
439};
440
441/**
442 * @param {number} voffset
443 * @param {number} value
444 * @param {number} defaultValue
445 */
446flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) {
447 if (this.force_defaults || value != defaultValue) {
448 this.addInt32(value);
449 this.slot(voffset);
450 }
451};
452
453/**
454 * @param {number} voffset
455 * @param {flatbuffers.Long} value
456 * @param {flatbuffers.Long} defaultValue
457 */
458flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) {
459 if (this.force_defaults || !value.equals(defaultValue)) {
460 this.addInt64(value);
461 this.slot(voffset);
462 }
463};
464
465/**
466 * @param {number} voffset
467 * @param {number} value
468 * @param {number} defaultValue
469 */
470flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) {
471 if (this.force_defaults || value != defaultValue) {
472 this.addFloat32(value);
473 this.slot(voffset);
474 }
475};
476
477/**
478 * @param {number} voffset
479 * @param {number} value
480 * @param {number} defaultValue
481 */
482flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) {
483 if (this.force_defaults || value != defaultValue) {
484 this.addFloat64(value);
485 this.slot(voffset);
486 }
487};
488
489/**
490 * @param {number} voffset
491 * @param {flatbuffers.Offset} value
492 * @param {flatbuffers.Offset} defaultValue
493 */
494flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) {
495 if (this.force_defaults || value != defaultValue) {
496 this.addOffset(value);
497 this.slot(voffset);
498 }
499};
500
501/**
502 * Structs are stored inline, so nothing additional is being added. `d` is always 0.
503 *
504 * @param {number} voffset
505 * @param {flatbuffers.Offset} value
506 * @param {flatbuffers.Offset} defaultValue
507 */
508flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) {
509 if (value != defaultValue) {
510 this.nested(value);
511 this.slot(voffset);
512 }
513};
514
515/**
516 * Structures are always stored inline, they need to be created right
517 * where they're used. You'll get this assertion failure if you
518 * created it elsewhere.
519 *
520 * @param {flatbuffers.Offset} obj The offset of the created object
521 */
522flatbuffers.Builder.prototype.nested = function(obj) {
523 if (obj != this.offset()) {
524 throw new Error('FlatBuffers: struct must be serialized inline.');
525 }
526};
527
528/**
529 * Should not be creating any other object, string or vector
530 * while an object is being constructed
531 */
532flatbuffers.Builder.prototype.notNested = function() {
533 if (this.isNested) {
534 throw new Error('FlatBuffers: object serialization must not be nested.');
535 }
536};
537
538/**
539 * Set the current vtable at `voffset` to the current location in the buffer.
540 *
541 * @param {number} voffset
542 */
543flatbuffers.Builder.prototype.slot = function(voffset) {
544 this.vtable[voffset] = this.offset();
545};
546
547/**
548 * @returns {flatbuffers.Offset} Offset relative to the end of the buffer.
549 */
550flatbuffers.Builder.prototype.offset = function() {
551 return this.bb.capacity() - this.space;
552};
553
554/**
555 * Doubles the size of the backing ByteBuffer and copies the old data towards
556 * the end of the new buffer (since we build the buffer backwards).
557 *
558 * @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
559 * @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied
560 * to it. The data is located at the end of the buffer.
561 *
562 * uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass
563 * it a uint8Array we need to suppress the type check:
564 * @suppress {checkTypes}
565 */
566flatbuffers.Builder.growByteBuffer = function(bb) {
567 var old_buf_size = bb.capacity();
568
569 // Ensure we don't grow beyond what fits in an int.
570 if (old_buf_size & 0xC0000000) {
571 throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.');
572 }
573
574 var new_buf_size = old_buf_size << 1;
575 var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size);
576 nbb.setPosition(new_buf_size - old_buf_size);
577 nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size);
578 return nbb;
579};
580/// @endcond
581
582/**
583 * Adds on offset, relative to where it will be written.
584 *
585 * @param {flatbuffers.Offset} offset The offset to add.
586 */
587flatbuffers.Builder.prototype.addOffset = function(offset) {
588 this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done.
589 this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT);
590};
591
592/// @cond FLATBUFFERS_INTERNAL
593/**
594 * Start encoding a new object in the buffer. Users will not usually need to
595 * call this directly. The FlatBuffers compiler will generate helper methods
596 * that call this method internally.
597 *
598 * @param {number} numfields
599 */
600flatbuffers.Builder.prototype.startObject = function(numfields) {
601 this.notNested();
602 if (this.vtable == null) {
603 this.vtable = [];
604 }
605 this.vtable_in_use = numfields;
606 for (var i = 0; i < numfields; i++) {
607 this.vtable[i] = 0; // This will push additional elements as needed
608 }
609 this.isNested = true;
610 this.object_start = this.offset();
611};
612
613/**
614 * Finish off writing the object that is under construction.
615 *
616 * @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer`
617 */
618flatbuffers.Builder.prototype.endObject = function() {
619 if (this.vtable == null || !this.isNested) {
620 throw new Error('FlatBuffers: endObject called without startObject');
621 }
622
623 this.addInt32(0);
624 var vtableloc = this.offset();
625
626 // Trim trailing zeroes.
627 var i = this.vtable_in_use - 1;
628 for (; i >= 0 && this.vtable[i] == 0; i--) {}
629 var trimmed_size = i + 1;
630
631 // Write out the current vtable.
632 for (; i >= 0; i--) {
633 // Offset relative to the start of the table.
634 this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
635 }
636
637 var standard_fields = 2; // The fields below:
638 this.addInt16(vtableloc - this.object_start);
639 var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
640 this.addInt16(len);
641
642 // Search for an existing vtable that matches the current one.
643 var existing_vtable = 0;
644 var vt1 = this.space;
645outer_loop:
646 for (i = 0; i < this.vtables.length; i++) {
647 var vt2 = this.bb.capacity() - this.vtables[i];
648 if (len == this.bb.readInt16(vt2)) {
649 for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
650 if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
651 continue outer_loop;
652 }
653 }
654 existing_vtable = this.vtables[i];
655 break;
656 }
657 }
658
659 if (existing_vtable) {
660 // Found a match:
661 // Remove the current vtable.
662 this.space = this.bb.capacity() - vtableloc;
663
664 // Point table to existing vtable.
665 this.bb.writeInt32(this.space, existing_vtable - vtableloc);
666 } else {
667 // No match:
668 // Add the location of the current vtable to the list of vtables.
669 this.vtables.push(this.offset());
670
671 // Point table to current vtable.
672 this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc);
673 }
674
675 this.isNested = false;
676 return vtableloc;
677};
678/// @endcond
679
680/**
681 * Finalize a buffer, poiting to the given `root_table`.
682 *
683 * @param {flatbuffers.Offset} root_table
684 * @param {string=} opt_file_identifier
685 * @param {boolean=} opt_size_prefix
686 */
687flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier, opt_size_prefix) {
688 var size_prefix = opt_size_prefix ? flatbuffers.SIZE_PREFIX_LENGTH : 0;
689 if (opt_file_identifier) {
690 var file_identifier = opt_file_identifier;
691 this.prep(this.minalign, flatbuffers.SIZEOF_INT +
692 flatbuffers.FILE_IDENTIFIER_LENGTH + size_prefix);
693 if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
694 throw new Error('FlatBuffers: file identifier must be length ' +
695 flatbuffers.FILE_IDENTIFIER_LENGTH);
696 }
697 for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
698 this.writeInt8(file_identifier.charCodeAt(i));
699 }
700 }
701 this.prep(this.minalign, flatbuffers.SIZEOF_INT + size_prefix);
702 this.addOffset(root_table);
703 if (size_prefix) {
704 this.addInt32(this.bb.capacity() - this.space);
705 }
706 this.bb.setPosition(this.space);
707};
708
709/**
710 * Finalize a size prefixed buffer, pointing to the given `root_table`.
711 *
712 * @param {flatbuffers.Offset} root_table
713 * @param {string=} opt_file_identifier
714 */
715flatbuffers.Builder.prototype.finishSizePrefixed = function (root_table, opt_file_identifier) {
716 this.finish(root_table, opt_file_identifier, true);
717};
718
719/// @cond FLATBUFFERS_INTERNAL
720/**
721 * This checks a required field has been set in a given table that has
722 * just been constructed.
723 *
724 * @param {flatbuffers.Offset} table
725 * @param {number} field
726 */
727flatbuffers.Builder.prototype.requiredField = function(table, field) {
728 var table_start = this.bb.capacity() - table;
729 var vtable_start = table_start - this.bb.readInt32(table_start);
730 var ok = this.bb.readInt16(vtable_start + field) != 0;
731
732 // If this fails, the caller will show what field needs to be set.
733 if (!ok) {
734 throw new Error('FlatBuffers: field ' + field + ' must be set');
735 }
736};
737
738/**
739 * Start a new array/vector of objects. Users usually will not call
740 * this directly. The FlatBuffers compiler will create a start/end
741 * method for vector types in generated code.
742 *
743 * @param {number} elem_size The size of each element in the array
744 * @param {number} num_elems The number of elements in the array
745 * @param {number} alignment The alignment of the array
746 */
747flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) {
748 this.notNested();
749 this.vector_num_elems = num_elems;
750 this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems);
751 this.prep(alignment, elem_size * num_elems); // Just in case alignment > int.
752};
753
754/**
755 * Finish off the creation of an array and all its elements. The array must be
756 * created with `startVector`.
757 *
758 * @returns {flatbuffers.Offset} The offset at which the newly created array
759 * starts.
760 */
761flatbuffers.Builder.prototype.endVector = function() {
762 this.writeInt32(this.vector_num_elems);
763 return this.offset();
764};
765/// @endcond
766
767/**
768 * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed
769 * instead of a string, it is assumed to contain valid UTF-8 encoded data.
770 *
771 * @param {string|Uint8Array} s The string to encode
772 * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts
773 */
774flatbuffers.Builder.prototype.createString = function(s) {
775 if (s instanceof Uint8Array) {
776 var utf8 = s;
777 } else {
778 var utf8 = [];
779 var i = 0;
780
781 while (i < s.length) {
782 var codePoint;
783
784 // Decode UTF-16
785 var a = s.charCodeAt(i++);
786 if (a < 0xD800 || a >= 0xDC00) {
787 codePoint = a;
788 } else {
789 var b = s.charCodeAt(i++);
790 codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00);
791 }
792
793 // Encode UTF-8
794 if (codePoint < 0x80) {
795 utf8.push(codePoint);
796 } else {
797 if (codePoint < 0x800) {
798 utf8.push(((codePoint >> 6) & 0x1F) | 0xC0);
799 } else {
800 if (codePoint < 0x10000) {
801 utf8.push(((codePoint >> 12) & 0x0F) | 0xE0);
802 } else {
803 utf8.push(
804 ((codePoint >> 18) & 0x07) | 0xF0,
805 ((codePoint >> 12) & 0x3F) | 0x80);
806 }
807 utf8.push(((codePoint >> 6) & 0x3F) | 0x80);
808 }
809 utf8.push((codePoint & 0x3F) | 0x80);
810 }
811 }
812 }
813
814 this.addInt8(0);
815 this.startVector(1, utf8.length, 1);
816 this.bb.setPosition(this.space -= utf8.length);
817 for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) {
818 bytes[offset++] = utf8[i];
819 }
820 return this.endVector();
821};
822
823/**
824 * A helper function to avoid generated code depending on this file directly.
825 *
826 * @param {number} low
827 * @param {number} high
828 * @returns {flatbuffers.Long}
829 */
830flatbuffers.Builder.prototype.createLong = function(low, high) {
831 return flatbuffers.Long.create(low, high);
832};
833////////////////////////////////////////////////////////////////////////////////
834/// @cond FLATBUFFERS_INTERNAL
835/**
836 * Create a new ByteBuffer with a given array of bytes (`Uint8Array`).
837 *
838 * @constructor
839 * @param {Uint8Array} bytes
840 */
841flatbuffers.ByteBuffer = function(bytes) {
842 /**
843 * @type {Uint8Array}
844 * @private
845 */
846 this.bytes_ = bytes;
847
848 /**
849 * @type {number}
850 * @private
851 */
852 this.position_ = 0;
853};
854
855/**
856 * Create and allocate a new ByteBuffer with a given size.
857 *
858 * @param {number} byte_size
859 * @returns {flatbuffers.ByteBuffer}
860 */
861flatbuffers.ByteBuffer.allocate = function(byte_size) {
862 return new flatbuffers.ByteBuffer(new Uint8Array(byte_size));
863};
864
865flatbuffers.ByteBuffer.prototype.clear = function() {
866 this.position_ = 0;
867};
868
869/**
870 * Get the underlying `Uint8Array`.
871 *
872 * @returns {Uint8Array}
873 */
874flatbuffers.ByteBuffer.prototype.bytes = function() {
875 return this.bytes_;
876};
877
878/**
879 * Get the buffer's position.
880 *
881 * @returns {number}
882 */
883flatbuffers.ByteBuffer.prototype.position = function() {
884 return this.position_;
885};
886
887/**
888 * Set the buffer's position.
889 *
890 * @param {number} position
891 */
892flatbuffers.ByteBuffer.prototype.setPosition = function(position) {
893 this.position_ = position;
894};
895
896/**
897 * Get the buffer's capacity.
898 *
899 * @returns {number}
900 */
901flatbuffers.ByteBuffer.prototype.capacity = function() {
902 return this.bytes_.length;
903};
904
905/**
906 * @param {number} offset
907 * @returns {number}
908 */
909flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) {
910 return this.readUint8(offset) << 24 >> 24;
911};
912
913/**
914 * @param {number} offset
915 * @returns {number}
916 */
917flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) {
918 return this.bytes_[offset];
919};
920
921/**
922 * @param {number} offset
923 * @returns {number}
924 */
925flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) {
926 return this.readUint16(offset) << 16 >> 16;
927};
928
929/**
930 * @param {number} offset
931 * @returns {number}
932 */
933flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) {
934 return this.bytes_[offset] | this.bytes_[offset + 1] << 8;
935};
936
937/**
938 * @param {number} offset
939 * @returns {number}
940 */
941flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) {
942 return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24;
943};
944
945/**
946 * @param {number} offset
947 * @returns {number}
948 */
949flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) {
950 return this.readInt32(offset) >>> 0;
951};
952
953/**
954 * @param {number} offset
955 * @returns {flatbuffers.Long}
956 */
957flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) {
958 return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4));
959};
960
961/**
962 * @param {number} offset
963 * @returns {flatbuffers.Long}
964 */
965flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) {
966 return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4));
967};
968
969/**
970 * @param {number} offset
971 * @returns {number}
972 */
973flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) {
974 flatbuffers.int32[0] = this.readInt32(offset);
975 return flatbuffers.float32[0];
976};
977
978/**
979 * @param {number} offset
980 * @returns {number}
981 */
982flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) {
983 flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset);
984 flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4);
985 return flatbuffers.float64[0];
986};
987
988/**
989 * @param {number} offset
990 * @param {number|boolean} value
991 */
992flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) {
993 this.bytes_[offset] = /** @type {number} */(value);
994};
995
996/**
997 * @param {number} offset
998 * @param {number} value
999 */
1000flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) {
1001 this.bytes_[offset] = value;
1002};
1003
1004/**
1005 * @param {number} offset
1006 * @param {number} value
1007 */
1008flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) {
1009 this.bytes_[offset] = value;
1010 this.bytes_[offset + 1] = value >> 8;
1011};
1012
1013/**
1014 * @param {number} offset
1015 * @param {number} value
1016 */
1017flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) {
1018 this.bytes_[offset] = value;
1019 this.bytes_[offset + 1] = value >> 8;
1020};
1021
1022/**
1023 * @param {number} offset
1024 * @param {number} value
1025 */
1026flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) {
1027 this.bytes_[offset] = value;
1028 this.bytes_[offset + 1] = value >> 8;
1029 this.bytes_[offset + 2] = value >> 16;
1030 this.bytes_[offset + 3] = value >> 24;
1031};
1032
1033/**
1034 * @param {number} offset
1035 * @param {number} value
1036 */
1037flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) {
1038 this.bytes_[offset] = value;
1039 this.bytes_[offset + 1] = value >> 8;
1040 this.bytes_[offset + 2] = value >> 16;
1041 this.bytes_[offset + 3] = value >> 24;
1042};
1043
1044/**
1045 * @param {number} offset
1046 * @param {flatbuffers.Long} value
1047 */
1048flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) {
1049 this.writeInt32(offset, value.low);
1050 this.writeInt32(offset + 4, value.high);
1051};
1052
1053/**
1054 * @param {number} offset
1055 * @param {flatbuffers.Long} value
1056 */
1057flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) {
1058 this.writeUint32(offset, value.low);
1059 this.writeUint32(offset + 4, value.high);
1060};
1061
1062/**
1063 * @param {number} offset
1064 * @param {number} value
1065 */
1066flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) {
1067 flatbuffers.float32[0] = value;
1068 this.writeInt32(offset, flatbuffers.int32[0]);
1069};
1070
1071/**
1072 * @param {number} offset
1073 * @param {number} value
1074 */
1075flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) {
1076 flatbuffers.float64[0] = value;
1077 this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]);
1078 this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]);
1079};
1080
1081/**
1082 * Return the file identifier. Behavior is undefined for FlatBuffers whose
1083 * schema does not include a file_identifier (likely points at padding or the
1084 * start of a the root vtable).
1085 * @returns {string}
1086 */
1087flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() {
1088 if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT +
1089 flatbuffers.FILE_IDENTIFIER_LENGTH) {
1090 throw new Error(
1091 'FlatBuffers: ByteBuffer is too short to contain an identifier.');
1092 }
1093 var result = "";
1094 for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
1095 result += String.fromCharCode(
1096 this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i));
1097 }
1098 return result;
1099};
1100
1101/**
1102 * Look up a field in the vtable, return an offset into the object, or 0 if the
1103 * field is not present.
1104 *
1105 * @param {number} bb_pos
1106 * @param {number} vtable_offset
1107 * @returns {number}
1108 */
1109flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) {
1110 var vtable = bb_pos - this.readInt32(bb_pos);
1111 return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0;
1112};
1113
1114/**
1115 * Initialize any Table-derived type to point to the union at the given offset.
1116 *
1117 * @param {flatbuffers.Table} t
1118 * @param {number} offset
1119 * @returns {flatbuffers.Table}
1120 */
1121flatbuffers.ByteBuffer.prototype.__union = function(t, offset) {
1122 t.bb_pos = offset + this.readInt32(offset);
1123 t.bb = this;
1124 return t;
1125};
1126
1127/**
1128 * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer.
1129 * This allocates a new string and converts to wide chars upon each access.
1130 *
1131 * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as
1132 * the "optionalEncoding" argument. This is useful for avoiding conversion to
1133 * and from UTF-16 when the data will just be packaged back up in another
1134 * FlatBuffer later on.
1135 *
1136 * @param {number} offset
1137 * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING
1138 * @returns {string|Uint8Array}
1139 */
1140flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) {
1141 offset += this.readInt32(offset);
1142
1143 var length = this.readInt32(offset);
1144 var result = '';
1145 var i = 0;
1146
1147 offset += flatbuffers.SIZEOF_INT;
1148
1149 if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) {
1150 return this.bytes_.subarray(offset, offset + length);
1151 }
1152
1153 while (i < length) {
1154 var codePoint;
1155
1156 // Decode UTF-8
1157 var a = this.readUint8(offset + i++);
1158 if (a < 0xC0) {
1159 codePoint = a;
1160 } else {
1161 var b = this.readUint8(offset + i++);
1162 if (a < 0xE0) {
1163 codePoint =
1164 ((a & 0x1F) << 6) |
1165 (b & 0x3F);
1166 } else {
1167 var c = this.readUint8(offset + i++);
1168 if (a < 0xF0) {
1169 codePoint =
1170 ((a & 0x0F) << 12) |
1171 ((b & 0x3F) << 6) |
1172 (c & 0x3F);
1173 } else {
1174 var d = this.readUint8(offset + i++);
1175 codePoint =
1176 ((a & 0x07) << 18) |
1177 ((b & 0x3F) << 12) |
1178 ((c & 0x3F) << 6) |
1179 (d & 0x3F);
1180 }
1181 }
1182 }
1183
1184 // Encode UTF-16
1185 if (codePoint < 0x10000) {
1186 result += String.fromCharCode(codePoint);
1187 } else {
1188 codePoint -= 0x10000;
1189 result += String.fromCharCode(
1190 (codePoint >> 10) + 0xD800,
1191 (codePoint & ((1 << 10) - 1)) + 0xDC00);
1192 }
1193 }
1194
1195 return result;
1196};
1197
1198/**
1199 * Retrieve the relative offset stored at "offset"
1200 * @param {number} offset
1201 * @returns {number}
1202 */
1203flatbuffers.ByteBuffer.prototype.__indirect = function(offset) {
1204 return offset + this.readInt32(offset);
1205};
1206
1207/**
1208 * Get the start of data of a vector whose offset is stored at "offset" in this object.
1209 *
1210 * @param {number} offset
1211 * @returns {number}
1212 */
1213flatbuffers.ByteBuffer.prototype.__vector = function(offset) {
1214 return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length
1215};
1216
1217/**
1218 * Get the length of a vector whose offset is stored at "offset" in this object.
1219 *
1220 * @param {number} offset
1221 * @returns {number}
1222 */
1223flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) {
1224 return this.readInt32(offset + this.readInt32(offset));
1225};
1226
1227/**
1228 * @param {string} ident
1229 * @returns {boolean}
1230 */
1231flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) {
1232 if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
1233 throw new Error('FlatBuffers: file identifier must be length ' +
1234 flatbuffers.FILE_IDENTIFIER_LENGTH);
1235 }
1236 for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
1237 if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) {
1238 return false;
1239 }
1240 }
1241 return true;
1242};
1243
1244/**
1245 * A helper function to avoid generated code depending on this file directly.
1246 *
1247 * @param {number} low
1248 * @param {number} high
1249 * @returns {flatbuffers.Long}
1250 */
1251flatbuffers.ByteBuffer.prototype.createLong = function(low, high) {
1252 return flatbuffers.Long.create(low, high);
1253};
1254
1255// Exports for Node.js and RequireJS
1256this.flatbuffers = flatbuffers;
1257
1258/// @endcond
1259/// @}