fastjsonの深さのソースコード解析-プログレッシブ(二)-プログレッシブバイトと文字列解析


SerializerWriterメンバー関数
プログレッシブ16進数バイト配列
    public void writeHex(byte[] bytes) {
        /**         ,   2          2  , 3      x       ' */
        int newcount = count + bytes.length * 2 + 3;
        if (newcount > buf.length) {
            if (writer != null) {
                char[] chars = new char[bytes.length + 3];
                int pos = 0;
                chars[pos++] = 'x';
                chars[pos++] = '\'';

                for (int i = 0; i < bytes.length; ++i) {
                    byte b = bytes[i];

                    int a = b & 0xFF;
                    /**         1111 0000*/
                    int b0 = a >> 4;
                    /**         0000 1111*/
                    int b1 = a & 0xf;

                    /**            
                     *    4        0~9,    ascii  0~9
                     *    4        ,    16  ascii   
                     */
                    chars[pos++] = (char) (b0 + (b0 < 10 ? 48 : 55));
                    chars[pos++] = (char) (b1 + (b1 < 10 ? 48 : 55));
                }
                chars[pos++] = '\'';
                try {
                    writer.write(chars);
                } catch (IOException ex) {
                    throw new JSONException("writeBytes error.", ex);
                }
                return;
            }
            /** buffer           ,     */
            expandCapacity(newcount);
        }

        buf[count++] = 'x';
        buf[count++] = '\'';

        for (int i = 0; i < bytes.length; ++i) {
            byte b = bytes[i];

            int a = b & 0xFF;
            /**         */
            int b0 = a >> 4;
            /**         */
            int b1 = a & 0xf;

            /**            
             *    4        0~9,    ascii  0~9
             *    4        ,    16  ascii   
             */
            buf[count++] = (char) (b0 + (b0 < 10 ? 48 : 55));
            buf[count++] = (char) (b1 + (b1 < 10 ? 48 : 55));
        }
        buf[count++] = '\'';
    }
writeHexこのプログレッシブ方法は主に16進数の自分を2つのasciiコード文字を占有するように変換し、シングルクォーテーションマークとxプレフィックスを追加する。
プログレッシブbyteバイト配列
   public void writeByteArray(byte[] bytes) {
        if (isEnabled(SerializerFeature.WriteClassName.mask)) {
            /**          WriteClassName,   16     */
            writeHex(bytes);
            return;
        }

        int bytesLen = bytes.length;
        final char quote = useSingleQuotes ? '\'' : '"';
        if (bytesLen == 0) {
            String emptyString = useSingleQuotes ? "''" : "\"\"";
            /**          0,       */
            write(emptyString);
            return;
        }

        final char[] CA = IOUtils.CA;

        /**      24bit     */
        int eLen = (bytesLen / 3) * 3;
        /** base64       
         *
         *  base64 :
         *     ,          ,   24     。
         *     ,  24         ,    6     。
         *     ,        00,   32     ,     。
         *     ,    ,               ,   Base64    。
         *
         *  ref: http://www.ruanyifeng.com/blog/2008/06/base64.html
         */
        int charsLen = ((bytesLen - 1) / 3 + 1) << 2;
        // char[] chars = new char[charsLen];
        int offset = count;
        int newcount = count + charsLen + 2;
        if (newcount > buf.length) {
            if (writer != null) {
                write(quote);

                for (int s = 0; s < eLen;) {
                    /**        ,         */
                    int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);

                    write(CA[(i >>> 18) & 0x3f]);
                    write(CA[(i >>> 12) & 0x3f]);
                    write(CA[(i >>> 6) & 0x3f]);
                    /**   00 */
                    write(CA[i & 0x3f]);
                }

                /**          3          */
                // Pad and encode last bits if source isn't even 24 bits.
                int left = bytesLen - eLen; // 0 - 2.
                if (left > 0) {

                    /**
                     * a) 1      :
                     *   1  8    , 6   2 ,         00,    0000,
                     *         Base64  ,      2 "=" 
                     *
                     * b) 2      :
                     *   2     16     , 6   3 ,         00,     00,
                     *      3  Base64  ,      "=" 
                     *
                     *
                     *     1   ,      a)
                     *  1  6 , 2   4 0,        10 = 6 + 4
                     *
                     *     2   ,      b)
                     *  1      10       2      2   0  
                     */
                    int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);

                    /**         */
                    write(CA[i >> 12]);
                    write(CA[(i >>> 6) & 0x3f]);
                    write(left == 2 ? CA[i & 0x3f] : '=');
                    write('=');
                }

                write(quote);
                return;
            }
            expandCapacity(newcount);
        }
        count = newcount;
        buf[offset++] = quote;

        // Encode even 24-bits
        for (int s = 0, d = offset; s < eLen;) {
            /**        ,         */
            int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);

            // Encode the int into four chars
            buf[d++] = CA[(i >>> 18) & 0x3f];
            buf[d++] = CA[(i >>> 12) & 0x3f];
            buf[d++] = CA[(i >>> 6) & 0x3f];
            /**   00 */
            buf[d++] = CA[i & 0x3f];
        }

        /**          3          */
        int left = bytesLen - eLen; // 0 - 2.
        if (left > 0) {
            // Prepare the int
            int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);

            /**         */
            buf[newcount - 5] = CA[i >> 12];
            buf[newcount - 4] = CA[(i >>> 6) & 0x3f];
            buf[newcount - 3] = left == 2 ? CA[i & 0x3f] : '=';
            buf[newcount - 2] = '=';
        }
        buf[newcount - 1] = quote;
    }
writeByteArrayは、序文化されたバイト群であり、実際にはbase 64符号化変換を行い、コードには詳細な注釈が付加されている。
プログレッシブ文字列
    public void write(String str, int off, int len) {
        /**           */
        int newcount = count + len;
        /**            */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 *      str       ,       
                 */
                do {
                    /**     buffer        */
                    int rest = buf.length - count;
                    /**     str[off, off + rest)    buf[count, ...] */
                    str.getChars(off, off + rest, buf, count);
                    count = buf.length;
                    /**        ,   count = 0 */
                    flush();
                    /**               */
                    len -= rest;
                    /**         str    (  ) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        /**       ,   str[off, off + len)    buf[count, ...] */
        str.getChars(off, off + len, buf, count);
        count = newcount;
    }
プログレッシブ文字列write(string)は、最終的には上の形態write(string, 0, string.length)に変換される。
プログレッシブ文字配列
    public void write(char c[], int off, int len) {
        if (off < 0 //
            || off > c.length //
            || len < 0 //
            || off + len > c.length //
            || off + len < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /**           */
        int newcount = count + len;
        /**            */
        if (newcount > buf.length) {
            if (writer == null) {
                expandCapacity(newcount);
            } else {
                /**
                 *       c       ,       
                 */
                do {
                    /**     buffer        */
                    int rest = buf.length - count;
                    /** c[off, off + rest)    buf[count, ...] */
                    System.arraycopy(c, off, buf, count, rest);
                    count = buf.length;
                    /**        ,   count = 0 */
                    flush();
                    /**               */
                    len -= rest;
                    /**         c    (  ) */
                    off += rest;
                } while (len > buf.length);
                newcount = len;
            }
        }
        System.arraycopy(c, off, buf, count, len);
        count = newcount;
    }
プログレッシブリスト文字列
    public void write(List list) {
        if (list.isEmpty()) {
            /**      ,  []    */
            write("[]");
            return;
        }

        int offset = count;
        final int initOffset = offset;
        for (int i = 0, list_size = list.size(); i < list_size; ++i) {
            /**               */
            String text = list.get(i);

            boolean hasSpecial = false;
            if (text == null) {
                /** list     null  */
                hasSpecial = true;
            } else {
                for (int j = 0, len = text.length(); j < len; ++j) {
                    char ch = text.charAt(j);
                    /**          */
                    if (hasSpecial = (ch < ' ' //
                                      || ch > '~' //
                                      || ch == '"' //
                                      || ch == '\\')) {
                        break;
                    }
                }
            }

            if (hasSpecial) {
                count = initOffset;
                write('[');
                for (int j = 0; j < list.size(); ++j) {
                    text = list.get(j);
                    /**      ,     */
                    if (j != 0) {
                        write(',');
                    }

                    if (text == null) {
                        /**      ,    null    */
                        write("null");
                    } else {
                        /**        ,        ,       */
                        writeStringWithDoubleQuote(text, (char) 0);
                    }
                }
                write(']');
                return;
            }

            /**           ,  3        "," */
            int newcount = offset + text.length() + 3;
            if (i == list.size() - 1) {
                newcount++;
            }
            /**           */
            if (newcount > buf.length) {
                count = offset;
                /**       buf  1.5 +1, copy  buf   */
                expandCapacity(newcount);
            }

            if (i == 0) {
                buf[offset++] = '[';
            } else {
                buf[offset++] = ',';
            }
            buf[offset++] = '"';
            /**   text    buffer    */
            text.getChars(0, text.length(), buf, offset);
            offset += text.length();
            buf[offset++] = '"';
        }
        /**          ["element", "element", ...] */
        buf[offset++] = ']';
        count = offset;
    }
順序文字列は[“element”, "element", ...]フォーマットに変換されます。リスト文字列に特殊文字が含まれている場合は、特化バージョンwriteStringWithDoubleQuote(text, (char) 0)を呼び出します。
プログレッシブには特殊文字列が含まれています。
    public void writeStringWithDoubleQuote(String text, final char seperator) {
        if (text == null) {
            /**        ,  null    */
            writeNull();
            if (seperator != 0) {
                /**            ' ',      */
                write(seperator);
            }
            return;
        }

        int len = text.length();
        int newcount = count + len + 2;
        if (seperator != 0) {
            newcount++;
        }

        /**            */
        if (newcount > buf.length) {
            if (writer != null) {
                /**        */
                write('"');

                for (int i = 0; i < text.length(); ++i) {
                    /**            */
                    char ch = text.charAt(i);

                    if (isEnabled(SerializerFeature.BrowserSecure)) {
                       if (ch == '(' || ch == ')' || ch == ' || ch == '>') {
                            /** ascii   native   */
                            write('\\');
                            write('u');
                            write(IOUtils.DIGITS[(ch >>> 12) & 15]);
                            write(IOUtils.DIGITS[(ch >>> 8) & 15]);
                            write(IOUtils.DIGITS[(ch >>> 4) & 15]);
                            write(IOUtils.DIGITS[ch & 15]);
                            continue;
                        }
                    }

                    if (isEnabled(SerializerFeature.BrowserCompatible)) {
                        if (ch == '\b'      //    
                            || ch == '\f'   //    
                            || ch == '
'
// || ch == '\r' // || ch == '\t' // tab || ch == '"' // || ch == '/' // || ch == '\\') {// /** + ascii */ write('\\'); // write(replaceChars[(int) ch]); continue; } if (ch < 32) { /** ascii native */ write('\\'); write('u'); write('0'); write('0'); write(IOUtils.ASCII_CHARS[ch * 2]); write(IOUtils.ASCII_CHARS[ch * 2 + 1]); continue; } if (ch >= 127) { /** ascii native */ write('\\'); write('u'); write(IOUtils.DIGITS[(ch >>> 12) & 15]); write(IOUtils.DIGITS[(ch >>> 8) & 15]); write(IOUtils.DIGITS[(ch >>> 4) & 15]); write(IOUtils.DIGITS[ch & 15]); continue; } } else { /** ascii native */ if (ch < IOUtils.specicalFlags_doubleQuotes.length && IOUtils.specicalFlags_doubleQuotes[ch] != 0 // || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { write('\\'); if (IOUtils.specicalFlags_doubleQuotes[ch] == 4) { write('u'); write(IOUtils.DIGITS[ch >>> 12 & 15]); write(IOUtils.DIGITS[ch >>> 8 & 15]); write(IOUtils.DIGITS[ch >>> 4 & 15]); write(IOUtils.DIGITS[ch & 15]); } else { write(IOUtils.replaceChars[ch]); } continue; } } /** , */ write(ch); } /** */ write('"'); if (seperator != 0) { write(seperator); } return; } /** buffer , */ expandCapacity(newcount); } int start = count + 1; int end = start + len; buf[count] = '\"'; /** buffer , text buf */ text.getChars(0, len, buf, start); count = newcount; if (isEnabled(SerializerFeature.BrowserCompatible)) { int lastSpecialIndex = -1; for (int i = start; i < end; ++i) { /** */ char ch = buf[i]; if (ch == '"' // || ch == '/' // || ch == '\\') { /** */ lastSpecialIndex = i; newcount += 1; continue; } if (ch == '\b' // || ch == '\f' // || ch == '
'
// || ch == '\r' // || ch == '\t') { /** */ lastSpecialIndex = i; newcount += 1; continue; } if (ch < 32) { lastSpecialIndex = i; newcount += 5; continue; } if (ch >= 127) { lastSpecialIndex = i; newcount += 5; continue; } } /** , (1.5 buffer +1) */ if (newcount > buf.length) { expandCapacity(newcount); } count = newcount; /** */ for (int i = lastSpecialIndex; i >= start; --i) { char ch = buf[i]; if (ch == '\b' // || ch == '\f'// || ch == '
'
// || ch == '\r' // || ch == '\t') { /** , \ */ System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1); buf[i] = '\\'; /** */ buf[i + 1] = replaceChars[(int) ch]; end += 1; continue; } if (ch == '"' // || ch == '/' // || ch == '\\') { /** , */ System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1); buf[i] = '\\'; buf[i + 1] = ch; end += 1; continue; } if (ch < 32) { System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1); /** ascii native */ buf[i] = '\\'; buf[i + 1] = 'u'; buf[i + 2] = '0'; buf[i + 3] = '0'; buf[i + 4] = IOUtils.ASCII_CHARS[ch * 2]; buf[i + 5] = IOUtils.ASCII_CHARS[ch * 2 + 1]; end += 5; continue; } if (ch >= 127) { System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1); /** ascii native */ buf[i] = '\\'; buf[i + 1] = 'u'; buf[i + 2] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[i + 3] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[i + 4] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[i + 5] = IOUtils.DIGITS[ch & 15]; end += 5; } } /** */ if (seperator != 0) { buf[count - 2] = '\"'; buf[count - 1] = seperator; } else { buf[count - 1] = '\"'; } return; } int specialCount = 0; int lastSpecialIndex = -1; int firstSpecialIndex = -1; char lastSpecial = '\0'; for (int i = start; i < end; ++i) { char ch = buf[i]; if (ch >= ']') { // 93 /** :http://www.mokuge.com/tool/asciito16/ */ if (ch >= 0x7F // 127 && (ch == '\u2028' // || ch == '\u2029' // || ch < 0xA0)) { // 160 [ ] if (firstSpecialIndex == -1) { firstSpecialIndex = i; } specialCount++; lastSpecialIndex = i; lastSpecial = ch; newcount += 4; } continue; } boolean special = (ch < 64 && (sepcialBits & (1L << ch)) != 0) || ch == '\\'; if (special) { specialCount++; lastSpecialIndex = i; lastSpecial = ch; if (ch == '(' || ch == ')' || ch == ' || ch == '>' || (ch < IOUtils.specicalFlags_doubleQuotes.length // && IOUtils.specicalFlags_doubleQuotes[ch] == 4) // ) { newcount += 4; } if (firstSpecialIndex == -1) { firstSpecialIndex = i; } } } if (specialCount > 0) { newcount += specialCount; /** buffer , */ if (newcount > buf.length) { expandCapacity(newcount); } count = newcount; /** native , */ if (specialCount == 1) { // if (lastSpecial == '\u2028') { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 6; int LengthOfCopy = end - lastSpecialIndex - 1; System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); buf[lastSpecialIndex] = '\\'; buf[++lastSpecialIndex] = 'u'; buf[++lastSpecialIndex] = '2'; buf[++lastSpecialIndex] = '0'; buf[++lastSpecialIndex] = '2'; buf[++lastSpecialIndex] = '8'; } // else if (lastSpecial == '\u2029') { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 6; int LengthOfCopy = end - lastSpecialIndex - 1; System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); buf[lastSpecialIndex] = '\\'; buf[++lastSpecialIndex] = 'u'; buf[++lastSpecialIndex] = '2'; buf[++lastSpecialIndex] = '0'; buf[++lastSpecialIndex] = '2'; buf[++lastSpecialIndex] = '9'; } else if (lastSpecial == '(' || lastSpecial == ')' || lastSpecial == ' || lastSpecial == '>') { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 6; int LengthOfCopy = end - lastSpecialIndex - 1; System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); buf[lastSpecialIndex] = '\\'; buf[++lastSpecialIndex] = 'u'; final char ch = lastSpecial; buf[++lastSpecialIndex] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[++lastSpecialIndex] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[++lastSpecialIndex] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[++lastSpecialIndex] = IOUtils.DIGITS[ch & 15]; } else { final char ch = lastSpecial; if (ch < IOUtils.specicalFlags_doubleQuotes.length // && IOUtils.specicalFlags_doubleQuotes[ch] == 4) { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 6; int LengthOfCopy = end - lastSpecialIndex - 1; System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); int bufIndex = lastSpecialIndex; buf[bufIndex++] = '\\'; buf[bufIndex++] = 'u'; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[bufIndex++] = IOUtils.DIGITS[ch & 15]; } else { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 2; int LengthOfCopy = end - lastSpecialIndex - 1; System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); buf[lastSpecialIndex] = '\\'; buf[++lastSpecialIndex] = replaceChars[(int) ch]; } } } else if (specialCount > 1) { int textIndex = firstSpecialIndex - start; int bufIndex = firstSpecialIndex; for (int i = textIndex; i < text.length(); ++i) { char ch = text.charAt(i); /** native , */ if (browserSecure && (ch == '(' || ch == ')' || ch == ' || ch == '>')) { buf[bufIndex++] = '\\'; buf[bufIndex++] = 'u'; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[bufIndex++] = IOUtils.DIGITS[ch & 15]; end += 5; } else if (ch < IOUtils.specicalFlags_doubleQuotes.length // && IOUtils.specicalFlags_doubleQuotes[ch] != 0 // || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { buf[bufIndex++] = '\\'; if (IOUtils.specicalFlags_doubleQuotes[ch] == 4) { buf[bufIndex++] = 'u'; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[bufIndex++] = IOUtils.DIGITS[ch & 15]; end += 5; } else { buf[bufIndex++] = replaceChars[(int) ch]; end++; } } else { // 、 if (ch == '\u2028' || ch == '\u2029') { buf[bufIndex++] = '\\'; buf[bufIndex++] = 'u'; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 12) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 8) & 15]; buf[bufIndex++] = IOUtils.DIGITS[(ch >>> 4) & 15]; buf[bufIndex++] = IOUtils.DIGITS[ch & 15]; end += 5; } else { buf[bufIndex++] = ch; } } } } } if (seperator != 0) { buf[count - 2] = '\"'; buf[count - 1] = seperator; } else { buf[count - 1] = '\"'; } }
writeStrigWithDoublQuote方法の実現は長すぎます。この方法は主に以下のいくつかのことをしました。
  • は、序文化BrowserComptible特性を開くと、asciiをnative符号に変換し、省スペース化する。
  • 出力器writerが空でないと、自動的にブザー拡がりをトリガする( 1.5 +1)
  • もう一つの特殊文字に対する文字列の序列化方法は、writestring WithDouble Quote(char[]text、final char seperator)と、writestring WithDouble Quote(String text、final char seperator)のバージョンときわめて類似しているので、冗長解析は行われない。
    プログレッシブ文字列の方法はシングルクォーテーションマークのバージョンを追加することを含みます。詳細はWriteStrigWithSingleQuoteを参照してください。
        protected void writeStringWithSingleQuote(String text) {
            if (text == null) {
                int newcount = count + 4;
                if (newcount > buf.length) {
                    expandCapacity(newcount);
                }
                /**       null,  "null"    */
                "null".getChars(0, 4, buf, count);
                count = newcount;
                return;
            }
    
            int len = text.length();
            int newcount = count + len + 2;
            if (newcount > buf.length) {
                if (writer != null) {
                    /**             */
                    write('\'');
                    for (int i = 0; i < text.length(); ++i) {
                        char ch = text.charAt(i);
                        if (ch <= 13 || ch == '\\' || ch == '\'' //
                            || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
                            /**                '\' ''' ,             */
                            write('\\');
                            write(replaceChars[(int) ch]);
                        } else {
                            write(ch);
                        }
                    }
                    write('\'');
                    return;
                }
                /** buffer           ,     */
                expandCapacity(newcount);
            }
    
            int start = count + 1;
            int end = start + len;
    
            buf[count] = '\'';
            /** buffer       ,    text buf     */
            text.getChars(0, len, buf, start);
            count = newcount;
    
            int specialCount = 0;
            int lastSpecialIndex = -1;
            char lastSpecial = '\0';
            for (int i = start; i < end; ++i) {
                char ch = buf[i];
                if (ch <= 13 || ch == '\\' || ch == '\'' //
                    || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
                    /**                     */
                    specialCount++;
                    lastSpecialIndex = i;
                    lastSpecial = ch;
                }
            }
    
            newcount += specialCount;
            if (newcount > buf.length) {
                expandCapacity(newcount);
            }
            count = newcount;
    
            if (specialCount == 1) {
                /**        ,      \             */
                System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
                buf[lastSpecialIndex] = '\\';
                buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
            } else if (specialCount > 1) {
                System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
                buf[lastSpecialIndex] = '\\';
                buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
                end++;
                for (int i = lastSpecialIndex - 2; i >= start; --i) {
                    char ch = buf[i];
    
                    if (ch <= 13 || ch == '\\' || ch == '\'' //
                        || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
                        /**        ,      \             */
                        System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
                        buf[i] = '\\';
                        buf[i + 1] = replaceChars[(int) ch];
                        end++;
                    }
                }
            }
    
            /**              */
            buf[count - 1] = '\'';
        }
    writeStrigWithSingleQuoteこの方法は主に以下のいくつかのことをしています。
  • 特殊文字に対して、変換文字を追加し、特殊文字を普通文字に置き換える
  • 出力器writerが空でないと、自動的にブザー拡がりをトリガする( 1.5 +1)
  • もう一つの特殊文字に対する文字列の順序付け方法writeStringWithSingleQuote(char[])は、writeStringWithSingleQuote(String)バージョンと極めて類似しているので、冗長解析は行われない。