Top Description Fields Constructors Methods
org.yaml.snakeyaml.external.com.google.gdata.util.common.base

public abstract Class UnicodeEscaper

extends Object
implements Escaper
Class Inheritance
All Implemented Interfaces
org.yaml.snakeyaml.external.com.google.gdata.util.common.base.Escaper
Known Direct Subclasses
org.yaml.snakeyaml.external.com.google.gdata.util.common.base.PercentEscaper
Imports
java.io.IOException

An Escaper that converts literal text into a format safe for inclusion in a particular context (such as an XML document). Typically (but not always), the inverse process of "unescaping" the text is performed automatically by the relevant parser.

For example, an XML escaper would convert the literal string "Foo<Bar>" into "Foo<Bar>" to prevent "<Bar>" from being confused with an XML tag. When the resulting XML document is parsed, the parser API will return this text as the original literal string "Foo<Bar>".

Note

This class is similar to CharEscaper but with one very important difference. A CharEscaper can only process Java UTF16 characters in isolation and may not cope when it encounters surrogate pairs. This class facilitates the correct escaping of all Unicode characters.

As there are important reasons, including potential security issues, to handle Unicode correctly if you are considering implementing a new escaper you should favor using UnicodeEscaper wherever possible.

A UnicodeEscaper instance is required to be stateless, and safe when used concurrently by multiple threads.

Several popular escapers are defined as constants in the class CharEscapers. To create your own escapers extend this class and implement the escape(int) method.

Field Summary

Modifier and TypeField and Description
private static final int
DEST_PAD

The amount of padding (chars) to use when growing the escape buffer.

private static final ThreadLocal<char[]>
DEST_TL

A thread-local destination buffer to keep us from creating new buffers.

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
protected static final int

Returns:

the Unicode code point for the given index or the negated value of the trailing high surrogate character at the end of the sequence
codePointAt
(CharSequence
the sequence of characters from which to decode the code point
seq
,
int
the index of the first character to decode
index
,
int
the index beyond the last valid character to decode
end
)

Returns the Unicode code point of the character at the given index.

protected abstract char[]

Returns:

the replacement characters, or null if no escaping was needed
escape
(int
the Unicode code point to escape if necessary
cp
)

Returns the escaped form of the given Unicode code point, or null if this code point does not need to be escaped.

public String

Returns:

the escaped form of string
escape
(String
the literal string to be escaped
string
)

Implements org.yaml.snakeyaml.external.com.google.gdata.util.common.base.Escaper.escape.

Returns the escaped form of a given literal string.
public Appendable

Returns:

an Appendable which passes text to out after escaping it
escape
(final Appendable
the underlying Appendable to append escaped output to
out
)

Implements org.yaml.snakeyaml.external.com.google.gdata.util.common.base.Escaper.escape.

Returns an Appendable instance which automatically escapes all text appended to it before passing the resulting text to an underlying Appendable.
protected final String

Returns:

the escaped form of string
escapeSlow
(String
the literal string to be escaped
s
,
int
the index to start escaping from
index
)

Returns the escaped form of a given literal string, starting at the given index.

private static final char[]
growBuffer(char[] dest, int index, int size)

Helper method to grow the character buffer as needed, this only happens once in a while so it's ok if it's in a method call.

protected int
nextEscapeIndex(CharSequence
a sequence of characters
csq
,
int
the index of the first character to be scanned
start
,
int
the index immediately after the last character to be scanned
end
)

Scans a sub-sequence of characters from a given CharSequence, returning the index of the next character that requires escaping.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

DEST_PADback to summary
private static final int DEST_PAD

The amount of padding (chars) to use when growing the escape buffer.

DEST_TLback to summary
private static final ThreadLocal<char[]> DEST_TL

A thread-local destination buffer to keep us from creating new buffers. The starting size is 1024 characters. If we grow past this we don't put it back in the threadlocal, we just keep going and grow as needed.

Constructor Detail

UnicodeEscaperback to summary
public UnicodeEscaper()

Method Detail

codePointAtback to summary
protected static final int codePointAt(CharSequence seq, int index, int end)

Returns the Unicode code point of the character at the given index.

Unlike Character#codePointAt(CharSequence, int) or String#codePointAt(int) this method will never fail silently when encountering an invalid surrogate pair.

The behaviour of this method is as follows:

  1. If index >= end, IndexOutOfBoundsException is thrown.
  2. If the character at the specified index is not a surrogate, it is returned.
  3. If the first character was a high surrogate value, then an attempt is made to read the next character.
    1. If the end of the sequence was reached, the negated value of the trailing high surrogate is returned.
    2. If the next character was a valid low surrogate, the code point value of the high/low surrogate pair is returned.
    3. If the next character was not a low surrogate value, then IllegalArgumentException is thrown.
  4. If the first character was a low surrogate value, IllegalArgumentException is thrown.
Parameters
seq:CharSequence

the sequence of characters from which to decode the code point

index:int

the index of the first character to decode

end:int

the index beyond the last valid character to decode

Returns:int

the Unicode code point for the given index or the negated value of the trailing high surrogate character at the end of the sequence

escapeback to summary
protected abstract char[] escape(int cp)

Returns the escaped form of the given Unicode code point, or null if this code point does not need to be escaped. When called as part of an escaping operation, the given code point is guaranteed to be in the range 0 <= cp <= Character#MAX_CODE_POINT.

If an empty array is returned, this effectively strips the input character from the resulting text.

If the character does not need to be escaped, this method should return null, rather than an array containing the character representation of the code point. This enables the escaping algorithm to perform more efficiently.

If the implementation of this method cannot correctly handle a particular code point then it should either throw an appropriate runtime exception or return a suitable replacement character. It must never silently discard invalid input as this may constitute a security risk.

Parameters
cp:int

the Unicode code point to escape if necessary

Returns:char[]

the replacement characters, or null if no escaping was needed

escapeback to summary
public String escape(String string)

Implements org.yaml.snakeyaml.external.com.google.gdata.util.common.base.Escaper.escape.

Returns the escaped form of a given literal string.

If you are escaping input in arbitrary successive chunks, then it is not generally safe to use this method. If an input string ends with an unmatched high surrogate character, then this method will throw IllegalArgumentException. You should either ensure your input is valid UTF-16 before calling this method or use an escaped Appendable (as returned by escape(Appendable)) which can cope with arbitrarily split input.

Note

When implementing an escaper it is a good idea to override this method for efficiency by inlining the implementation of nextEscapeIndex(CharSequence, int, int) directly. Doing this for PercentEscaper more than doubled the performance for unescaped strings (as measured by CharEscapersBenchmark).

Parameters
string:String

the literal string to be escaped

Returns:String

the escaped form of string

Exceptions
NullPointerException:
if string is null
IllegalArgumentException:
if invalid surrogate characters are encountered
escapeback to summary
public Appendable escape(final Appendable out)

Implements org.yaml.snakeyaml.external.com.google.gdata.util.common.base.Escaper.escape.

Returns an Appendable instance which automatically escapes all text appended to it before passing the resulting text to an underlying Appendable.

Unlike escape(String) it is permitted to append arbitrarily split input to this Appendable, including input that is split over a surrogate pair. In this case the pending high surrogate character will not be processed until the corresponding low surrogate is appended. This means that a trailing high surrogate character at the end of the input cannot be detected and will be silently ignored. This is unavoidable since the Appendable interface has no close() method, and it is impossible to determine when the last characters have been appended.

The methods of the returned object will propagate any exceptions thrown by the underlying Appendable.

For well formed UTF-16 the escaping behavior is identical to that of escape(String) and the following code is equivalent to (but much slower than) escaper.escape(string):

{
  @code
  StringBuilder sb = new StringBuilder();
  escaper.escape(sb).append(string);
  return sb.toString();
}
Parameters
out:Appendable

the underlying Appendable to append escaped output to

Returns:Appendable

an Appendable which passes text to out after escaping it

Exceptions
NullPointerException:
if out is null
IllegalArgumentException:
if invalid surrogate characters are encountered
escapeSlowback to summary
protected final String escapeSlow(String s, int index)

Returns the escaped form of a given literal string, starting at the given index. This method is called by the escape(String) method when it discovers that escaping is required. It is protected to allow subclasses to override the fastpath escaping function to inline their escaping test. See CharEscaperBuilder for an example usage.

This method is not reentrant and may only be invoked by the top level escape(String) method.

Parameters
s:String

the literal string to be escaped

index:int

the index to start escaping from

Returns:String

the escaped form of string

Exceptions
NullPointerException:
if string is null
IllegalArgumentException:
if invalid surrogate characters are encountered
growBufferback to summary
private static final char[] growBuffer(char[] dest, int index, int size)

Helper method to grow the character buffer as needed, this only happens once in a while so it's ok if it's in a method call. If the index passed in is 0 then no copying will be done.

nextEscapeIndexback to summary
protected int nextEscapeIndex(CharSequence csq, int start, int end)

Scans a sub-sequence of characters from a given CharSequence, returning the index of the next character that requires escaping.

Note

When implementing an escaper, it is a good idea to override this method for efficiency. The base class implementation determines successive Unicode code points and invokes escape(int) for each of them. If the semantics of your escaper are such that code points in the supplementary range are either all escaped or all unescaped, this method can be implemented more efficiently using CharSequence#charAt(int).

Note however that if your escaper does not escape characters in the supplementary range, you should either continue to validate the correctness of any surrogate characters encountered or provide a clear warning to users that your escaper does not validate its input.

See PercentEscaper for an example.

Parameters
csq:CharSequence

a sequence of characters

start:int

the index of the first character to be scanned

end:int

the index immediately after the last character to be scanned

Exceptions
IllegalArgumentException:
if the scanned sub-sequence of csq contains invalid surrogate pairs