Skip to content

Commit

Permalink
Implement #524: add CBORWriteFeature (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder authored Nov 30, 2024
1 parent ab14f2b commit 5119905
Show file tree
Hide file tree
Showing 18 changed files with 179 additions and 254 deletions.
35 changes: 12 additions & 23 deletions cbor/src/main/java/tools/jackson/dataformat/cbor/CBORFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,11 @@ public class CBORFactory
*/
public final static String FORMAT_NAME = "CBOR";

/**
* Bitfield (set of flags) of all parser features that are enabled
* by default.
*/
final static int DEFAULT_CBOR_PARSER_FEATURE_FLAGS = CBORParser.Feature.collectDefaults();

/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
final static int DEFAULT_CBOR_GENERATOR_FEATURE_FLAGS = CBORGenerator.Feature.collectDefaults();
final static int DEFAULT_CBOR_GENERATOR_FEATURE_FLAGS = CBORWriteFeature.collectDefaults();

/*
/**********************************************************************
Expand Down Expand Up @@ -87,7 +81,7 @@ public CBORFactory() {
super(StreamReadConstraints.defaults(),
StreamWriteConstraints.defaults(),
ErrorReportConfiguration.defaults(),
DEFAULT_CBOR_PARSER_FEATURE_FLAGS,
0,
DEFAULT_CBOR_GENERATOR_FEATURE_FLAGS);
}

Expand Down Expand Up @@ -179,27 +173,22 @@ public boolean canUseSchema(FormatSchema schema) {
return false; // no (mandatory) FormatSchema for cbor
}

@Override
public Class<CBORParser.Feature> getFormatReadFeatureType() {
return CBORParser.Feature.class;
// No Reader features yet for CBOR
/*@Override
public Class<CBORReadFeature> getFormatReadFeatureType() {
return CBORReadFeature.class;
}
*/

@Override
public Class<CBORGenerator.Feature> getFormatWriteFeatureType() {
return CBORGenerator.Feature.class;
}

/**
* Checked whether specified parser feature is enabled.
*/
public final boolean isEnabled(CBORParser.Feature f) {
return f.enabledIn(_formatReadFeatures);
public Class<CBORWriteFeature> getFormatWriteFeatureType() {
return CBORWriteFeature.class;
}

/**
* Check whether specified generator feature is enabled.
*/
public final boolean isEnabled(CBORGenerator.Feature f) {
public final boolean isEnabled(CBORWriteFeature f) {
return f.enabledIn(_formatWriteFeatures);
}

Expand Down Expand Up @@ -267,10 +256,10 @@ protected JsonGenerator _createGenerator(ObjectWriteContext writeCtxt,
writeCtxt.getStreamWriteFeatures(_streamWriteFeatures),
writeCtxt.getFormatWriteFeatures(_formatWriteFeatures),
out);
if (CBORGenerator.Feature.WRITE_TYPE_HEADER.enabledIn(_formatWriteFeatures)) {
if (CBORWriteFeature.WRITE_TYPE_HEADER.enabledIn(_formatWriteFeatures)) {
gen.writeTag(CBORConstants.TAG_ID_SELF_DESCRIBE);
}
if (CBORGenerator.Feature.STRINGREF.enabledIn(_formatWriteFeatures)) {
if (CBORWriteFeature.STRINGREF.enabledIn(_formatWriteFeatures)) {
gen.writeTag(CBORConstants.TAG_ID_STRINGREF_NAMESPACE);
}
return gen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,75 +24,43 @@ protected CBORFactoryBuilder() {
super(StreamReadConstraints.defaults(),
StreamWriteConstraints.defaults(),
ErrorReportConfiguration.defaults(),
CBORFactory.DEFAULT_CBOR_PARSER_FEATURE_FLAGS,
0,
CBORFactory.DEFAULT_CBOR_GENERATOR_FEATURE_FLAGS);
}

public CBORFactoryBuilder(CBORFactory base) {
super(base);
}

// // // Parser features

public CBORFactoryBuilder enable(CBORParser.Feature f) {
_formatReadFeatures |= f.getMask();
return _this();
}

public CBORFactoryBuilder enable(CBORParser.Feature first, CBORParser.Feature... other) {
_formatReadFeatures |= first.getMask();
for (CBORParser.Feature f : other) {
_formatReadFeatures |= f.getMask();
}
return _this();
}

public CBORFactoryBuilder disable(CBORParser.Feature f) {
_formatReadFeatures &= ~f.getMask();
return _this();
}

public CBORFactoryBuilder disable(CBORParser.Feature first, CBORParser.Feature... other) {
_formatReadFeatures &= ~first.getMask();
for (CBORParser.Feature f : other) {
_formatReadFeatures &= ~f.getMask();
}
return _this();
}

public CBORFactoryBuilder configure(CBORParser.Feature f, boolean state) {
return state ? enable(f) : disable(f);
}

// // // Generator features

public CBORFactoryBuilder enable(CBORGenerator.Feature f) {
public CBORFactoryBuilder enable(CBORWriteFeature f) {
_formatWriteFeatures |= f.getMask();
return _this();
}

public CBORFactoryBuilder enable(CBORGenerator.Feature first, CBORGenerator.Feature... other) {
public CBORFactoryBuilder enable(CBORWriteFeature first, CBORWriteFeature... other) {
_formatWriteFeatures |= first.getMask();
for (CBORGenerator.Feature f : other) {
for (CBORWriteFeature f : other) {
_formatWriteFeatures |= f.getMask();
}
return _this();
}

public CBORFactoryBuilder disable(CBORGenerator.Feature f) {
public CBORFactoryBuilder disable(CBORWriteFeature f) {
_formatWriteFeatures &= ~f.getMask();
return _this();
}

public CBORFactoryBuilder disable(CBORGenerator.Feature first, CBORGenerator.Feature... other) {
public CBORFactoryBuilder disable(CBORWriteFeature first, CBORWriteFeature... other) {
_formatWriteFeatures &= ~first.getMask();
for (CBORGenerator.Feature f : other) {
for (CBORWriteFeature f : other) {
_formatWriteFeatures &= ~f.getMask();
}
return _this();
}

public CBORFactoryBuilder configure(CBORGenerator.Feature f, boolean state) {
public CBORFactoryBuilder configure(CBORWriteFeature f, boolean state) {
return state ? enable(f) : disable(f);
}

Expand Down
120 changes: 10 additions & 110 deletions cbor/src/main/java/tools/jackson/dataformat/cbor/CBORGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,106 +49,6 @@ public class CBORGenerator extends GeneratorBase
*/
private final static int MAX_LONG_STRING_BYTES = (MAX_LONG_STRING_CHARS * 3) + 3;

/**
* Enumeration that defines all togglable features for CBOR generator.
*/
public enum Feature implements FormatFeature {
/**
* Feature that determines whether generator should try to use smallest
* (size-wise) integer representation: if true, will use smallest
* representation that is enough to retain value; if false, will use
* length indicated by argument type (4-byte for <code>int</code>,
* 8-byte for <code>long</code> and so on).
*/
WRITE_MINIMAL_INTS(true),

/**
* Feature that determines whether CBOR "Self-Describe Tag" (value
* 55799, encoded as 3-byte sequence of <code>0xD9, 0xD9, 0xF7</code>)
* should be written at the beginning of document or not.
* <p>
* Default value is {@code false} meaning that type tag will not be
* written at the beginning of a new document.
*/
WRITE_TYPE_HEADER(false),

/**
* Feature that determines if an invalid surrogate encoding found in the
* incoming String should fail with an exception or silently be output
* as the Unicode 'REPLACEMENT CHARACTER' (U+FFFD) or not; if not,
* an exception will be thrown to indicate invalid content.
* <p>
* Default value is {@code false} (for backwards compatibility) meaning that
* an invalid surrogate will result in exception ({@code StreamWriteException}).
*/
LENIENT_UTF_ENCODING(false),

/**
* Feature that determines if string references are generated based on the
* <a href="http://cbor.schmorp.de/stringref">stringref</a>) extension. This can save
* storage space, parsing time, and pool string memory when parsing. Readers of the output
* must also support the stringref extension to properly decode the data. Extra overhead may
* be added to generation time and memory usage to compute the shared binary and text
* strings.
* <p>
* Default value is {@code false} meaning that the stringref extension will not be used.
*
* @since 2.15
*/
STRINGREF(false),

/**
* Feature that determines whether generator should try to write doubles
* as floats: if {@code true}, will write a {@code double} as a 4-byte float if no
* precision loss will occur; if {@code false}, will always write a {@code double}
* as an 8-byte double.
* <p>
* Default value is {@code false} meaning that doubles will always be written as
* 8-byte values.
*
* @since 2.15
*/
WRITE_MINIMAL_DOUBLES(false),
;

protected final boolean _defaultState;
protected final int _mask;

/**
* Method that calculates bit set (flags) of all features that are
* enabled by default.
*/
public static int collectDefaults() {
int flags = 0;
for (Feature f : values()) {
if (f.enabledByDefault()) {
flags |= f.getMask();
}
}
return flags;
}

private Feature(boolean defaultState) {
_defaultState = defaultState;
_mask = (1 << ordinal());
}

@Override
public boolean enabledByDefault() {
return _defaultState;
}

@Override
public boolean enabledIn(int flags) {
return (flags & getMask()) != 0;
}

@Override
public int getMask() {
return _mask;
}
}

/**
* To simplify certain operations, we require output buffer length to allow
* outputting of contiguous 256 character UTF-8 encoded String value. Length
Expand Down Expand Up @@ -176,7 +76,7 @@ public int getMask() {

/**
* Bit flag composed of bits that indicate which
* {@link CBORGenerator.Feature}s are enabled.
* {@link CBORWriteFeature}s are enabled.
*/
protected final int _formatFeatures;

Expand Down Expand Up @@ -280,11 +180,11 @@ public CBORGenerator(ObjectWriteContext writeCtxt, IOContext ioCtxt,
? DupDetector.rootDetector(this)
: null;
_streamWriteContext = CBORWriteContext.createRootContext(dups);
_cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = Feature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_cfgMinimalInts = CBORWriteFeature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = CBORWriteFeature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_out = out;
_bufferRecyclable = true;
_stringRefs = Feature.STRINGREF.enabledIn(formatFeatures) ? new HashMap<>() : null;
_stringRefs = CBORWriteFeature.STRINGREF.enabledIn(formatFeatures) ? new HashMap<>() : null;
_outputBuffer = ioCtxt.allocWriteEncodingBuffer(BYTE_BUFFER_FOR_OUTPUT);
_outputEnd = _outputBuffer.length;
_charBuffer = ioCtxt.allocConcatBuffer();
Expand Down Expand Up @@ -317,13 +217,13 @@ public CBORGenerator(ObjectWriteContext writeCtxt, IOContext ioCtxt,
? DupDetector.rootDetector(this)
: null;
_streamWriteContext = CBORWriteContext.createRootContext(dups);
_cfgMinimalInts = Feature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = Feature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_cfgMinimalInts = CBORWriteFeature.WRITE_MINIMAL_INTS.enabledIn(formatFeatures);
_cfgMinimalDoubles = CBORWriteFeature.WRITE_MINIMAL_DOUBLES.enabledIn(formatFeatures);
_out = out;
_bufferRecyclable = bufferRecyclable;
_outputTail = offset;
_outputBuffer = outputBuffer;
_stringRefs = Feature.STRINGREF.enabledIn(formatFeatures) ? new HashMap<>() : null;
_stringRefs = CBORWriteFeature.STRINGREF.enabledIn(formatFeatures) ? new HashMap<>() : null;
_outputEnd = _outputBuffer.length;
_charBuffer = ioCtxt.allocConcatBuffer();
_charBufferLength = _charBuffer.length;
Expand Down Expand Up @@ -422,7 +322,7 @@ public CBORGenerator disable(Feature f) {
}
*/

public final boolean isEnabled(Feature f) {
public final boolean isEnabled(CBORWriteFeature f) {
return (_formatFeatures & f.getMask()) != 0;
}

Expand Down Expand Up @@ -1653,7 +1553,7 @@ private final int _encode2(int i, int outputPtr, String str, int len,
private int _invalidSurrogateStart(int code, byte[] outBuf, int outputPtr)
throws JacksonException
{
if (isEnabled(Feature.LENIENT_UTF_ENCODING)) {
if (isEnabled(CBORWriteFeature.LENIENT_UTF_ENCODING)) {
return _appendReplacementChar(outBuf, outputPtr);
}
// Will be called in two distinct cases: either first character is
Expand All @@ -1675,7 +1575,7 @@ private int _invalidSurrogateEnd(int surr1, int surr2,
byte[] outBuf, int outputPtr)
throws JacksonException
{
if (isEnabled(Feature.LENIENT_UTF_ENCODING)) {
if (isEnabled(CBORWriteFeature.LENIENT_UTF_ENCODING)) {
return _appendReplacementChar(outBuf, outputPtr);
}
_reportError(String.format(
Expand Down
38 changes: 0 additions & 38 deletions cbor/src/main/java/tools/jackson/dataformat/cbor/CBORParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,46 +24,8 @@

public class CBORParser extends ParserBase
{
/**
* Enumeration that defines all togglable features for CBOR generators.
*/
public enum Feature implements FormatFeature
{
// BOGUS(false)
;

final boolean _defaultState;
final int _mask;

/**
* Method that calculates bit set (flags) of all features that
* are enabled by default.
*/
public static int collectDefaults()
{
int flags = 0;
for (Feature f : values()) {
if (f.enabledByDefault()) {
flags |= f.getMask();
}
}
return flags;
}

private Feature(boolean defaultState) {
_defaultState = defaultState;
_mask = (1 << ordinal());
}

@Override public boolean enabledByDefault() { return _defaultState; }
@Override public int getMask() { return _mask; }
@Override public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
}

/**
* Class for keeping track of tags in an optimized manner.
*
* @since 2.15
*/
public static final class TagList
{
Expand Down
Loading

0 comments on commit 5119905

Please sign in to comment.