Fix #307
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index f05c389..463d97e 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -79,8 +79,12 @@
   * Contributed #209: Make use of `_allowMultipleMatches` in `FilteringParserDelegate`
    (2.7.4)
 
-
 Tanguy Leroux (tlrx@github)
   * Reported, contributed fix for #280: FilteringGeneratorDelegate.writeUTF8String()
     should delegate to writeUTF8String()
    (2.7.5)
+
+Mike Naseef (mtnaseef@github)
+  * Reported #307: JsonGenerationException: Split surrogate on writeRaw() input thrown for
+   input of a certain size
+   (2.7.7)
diff --git a/release-notes/VERSION b/release-notes/VERSION
index cdf032d..1d372a3 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -14,6 +14,12 @@
 === Releases ===
 ------------------------------------------------------------------------
 
+2.7.7 (not yet released)
+
+#307: JsonGenerationException: Split surrogate on writeRaw() input thrown for
+  input of a certain size
+ (reported by Mike N)
+
 2.7.6 (23-Jul-2016)
 
 - Clean up of FindBugs reported possible issues.
diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
index 8f17ea3..a638519 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
@@ -515,39 +515,50 @@
      */
 
     @Override
-    public void writeRaw(String text)
-        throws IOException, JsonGenerationException
-    {
-        int start = 0;
-        int len = text.length();
-        while (len > 0) {
-            char[] buf = _charBuffer;
-            final int blen = buf.length;
-            final int len2 = (len < blen) ? len : blen;
-            text.getChars(start, start+len2, buf, 0);
-            writeRaw(buf, 0, len2);
-            start += len2;
-            len -= len2;
-        }
+    public void writeRaw(String text) throws IOException {
+        writeRaw(text, 0, text.length());
     }
 
     @Override
-    public void writeRaw(String text, int offset, int len)
-        throws IOException, JsonGenerationException
+    public void writeRaw(String text, int offset, int len) throws IOException
     {
+        final char[] buf = _charBuffer;
+
+        // minor optimization: see if we can just get and copy
+        if (len <= buf.length) {
+            text.getChars(offset, offset+len, buf, 0);
+            _writeRawSegment(buf, 0, len);
+            return;
+        }
+
+        // If not, need segmented approach. For speed, let's also use input buffer
+        // size that is guaranteed to fit in output buffer; each char can expand to
+        // at most 3 bytes, so at most 1/3 of buffer size.
+        final int maxChunk = (_outputEnd >> 2) + (_outputEnd >> 4); // == (1/4 + 1/16) == 5/16
+        final int maxBytes = maxChunk * 3;
+
         while (len > 0) {
-            char[] buf = _charBuffer;
-            final int blen = buf.length;
-            final int len2 = (len < blen) ? len : blen;
+            int len2 = Math.min(maxChunk, len);
             text.getChars(offset, offset+len2, buf, 0);
-            writeRaw(buf, 0, len2);
+            if ((_outputTail + maxBytes) > _outputEnd) {
+                _flushBuffer();
+            }
+            // If this is NOT the last segment and if the last character looks like
+            // split surrogate second half, drop it
+            if (len > 0) {
+                char ch = buf[len2-1];
+                if ((ch >= SURR1_FIRST) && (ch <= SURR1_LAST)) {
+                    --len2;
+                }
+            }
+            _writeRawSegment(buf, 0, len2);
             offset += len2;
             len -= len2;
         }
     }
 
     @Override
-    public void writeRaw(SerializableString text) throws IOException, JsonGenerationException
+    public void writeRaw(SerializableString text) throws IOException
     {
         byte[] raw = text.asUnquotedUTF8();
         if (raw.length > 0) {
@@ -567,8 +578,7 @@
 
     // @TODO: rewrite for speed...
     @Override
-    public final void writeRaw(char[] cbuf, int offset, int len)
-        throws IOException, JsonGenerationException
+    public final void writeRaw(char[] cbuf, int offset, int len) throws IOException
     {
         // First: if we have 3 x charCount spaces, we know it'll fit just fine
         {
@@ -610,8 +620,7 @@
     }
 
     @Override
-    public void writeRaw(char ch)
-        throws IOException, JsonGenerationException
+    public void writeRaw(char ch) throws IOException
     {
         if ((_outputTail + 3) >= _outputEnd) {
             _flushBuffer();
@@ -631,14 +640,14 @@
      * Helper method called when it is possible that output of raw section
      * to output may cross buffer boundary
      */
-    private final void _writeSegmentedRaw(char[] cbuf, int offset, int len)
-        throws IOException, JsonGenerationException
+    private final void _writeSegmentedRaw(char[] cbuf, int offset, int len) throws IOException
     {
         final int end = _outputEnd;
         final byte[] bbuf = _outputBuffer;
+        final int inputEnd = offset + len;
         
         main_loop:
-        while (offset < len) {
+        while (offset < inputEnd) {
             inner_loop:
             while (true) {
                 int ch = (int) cbuf[offset];
@@ -650,7 +659,7 @@
                     _flushBuffer();
                 }
                 bbuf[_outputTail++] = (byte) ch;
-                if (++offset >= len) {
+                if (++offset >= inputEnd) {
                     break main_loop;
                 }
             }
@@ -662,11 +671,45 @@
                 bbuf[_outputTail++] = (byte) (0xc0 | (ch >> 6));
                 bbuf[_outputTail++] = (byte) (0x80 | (ch & 0x3f));
             } else {
-                offset = _outputRawMultiByteChar(ch, cbuf, offset, len);
+                offset = _outputRawMultiByteChar(ch, cbuf, offset, inputEnd);
             }
         }
     }
-    
+
+    /**
+     * Helper method that is called for segmented write of raw content
+     * when explicitly outputting a segment of longer thing.
+     * Caller has to take care of ensuring there's no split surrogate
+     * pair at the end (that is, last char can not be first part of a
+     * surrogate char pair).
+     *
+     * @since 2.8.2
+     */
+    private void _writeRawSegment(char[] cbuf, int offset, int end) throws IOException
+    {
+        main_loop:
+        while (offset < end) {
+            inner_loop:
+            while (true) {
+                int ch = (int) cbuf[offset];
+                if (ch > 0x7F) {
+                    break inner_loop;
+                }
+                _outputBuffer[_outputTail++] = (byte) ch;
+                if (++offset >= end) {
+                    break main_loop;
+                }
+            }
+            char ch = cbuf[offset++];
+            if (ch < 0x800) { // 2-byte?
+                _outputBuffer[_outputTail++] = (byte) (0xc0 | (ch >> 6));
+                _outputBuffer[_outputTail++] = (byte) (0x80 | (ch & 0x3f));
+            } else {
+                offset = _outputRawMultiByteChar(ch, cbuf, offset, end);
+            }
+        }
+    }
+
     /*
     /**********************************************************
     /* Output method implementations, base64-encoded binary
@@ -1873,18 +1916,19 @@
      * 1- and 2-byte UTF-8 encodings, when outputting "raw" 
      * text (meaning it is not to be escaped or quoted)
      */
-    private final int _outputRawMultiByteChar(int ch, char[] cbuf, int inputOffset, int inputLen)
+    private final int _outputRawMultiByteChar(int ch, char[] cbuf, int inputOffset, int inputEnd)
         throws IOException
     {
         // Let's handle surrogates gracefully (as 4 byte output):
         if (ch >= SURR1_FIRST) {
             if (ch <= SURR2_LAST) { // yes, outside of BMP
                 // Do we have second part?
-                if (inputOffset >= inputLen || cbuf == null) { // nope... have to note down
-                    _reportError("Split surrogate on writeRaw() input (last character)");
+                if (inputOffset >= inputEnd || cbuf == null) { // nope... have to note down
+                    _reportError(String.format(
+"Split surrogate on writeRaw() input (last character): first character 0x%4x", ch));
                 }
                 _outputSurrogates(ch, cbuf[inputOffset]);
-                return (inputOffset+1);
+                return inputOffset+1;
             }
         }
         final byte[] bbuf = _outputBuffer;
diff --git a/src/test/java/com/fasterxml/jackson/core/json/RawValueWithSurrogatesTest.java b/src/test/java/com/fasterxml/jackson/core/json/RawValueWithSurrogatesTest.java
new file mode 100644
index 0000000..e94e4ed
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/core/json/RawValueWithSurrogatesTest.java
@@ -0,0 +1,89 @@
+package com.fasterxml.jackson.core.json;

+

+import java.io.ByteArrayOutputStream;

+import com.fasterxml.jackson.core.JsonFactory;

+import com.fasterxml.jackson.core.JsonGenerator;

+

+public class RawValueWithSurrogatesTest

+    extends com.fasterxml.jackson.core.BaseTest

+{

+    final String SURROGATES_307;

+    {

+        // This one fails:

+        String msg ="{'xxxxxxx':{'xxxx':'xxxxxxxxx','xx':'xxxxxxxxxxxxxxxxxxx','xxxxxxxxx':'xxxx://xxxxxxx.xxx',"

++"'xxxxxx':{'xxxx':'xxxxxxxxxxx','xxxxxxxx':{'xxxxxxxxxxx':'xx','xxxxxxxxxx':'xx-xx'}},"

++"'xxxxx':[{'xxxx':'xxxx','xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'}]},"

++"'xxxxxxxxxxx':[{'xxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"

++"{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'"

++",'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"

++"{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':"

++"[{'xxxxxx':3,'xxxxxx':123,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':24,'xxxxxx':4,'xxxx':'xxxxx'}},{'xxxxxx':0,'xxxxxx':123,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':123,'xxxxxx':1,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':1,'xxxxxx':123,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"

++"{'xxxxxx':x,'xxxxxx':123,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"

++"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"

++"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]}]}";

+        // This one works:

+// String msg ="{'xxx':{'xxxx':'xxxxxxxxx','xx':'xxxxxxxxxxxxxxxxxxx','xxxxxxxxx':'xxxx://xxxxxxx.xxx','xxxxxx':{'xxxx':'xxxxxxxxxxx','xxxxxxxx':{'xxxxxxxxxxx':'xx','xxxxxxxxxx':'xx-xx'}},'xxxxx':[{'xxxx':'xxxx','xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'}]},'xxxxxxxxxxx':[{'xxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]}]}";

+

+        SURROGATES_307 = aposToQuotes(msg);

+    }

+

+    private final JsonFactory JSON_F = new JsonFactory();

+

+    // for [jackson-core#307]

+    public void testRawWithSurrogatesString() throws Exception {

+        _testRawWithSurrogatesString(false);

+    }

+

+    // for [jackson-core#307]

+    public void testRawWithSurrogatesCharArray() throws Exception {

+        _testRawWithSurrogatesString(true);

+    }

+

+    private void _testRawWithSurrogatesString(boolean useCharArray) throws Exception

+    {

+        // boundaries are not exact, may vary, so use this:

+

+        final int OFFSET = 3;

+        final int COUNT = 100;

+

+        for (int i = OFFSET; i < COUNT; ++i) {

+            StringBuilder sb = new StringBuilder(1000);

+            for (int j = 0; j < i; ++j) {

+                sb.append(' ');

+            }

+            sb.append(SURROGATES_307);

+            final String text = sb.toString();

+            ByteArrayOutputStream out = new ByteArrayOutputStream(1000);

+            JsonGenerator g = JSON_F.createGenerator(out);

+            if (useCharArray) {

+                char[] ch = text.toCharArray();

+                g.writeRawValue(ch, OFFSET, ch.length - OFFSET);

+            } else {

+                g.writeRawValue(text, OFFSET, text.length() - OFFSET);

+            }

+            g.close();

+            byte[] b = out.toByteArray();

+            assertNotNull(b);

+        }

+    }

+}