Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.dataformat.yaml;
  
  import java.io.*;
  
  public final class UTF8Writer
      extends Writer
  {
      final static int SURR1_FIRST = 0xD800;
     final static int SURR1_LAST = 0xDBFF;
     final static int SURR2_FIRST = 0xDC00;
     final static int SURR2_LAST = 0xDFFF;
 
     private final static int DEFAULT_BUFFER_SIZE = 8000;
    
    
This ThreadLocal contains a java.lang.ref.SoftRerefence to a byte array used for holding content to decode
 
     final protected static ThreadLocal<SoftReference<byte[][]>> _bufferRecycler
         = new ThreadLocal<SoftReference<byte[][]>>();
 
     protected final byte[][] _bufferHolder;
     
     private OutputStream _out;
 
     private byte[] _outBuffer;
 
     private final int _outBufferEnd;
 
     private int _outPtr;

    
When outputting chars from BMP, surrogate pairs need to be coalesced. To do this, both pairs must be known first; and since it is possible pairs may be split, we need temporary storage for the first half
 
     int _surrogate = 0;
 
     public UTF8Writer(OutputStream out)
     {
          = out;
          = _findBufferHolder();
         byte[] buffer = [0];
         if (buffer == null) {
             [0] = buffer = new byte[];
         }
          = buffer;
         /* Max. expansion for a single char (in unmodified UTF-8) is
          * 4 bytes (or 3 depending on how you view it -- 4 when recombining
          * surrogate pairs)
          */
          = . - 4;
          = 0;
     }
 
     private static byte[][] _findBufferHolder()
     {
         byte[][] bufs = null;
         SoftReference<byte[][]> ref = .get();
         if (ref != null) {
             bufs = ref.get();
         }
         if (bufs == null) {
             bufs = new byte[1][];
             .set(new SoftReference<byte[][]>(bufs));
         }
         return bufs;
     }
     
     @Override
     public Writer append(char c)
         throws IOException
     {
         write(c);
         return this;
     }
 
     @Override
     public void close()
         throws IOException
     {
         if ( != null) {
             if ( > 0) {
                 .write(, 0, );
                  = 0;
             }
             OutputStream out = ;
              = null;
 
             byte[] buf = ;
             if (buf != null) {
                  = null;
                 [0] = buf;
             }
             out.close();
 
             /* Let's 'flush' orphan surrogate, no matter what; but only
              * after cleanly closing everything else.
             */
            int code = ;
             = 0;
            if (code > 0) {
                throwIllegal(code);
            }
        }
    }
    @Override
    public void flush()
        throws IOException
    {
        if ( != null) {
            if ( > 0) {
                .write(, 0, );
                 = 0;
            }
            .flush();
        }
    }
    @Override
    public void write(char[] cbuf)
        throws IOException
    {
        write(cbuf, 0, cbuf.length);
    }
    @Override
    public void write(char[] cbufint offint len)
        throws IOException
    {
        if (len < 2) {
            if (len == 1) {
                write(cbuf[off]);
            }
            return;
        }
        // First: do we have a leftover surrogate to deal with?
        if ( > 0) {
            char second = cbuf[off++];
            --len;
            write(convertSurrogate(second));
            // will have at least one more char
        }
        int outPtr = ;
        byte[] outBuf = ;
        int outBufLast = // has 4 'spare' bytes
        // All right; can just loop it nice and easy now:
        len += off// len will now be the end of input buffer
        output_loop:
        for (; off < len; ) {
            /* First, let's ensure we can output at least 4 bytes
             * (longest UTF-8 encoded codepoint):
             */
            if (outPtr >= outBufLast) {
                .write(outBuf, 0, outPtr);
                outPtr = 0;
            }
            int c = cbuf[off++];
            // And then see if we have an Ascii char:
            if (c < 0x80) { // If so, can do a tight inner loop:
                outBuf[outPtr++] = (byte)c;
                // Let's calc how many ascii chars we can copy at most:
                int maxInCount = (len - off);
                int maxOutCount = (outBufLast - outPtr);
                if (maxInCount > maxOutCount) {
                    maxInCount = maxOutCount;
                }
                maxInCount += off;
                ascii_loop:
                while (true) {
                    if (off >= maxInCount) { // done with max. ascii seq
                        continue output_loop;
                    }
                    c = cbuf[off++];
                    if (c >= 0x80) {
                        break ascii_loop;
                    }
                    outBuf[outPtr++] = (bytec;
                }
            }
            // Nope, multi-byte:
            if (c < 0x800) { // 2-byte
                outBuf[outPtr++] = (byte) (0xc0 | (c >> 6));
                outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
            } else { // 3 or 4 bytes
                // Surrogates?
                if (c <  || c > ) {
                    outBuf[outPtr++] = (byte) (0xe0 | (c >> 12));
                    outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                    outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
                    continue;
                }
                // Yup, a surrogate:
                if (c > ) { // must be from first range
                     = outPtr;
                    throwIllegal(c);
                }
                 = c;
                // and if so, followed by another from next range
                if (off >= len) { // unless we hit the end?
                    break;
                }
                c = convertSurrogate(cbuf[off++]);
                if (c > 0x10FFFF) { // illegal in JSON as well as in XML
                     = outPtr;
                    throwIllegal(c);
                }
                outBuf[outPtr++] = (byte) (0xf0 | (c >> 18));
                outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
                outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
            }
        }
         = outPtr;
    }
    
    @Override
    public void write(int cthrows IOException
    {
        // First; do we have a left over surrogate?
        if ( > 0) {
            c = convertSurrogate(c);
            // If not, do we start with a surrogate?
        } else if (c >=  && c <= ) {
            // Illegal to get second part without first:
            if (c > ) {
                throwIllegal(c);
            }
            // First part just needs to be held for now
             = c;
            return;
        }
        if ( >= ) { // let's require enough room, first
            .write(, 0, );
             = 0;
        }
        if (c < 0x80) { // ascii
            [++] = (bytec;
        } else {
            int ptr = ;
            if (c < 0x800) { // 2-byte
                [ptr++] = (byte) (0xc0 | (c >> 6));
                [ptr++] = (byte) (0x80 | (c & 0x3f));
            } else if (c <= 0xFFFF) { // 3 bytes
                [ptr++] = (byte) (0xe0 | (c >> 12));
                [ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                [ptr++] = (byte) (0x80 | (c & 0x3f));
            } else { // 4 bytes
                if (c > 0x10FFFF) { // illegal
                    throwIllegal(c);
                }
                [ptr++] = (byte) (0xf0 | (c >> 18));
                [ptr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
                [ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                [ptr++] = (byte) (0x80 | (c & 0x3f));
            }
             = ptr;
        }
    }
    @Override
    public void write(String strthrows IOException
    {
        write(str, 0, str.length());
    }
    @Override
    public void write(String strint offint len)  throws IOException
    {
        if (len < 2) {
            if (len == 1) {
                write(str.charAt(off));
            }
            return;
        }
        // First: do we have a leftover surrogate to deal with?
        if ( > 0) {
            char second = str.charAt(off++);
            --len;
            write(convertSurrogate(second));
            // will have at least one more char (case of 1 char was checked earlier on)
        }
        int outPtr = ;
        byte[] outBuf = ;
        int outBufLast = // has 4 'spare' bytes
        // All right; can just loop it nice and easy now:
        len += off// len will now be the end of input buffer
        output_loop:
        for (; off < len; ) {
            /* First, let's ensure we can output at least 4 bytes
             * (longest UTF-8 encoded codepoint):
             */
            if (outPtr >= outBufLast) {
                .write(outBuf, 0, outPtr);
                outPtr = 0;
            }
            int c = str.charAt(off++);
            // And then see if we have an Ascii char:
            if (c < 0x80) { // If so, can do a tight inner loop:
                outBuf[outPtr++] = (byte)c;
                // Let's calc how many ascii chars we can copy at most:
                int maxInCount = (len - off);
                int maxOutCount = (outBufLast - outPtr);
                if (maxInCount > maxOutCount) {
                    maxInCount = maxOutCount;
                }
                maxInCount += off;
                ascii_loop:
                while (true) {
                    if (off >= maxInCount) { // done with max. ascii seq
                        continue output_loop;
                    }
                    c = str.charAt(off++);
                    if (c >= 0x80) {
                        break ascii_loop;
                    }
                    outBuf[outPtr++] = (bytec;
                }
            }
            // Nope, multi-byte:
            if (c < 0x800) { // 2-byte
                outBuf[outPtr++] = (byte) (0xc0 | (c >> 6));
                outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
            } else { // 3 or 4 bytes
                // Surrogates?
                if (c <  || c > ) {
                    outBuf[outPtr++] = (byte) (0xe0 | (c >> 12));
                    outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                    outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
                    continue;
                }
                // Yup, a surrogate:
                if (c > ) { // must be from first range
                     = outPtr;
                    throwIllegal(c);
                }
                 = c;
                // and if so, followed by another from next range
                if (off >= len) { // unless we hit the end?
                    break;
                }
                c = convertSurrogate(str.charAt(off++));
                if (c > 0x10FFFF) { // illegal, as per RFC 4627
                     = outPtr;
                    throwIllegal(c);
                }
                outBuf[outPtr++] = (byte) (0xf0 | (c >> 18));
                outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
                outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f));
                outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f));
            }
        }
         = outPtr;
    }
    /*
    /**********************************************************
    /* Internal methods
    /**********************************************************
     */

    
Method called to calculate UTF codepoint, from a surrogate pair.
    private int convertSurrogate(int secondPart)
        throws IOException
    {
        int firstPart = ;
         = 0;
        // Ok, then, is the second part valid?
        if (secondPart <  || secondPart > ) {
            throw new IOException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination");
        }
        return 0x10000 + ((firstPart - ) << 10) + (secondPart - );
    }
    private void throwIllegal(int code)
        throws IOException
    {
        if (code > 0x10FFFF) { // over max?
            throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 4627");
        }
        if (code >= ) {
            if (code <= ) { // Unmatched first part (closing without second part?)
                throw new IOException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")");
            }
            throw new IOException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")");
        }
        // should we ever get this?
        throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output");
    }
New to GrepCode? Check out our FAQ X