Use Tree Navigation
public static class

Surrogate.Parser

extends Object
/*
 * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package sun.nio.cs;

import java.nio.CharBuffer;
import java.nio.charset.CoderResult;
import java.nio.charset.MalformedInputException;
import java.nio.charset.UnmappableCharacterException;


/**
 * Utility class for dealing with surrogates.
 *
 * @author Mark Reinhold
 */


public class Surrogate {

   
private Surrogate() { }

   
// UTF-16 surrogate-character ranges
   
//
   
public static final char MIN_HIGH = '\uD800';
   
public static final char MAX_HIGH = '\uDBFF';
   
public static final char MIN_LOW  = '\uDC00';
   
public static final char MAX_LOW  = '\uDFFF';
   
public static final char MIN = MIN_HIGH;
   
public static final char MAX = MAX_LOW;

   
// Range of UCS-4 values that need surrogates in UTF-16
   
//
   
public static final int UCS4_MIN = 0x10000;
   
public static final int UCS4_MAX = (1 << 20) + UCS4_MIN - 1;

   
/**
     * Tells whether or not the given UTF-16 value is a high surrogate.
     */

   
public static boolean isHigh(int c) {
       
return (MIN_HIGH <= c) && (c <= MAX_HIGH);
   
}

   
/**
     * Tells whether or not the given UTF-16 value is a low surrogate.
     */

   
public static boolean isLow(int c) {
       
return (MIN_LOW <= c) && (c <= MAX_LOW);
   
}

   
/**
     * Tells whether or not the given UTF-16 value is a surrogate character,
     */

   
public static boolean is(int c) {
       
return (MIN <= c) && (c <= MAX);
   
}

   
/**
     * Tells whether or not the given UCS-4 character must be represented as a
     * surrogate pair in UTF-16.
     */

   
public static boolean neededFor(int uc) {
       
return (uc >= UCS4_MIN) && (uc <= UCS4_MAX);
   
}

   
/**
     * Returns the high UTF-16 surrogate for the given UCS-4 character.
     */

   
public static char high(int uc) {
       
assert neededFor(uc);
       
return (char)(0xd800 | (((uc - UCS4_MIN) >> 10) & 0x3ff));
   
}

   
/**
     * Returns the low UTF-16 surrogate for the given UCS-4 character.
     */

   
public static char low(int uc) {
       
assert neededFor(uc);
       
return (char)(0xdc00 | ((uc - UCS4_MIN) & 0x3ff));
   
}

   
/**
     * Converts the given surrogate pair into a 32-bit UCS-4 character.
     */

   
public static int toUCS4(char c, char d) {
       
assert isHigh(c) && isLow(d);
       
return (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000;
   
}

   
/**
     * Surrogate parsing support.  Charset implementations may use instances of
     * this class to handle the details of parsing UTF-16 surrogate pairs.
     */

   
public static class Parser {

       
public Parser() { }

       
private int character;          // UCS-4
       
private CoderResult error = CoderResult.UNDERFLOW;
       
private boolean isPair;

       
/**
         * Returns the UCS-4 character previously parsed.
         */

       
public int character() {
           
assert (error == null);
           
return character;
       
}

       
/**
         * Tells whether or not the previously-parsed UCS-4 character was
         * originally represented by a surrogate pair.
         */

       
public boolean isPair() {
           
assert (error == null);
           
return isPair;
       
}

       
/**
         * Returns the number of UTF-16 characters consumed by the previous
         * parse.
         */

       
public int increment() {
           
assert (error == null);
           
return isPair ? 2 : 1;
       
}

       
/**
         * If the previous parse operation detected an error, return the object
         * describing that error.
         */

       
public CoderResult error() {
           
assert (error != null);
           
return error;
       
}

       
/**
         * Returns an unmappable-input result object, with the appropriate
         * input length, for the previously-parsed character.
         */

       
public CoderResult unmappableResult() {
           
assert (error == null);
           
return CoderResult.unmappableForLength(isPair ? 2 : 1);
       
}

       
/**
         * Parses a UCS-4 character from the given source buffer, handling
         * surrogates.
         *
         * @param  c    The first character
         * @param  in   The source buffer, from which one more character
         *              will be consumed if c is a high surrogate
         *
         * @returns  Either a parsed UCS-4 character, in which case the isPair()
         *           and increment() methods will return meaningful values, or
         *           -1, in which case error() will return a descriptive result
         *           object
         */

       
public int parse(char c, CharBuffer in) {
           
if (Surrogate.isHigh(c)) {
               
if (!in.hasRemaining()) {
                    error
= CoderResult.UNDERFLOW;
                   
return -1;
               
}
               
char d = in.get();
               
if (Surrogate.isLow(d)) {
                    character
= toUCS4(c, d);
                    isPair
= true;
                    error
= null;
                   
return character;
               
}
                error
= CoderResult.malformedForLength(1);
               
return -1;
           
}
           
if (Surrogate.isLow(c)) {
                error
= CoderResult.malformedForLength(1);
               
return -1;
           
}
            character
= c;
            isPair
= false;
            error
= null;
           
return character;
       
}

       
/**
         * Parses a UCS-4 character from the given source buffer, handling
         * surrogates.
         *
         * @param  c    The first character
         * @param  ia   The input array, from which one more character
         *              will be consumed if c is a high surrogate
         * @param  ip   The input index
         * @param  il   The input limit
         *
         * @returns  Either a parsed UCS-4 character, in which case the isPair()
         *           and increment() methods will return meaningful values, or
         *           -1, in which case error() will return a descriptive result
         *           object
         */

       
public int parse(char c, char[] ia, int ip, int il) {
           
assert (ia[ip] == c);
           
if (Surrogate.isHigh(c)) {
               
if (il - ip < 2) {
                    error
= CoderResult.UNDERFLOW;
                   
return -1;
               
}
               
char d = ia[ip + 1];
               
if (Surrogate.isLow(d)) {
                    character
= toUCS4(c, d);
                    isPair
= true;
                    error
= null;
                   
return character;
               
}
                error
= CoderResult.malformedForLength(1);
               
return -1;
           
}
           
if (Surrogate.isLow(c)) {
                error
= CoderResult.malformedForLength(1);
               
return -1;
           
}
            character
= c;
            isPair
= false;
            error
= null;
           
return character;
       
}

   
}

   
/**
     * Surrogate generation support.  Charset implementations may use instances
     * of this class to handle the details of generating UTF-16 surrogate
     * pairs.
     */

   
public static class Generator {

       
public Generator() { }

       
private CoderResult error = CoderResult.OVERFLOW;

       
/**
         * If the previous generation operation detected an error, return the
         * object describing that error.
         */

       
public CoderResult error() {
           
assert error != null;
           
return error;
       
}

       
/**
         * Generates one or two UTF-16 characters to represent the given UCS-4
         * character.
         *
         * @param  uc   The UCS-4 character
         * @param  len  The number of input bytes from which the UCS-4 value
         *              was constructed (used when creating result objects)
         * @param  dst  The destination buffer, to which one or two UTF-16
         *              characters will be written
         *
         * @returns  Either a positive count of the number of UTF-16 characters
         *           written to the destination buffer, or -1, in which case
         *           error() will return a descriptive result object
         */

       
public int generate(int uc, int len, CharBuffer dst) {
           
if (uc <= 0xffff) {
               
if (Surrogate.is(uc)) {
                    error
= CoderResult.malformedForLength(len);
                   
return -1;
               
}
               
if (dst.remaining() < 1) {
                    error
= CoderResult.OVERFLOW;
                   
return -1;
               
}
                dst
.put((char)uc);
                error
= null;
               
return 1;
           
}
           
if (uc < Surrogate.UCS4_MIN) {
                error
= CoderResult.malformedForLength(len);
               
return -1;
           
}
           
if (uc <= Surrogate.UCS4_MAX) {
               
if (dst.remaining() < 2) {
                    error
= CoderResult.OVERFLOW;
                   
return -1;
               
}
                dst
.put(Surrogate.high(uc));
                dst
.put(Surrogate.low(uc));
                error
= null;
               
return 2;
           
}
            error
= CoderResult.unmappableForLength(len);
           
return -1;
       
}

       
/**
         * Generates one or two UTF-16 characters to represent the given UCS-4
         * character.
         *
         * @param  uc   The UCS-4 character
         * @param  len  The number of input bytes from which the UCS-4 value
         *              was constructed (used when creating result objects)
         * @param  da   The destination array, to which one or two UTF-16
         *              characters will be written
         * @param  dp   The destination position
         * @param  dl   The destination limit
         *
         * @returns  Either a positive count of the number of UTF-16 characters
         *           written to the destination buffer, or -1, in which case
         *           error() will return a descriptive result object
         */

       
public int generate(int uc, int len, char[] da, int dp, int dl) {
           
if (uc <= 0xffff) {
               
if (Surrogate.is(uc)) {
                    error
= CoderResult.malformedForLength(len);
                   
return -1;
               
}
               
if (dl - dp < 1) {
                    error
= CoderResult.OVERFLOW;
                   
return -1;
               
}
                da
[dp] = (char)uc;
                error
= null;
               
return 1;
           
}
           
if (uc < Surrogate.UCS4_MIN) {
                error
= CoderResult.malformedForLength(len);
               
return -1;
           
}
           
if (uc <= Surrogate.UCS4_MAX) {
               
if (dl - dp < 2) {
                    error
= CoderResult.OVERFLOW;
                   
return -1;
               
}
                da
[dp] = Surrogate.high(uc);
                da
[dp + 1] = Surrogate.low(uc);
                error
= null;
               
return 2;
           
}
            error
= CoderResult.unmappableForLength(len);
           
return -1;
       
}

   
}

}