@@ -97,6 +97,19 @@ public enum Feature implements FormatFeature {
97
97
* @since 2.15
98
98
*/
99
99
STRINGREF (false ),
100
+
101
+ /**
102
+ * Feature that determines whether generator should try to write doubles
103
+ * as floats: if {@code true}, will write a {@code double} as a 4-byte float if no
104
+ * precision loss will occur; if {@code false}, will always write a {@code double}
105
+ * as an 8-byte double.
106
+ * <p>
107
+ * Default value is {@code false} meaning that doubles will always be written as
108
+ * 8-byte values.
109
+ *
110
+ * @since 2.15
111
+ */
112
+ WRITE_MINIMAL_DOUBLES (false ),
100
113
;
101
114
102
115
protected final boolean _defaultState ;
@@ -160,17 +173,19 @@ public int getMask() {
160
173
/**********************************************************************
161
174
*/
162
175
163
- final protected IOContext _ioContext ;
176
+ protected final IOContext _ioContext ;
164
177
165
- final protected OutputStream _out ;
178
+ protected final OutputStream _out ;
166
179
167
180
/**
168
181
* Bit flag composed of bits that indicate which
169
182
* {@link CBORGenerator.Feature}s are enabled.
170
183
*/
171
- protected int _formatFeatures ;
184
+ protected final int _formatFeatures ;
172
185
173
- protected boolean _cfgMinimalInts ;
186
+ protected final boolean _cfgMinimalInts ;
187
+
188
+ protected final boolean _cfgMinimalDoubles ;
174
189
175
190
/*
176
191
/**********************************************************************
@@ -271,6 +286,7 @@ public CBORGenerator(ObjectWriteContext writeCtxt, IOContext ctxt,
271
286
: null ;
272
287
_streamWriteContext = CBORWriteContext .createRootContext (dups );
273
288
_cfgMinimalInts = Feature .WRITE_MINIMAL_INTS .enabledIn (formatFeatures );
289
+ _cfgMinimalDoubles = Feature .WRITE_MINIMAL_DOUBLES .enabledIn (formatFeatures );
274
290
_out = out ;
275
291
_bufferRecyclable = true ;
276
292
_stringRefs = Feature .STRINGREF .enabledIn (formatFeatures ) ? new HashMap <>() : null ;
@@ -308,6 +324,7 @@ public CBORGenerator(ObjectWriteContext writeCtxt, IOContext ctxt,
308
324
: null ;
309
325
_streamWriteContext = CBORWriteContext .createRootContext (dups );
310
326
_cfgMinimalInts = Feature .WRITE_MINIMAL_INTS .enabledIn (formatFeatures );
327
+ _cfgMinimalDoubles = Feature .WRITE_MINIMAL_DOUBLES .enabledIn (formatFeatures );
311
328
_out = out ;
312
329
_bufferRecyclable = bufferRecyclable ;
313
330
_outputTail = offset ;
@@ -389,10 +406,13 @@ public TokenStreamContext streamWriteContext() {
389
406
/**********************************************************************
390
407
*/
391
408
409
+ /*
392
410
public CBORGenerator enable(Feature f) {
393
411
_formatFeatures |= f.getMask();
394
412
if (f == Feature.WRITE_MINIMAL_INTS) {
395
413
_cfgMinimalInts = true;
414
+ } else if (f == Feature.WRITE_MINIMAL_DOUBLES) {
415
+ _cfgMinimalDoubles = true;
396
416
}
397
417
return this;
398
418
}
@@ -401,9 +421,12 @@ public CBORGenerator disable(Feature f) {
401
421
_formatFeatures &= ~f.getMask();
402
422
if (f == Feature.WRITE_MINIMAL_INTS) {
403
423
_cfgMinimalInts = false;
424
+ } else if (f == Feature.WRITE_MINIMAL_DOUBLES) {
425
+ _cfgMinimalDoubles = false;
404
426
}
405
427
return this;
406
428
}
429
+ */
407
430
408
431
public final boolean isEnabled (Feature f ) {
409
432
return (_formatFeatures & f .getMask ()) != 0 ;
@@ -610,8 +633,14 @@ public JsonGenerator writeArray(double[] array, int offset, int length) throws J
610
633
// short-cut, do not create child array context etc
611
634
_verifyValueWrite ("write int array" );
612
635
_writeLengthMarker (PREFIX_TYPE_ARRAY , length );
613
- for (int i = offset , end = offset +length ; i < end ; ++i ) {
614
- _writeDoubleNoCheck (array [i ]);
636
+ if (_cfgMinimalDoubles ) {
637
+ for (int i = offset , end = offset +length ; i < end ; ++i ) {
638
+ _writeDoubleMinimal (array [i ]);
639
+ }
640
+ } else {
641
+ for (int i = offset , end = offset +length ; i < end ; ++i ) {
642
+ _writeDoubleNoCheck (array [i ]);
643
+ }
615
644
}
616
645
return this ;
617
646
}
@@ -705,8 +734,24 @@ private final void _writeLongNoCheck(long l) throws JacksonException
705
734
_outputBuffer [_outputTail ++] = (byte ) i ;
706
735
}
707
736
737
+ private final void _writeFloatNoCheck (float f ) throws JacksonException {
738
+ _ensureRoomForOutput (5 );
739
+ /*
740
+ * 17-Apr-2010, tatu: could also use 'floatToIntBits', but it seems more
741
+ * accurate to use exact representation; and possibly faster. However,
742
+ * if there are cases where collapsing of NaN was needed (for non-Java
743
+ * clients), this can be changed
744
+ */
745
+ int i = Float .floatToRawIntBits (f );
746
+ _outputBuffer [_outputTail ++] = BYTE_FLOAT32 ;
747
+ _outputBuffer [_outputTail ++] = (byte ) (i >> 24 );
748
+ _outputBuffer [_outputTail ++] = (byte ) (i >> 16 );
749
+ _outputBuffer [_outputTail ++] = (byte ) (i >> 8 );
750
+ _outputBuffer [_outputTail ++] = (byte ) i ;
751
+ }
752
+
708
753
private final void _writeDoubleNoCheck (double d ) throws JacksonException {
709
- _ensureRoomForOutput (11 );
754
+ _ensureRoomForOutput (9 );
710
755
// 17-Apr-2010, tatu: could also use 'doubleToIntBits', but it seems
711
756
// more accurate to use exact representation; and possibly faster.
712
757
// However, if there are cases where collapsing of NaN was needed (for
@@ -726,6 +771,15 @@ private final void _writeDoubleNoCheck(double d) throws JacksonException {
726
771
_outputBuffer [_outputTail ++] = (byte ) i ;
727
772
}
728
773
774
+ private final void _writeDoubleMinimal (double d ) throws JacksonException {
775
+ float f = (float )d ;
776
+ if (f == d ) {
777
+ _writeFloatNoCheck (f );
778
+ } else {
779
+ _writeDoubleNoCheck (d );
780
+ }
781
+ }
782
+
729
783
/*
730
784
/**********************************************************************
731
785
/* Output method implementations, textual
@@ -1110,47 +1164,18 @@ protected void _write(BigInteger v) throws JacksonException {
1110
1164
@ Override
1111
1165
public JsonGenerator writeNumber (double d ) throws JacksonException {
1112
1166
_verifyValueWrite ("write number" );
1113
- _ensureRoomForOutput (11 );
1114
- /*
1115
- * 17-Apr-2010, tatu: could also use 'doubleToIntBits', but it seems
1116
- * more accurate to use exact representation; and possibly faster.
1117
- * However, if there are cases where collapsing of NaN was needed (for
1118
- * non-Java clients), this can be changed
1119
- */
1120
- long l = Double .doubleToRawLongBits (d );
1121
- _outputBuffer [_outputTail ++] = BYTE_FLOAT64 ;
1122
-
1123
- int i = (int ) (l >> 32 );
1124
- _outputBuffer [_outputTail ++] = (byte ) (i >> 24 );
1125
- _outputBuffer [_outputTail ++] = (byte ) (i >> 16 );
1126
- _outputBuffer [_outputTail ++] = (byte ) (i >> 8 );
1127
- _outputBuffer [_outputTail ++] = (byte ) i ;
1128
- i = (int ) l ;
1129
- _outputBuffer [_outputTail ++] = (byte ) (i >> 24 );
1130
- _outputBuffer [_outputTail ++] = (byte ) (i >> 16 );
1131
- _outputBuffer [_outputTail ++] = (byte ) (i >> 8 );
1132
- _outputBuffer [_outputTail ++] = (byte ) i ;
1167
+ if (_cfgMinimalDoubles ) {
1168
+ _writeDoubleMinimal (d );
1169
+ } else {
1170
+ _writeDoubleNoCheck (d );
1171
+ }
1133
1172
return this ;
1134
1173
}
1135
1174
1136
1175
@ Override
1137
1176
public JsonGenerator writeNumber (float f ) throws JacksonException {
1138
- // Ok, now, we needed token type byte plus 5 data bytes (7 bits each)
1139
- _ensureRoomForOutput (6 );
1140
1177
_verifyValueWrite ("write number" );
1141
-
1142
- /*
1143
- * 17-Apr-2010, tatu: could also use 'floatToIntBits', but it seems more
1144
- * accurate to use exact representation; and possibly faster. However,
1145
- * if there are cases where collapsing of NaN was needed (for non-Java
1146
- * clients), this can be changed
1147
- */
1148
- int i = Float .floatToRawIntBits (f );
1149
- _outputBuffer [_outputTail ++] = BYTE_FLOAT32 ;
1150
- _outputBuffer [_outputTail ++] = (byte ) (i >> 24 );
1151
- _outputBuffer [_outputTail ++] = (byte ) (i >> 16 );
1152
- _outputBuffer [_outputTail ++] = (byte ) (i >> 8 );
1153
- _outputBuffer [_outputTail ++] = (byte ) i ;
1178
+ _writeFloatNoCheck (f );
1154
1179
return this ;
1155
1180
}
1156
1181
0 commit comments