Implement [JACKSON-326], addition of JsonParser.hasTextCharacters()
diff --git a/build-test.xml b/build-test.xml
index 9ecdd81..8197074 100644
--- a/build-test.xml
+++ b/build-test.xml
@@ -48,7 +48,8 @@
<!-- Compiling and running test cases
-->
- <target name="test.compile" depends="test.prepare, compile.mapper, compile.xc, compile.jaxrs, compile.mrbean">
+ <target name="test.compile" depends="test.prepare, compile.mapper,
+compile.xc, compile.jaxrs, compile.smile, compile.mrbean">
<javac srcdir="${dir.src.test}" destdir="${dir.test.classes}"
source="1.5" target="1.5"
debug="true"
@@ -60,6 +61,7 @@
<pathelement path="${dir.build.classes.mapper}"/>
<pathelement path="${dir.build.classes.jaxrs}"/>
<pathelement path="${dir.build.classes.xc}"/>
+ <pathelement path="${dir.build.classes.smile}"/>
<pathelement path="${dir.build.classes.mrbean}"/>
<path refid="test-libs"/>
<fileset dir="${dir.lib}/jaxrs">
@@ -113,6 +115,7 @@
<pathelement path="${dir.build.classes.core}" />
<pathelement path="${dir.build.classes.mapper}" />
<pathelement path="${dir.build.classes.xc}" />
+ <pathelement path="${dir.build.classes.smile}" />
<pathelement path="${dir.build.classes.mrbean}" />
<pathelement location="${dir.test.classes}" />
<path refid="test-libs"/>
@@ -178,6 +181,8 @@
<pathelement path="${dir.build.classes.mapper}" />
<pathelement path="${dir.build.classes.xc}" />
<pathelement path="${dir.build.classes.jaxrs}" />
+ <pathelement path="${dir.build.classes.smile}" />
+ <pathelement path="${dir.build.classes.mrbean}" />
<pathelement location="${dir.test.classes}" />
<path refid="test-libs"/>
<path refid="test-libs-ext"/>
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 52bdedd..8da122c 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -34,6 +34,8 @@
of whether JSON Object/Array nodes have specified value.
* [JACKSON-321] Allow passing JsonNodeFactory to use for ObjectMapper, ObjectReader,
to allow use of custom JsonNode types.
+ * [JACKSON-326] Add 'JsonParser.hasTextCharacters()' to make it easire to optimize
+ text access (esp. when copying events)
New features:
diff --git a/src/java/org/codehaus/jackson/JsonFactory.java b/src/java/org/codehaus/jackson/JsonFactory.java
index eef1e86..5d5cdd1 100644
--- a/src/java/org/codehaus/jackson/JsonFactory.java
+++ b/src/java/org/codehaus/jackson/JsonFactory.java
@@ -556,6 +556,8 @@
protected JsonGenerator _createUTF8JsonGenerator(OutputStream out, IOContext ctxt)
throws IOException
{
+ // !!! TEST
+ //if (true) return _createJsonGenerator(_createWriter(out, JsonEncoding.UTF8, ctxt), ctxt);
return new Utf8Generator(ctxt, _generatorFeatures, _objectCodec, out);
}
@@ -581,6 +583,7 @@
protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException
{
+ // note: this should not get called any more (caller checks, dispatches)
if (enc == JsonEncoding.UTF8) { // We have optimized writer for UTF-8
return new UTF8Writer(ctxt, out);
}
diff --git a/src/java/org/codehaus/jackson/JsonParser.java b/src/java/org/codehaus/jackson/JsonParser.java
index 7138d73..464a046 100644
--- a/src/java/org/codehaus/jackson/JsonParser.java
+++ b/src/java/org/codehaus/jackson/JsonParser.java
@@ -621,6 +621,29 @@
public abstract int getTextOffset()
throws IOException, JsonParseException;
+ /**
+ * Method that can be used to determine whether calling of
+ * {@link #getTextCharacters} would be the most efficient
+ * way to access textual content for the event parser currently
+ * points to.
+ *<p>
+ * Default implementation simply returns false since only actual
+ * implementation class has knowledge of its internal buffering
+ * state.
+ * Implementations are strongly encouraged to properly override
+ * this method, to allow efficient copying of content by other
+ * code.
+ *
+ * @return True if parser currently has character array that can
+ * be efficiently returned via {@link #getTextCharacters}; false
+ * means that it may or may not exist
+ *
+ * @since 1.6
+ */
+ public boolean hasTextCharacters() {
+ return false;
+ }
+
/*
/**********************************************************
/* Public API, access to token information, numeric
diff --git a/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java b/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java
index b20c785..a4815dd 100644
--- a/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java
+++ b/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java
@@ -361,7 +361,11 @@
writeFieldName(jp.getCurrentName());
break;
case VALUE_STRING:
- writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength());
+ if (jp.hasTextCharacters()) {
+ writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength());
+ } else {
+ writeString(jp.getText());
+ }
break;
case VALUE_NUMBER_INT:
switch (jp.getNumberType()) {
diff --git a/src/java/org/codehaus/jackson/impl/JsonParserBase.java b/src/java/org/codehaus/jackson/impl/JsonParserBase.java
index 1c1926c..5e88f27 100644
--- a/src/java/org/codehaus/jackson/impl/JsonParserBase.java
+++ b/src/java/org/codehaus/jackson/impl/JsonParserBase.java
@@ -418,6 +418,20 @@
return null;
}
+ @Override
+ public boolean hasTextCharacters()
+ {
+ if (_currToken != null) { // null only before/after document
+ switch (_currToken) {
+ case FIELD_NAME:
+ return _nameCopied;
+ case VALUE_STRING:
+ return true; // usually true
+ }
+ }
+ return false;
+ }
+
public int getTextLength()
throws IOException, JsonParseException
{
diff --git a/src/java/org/codehaus/jackson/impl/Utf8Generator.java b/src/java/org/codehaus/jackson/impl/Utf8Generator.java
index 7756b3a..cd538d8 100644
--- a/src/java/org/codehaus/jackson/impl/Utf8Generator.java
+++ b/src/java/org/codehaus/jackson/impl/Utf8Generator.java
@@ -780,7 +780,7 @@
* This method called when the string content is already in
* a char buffer, and need not be copied for processing.
*/
- private void _writeStringSegment(char[] cbuf, int offset, int len)
+ private final void _writeStringSegment(char[] cbuf, int offset, int len)
throws IOException, JsonGenerationException
{
// First: if we have 2 x charCount spaces, we know it'll be fine for common case...
diff --git a/src/java/org/codehaus/jackson/util/TokenBuffer.java b/src/java/org/codehaus/jackson/util/TokenBuffer.java
index a015040..55f0f23 100644
--- a/src/java/org/codehaus/jackson/util/TokenBuffer.java
+++ b/src/java/org/codehaus/jackson/util/TokenBuffer.java
@@ -898,6 +898,12 @@
@Override
public int getTextOffset() { return 0; }
+ @Override
+ public boolean hasTextCharacters() {
+ // We never have raw buffer available, so:
+ return false;
+ }
+
/*
/**********************************************************
/* Public API, access to token information, numeric
diff --git a/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java b/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java
index 8f3699f..6db5caf 100644
--- a/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java
+++ b/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java
@@ -240,10 +240,15 @@
@Override
public int getTextOffset() throws IOException, JsonParseException {
- // TODO Auto-generated method stub
return 0;
}
+ @Override
+ public boolean hasTextCharacters() {
+ // generally we do not have efficient access as char[], hence:
+ return false;
+ }
+
/*
/**********************************************************
/* Public API, typed non-text access
diff --git a/src/perf/TestCopyPerf.java b/src/perf/TestCopyPerf.java
index 1998316..4113eda 100644
--- a/src/perf/TestCopyPerf.java
+++ b/src/perf/TestCopyPerf.java
@@ -1,15 +1,16 @@
import java.io.*;
import org.codehaus.jackson.*;
+import org.codehaus.jackson.util.TokenBuffer;
import org.codehaus.jackson.map.ObjectMapper;
public final class TestCopyPerf
{
- private final static int REPS = 2500;
+ private final static int REPS = 7500;
final JsonFactory _jsonFactory;
- final JsonNode _tree;
+ final TokenBuffer _tokens;
private TestCopyPerf(File f)
throws Exception
@@ -18,7 +19,7 @@
FileInputStream fis = new FileInputStream(f);
ObjectMapper mapper = new ObjectMapper();
JsonParser jp = _jsonFactory.createJsonParser(fis);
- _tree = mapper.readTree(jp);
+ _tokens = mapper.readValue(jp, TokenBuffer.class);
jp.close();
}
@@ -48,7 +49,11 @@
while (--reps >= 0) {
bos.reset();
jg = _jsonFactory.createJsonGenerator(bos, JsonEncoding.UTF8);
- jg.writeTree(_tree);
+ JsonParser jp = _tokens.asParser();
+ while (jp.nextToken() != null) {
+ jg.copyCurrentEvent(jp);
+ }
+ jp.close();
jg.close();
}
return jg.hashCode();
diff --git a/src/smile/test/org/codehaus/jackson/smile/SmileTestBase.java b/src/test/org/codehaus/jackson/smile/SmileTestBase.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/SmileTestBase.java
rename to src/test/org/codehaus/jackson/smile/SmileTestBase.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileGenerator.java b/src/test/org/codehaus/jackson/smile/TestSmileGenerator.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileGenerator.java
rename to src/test/org/codehaus/jackson/smile/TestSmileGenerator.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java b/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
rename to src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java b/src/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java
rename to src/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileParser.java b/src/test/org/codehaus/jackson/smile/TestSmileParser.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileParser.java
rename to src/test/org/codehaus/jackson/smile/TestSmileParser.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileParserBinary.java b/src/test/org/codehaus/jackson/smile/TestSmileParserBinary.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileParserBinary.java
rename to src/test/org/codehaus/jackson/smile/TestSmileParserBinary.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java b/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
rename to src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java b/src/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java
rename to src/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java
diff --git a/src/smile/test/org/codehaus/jackson/smile/TestSmileUtil.java b/src/test/org/codehaus/jackson/smile/TestSmileUtil.java
similarity index 100%
rename from src/smile/test/org/codehaus/jackson/smile/TestSmileUtil.java
rename to src/test/org/codehaus/jackson/smile/TestSmileUtil.java