1 package com.fasterxml.jackson.dataformat.cbor;
2
3 import java.util.Arrays;
4 import java.io.*;
5 import java.math.BigDecimal;
6 import java.math.BigInteger;
7
8 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.core.base.GeneratorBase;
10 import com.fasterxml.jackson.core.io.IOContext;
11 import com.fasterxml.jackson.core.json.DupDetector;
12
13 import static com.fasterxml.jackson.dataformat.cbor.CBORConstants.*;
14
15
20 public class CBORGenerator extends GeneratorBase
21 {
22 private final static int[] NO_INTS = new int[0];
23
24
28 final static int BYTE_BUFFER_FOR_OUTPUT = 16000;
29
30
35 private final static int MAX_LONG_STRING_CHARS = (BYTE_BUFFER_FOR_OUTPUT / 4) - 4;
36
37
40 private final static int MAX_LONG_STRING_BYTES = (MAX_LONG_STRING_CHARS * 3) + 3;
41
42
45 public enum Feature implements FormatFeature {
46
53 WRITE_MINIMAL_INTS(true),
54
55
65 WRITE_TYPE_HEADER(false), ;
66
67 protected final boolean _defaultState;
68 protected final int _mask;
69
70
74 public static int collectDefaults() {
75 int flags = 0;
76 for (Feature f : values()) {
77 if (f.enabledByDefault()) {
78 flags |= f.getMask();
79 }
80 }
81 return flags;
82 }
83
84 private Feature(boolean defaultState) {
85 _defaultState = defaultState;
86 _mask = (1 << ordinal());
87 }
88
89 @Override
90 public boolean enabledByDefault() {
91 return _defaultState;
92 }
93
94 @Override
95 public boolean enabledIn(int flags) {
96 return (flags & getMask()) != 0;
97 }
98
99 @Override
100 public int getMask() {
101 return _mask;
102 }
103 }
104
105
115 private final static int MIN_BUFFER_LENGTH = (3 * 256) + 2;
116
117
120 private final static int INDEFINITE_LENGTH = -2;
121
122
127
128 final protected IOContext _ioContext;
129
130 final protected OutputStream _out;
131
132
136 protected int _formatFeatures;
137
138 protected boolean _cfgMinimalInts;
139
140
145
146
149 protected CBORWriteContext _cborContext;
150
151
156
157
161 protected byte[] _outputBuffer;
162
163
166 protected int _outputTail = 0;
167
168
172 protected final int _outputEnd;
173
174
178 protected char[] _charBuffer;
179
180 protected final int _charBufferLength;
181
182
187 protected int _bytesWritten;
188
189
194
195 protected int[] _elementCounts = NO_INTS;
196
197 protected int _elementCountsPtr;
198
199
204 protected int _currentRemainingElements = INDEFINITE_LENGTH;
205
206
211
212
216 protected boolean _bufferRecyclable;
217
218
223
224 public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
225 ObjectCodec codec, OutputStream out) {
226 super(stdFeatures, codec, null);
227 DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
228 ? DupDetector.rootDetector(this)
229 : null;
230
231 _cborContext = CBORWriteContext.createRootContext(dups);
232 _formatFeatures = formatFeatures;
233 _cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
234 _ioContext = ctxt;
235 _out = out;
236 _bufferRecyclable = true;
237 _outputBuffer = ctxt.allocWriteEncodingBuffer(BYTE_BUFFER_FOR_OUTPUT);
238 _outputEnd = _outputBuffer.length;
239 _charBuffer = ctxt.allocConcatBuffer();
240 _charBufferLength = _charBuffer.length;
241
242 if (_outputEnd < MIN_BUFFER_LENGTH) {
243 throw new IllegalStateException("Internal encoding buffer length ("
244 + _outputEnd + ") too short, must be at least "
245 + MIN_BUFFER_LENGTH);
246 }
247 }
248
249
258 public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
259 ObjectCodec codec, OutputStream out, byte[] outputBuffer,
260 int offset, boolean bufferRecyclable) {
261 super(stdFeatures, codec, null);
262 DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
263 ? DupDetector.rootDetector(this)
264 : null;
265
266 _cborContext = CBORWriteContext.createRootContext(dups);
267 _formatFeatures = formatFeatures;
268 _cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
269 _ioContext = ctxt;
270 _out = out;
271 _bufferRecyclable = bufferRecyclable;
272 _outputTail = offset;
273 _outputBuffer = outputBuffer;
274 _outputEnd = _outputBuffer.length;
275 _charBuffer = ctxt.allocConcatBuffer();
276 _charBufferLength = _charBuffer.length;
277
278 if (_outputEnd < MIN_BUFFER_LENGTH) {
279 throw new IllegalStateException("Internal encoding buffer length ("
280 + _outputEnd + ") too short, must be at least "
281 + MIN_BUFFER_LENGTH);
282 }
283 }
284
285
290
291 @Override
292 public Version version() {
293 return PackageVersion.VERSION;
294 }
295
296
301
302 @Override
303 public boolean canWriteBinaryNatively() {
304 return true;
305 }
306
307
312
313
317 @Override
318 public JsonGenerator useDefaultPrettyPrinter() {
319 return this;
320 }
321
322
326 @Override
327 public JsonGenerator setPrettyPrinter(PrettyPrinter pp) {
328 return this;
329 }
330
331 @Override
332 public Object getOutputTarget() {
333 return _out;
334 }
335
336 @Override
337 public int getOutputBuffered() {
338 return _outputTail;
339 }
340
341
342
343 @Override
344 public int getFormatFeatures() {
345 return _formatFeatures;
346 }
347
348 @Override
349 public JsonGenerator overrideStdFeatures(int values, int mask) {
350 int oldState = _features;
351 int newState = (oldState & ~mask) | (values & mask);
352 if (oldState != newState) {
353 _features = newState;
354 }
355 return this;
356 }
357
358 @Override
359 public JsonGenerator overrideFormatFeatures(int values, int mask) {
360 int oldState = _formatFeatures;
361 int newState = (_formatFeatures & ~mask) | (values & mask);
362 if (oldState != newState) {
363 _formatFeatures = newState;
364 _cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(newState);
365 }
366 return this;
367 }
368
369
374
375 @Override
376 public Object getCurrentValue() {
377 return _cborContext.getCurrentValue();
378 }
379
380 @Override
381 public void setCurrentValue(Object v) {
382 _cborContext.setCurrentValue(v);
383 }
384
385 @Override
386 public JsonStreamContext getOutputContext() {
387 return _cborContext;
388 }
389
390
395
396 public CBORGenerator enable(Feature f) {
397 _formatFeatures |= f.getMask();
398 if (f == Feature.WRITE_MINIMAL_INTS) {
399 _cfgMinimalInts = true;
400 }
401 return this;
402 }
403
404 public CBORGenerator disable(Feature f) {
405 _formatFeatures &= ~f.getMask();
406 if (f == Feature.WRITE_MINIMAL_INTS) {
407 _cfgMinimalInts = false;
408 }
409 return this;
410 }
411
412 public final boolean isEnabled(Feature f) {
413 return (_formatFeatures & f.getMask()) != 0;
414 }
415
416 public CBORGenerator configure(Feature f, boolean state) {
417 if (state) {
418 enable(f);
419 } else {
420 disable(f);
421 }
422 return this;
423 }
424
425
430
431
434
435 @Override
436 public final void writeFieldName(String name) throws IOException {
437 if (!_cborContext.writeFieldName(name)) {
438 _reportError("Can not write a field name, expecting a value");
439 }
440 _writeString(name);
441 }
442
443 @Override
444 public final void writeFieldName(SerializableString name)
445 throws IOException {
446
447 if (!_cborContext.writeFieldName(name.getValue())) {
448 _reportError("Can not write a field name, expecting a value");
449 }
450 byte[] raw = name.asUnquotedUTF8();
451 final int len = raw.length;
452 if (len == 0) {
453 _writeByte(BYTE_EMPTY_STRING);
454 return;
455 }
456 _writeLengthMarker(PREFIX_TYPE_TEXT, len);
457 _writeBytes(raw, 0, len);
458 }
459
460 @Override
461 public final void writeFieldId(long id) throws IOException {
462 if (!_cborContext.writeFieldId(id)) {
463 _reportError("Can not write a field id, expecting a value");
464 }
465 _writeLongNoCheck(id);
466 }
467
468
473
474
477 @Override
478 public void copyCurrentEvent(JsonParser p) throws IOException {
479 maybeCopyTag(p);
480 super.copyCurrentEvent(p);
481 }
482
483
486 @Override
487 public void copyCurrentStructure(JsonParser p) throws IOException {
488 maybeCopyTag(p);
489 super.copyCurrentStructure(p);
490 }
491
492 protected void maybeCopyTag(JsonParser p) throws IOException {
493 if (p instanceof CBORParser) {
494 if (p.hasCurrentToken()) {
495 final int currentTag = ((CBORParser) p).getCurrentTag();
496
497 if (currentTag != -1) {
498 writeTag(currentTag);
499 }
500 }
501 }
502 }
503
504
509
510 @Override
511 public final void writeStartArray() throws IOException {
512 _verifyValueWrite("start an array");
513 _cborContext = _cborContext.createChildArrayContext(null);
514 if (_elementCountsPtr > 0) {
515 _pushRemainingElements();
516 }
517 _currentRemainingElements = INDEFINITE_LENGTH;
518 _writeByte(BYTE_ARRAY_INDEFINITE);
519 }
520
521
525
526 @Override
527 public void writeStartArray(int elementsToWrite) throws IOException {
528 _verifyValueWrite("start an array");
529 _cborContext = _cborContext.createChildArrayContext(null);
530 _pushRemainingElements();
531 _currentRemainingElements = elementsToWrite;
532 _writeLengthMarker(PREFIX_TYPE_ARRAY, elementsToWrite);
533 }
534
535 @Override
536 public final void writeEndArray() throws IOException {
537 if (!_cborContext.inArray()) {
538 _reportError("Current context not Array but "+_cborContext.typeDesc());
539 }
540 closeComplexElement();
541 _cborContext = _cborContext.getParent();
542 }
543
544 @Override
545 public final void writeStartObject() throws IOException {
546 _verifyValueWrite("start an object");
547 _cborContext = _cborContext.createChildObjectContext(null);
548 if (_elementCountsPtr > 0) {
549 _pushRemainingElements();
550 }
551 _currentRemainingElements = INDEFINITE_LENGTH;
552 _writeByte(BYTE_OBJECT_INDEFINITE);
553 }
554
555 @Override
556
557 public final void writeStartObject(Object forValue) throws IOException {
558 _verifyValueWrite("start an object");
559 CBORWriteContext ctxt = _cborContext.createChildObjectContext(forValue);
560 _cborContext = ctxt;
561 if (_elementCountsPtr > 0) {
562 _pushRemainingElements();
563 }
564 _currentRemainingElements = INDEFINITE_LENGTH;
565 _writeByte(BYTE_OBJECT_INDEFINITE);
566 }
567
568 public final void writeStartObject(int elementsToWrite) throws IOException {
569 _verifyValueWrite("start an object");
570 _cborContext = _cborContext.createChildObjectContext(null);
571 _pushRemainingElements();
572 _currentRemainingElements = elementsToWrite;
573 _writeLengthMarker(PREFIX_TYPE_OBJECT, elementsToWrite);
574 }
575
576 @Override
577 public final void writeEndObject() throws IOException {
578 if (!_cborContext.inObject()) {
579 _reportError("Current context not Object but "+ _cborContext.typeDesc());
580 }
581 closeComplexElement();
582 _cborContext = _cborContext.getParent();
583 }
584
585 @Override
586 public void writeArray(int[] array, int offset, int length) throws IOException
587 {
588 _verifyOffsets(array.length, offset, length);
589
590 _verifyValueWrite("write int array");
591 _writeLengthMarker(PREFIX_TYPE_ARRAY, length);
592
593 if (_cfgMinimalInts) {
594 for (int i = offset, end = offset+length; i < end; ++i) {
595 final int value = array[i];
596 if (value < 0) {
597 _writeIntMinimal(PREFIX_TYPE_INT_NEG, -value - 1);
598 } else {
599 _writeIntMinimal(PREFIX_TYPE_INT_POS, value);
600 }
601 }
602 } else {
603 for (int i = offset, end = offset+length; i < end; ++i) {
604 final int value = array[i];
605 if (value < 0) {
606 _writeIntFull(PREFIX_TYPE_INT_NEG, -value - 1);
607 } else {
608 _writeIntFull(PREFIX_TYPE_INT_POS, value);
609 }
610 }
611 }
612 }
613
614 @Override
615 public void writeArray(long[] array, int offset, int length) throws IOException
616 {
617 _verifyOffsets(array.length, offset, length);
618
619 _verifyValueWrite("write int array");
620 _writeLengthMarker(PREFIX_TYPE_ARRAY, length);
621 for (int i = offset, end = offset+length; i < end; ++i) {
622 _writeLongNoCheck(array[i]);
623 }
624 }
625
626 @Override
627 public void writeArray(double[] array, int offset, int length) throws IOException
628 {
629 _verifyOffsets(array.length, offset, length);
630
631 _verifyValueWrite("write int array");
632 _writeLengthMarker(PREFIX_TYPE_ARRAY, length);
633 for (int i = offset, end = offset+length; i < end; ++i) {
634 _writeDoubleNoCheck(array[i]);
635 }
636 }
637
638
639 private final void _pushRemainingElements() {
640 if (_elementCounts.length == _elementCountsPtr) {
641 _elementCounts = Arrays.copyOf(_elementCounts, _elementCounts.length+10);
642 }
643 _elementCounts[_elementCountsPtr++] = _currentRemainingElements;
644 }
645
646 private final void _writeIntMinimal(int markerBase, int i) throws IOException
647 {
648 _ensureRoomForOutput(5);
649 byte b0;
650 if (i >= 0) {
651 if (i < 24) {
652 _outputBuffer[_outputTail++] = (byte) (markerBase + i);
653 return;
654 }
655 if (i <= 0xFF) {
656 _outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT8_ELEMENTS);
657 _outputBuffer[_outputTail++] = (byte) i;
658 return;
659 }
660 b0 = (byte) i;
661 i >>= 8;
662 if (i <= 0xFF) {
663 _outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT16_ELEMENTS);
664 _outputBuffer[_outputTail++] = (byte) i;
665 _outputBuffer[_outputTail++] = b0;
666 return;
667 }
668 } else {
669 b0 = (byte) i;
670 i >>= 8;
671 }
672 _outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT32_ELEMENTS);
673 _outputBuffer[_outputTail++] = (byte) (i >> 16);
674 _outputBuffer[_outputTail++] = (byte) (i >> 8);
675 _outputBuffer[_outputTail++] = (byte) i;
676 _outputBuffer[_outputTail++] = b0;
677 }
678
679 private final void _writeIntFull(int markerBase, int i) throws IOException
680 {
681
682 _ensureRoomForOutput(5);
683
684 _outputBuffer[_outputTail++] = (byte) (markerBase + SUFFIX_UINT32_ELEMENTS);
685 _outputBuffer[_outputTail++] = (byte) (i >> 24);
686 _outputBuffer[_outputTail++] = (byte) (i >> 16);
687 _outputBuffer[_outputTail++] = (byte) (i >> 8);
688 _outputBuffer[_outputTail++] = (byte) i;
689 }
690
691
692
693 private final void _writeLongNoCheck(long l) throws IOException {
694 if (_cfgMinimalInts) {
695 if (l >= 0) {
696 if (l <= 0x100000000L) {
697 _writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
698 return;
699 }
700 } else if (l >= -0x100000000L) {
701 _writeIntMinimal(PREFIX_TYPE_INT_NEG, (int) (-l - 1));
702 return;
703 }
704 }
705 _ensureRoomForOutput(9);
706 if (l < 0L) {
707 l += 1;
708 l = -l;
709 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_NEG + SUFFIX_UINT64_ELEMENTS);
710 } else {
711 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_POS + SUFFIX_UINT64_ELEMENTS);
712 }
713 int i = (int) (l >> 32);
714 _outputBuffer[_outputTail++] = (byte) (i >> 24);
715 _outputBuffer[_outputTail++] = (byte) (i >> 16);
716 _outputBuffer[_outputTail++] = (byte) (i >> 8);
717 _outputBuffer[_outputTail++] = (byte) i;
718 i = (int) l;
719 _outputBuffer[_outputTail++] = (byte) (i >> 24);
720 _outputBuffer[_outputTail++] = (byte) (i >> 16);
721 _outputBuffer[_outputTail++] = (byte) (i >> 8);
722 _outputBuffer[_outputTail++] = (byte) i;
723 }
724
725 private final void _writeDoubleNoCheck(double d) throws IOException {
726 _ensureRoomForOutput(11);
727
728
729
730
731 long l = Double.doubleToRawLongBits(d);
732 _outputBuffer[_outputTail++] = BYTE_FLOAT64;
733
734 int i = (int) (l >> 32);
735 _outputBuffer[_outputTail++] = (byte) (i >> 24);
736 _outputBuffer[_outputTail++] = (byte) (i >> 16);
737 _outputBuffer[_outputTail++] = (byte) (i >> 8);
738 _outputBuffer[_outputTail++] = (byte) i;
739 i = (int) l;
740 _outputBuffer[_outputTail++] = (byte) (i >> 24);
741 _outputBuffer[_outputTail++] = (byte) (i >> 16);
742 _outputBuffer[_outputTail++] = (byte) (i >> 8);
743 _outputBuffer[_outputTail++] = (byte) i;
744 }
745
746
751
752 @Override
753 public void writeString(String text) throws IOException {
754 if (text == null) {
755 writeNull();
756 return;
757 }
758 _verifyValueWrite("write String value");
759 _writeString(text);
760 }
761
762 @Override
763 public final void writeString(SerializableString sstr) throws IOException {
764 _verifyValueWrite("write String value");
765 byte[] raw = sstr.asUnquotedUTF8();
766 final int len = raw.length;
767 if (len == 0) {
768 _writeByte(BYTE_EMPTY_STRING);
769 return;
770 }
771 _writeLengthMarker(PREFIX_TYPE_TEXT, len);
772 _writeBytes(raw, 0, len);
773 }
774
775 @Override
776 public void writeString(char[] text, int offset, int len)
777 throws IOException {
778 _verifyValueWrite("write String value");
779 if (len == 0) {
780 _writeByte(BYTE_EMPTY_STRING);
781 return;
782 }
783 _writeString(text, offset, len);
784 }
785
786 @Override
787 public void writeRawUTF8String(byte[] raw, int offset, int len)
788 throws IOException
789 {
790 _verifyValueWrite("write String value");
791 if (len == 0) {
792 _writeByte(BYTE_EMPTY_STRING);
793 return;
794 }
795 _writeLengthMarker(PREFIX_TYPE_TEXT, len);
796 _writeBytes(raw, 0, len);
797 }
798
799 @Override
800 public final void writeUTF8String(byte[] text, int offset, int len)
801 throws IOException {
802
803 writeRawUTF8String(text, offset, len);
804 }
805
806
811
812 @Override
813 public void writeRaw(String text) throws IOException {
814 throw _notSupported();
815 }
816
817 @Override
818 public void writeRaw(String text, int offset, int len) throws IOException {
819 throw _notSupported();
820 }
821
822 @Override
823 public void writeRaw(char[] text, int offset, int len) throws IOException {
824 throw _notSupported();
825 }
826
827 @Override
828 public void writeRaw(char c) throws IOException {
829 throw _notSupported();
830 }
831
832 @Override
833 public void writeRawValue(String text) throws IOException {
834 throw _notSupported();
835 }
836
837 @Override
838 public void writeRawValue(String text, int offset, int len)
839 throws IOException {
840 throw _notSupported();
841 }
842
843 @Override
844 public void writeRawValue(char[] text, int offset, int len)
845 throws IOException {
846 throw _notSupported();
847 }
848
849
854
855 @Override
856 public void writeBinary(Base64Variant b64variant, byte[] data, int offset,
857 int len) throws IOException {
858 if (data == null) {
859 writeNull();
860 return;
861 }
862 _verifyValueWrite("write Binary value");
863 _writeLengthMarker(PREFIX_TYPE_BYTES, len);
864 _writeBytes(data, offset, len);
865 }
866
867 @Override
868 public int writeBinary(InputStream data, int dataLength) throws IOException {
869
875 if (dataLength < 0) {
876 throw new UnsupportedOperationException(
877 "Must pass actual length for CBOR encoded data");
878 }
879 _verifyValueWrite("write Binary value");
880 int missing;
881
882 _writeLengthMarker(PREFIX_TYPE_BYTES, dataLength);
883 missing = _writeBytes(data, dataLength);
884 if (missing > 0) {
885 _reportError("Too few bytes available: missing " + missing
886 + " bytes (out of " + dataLength + ")");
887 }
888 return dataLength;
889 }
890
891 @Override
892 public int writeBinary(Base64Variant b64variant, InputStream data,
893 int dataLength) throws IOException {
894 return writeBinary(data, dataLength);
895 }
896
897
902
903 @Override
904 public void writeBoolean(boolean state) throws IOException {
905 _verifyValueWrite("write boolean value");
906 if (state) {
907 _writeByte(BYTE_TRUE);
908 } else {
909 _writeByte(BYTE_FALSE);
910 }
911 }
912
913 @Override
914 public void writeNull() throws IOException {
915 _verifyValueWrite("write null value");
916 _writeByte(BYTE_NULL);
917 }
918
919 @Override
920 public void writeNumber(int i) throws IOException {
921 _verifyValueWrite("write number");
922 int marker;
923 if (i < 0) {
924 i = -i - 1;
925 marker = PREFIX_TYPE_INT_NEG;
926 } else {
927 marker = PREFIX_TYPE_INT_POS;
928 }
929 _ensureRoomForOutput(5);
930 byte b0;
931 if (_cfgMinimalInts) {
932 if (i < 24) {
933 _outputBuffer[_outputTail++] = (byte) (marker + i);
934 return;
935 }
936 if (i <= 0xFF) {
937 _outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT8_ELEMENTS);
938 _outputBuffer[_outputTail++] = (byte) i;
939 return;
940 }
941 b0 = (byte) i;
942 i >>= 8;
943 if (i <= 0xFF) {
944 _outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT16_ELEMENTS);
945 _outputBuffer[_outputTail++] = (byte) i;
946 _outputBuffer[_outputTail++] = b0;
947 return;
948 }
949 } else {
950 b0 = (byte) i;
951 i >>= 8;
952 }
953 _outputBuffer[_outputTail++] = (byte) (marker + SUFFIX_UINT32_ELEMENTS);
954 _outputBuffer[_outputTail++] = (byte) (i >> 16);
955 _outputBuffer[_outputTail++] = (byte) (i >> 8);
956 _outputBuffer[_outputTail++] = (byte) i;
957 _outputBuffer[_outputTail++] = b0;
958 }
959
960 @Override
961 public void writeNumber(long l) throws IOException {
962 _verifyValueWrite("write number");
963 if (_cfgMinimalInts) {
964 if (l >= 0) {
965 if (l <= 0x100000000L) {
966 _writeIntMinimal(PREFIX_TYPE_INT_POS, (int) l);
967 return;
968 }
969 } else if (l >= -0x100000000L) {
970 _writeIntMinimal(PREFIX_TYPE_INT_NEG, (int) (-l - 1));
971 return;
972 }
973 }
974 _ensureRoomForOutput(9);
975 if (l < 0L) {
976 l += 1;
977 l = -l;
978 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_NEG + SUFFIX_UINT64_ELEMENTS);
979 } else {
980 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_POS + SUFFIX_UINT64_ELEMENTS);
981 }
982 int i = (int) (l >> 32);
983 _outputBuffer[_outputTail++] = (byte) (i >> 24);
984 _outputBuffer[_outputTail++] = (byte) (i >> 16);
985 _outputBuffer[_outputTail++] = (byte) (i >> 8);
986 _outputBuffer[_outputTail++] = (byte) i;
987 i = (int) l;
988 _outputBuffer[_outputTail++] = (byte) (i >> 24);
989 _outputBuffer[_outputTail++] = (byte) (i >> 16);
990 _outputBuffer[_outputTail++] = (byte) (i >> 8);
991 _outputBuffer[_outputTail++] = (byte) i;
992 }
993
994 @Override
995 public void writeNumber(BigInteger v) throws IOException {
996 if (v == null) {
997 writeNull();
998 return;
999 }
1000 _verifyValueWrite("write number");
1001 _write(v);
1002 }
1003
1004
1005
1006 protected void _write(BigInteger v) throws IOException {
1007
1012 if (v.signum() < 0) {
1013 _writeByte(BYTE_TAG_BIGNUM_NEG);
1014 v = v.negate();
1015 } else {
1016 _writeByte(BYTE_TAG_BIGNUM_POS);
1017 }
1018 byte[] data = v.toByteArray();
1019 final int len = data.length;
1020 _writeLengthMarker(PREFIX_TYPE_BYTES, len);
1021 _writeBytes(data, 0, len);
1022 }
1023
1024 @Override
1025 public void writeNumber(double d) throws IOException {
1026 _verifyValueWrite("write number");
1027 _ensureRoomForOutput(11);
1028
1034 long l = Double.doubleToRawLongBits(d);
1035 _outputBuffer[_outputTail++] = BYTE_FLOAT64;
1036
1037 int i = (int) (l >> 32);
1038 _outputBuffer[_outputTail++] = (byte) (i >> 24);
1039 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1040 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1041 _outputBuffer[_outputTail++] = (byte) i;
1042 i = (int) l;
1043 _outputBuffer[_outputTail++] = (byte) (i >> 24);
1044 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1045 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1046 _outputBuffer[_outputTail++] = (byte) i;
1047 }
1048
1049 @Override
1050 public void writeNumber(float f) throws IOException {
1051
1052 _ensureRoomForOutput(6);
1053 _verifyValueWrite("write number");
1054
1055
1061 int i = Float.floatToRawIntBits(f);
1062 _outputBuffer[_outputTail++] = BYTE_FLOAT32;
1063 _outputBuffer[_outputTail++] = (byte) (i >> 24);
1064 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1065 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1066 _outputBuffer[_outputTail++] = (byte) i;
1067 }
1068
1069 @Override
1070 public void writeNumber(BigDecimal dec) throws IOException {
1071 if (dec == null) {
1072 writeNull();
1073 return;
1074 }
1075 _verifyValueWrite("write number");
1076
1080
1081
1082 _writeByte(BYTE_TAG_DECIMAL_FRACTION);
1083 _writeByte(BYTE_ARRAY_2_ELEMENTS);
1084
1085
1086 int scale = dec.scale();
1087 _writeIntValue(-scale);
1088
1089
1090 BigInteger unscaled = dec.unscaledValue();
1091 int bitLength = unscaled.bitLength();
1092 if (bitLength <= 31) {
1093 _writeIntValue(unscaled.intValue());
1094 } else if (bitLength <= 63) {
1095 _writeLongValue(unscaled.longValue());
1096 } else {
1097 _write(unscaled);
1098 }
1099 }
1100
1101 @Override
1102 public void writeNumber(String encodedValue) throws IOException,
1103 JsonGenerationException, UnsupportedOperationException {
1104
1105
1106
1107 writeString(encodedValue);
1108 }
1109
1110
1115
1116 @Override
1117 protected final void _verifyValueWrite(String typeMsg) throws IOException {
1118 if (!_cborContext.writeValue()) {
1119 _reportError("Can not " + typeMsg + ", expecting field name/id");
1120 }
1121
1122 int count = _currentRemainingElements;
1123 if (count != INDEFINITE_LENGTH) {
1124 --count;
1125
1126
1127
1128
1129 if (count < 0) {
1130 _failSizedArrayOrObject();
1131 return;
1132 }
1133 _currentRemainingElements = count;
1134 }
1135 }
1136
1137 private void _failSizedArrayOrObject() throws IOException
1138 {
1139 _reportError(String.format("%s size mismatch: number of element encoded is not equal to reported array/map size.",
1140 _cborContext.typeDesc()));
1141 }
1142
1143
1148
1149 @Override
1150 public final void flush() throws IOException {
1151 _flushBuffer();
1152 if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
1153 _out.flush();
1154 }
1155 }
1156
1157 @Override
1158 public void close() throws IOException {
1159
1160 if ((_outputBuffer != null)
1161 && isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)) {
1162 while (true) {
1163 JsonStreamContext ctxt = getOutputContext();
1164 if (ctxt.inArray()) {
1165 writeEndArray();
1166 } else if (ctxt.inObject()) {
1167 writeEndObject();
1168 } else {
1169 break;
1170 }
1171 }
1172 }
1173
1174 super.close();
1175 _flushBuffer();
1176
1177 if (_ioContext.isResourceManaged()
1178 || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) {
1179 _out.close();
1180 } else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
1181
1182
1183 _out.flush();
1184 }
1185
1186 _releaseBuffers();
1187 }
1188
1189
1194
1195
1203 public void writeTag(int tagId) throws IOException {
1204 if (tagId < 0) {
1205 throw new IllegalArgumentException(
1206 "Can not write negative tag ids (" + tagId + ")");
1207 }
1208 _writeLengthMarker(PREFIX_TYPE_TAG, tagId);
1209 }
1210
1211
1216
1217
1223 public void writeRaw(byte b) throws IOException {
1224 _writeByte(b);
1225 }
1226
1227
1233 public void writeBytes(byte[] data, int offset, int len) throws IOException {
1234 _writeBytes(data, offset, len);
1235 }
1236
1237
1242
1243 private final static int MAX_SHORT_STRING_CHARS = 23;
1244
1245 private final static int MAX_SHORT_STRING_BYTES = 23 * 3 + 2;
1246
1247 private final static int MAX_MEDIUM_STRING_CHARS = 255;
1248
1249 private final static int MAX_MEDIUM_STRING_BYTES = 255 * 3 + 3;
1250
1251 protected final void _writeString(String name) throws IOException {
1252 int len = name.length();
1253 if (len == 0) {
1254 _writeByte(BYTE_EMPTY_STRING);
1255 return;
1256 }
1257
1258 if (len <= MAX_SHORT_STRING_CHARS) {
1259 _ensureSpace(MAX_SHORT_STRING_BYTES);
1260
1261 int actual = _encode(_outputTail + 1, name, len);
1262 final byte[] buf = _outputBuffer;
1263 int ix = _outputTail;
1264 if (actual <= MAX_SHORT_STRING_CHARS) {
1265 buf[ix++] = (byte) (PREFIX_TYPE_TEXT + actual);
1266 _outputTail = ix + actual;
1267 return;
1268 }
1269
1270 System.arraycopy(buf, ix + 1, buf, ix + 2, actual);
1271 buf[ix++] = BYTE_STRING_1BYTE_LEN;
1272 buf[ix++] = (byte) actual;
1273 _outputTail = ix + actual;
1274 return;
1275 }
1276
1277 char[] cbuf = _charBuffer;
1278 if (len > cbuf.length) {
1279 _charBuffer = cbuf = new char[Math
1280 .max(_charBuffer.length + 32, len)];
1281 }
1282 name.getChars(0, len, cbuf, 0);
1283 _writeString(cbuf, 0, len);
1284 }
1285
1286 protected final void _ensureSpace(int needed) throws IOException {
1287 if ((_outputTail + needed + 3) > _outputEnd) {
1288 _flushBuffer();
1289 }
1290 }
1291
1292 protected final void _writeString(char[] text, int offset, int len)
1293 throws IOException
1294 {
1295 if (len <= MAX_SHORT_STRING_CHARS) {
1296 _ensureSpace(MAX_SHORT_STRING_BYTES);
1297 int actual = _encode(_outputTail + 1, text, offset, offset + len);
1298 final byte[] buf = _outputBuffer;
1299 int ix = _outputTail;
1300 if (actual <= MAX_SHORT_STRING_CHARS) {
1301 buf[ix++] = (byte) (PREFIX_TYPE_TEXT + actual);
1302 _outputTail = ix + actual;
1303 return;
1304 }
1305
1306 System.arraycopy(buf, ix + 1, buf, ix + 2, actual);
1307 buf[ix++] = BYTE_STRING_1BYTE_LEN;
1308 buf[ix++] = (byte) actual;
1309 _outputTail = ix + actual;
1310 return;
1311 }
1312 if (len <= MAX_MEDIUM_STRING_CHARS) {
1313 _ensureSpace(MAX_MEDIUM_STRING_BYTES);
1314 int actual = _encode(_outputTail + 2, text, offset, offset + len);
1315 final byte[] buf = _outputBuffer;
1316 int ix = _outputTail;
1317 if (actual <= MAX_MEDIUM_STRING_CHARS) {
1318 buf[ix++] = BYTE_STRING_1BYTE_LEN;
1319 buf[ix++] = (byte) actual;
1320 _outputTail = ix + actual;
1321 return;
1322 }
1323
1324 System.arraycopy(buf, ix + 2, buf, ix + 3, actual);
1325 buf[ix++] = BYTE_STRING_2BYTE_LEN;
1326 buf[ix++] = (byte) (actual >> 8);
1327 buf[ix++] = (byte) actual;
1328 _outputTail = ix + actual;
1329 return;
1330 }
1331 if (len <= MAX_LONG_STRING_CHARS) {
1332
1333 _ensureSpace(MAX_LONG_STRING_BYTES);
1334
1335 int ix = _outputTail;
1336 int actual = _encode(ix + 3, text, offset, offset+len);
1337 final byte[] buf = _outputBuffer;
1338 buf[ix++] = BYTE_STRING_2BYTE_LEN;
1339 buf[ix++] = (byte) (actual >> 8);
1340 buf[ix++] = (byte) actual;
1341 _outputTail = ix + actual;
1342 return;
1343 }
1344 _writeChunkedString(text, offset, len);
1345 }
1346
1347 protected final void _writeChunkedString(char[] text, int offset, int len)
1348 throws IOException
1349 {
1350
1351 _writeByte(BYTE_STRING_INDEFINITE);
1352
1353 while (len > MAX_LONG_STRING_CHARS) {
1354 _ensureSpace(MAX_LONG_STRING_BYTES);
1355 int ix = _outputTail;
1356 int amount = MAX_LONG_STRING_CHARS;
1357
1358
1359 int end = offset + amount;
1360 char c = text[end-1];
1361 if (c >= SURR1_FIRST && c <= SURR1_LAST) {
1362 --end;
1363 --amount;
1364 }
1365 int actual = _encode(_outputTail + 3, text, offset, end);
1366 final byte[] buf = _outputBuffer;
1367 buf[ix++] = BYTE_STRING_2BYTE_LEN;
1368 buf[ix++] = (byte) (actual >> 8);
1369 buf[ix++] = (byte) actual;
1370 _outputTail = ix + actual;
1371 offset += amount;
1372 len -= amount;
1373 }
1374
1375 if (len > 0) {
1376 _writeString(text, offset, len);
1377 }
1378
1379 _writeByte(BYTE_BREAK);
1380 }
1381
1382
1387
1388
1392 private final int _encode(int outputPtr, char[] str, int i, int end) {
1393
1394 final byte[] outBuf = _outputBuffer;
1395 final int outputStart = outputPtr;
1396 do {
1397 int c = str[i];
1398 if (c > 0x7F) {
1399 return _shortUTF8Encode2(str, i, end, outputPtr, outputStart);
1400 }
1401 outBuf[outputPtr++] = (byte) c;
1402 } while (++i < end);
1403 return outputPtr - outputStart;
1404 }
1405
1406
1411 private final int _shortUTF8Encode2(char[] str, int i, int end,
1412 int outputPtr, int outputStart) {
1413 final byte[] outBuf = _outputBuffer;
1414 while (i < end) {
1415 int c = str[i++];
1416 if (c <= 0x7F) {
1417 outBuf[outputPtr++] = (byte) c;
1418 continue;
1419 }
1420
1421 if (c < 0x800) {
1422 outBuf[outputPtr++] = (byte) (0xc0 | (c >> 6));
1423 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1424 continue;
1425 }
1426
1427
1428 if (c < SURR1_FIRST || c > SURR2_LAST) {
1429 outBuf[outputPtr++] = (byte) (0xe0 | (c >> 12));
1430 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
1431 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1432 continue;
1433 }
1434
1435 if (c > SURR1_LAST) {
1436 _throwIllegalSurrogate(c);
1437 }
1438
1439 if (i >= end) {
1440 _throwIllegalSurrogate(c);
1441 }
1442 c = _convertSurrogate(c, str[i++]);
1443 if (c > 0x10FFFF) {
1444 _throwIllegalSurrogate(c);
1445 }
1446 outBuf[outputPtr++] = (byte) (0xf0 | (c >> 18));
1447 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
1448 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
1449 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1450 }
1451 return (outputPtr - outputStart);
1452 }
1453
1454 private final int _encode(int outputPtr, String str, int len) {
1455 final byte[] outBuf = _outputBuffer;
1456 final int outputStart = outputPtr;
1457
1458 for (int i = 0; i < len; ++i) {
1459 int c = str.charAt(i);
1460 if (c > 0x7F) {
1461 return _encode2(i, outputPtr, str, len, outputStart);
1462 }
1463 outBuf[outputPtr++] = (byte) c;
1464 }
1465 return (outputPtr - outputStart);
1466 }
1467
1468 private final int _encode2(int i, int outputPtr, String str, int len,
1469 int outputStart) {
1470 final byte[] outBuf = _outputBuffer;
1471
1472 while (i < len) {
1473 int c = str.charAt(i++);
1474 if (c <= 0x7F) {
1475 outBuf[outputPtr++] = (byte) c;
1476 continue;
1477 }
1478
1479 if (c < 0x800) {
1480 outBuf[outputPtr++] = (byte) (0xc0 | (c >> 6));
1481 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1482 continue;
1483 }
1484
1485
1486 if (c < SURR1_FIRST || c > SURR2_LAST) {
1487
1488 outBuf[outputPtr++] = (byte) (0xe0 | (c >> 12));
1489 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
1490 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1491 continue;
1492 }
1493
1494 if (c > SURR1_LAST) {
1495 _throwIllegalSurrogate(c);
1496 }
1497
1498 if (i >= len) {
1499 _throwIllegalSurrogate(c);
1500 }
1501 c = _convertSurrogate(c, str.charAt(i++));
1502 if (c > 0x10FFFF) {
1503 _throwIllegalSurrogate(c);
1504 }
1505 outBuf[outputPtr++] = (byte) (0xf0 | (c >> 18));
1506 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
1507 outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
1508 outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f));
1509 }
1510 return (outputPtr - outputStart);
1511 }
1512
1513
1516 private int _convertSurrogate(int firstPart, int secondPart) {
1517
1518 if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) {
1519 throw new IllegalArgumentException(
1520 "Broken surrogate pair: first char 0x"
1521 + Integer.toHexString(firstPart) + ", second 0x"
1522 + Integer.toHexString(secondPart)
1523 + "; illegal combination");
1524 }
1525 return 0x10000 + ((firstPart - SURR1_FIRST) << 10)
1526 + (secondPart - SURR2_FIRST);
1527 }
1528
1529 private void _throwIllegalSurrogate(int code) {
1530 if (code > 0x10FFFF) {
1531 throw new IllegalArgumentException("Illegal character point (0x"
1532 + Integer.toHexString(code)
1533 + ") to output; max is 0x10FFFF as per RFC 4627");
1534 }
1535 if (code >= SURR1_FIRST) {
1536 if (code <= SURR1_LAST) {
1537
1538 throw new IllegalArgumentException(
1539 "Unmatched first part of surrogate pair (0x"
1540 + Integer.toHexString(code) + ")");
1541 }
1542 throw new IllegalArgumentException(
1543 "Unmatched second part of surrogate pair (0x"
1544 + Integer.toHexString(code) + ")");
1545 }
1546
1547 throw new IllegalArgumentException("Illegal character point (0x"
1548 + Integer.toHexString(code) + ") to output");
1549 }
1550
1551
1556
1557 private final void _ensureRoomForOutput(int needed) throws IOException {
1558 if ((_outputTail + needed) >= _outputEnd) {
1559 _flushBuffer();
1560 }
1561 }
1562
1563 private final void _writeIntValue(int i) throws IOException {
1564 int marker;
1565 if (i < 0) {
1566 i = -i - 1;
1567 marker = PREFIX_TYPE_INT_NEG;
1568 } else {
1569 marker = PREFIX_TYPE_INT_POS;
1570 }
1571 _writeLengthMarker(marker, i);
1572 }
1573
1574 private final void _writeLongValue(long l) throws IOException {
1575 _ensureRoomForOutput(9);
1576 if (l < 0) {
1577 l += 1;
1578 l = -l;
1579 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_NEG + SUFFIX_UINT64_ELEMENTS);
1580 } else {
1581 _outputBuffer[_outputTail++] = (PREFIX_TYPE_INT_POS + SUFFIX_UINT64_ELEMENTS);
1582 }
1583 int i = (int) (l >> 32);
1584 _outputBuffer[_outputTail++] = (byte) (i >> 24);
1585 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1586 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1587 _outputBuffer[_outputTail++] = (byte) i;
1588 i = (int) l;
1589 _outputBuffer[_outputTail++] = (byte) (i >> 24);
1590 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1591 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1592 _outputBuffer[_outputTail++] = (byte) i;
1593 }
1594
1595 private final void _writeLengthMarker(int majorType, int i)
1596 throws IOException {
1597 _ensureRoomForOutput(5);
1598 if (i < 24) {
1599 _outputBuffer[_outputTail++] = (byte) (majorType + i);
1600 return;
1601 }
1602 if (i <= 0xFF) {
1603 _outputBuffer[_outputTail++] = (byte) (majorType + SUFFIX_UINT8_ELEMENTS);
1604 _outputBuffer[_outputTail++] = (byte) i;
1605 return;
1606 }
1607 final byte b0 = (byte) i;
1608 i >>= 8;
1609 if (i <= 0xFF) {
1610 _outputBuffer[_outputTail++] = (byte) (majorType + SUFFIX_UINT16_ELEMENTS);
1611 _outputBuffer[_outputTail++] = (byte) i;
1612 _outputBuffer[_outputTail++] = b0;
1613 return;
1614 }
1615 _outputBuffer[_outputTail++] = (byte) (majorType + SUFFIX_UINT32_ELEMENTS);
1616 _outputBuffer[_outputTail++] = (byte) (i >> 16);
1617 _outputBuffer[_outputTail++] = (byte) (i >> 8);
1618 _outputBuffer[_outputTail++] = (byte) i;
1619 _outputBuffer[_outputTail++] = b0;
1620 }
1621
1622 private final void _writeByte(byte b) throws IOException {
1623 if (_outputTail >= _outputEnd) {
1624 _flushBuffer();
1625 }
1626 _outputBuffer[_outputTail++] = b;
1627 }
1628
1629
1634
1635 private final void _writeBytes(byte[] data, int offset, int len)
1636 throws IOException {
1637 if (len == 0) {
1638 return;
1639 }
1640 if ((_outputTail + len) >= _outputEnd) {
1641 _writeBytesLong(data, offset, len);
1642 return;
1643 }
1644
1645 System.arraycopy(data, offset, _outputBuffer, _outputTail, len);
1646 _outputTail += len;
1647 }
1648
1649 private final int _writeBytes(InputStream in, int bytesLeft)
1650 throws IOException {
1651 while (bytesLeft > 0) {
1652 int room = _outputEnd - _outputTail;
1653 if (room <= 0) {
1654 _flushBuffer();
1655 room = _outputEnd - _outputTail;
1656 }
1657 int count = in.read(_outputBuffer, _outputTail, room);
1658 if (count < 0) {
1659 break;
1660 }
1661 _outputTail += count;
1662 bytesLeft -= count;
1663 }
1664 return bytesLeft;
1665 }
1666
1667 private final void _writeBytesLong(byte[] data, int offset, int len)
1668 throws IOException {
1669 if (_outputTail >= _outputEnd) {
1670 _flushBuffer();
1671 }
1672 while (true) {
1673 int currLen = Math.min(len, (_outputEnd - _outputTail));
1674 System.arraycopy(data, offset, _outputBuffer, _outputTail, currLen);
1675 _outputTail += currLen;
1676 if ((len -= currLen) == 0) {
1677 break;
1678 }
1679 offset += currLen;
1680 _flushBuffer();
1681 }
1682 }
1683
1684
1689
1690 @Override
1691 protected void _releaseBuffers() {
1692 byte[] buf = _outputBuffer;
1693 if (buf != null && _bufferRecyclable) {
1694 _outputBuffer = null;
1695 _ioContext.releaseWriteEncodingBuffer(buf);
1696 }
1697 char[] cbuf = _charBuffer;
1698 if (cbuf != null) {
1699 _charBuffer = null;
1700 _ioContext.releaseConcatBuffer(cbuf);
1701 }
1702 }
1703
1704 protected final void _flushBuffer() throws IOException {
1705 if (_outputTail > 0) {
1706 _bytesWritten += _outputTail;
1707 _out.write(_outputBuffer, 0, _outputTail);
1708 _outputTail = 0;
1709 }
1710 }
1711
1712
1717
1718 private final void closeComplexElement() throws IOException {
1719 switch (_currentRemainingElements) {
1720 case INDEFINITE_LENGTH:
1721 _writeByte(BYTE_BREAK);
1722 break;
1723 case 0:
1724 break;
1725 default:
1726 _reportError(String.format("%s size mismatch: expected %d more elements",
1727 _cborContext.typeDesc(), _currentRemainingElements));
1728 }
1729 _currentRemainingElements = (_elementCountsPtr == 0)
1730 ? INDEFINITE_LENGTH
1731 : _elementCounts[--_elementCountsPtr];
1732 }
1733
1734
1739
1740 protected UnsupportedOperationException _notSupported() {
1741 return new UnsupportedOperationException();
1742 }
1743 }
1744