Skip to content

Commit 04be073

Browse files
committed
Change Smile output context similar to CBOR
1 parent aad43e6 commit 04be073

File tree

5 files changed

+294
-27
lines changed

5 files changed

+294
-27
lines changed

cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public int getMask() {
226226

227227
public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
228228
ObjectCodec codec, OutputStream out) {
229-
super(stdFeatures, codec, /* DupDetector */ null);
229+
super(stdFeatures, codec, /* Write Context */ null);
230230
DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
231231
? DupDetector.rootDetector(this)
232232
: null;
@@ -261,7 +261,12 @@ public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
261261
public CBORGenerator(IOContext ctxt, int stdFeatures, int formatFeatures,
262262
ObjectCodec codec, OutputStream out, byte[] outputBuffer,
263263
int offset, boolean bufferRecyclable) {
264-
super(stdFeatures, codec);
264+
super(stdFeatures, codec, /* Write Context */ null);
265+
DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
266+
? DupDetector.rootDetector(this)
267+
: null;
268+
// NOTE: we passed `null` for default write context
269+
_cborContext = CBORWriteContext.createRootContext(dups);
265270
_formatFeatures = formatFeatures;
266271
_cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
267272
_ioContext = ctxt;

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/GeneratorDeepNestingTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.fasterxml.jackson.dataformat.cbor;
22

33
import java.io.ByteArrayOutputStream;
4+
import java.io.OutputStream;
45
import java.util.*;
56

67
import com.fasterxml.jackson.core.JsonGenerator;
8+
import com.fasterxml.jackson.core.ObjectCodec;
9+
import com.fasterxml.jackson.core.io.IOContext;
10+
import com.fasterxml.jackson.core.util.BufferRecycler;
711
import com.fasterxml.jackson.databind.ObjectMapper;
812

913
public class GeneratorDeepNestingTest extends CBORTestBase
@@ -29,6 +33,23 @@ public void testDeeplyNestedMap() throws Exception
2933
_verifyNestedMap(result, 23);
3034
}
3135

36+
// Alternative to exercise secondary constructor: since it is not directly
37+
// used by or exposed by factory (can't remember why it was added actually)
38+
@SuppressWarnings("unchecked")
39+
public void testDeeplyNestedWithAltConstructor() throws Exception
40+
{
41+
IOContext ctxt = new IOContext(new BufferRecycler(), this, true);
42+
ByteArrayOutputStream out = new ByteArrayOutputStream();
43+
JsonGenerator gen = new CBORGenerator(ctxt, 0, 0,
44+
(ObjectCodec) null, out, new byte[1000], 0, false);
45+
46+
_writeNestedMap(gen, 23);
47+
gen.close();
48+
byte[] encoded = out.toByteArray();
49+
Map<String,Object> result = (Map<String,Object>) MAPPER.readValue(encoded, Map.class);
50+
_verifyNestedMap(result, 23);
51+
}
52+
3253
private void _writeNestedMap(JsonGenerator gen, int levelsLeft) throws Exception
3354
{
3455
if (levelsLeft == 0) {

release-notes/VERSION-2.x

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Project: jackson-datatypes-binaryModules:
1818
#163: (ion) Update `ion-java` dependency
1919
(contributed by Fernando R-B)
2020
- asm version upgrade to 6.2.1 (from 5.1)
21-
- (cbor) Rewrote handling of "output context" for better field id write support
21+
- (cbor, smile) Rewrote handling of "output context" for better field id write support
2222

2323
2.9.9 (16-May-2019)
2424

smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileGenerator.java

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import com.fasterxml.jackson.core.*;
1010
import com.fasterxml.jackson.core.io.*;
11-
import com.fasterxml.jackson.core.json.JsonWriteContext;
11+
import com.fasterxml.jackson.core.json.DupDetector;
1212
import com.fasterxml.jackson.core.base.GeneratorBase;
1313

1414
import static com.fasterxml.jackson.dataformat.smile.SmileConstants.*;
@@ -178,6 +178,17 @@ public SharedStringNode(String value, int index, SharedStringNode next)
178178
*/
179179
final protected SmileBufferRecycler<SharedStringNode> _smileBufferRecycler;
180180

181+
/*
182+
/**********************************************************
183+
/* Output state
184+
/**********************************************************
185+
*/
186+
187+
/**
188+
* @since 2.10
189+
*/
190+
protected SmileWriteContext _smileContext;
191+
181192
/*
182193
/**********************************************************
183194
/* Output buffering
@@ -265,10 +276,15 @@ public SharedStringNode(String value, int index, SharedStringNode next)
265276
/**********************************************************
266277
*/
267278

268-
public SmileGenerator(IOContext ctxt, int jsonFeatures, int smileFeatures,
279+
public SmileGenerator(IOContext ctxt, int stdFeatures, int smileFeatures,
269280
ObjectCodec codec, OutputStream out)
270281
{
271-
super(jsonFeatures, codec);
282+
super(stdFeatures, codec, /*WriteContext*/ null);
283+
DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
284+
? DupDetector.rootDetector(this)
285+
: null;
286+
// NOTE: we passed `null` for default write context
287+
_smileContext = SmileWriteContext.createRootContext(dups);
272288
_formatFeatures = smileFeatures;
273289
_ioContext = ctxt;
274290
_smileBufferRecycler = _smileBufferRecycler();
@@ -305,11 +321,16 @@ public SmileGenerator(IOContext ctxt, int jsonFeatures, int smileFeatures,
305321
}
306322
}
307323

308-
public SmileGenerator(IOContext ctxt, int jsonFeatures, int smileFeatures,
324+
public SmileGenerator(IOContext ctxt, int stdFeatures, int smileFeatures,
309325
ObjectCodec codec, OutputStream out, byte[] outputBuffer, int offset,
310326
boolean bufferRecyclable)
311327
{
312-
super(jsonFeatures, codec);
328+
super(stdFeatures, codec, null);
329+
DupDetector dups = JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
330+
? DupDetector.rootDetector(this)
331+
: null;
332+
// NOTE: we passed `null` for default write context
333+
_smileContext = SmileWriteContext.createRootContext(dups);
313334
_formatFeatures = smileFeatures;
314335
_ioContext = ctxt;
315336
_smileBufferRecycler = _smileBufferRecycler();
@@ -451,6 +472,27 @@ public JsonGenerator overrideFormatFeatures(int values, int mask) {
451472
return this;
452473
}
453474

475+
/*
476+
/**********************************************************
477+
/* Overridden methods, output context (and related)
478+
/**********************************************************
479+
*/
480+
481+
@Override
482+
public Object getCurrentValue() {
483+
return _smileContext.getCurrentValue();
484+
}
485+
486+
@Override
487+
public void setCurrentValue(Object v) {
488+
_smileContext.setCurrentValue(v);
489+
}
490+
491+
@Override
492+
public JsonStreamContext getOutputContext() {
493+
return _smileContext;
494+
}
495+
454496
/*
455497
/**********************************************************
456498
/* Overridden methods, write methods
@@ -464,7 +506,7 @@ public JsonGenerator overrideFormatFeatures(int values, int mask) {
464506
@Override
465507
public final void writeFieldName(String name) throws IOException
466508
{
467-
if (_writeContext.writeFieldName(name) == JsonWriteContext.STATUS_EXPECT_VALUE) {
509+
if (!_smileContext.writeFieldName(name)) {
468510
_reportError("Can not write a field name, expecting a value");
469511
}
470512
_writeFieldName(name);
@@ -475,7 +517,7 @@ public final void writeFieldName(SerializableString name)
475517
throws IOException
476518
{
477519
// Object is a value, need to verify it's allowed
478-
if (_writeContext.writeFieldName(name.getValue()) == JsonWriteContext.STATUS_EXPECT_VALUE) {
520+
if (!_smileContext.writeFieldName(name.getValue())) {
479521
_reportError("Can not write a field name, expecting a value");
480522
}
481523
_writeFieldName(name);
@@ -485,7 +527,7 @@ public final void writeFieldName(SerializableString name)
485527
public final void writeStringField(String fieldName, String value)
486528
throws IOException
487529
{
488-
if (_writeContext.writeFieldName(fieldName) == JsonWriteContext.STATUS_EXPECT_VALUE) {
530+
if (!_smileContext.writeFieldName(fieldName)) {
489531
_reportError("Can not write a field name, expecting a value");
490532
}
491533
_writeFieldName(fieldName);
@@ -562,55 +604,52 @@ public void writeBytes(byte[] data, int offset, int len) throws IOException
562604
public final void writeStartArray() throws IOException
563605
{
564606
_verifyValueWrite("start an array");
565-
_writeContext = _writeContext.createChildArrayContext();
607+
_smileContext = _smileContext.createChildArrayContext();
566608
_writeByte(TOKEN_LITERAL_START_ARRAY);
567609
}
568610

569611
@Override // defined since 2.6.3
570612
public final void writeStartArray(int size) throws IOException
571613
{
572614
_verifyValueWrite("start an array");
573-
_writeContext = _writeContext.createChildArrayContext();
615+
_smileContext = _smileContext.createChildArrayContext();
574616
_writeByte(TOKEN_LITERAL_START_ARRAY);
575617
}
576618

577619
@Override
578620
public final void writeEndArray() throws IOException
579621
{
580-
if (!_writeContext.inArray()) {
581-
_reportError("Current context not Array but "+_writeContext.typeDesc());
622+
if (!_smileContext.inArray()) {
623+
_reportError("Current context not Array but "+_smileContext.typeDesc());
582624
}
583625
_writeByte(TOKEN_LITERAL_END_ARRAY);
584-
_writeContext = _writeContext.getParent();
626+
_smileContext = _smileContext.getParent();
585627
}
586628

587629
@Override
588630
public final void writeStartObject() throws IOException
589631
{
590632
_verifyValueWrite("start an object");
591-
_writeContext = _writeContext.createChildObjectContext();
633+
_smileContext = _smileContext.createChildObjectContext(null);
592634
_writeByte(TOKEN_LITERAL_START_OBJECT);
593635
}
594636

595637
@Override // since 2.8
596638
public final void writeStartObject(Object forValue) throws IOException
597639
{
598640
_verifyValueWrite("start an object");
599-
JsonWriteContext ctxt = _writeContext.createChildObjectContext();
600-
_writeContext = ctxt;
601-
if (forValue != null) {
602-
ctxt.setCurrentValue(forValue);
603-
}
641+
SmileWriteContext ctxt = _smileContext.createChildObjectContext(forValue);
642+
_smileContext = ctxt;
604643
_writeByte(TOKEN_LITERAL_START_OBJECT);
605644
}
606645

607646
@Override
608647
public final void writeEndObject() throws IOException
609648
{
610-
if (!_writeContext.inObject()) {
611-
_reportError("Current context not Object but "+_writeContext.typeDesc());
649+
if (!_smileContext.inObject()) {
650+
_reportError("Current context not Object but "+_smileContext.typeDesc());
612651
}
613-
_writeContext = _writeContext.getParent();
652+
_smileContext = _smileContext.getParent();
614653
_writeByte(TOKEN_LITERAL_END_OBJECT);
615654
}
616655

@@ -1758,8 +1797,7 @@ protected void _writeDecimalNumber(String enc) throws IOException
17581797
protected final void _verifyValueWrite(String typeMsg)
17591798
throws IOException
17601799
{
1761-
int status = _writeContext.writeValue();
1762-
if (status == JsonWriteContext.STATUS_EXPECT_NAME) {
1800+
if (!_smileContext.writeValue()) {
17631801
_reportError("Can not "+typeMsg+", expecting field name");
17641802
}
17651803
}

0 commit comments

Comments
 (0)