Implemented [JACKSON-24], some testing improvements.

diff --git a/src/java/org/codehaus/jackson/JsonFactory.java b/src/java/org/codehaus/jackson/JsonFactory.java
index e34daf8..8e2d955 100644
--- a/src/java/org/codehaus/jackson/JsonFactory.java
+++ b/src/java/org/codehaus/jackson/JsonFactory.java
@@ -254,21 +254,20 @@
         return new ReaderBasedParser(_createContext(r, false), _parserFeatures, r, _charSymbols.makeChild());
     }
 
-    public JsonParser createJsonParser(byte[] data, int offset, int len)
-        throws IOException, JsonParseException
-    {
-        // !!! TODO: make efficient (see [JACKSON-24])
-        InputStream in = new ByteArrayInputStream(data, offset, len);
-        // true -> must be managed as caller didn't hand stream
-        return _createJsonParser(in,  _createContext(in, true));
-    }
-
     public final JsonParser createJsonParser(byte[] data)
         throws IOException, JsonParseException
     {
         return createJsonParser(data, 0, data.length);
     }
 
+    public JsonParser createJsonParser(byte[] data, int offset, int len)
+        throws IOException, JsonParseException
+    {
+        // true -> managed (doesn't really matter; we have no stream!)
+        IOContext ctxt = _createContext(data, true);
+        return new ByteSourceBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures, _byteSymbols.makeChild(), _charSymbols.makeChild());
+    }
+
     public final JsonParser createJsonParser(String content)
         throws IOException, JsonParseException
     {
@@ -280,7 +279,7 @@
     private JsonParser _createJsonParser(InputStream in, IOContext ctxt)
         throws IOException, JsonParseException
     {
-        return new ByteSourceBootstrapper(ctxt, in).constructParser(_parserFeatures, _byteSymbols, _charSymbols);
+        return new ByteSourceBootstrapper(ctxt, in).constructParser(_parserFeatures, _byteSymbols.makeChild(), _charSymbols.makeChild());
     }
 
     /*
diff --git a/src/java/org/codehaus/jackson/map/ObjectMapper.java b/src/java/org/codehaus/jackson/map/ObjectMapper.java
index eb4ab25..f6e3d55 100644
--- a/src/java/org/codehaus/jackson/map/ObjectMapper.java
+++ b/src/java/org/codehaus/jackson/map/ObjectMapper.java
@@ -257,6 +257,22 @@
         return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), TypeFactory.instance.fromTypeReference(valueTypeRef));
     } 
 
+    @SuppressWarnings("unchecked")
+    public <T> T readValue(byte[] src, int offset, int len, 
+                               Class<T> valueType)
+        throws IOException, JsonParseException, JsonMappingException
+    {
+        return (T) _readMapAndClose(_jsonFactory.createJsonParser(src, offset, len), TypeFactory.instance.fromClass(valueType));
+    } 
+
+    @SuppressWarnings("unchecked")
+    public <T> T readValue(byte[] src, int offset, int len,
+                           TypeReference valueTypeRef)
+        throws IOException, JsonParseException, JsonMappingException
+    {
+        return (T) _readMapAndClose(_jsonFactory.createJsonParser(src, offset, len), TypeFactory.instance.fromTypeReference(valueTypeRef));
+    } 
+
     /*
     ////////////////////////////////////////////////////
     // Public API: serialization
diff --git a/src/perf/TestCopyPerf.java b/src/perf/TestCopyPerf.java
index 73e5c84..d81cace 100644
--- a/src/perf/TestCopyPerf.java
+++ b/src/perf/TestCopyPerf.java
@@ -1,7 +1,7 @@
 import java.io.*;
 
 import org.codehaus.jackson.*;
-import org.codehaus.jackson.map.JsonTypeMapper;
+import org.codehaus.jackson.map.TreeMapper;
 import org.codehaus.jackson.map.JsonNode;
 
 public final class TestCopyPerf
@@ -17,9 +17,9 @@
     {
         mJsonFactory = new JsonFactory();
         FileInputStream fis = new FileInputStream(f);
-        JsonTypeMapper mapper = new JsonTypeMapper();
+        TreeMapper mapper = new TreeMapper();
         JsonParser jp = mJsonFactory.createJsonParser(fis);
-        mTree = mapper.read(jp);
+        mTree = mapper.readTree(jp);
         jp.close();
     }
 
diff --git a/src/perf/TestJsonPerf.java b/src/perf/TestJsonPerf.java
index e37b561..4c6ebc5 100644
--- a/src/perf/TestJsonPerf.java
+++ b/src/perf/TestJsonPerf.java
@@ -33,8 +33,8 @@
         mJsonFactory = new JsonFactory();
         mData = readData(f);
 
-        // Let's try to guestimate suitable size... to get to 100 megs parsed
-        REPS = (int) ((double) (100 * 1000 * 1000) / (double) mData.length);
+        // Let's try to guestimate suitable size... to get to 50 megs parsed
+        REPS = (int) ((double) (50 * 1000 * 1000) / (double) mData.length);
 
         System.out.println("Read "+mData.length+" bytes from '"+f+"'; will do "+REPS+" reps");
         System.out.println();
@@ -49,7 +49,7 @@
         while (true) {
             try {  Thread.sleep(100L); } catch (InterruptedException ie) { }
             // Use 9 to test all...
-            int round = (i++ % 7);
+            int round = (i++ % 2);
 
             long curr = System.currentTimeMillis();
             String msg;
@@ -226,7 +226,13 @@
         int sum = 0;
         for (int i = 0; i < reps; ++i) {
             // note: fast is not used any more
-            JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
+            JsonParser jp;
+
+            if (fast) {
+                jp = mJsonFactory.createJsonParser(mData, 0, mData.length);
+            } else {
+                jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
+            }
             JsonToken t;
             while ((t = jp.nextToken()) != null) {
                 // Field names are always constructed
diff --git a/src/test/main/TestJsonParser.java b/src/test/main/TestJsonParser.java
index 52f642c..f96b4d8 100644
--- a/src/test/main/TestJsonParser.java
+++ b/src/test/main/TestJsonParser.java
@@ -320,6 +320,38 @@
         }
     }
 
+    /**
+     * Simple unit test that verifies that passing in a byte array
+     * as source works as expected.
+     */
+    public void testBytesAsSource() throws Exception
+    {
+        String JSON = "[ 1, 2, 3, 4 ]";
+        byte[] b = JSON.getBytes("UTF-8");
+        int offset = 50;
+        int len = b.length;
+        byte[] src = new byte[offset + len + offset];
+
+        System.arraycopy(b, 0, src, offset, len);
+
+        JsonFactory jf = new JsonFactory();
+        JsonParser jp = jf.createJsonParser(src, offset, len);
+
+        assertToken(JsonToken.START_ARRAY, jp.nextToken());
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        assertEquals(1, jp.getIntValue());
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        assertEquals(2, jp.getIntValue());
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        assertEquals(3, jp.getIntValue());
+        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
+        assertEquals(4, jp.getIntValue());
+        assertToken(JsonToken.END_ARRAY, jp.nextToken());
+        assertNull(jp.nextToken());
+
+        jp.close();
+    }
+
     /*
     /////////////////////////////////////////////
     // Helper methods