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