Methods Summary |
---|
public static byte[] | _parseBase64Binary(java.lang.String text)
final int buflen = guessLength(text);
final byte[] out = new byte[buflen];
int o=0;
final int len = text.length();
int i;
final byte[] quadruplet = new byte[4];
int q=0;
// convert each quadruplet to three bytes.
for( i=0; i<len; i++ ) {
char ch = text.charAt(i);
byte v = decodeMap[ch];
if( v!=-1 )
quadruplet[q++] = v;
if(q==4) {
// quadruplet is now filled.
out[o++] = (byte)((quadruplet[0]<<2)|(quadruplet[1]>>4));
if( quadruplet[2]!=PADDING )
out[o++] = (byte)((quadruplet[1]<<4)|(quadruplet[2]>>2));
if( quadruplet[3]!=PADDING )
out[o++] = (byte)((quadruplet[2]<<6)|(quadruplet[3]));
q=0;
}
}
if(buflen==o) // speculation worked out to be OK
return out;
// we overestimated, so need to create a new buffer
byte[] nb = new byte[o];
System.arraycopy(out,0,nb,0,o);
return nb;
|
public static boolean | _parseBoolean(java.lang.CharSequence literal)
int i=0;
int len = literal.length();
char ch;
do {
ch = literal.charAt(i++);
} while(WhiteSpaceProcessor.isWhiteSpace(ch) && i<len);
// if we are strict about errors, check i==len. and report an error
if( ch=='t" || ch=='1" ) return true;
if( ch=='f" || ch=='0" ) return false;
return false;
|
public static byte | _parseByte(java.lang.CharSequence literal)
return (byte)_parseInt(literal);
|
public static java.util.GregorianCalendar | _parseDateTime(java.lang.CharSequence s)
String val = WhiteSpaceProcessor.trim(s).toString();
return datatypeFactory.newXMLGregorianCalendar(val).toGregorianCalendar();
|
public static java.math.BigDecimal | _parseDecimal(java.lang.CharSequence content)
content = WhiteSpaceProcessor.trim(content);
return new BigDecimal(content.toString());
// from purely XML Schema perspective,
// this implementation has a problem, since
// in xs:decimal "1.0" and "1" is equal whereas the above
// code will return different values for those two forms.
//
// the code was originally using com.sun.msv.datatype.xsd.NumberType.load,
// but a profiling showed that the process of normalizing "1.0" into "1"
// could take non-trivial time.
//
// also, from the user's point of view, one might be surprised if
// 1 (not 1.0) is returned from "1.000"
|
public static double | _parseDouble(java.lang.CharSequence _val)
String val = WhiteSpaceProcessor.trim(_val).toString();
if(val.equals("NaN")) return Double.NaN;
if(val.equals("INF")) return Double.POSITIVE_INFINITY;
if(val.equals("-INF")) return Double.NEGATIVE_INFINITY;
if(val.length()==0
|| !isDigitOrPeriodOrSign(val.charAt(0))
|| !isDigitOrPeriodOrSign(val.charAt(val.length()-1)) )
throw new NumberFormatException(val);
// these screening process is necessary due to the wobble of Float.valueOf method
return Double.parseDouble(val);
|
public static float | _parseFloat(java.lang.CharSequence _val)
String s = WhiteSpaceProcessor.trim(_val).toString();
/* Incompatibilities of XML Schema's float "xfloat" and Java's float "jfloat"
* jfloat.valueOf ignores leading and trailing whitespaces,
whereas this is not allowed in xfloat.
* jfloat.valueOf allows "float type suffix" (f, F) to be
appended after float literal (e.g., 1.52e-2f), whereare
this is not the case of xfloat.
gray zone
---------
* jfloat allows ".523". And there is no clear statement that mentions
this case in xfloat. Although probably this is allowed.
*
*/
if(s.equals("NaN")) return Float.NaN;
if(s.equals("INF")) return Float.POSITIVE_INFINITY;
if(s.equals("-INF")) return Float.NEGATIVE_INFINITY;
if(s.length()==0
|| !isDigitOrPeriodOrSign(s.charAt(0))
|| !isDigitOrPeriodOrSign(s.charAt(s.length()-1)) )
throw new NumberFormatException();
// these screening process is necessary due to the wobble of Float.valueOf method
return Float.parseFloat(s);
|
public static int | _parseInt(java.lang.CharSequence s)Faster but less robust String->int conversion.
Note that:
- XML Schema allows '+', but {@link Integer#valueOf(String)} is not.
- XML Schema allows leading and trailing (but not in-between) whitespaces..
{@link Integer#valueOf(String)} doesn't allow any.
int len = s.length();
int sign = 1;
int r = 0;
for( int i=0; i<len; i++ ) {
char ch = s.charAt(i);
if(WhiteSpaceProcessor.isWhiteSpace(ch)) {
// skip whitespace
} else
if('0"<=ch && ch<='9") {
r = r*10 + (ch-'0");
} else
if(ch=='-") {
sign = -1;
} else
if(ch=='+") {
// noop
} else
throw new NumberFormatException("Not a number: "+s);
}
return r*sign;
|
public static java.math.BigInteger | _parseInteger(java.lang.CharSequence s)
return new BigInteger(removeOptionalPlus(WhiteSpaceProcessor.trim(s)).toString());
|
public static long | _parseLong(java.lang.CharSequence s)
return Long.valueOf(removeOptionalPlus(WhiteSpaceProcessor.trim(s)).toString());
|
public static javax.xml.namespace.QName | _parseQName(java.lang.CharSequence text, javax.xml.namespace.NamespaceContext nsc)
int length = text.length();
// trim whitespace
int start=0;
while(start<length && WhiteSpaceProcessor.isWhiteSpace(text.charAt(start)))
start++;
int end = length;
while(end>start && WhiteSpaceProcessor.isWhiteSpace(text.charAt(end-1)))
end--;
if(end==start)
throw new IllegalArgumentException("input is empty");
String uri;
String localPart;
String prefix;
// search ':'
int idx=start+1; // no point in searching the first char. that's not valid.
while(idx<end && text.charAt(idx)!=':" )
idx++;
if( idx==end ) {
uri = nsc.getNamespaceURI("");
localPart = text.subSequence(start,end).toString();
prefix = "";
} else {
// Prefix exists, check everything
prefix = text.subSequence(start,idx).toString();
localPart = text.subSequence(idx+1,end).toString();
uri = nsc.getNamespaceURI(prefix);
// uri can never be null according to javadoc,
// but some users reported that there are implementations that return null.
if(uri==null || uri.length()==0) // crap. the NamespaceContext interface is broken.
// error: unbound prefix
throw new IllegalArgumentException("prefix "+prefix+" is not bound to a namespace");
}
return new QName(uri,localPart,prefix);
|
public static short | _parseShort(java.lang.CharSequence s)
return (short)_parseInt(s);
|
public static java.lang.String | _printBase64Binary(byte[] input)
return _printBase64Binary(input, 0, input.length);
|
public static java.lang.String | _printBase64Binary(byte[] input, int offset, int len)
char[] buf = new char[((len+2)/3)*4];
int ptr = _printBase64Binary(input,offset,len,buf,0);
assert ptr==buf.length;
return new String(buf);
|
public static int | _printBase64Binary(byte[] input, int offset, int len, char[] buf, int ptr)Encodes a byte array into a char array by doing base64 encoding.
The caller must supply a big enough buffer.
for( int i=offset; i<len; i+=3 ) {
switch( len-i ) {
case 1:
buf[ptr++] = encode(input[i]>>2);
buf[ptr++] = encode(((input[i])&0x3)<<4);
buf[ptr++] = '=";
buf[ptr++] = '=";
break;
case 2:
buf[ptr++] = encode(input[i]>>2);
buf[ptr++] = encode(
((input[i]&0x3)<<4) |
((input[i+1]>>4)&0xF));
buf[ptr++] = encode((input[i+1]&0xF)<<2);
buf[ptr++] = '=";
break;
default:
buf[ptr++] = encode(input[i]>>2);
buf[ptr++] = encode(
((input[i]&0x3)<<4) |
((input[i+1]>>4)&0xF));
buf[ptr++] = encode(
((input[i+1]&0xF)<<2)|
((input[i+2]>>6)&0x3));
buf[ptr++] = encode(input[i+2]&0x3F);
break;
}
}
return ptr;
|
public static int | _printBase64Binary(byte[] input, int offset, int len, byte[] out, int ptr)Encodes a byte array into another byte array by first doing base64 encoding
then encoding the result in ASCII.
The caller must supply a big enough buffer.
byte[] buf = out;
int max = len+offset;
for( int i=offset; i<max; i+=3 ) {
switch( max-i ) {
case 1:
buf[ptr++] = encodeByte(input[i]>>2);
buf[ptr++] = encodeByte(((input[i])&0x3)<<4);
buf[ptr++] = '=";
buf[ptr++] = '=";
break;
case 2:
buf[ptr++] = encodeByte(input[i]>>2);
buf[ptr++] = encodeByte(
((input[i]&0x3)<<4) |
((input[i+1]>>4)&0xF));
buf[ptr++] = encodeByte((input[i+1]&0xF)<<2);
buf[ptr++] = '=";
break;
default:
buf[ptr++] = encodeByte(input[i]>>2);
buf[ptr++] = encodeByte(
((input[i]&0x3)<<4) |
((input[i+1]>>4)&0xF));
buf[ptr++] = encodeByte(
((input[i+1]&0xF)<<2)|
((input[i+2]>>6)&0x3));
buf[ptr++] = encodeByte(input[i+2]&0x3F);
break;
}
}
return ptr;
|
public static java.lang.String | _printBoolean(boolean val)
return val?"true":"false";
|
public static java.lang.String | _printByte(byte val)
return String.valueOf(val);
|
public static java.lang.String | _printDateTime(java.util.Calendar val)
return CalendarFormatter.doFormat("%Y-%M-%DT%h:%m:%s%z",val);
|
public static java.lang.String | _printDecimal(java.math.BigDecimal val)
return val.toPlainString();
|
public static java.lang.String | _printDouble(double v)
if( v==Double.NaN ) return "NaN";
if( v==Double.POSITIVE_INFINITY ) return "INF";
if( v==Double.NEGATIVE_INFINITY ) return "-INF";
return String.valueOf(v);
|
public static java.lang.String | _printFloat(float v)
if( v==Float.NaN ) return "NaN";
if( v==Float.POSITIVE_INFINITY ) return "INF";
if( v==Float.NEGATIVE_INFINITY ) return "-INF";
return String.valueOf(v);
|
public static java.lang.String | _printInt(int val)
return String.valueOf(val);
|
public static java.lang.String | _printInteger(java.math.BigInteger val)
return val.toString();
|
public static java.lang.String | _printLong(long val)
return String.valueOf(val);
|
public static java.lang.String | _printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc)
// Double-check
String qname;
String prefix = nsc.getPrefix( val.getNamespaceURI() );
String localPart = val.getLocalPart();
if( prefix == null || prefix.length()==0 ) { // be defensive
qname = localPart;
} else {
qname = prefix + ':" + localPart;
}
return qname;
|
public static java.lang.String | _printShort(short val)
return String.valueOf(val);
|
public static char | encode(int i)
return encodeMap[i&0x3F];
|
public static byte | encodeByte(int i)
return (byte)encodeMap[i&0x3F];
|
private static int | guessLength(java.lang.String text)computes the length of binary data speculatively.
Our requirement is to create byte[] of the exact length to store the binary data.
If we do this in a straight-forward way, it takes two passes over the data.
Experiments show that this is a non-trivial overhead (35% or so is spent on
the first pass in calculating the length.)
So the approach here is that we compute the length speculatively, without looking
at the whole contents. The obtained speculative value is never less than the
actual length of the binary data, but it may be bigger. So if the speculation
goes wrong, we'll pay the cost of reallocation and buffer copying.
If the base64 text is tightly packed with no indentation nor illegal char
(like what most web services produce), then the speculation of this method
will be correct, so we get the performance benefit.
final int len = text.length();
// compute the tail '=' chars
int j=len-1;
for(; j>=0; j-- ) {
byte code = decodeMap[text.charAt(j)];
if(code==PADDING)
continue;
if(code==-1)
// most likely this base64 text is indented. go with the upper bound
return text.length()/4*3;
break;
}
j++; // text.charAt(j) is now at some base64 char, so +1 to make it the size
int padSize = len-j;
if(padSize >2) // something is wrong with base64. be safe and go with the upper bound
return text.length()/4*3;
// so far this base64 looks like it's unindented tightly packed base64.
// take a chance and create an array with the expected size
return text.length()/4*3-padSize;
|
private static int | hexToBin(char ch)
if( '0"<=ch && ch<='9" ) return ch-'0";
if( 'A"<=ch && ch<='F" ) return ch-'A"+10;
if( 'a"<=ch && ch<='f" ) return ch-'a"+10;
return -1;
|
private static byte[] | initDecodeMap()
byte[] map = new byte[128];
int i;
for( i=0; i<128; i++ ) map[i] = -1;
for( i='A"; i<='Z"; i++ ) map[i] = (byte)(i-'A");
for( i='a"; i<='z"; i++ ) map[i] = (byte)(i-'a"+26);
for( i='0"; i<='9"; i++ ) map[i] = (byte)(i-'0"+52);
map['+"] = 62;
map['/"] = 63;
map['="] = PADDING;
return map;
|
private static char[] | initEncodeMap()
char[] map = new char[64];
int i;
for( i= 0; i<26; i++ ) map[i] = (char)('A"+i);
for( i=26; i<52; i++ ) map[i] = (char)('a"+(i-26));
for( i=52; i<62; i++ ) map[i] = (char)('0"+(i-52));
map[62] = '+";
map[63] = '/";
return map;
|
public static java.lang.String | installHook(java.lang.String s)Just return the string passed as a parameter but
installs an instance of this class as the DatatypeConverter
implementation. Used from static fixed value initializers.
DatatypeConverter.setDatatypeConverter(theInstance);
return s;
|
private static boolean | isDigitOrPeriodOrSign(char ch)
if( '0"<=ch && ch<='9" ) return true;
if( ch=='+" || ch=='-" || ch=='." ) return true;
return false;
|
public java.lang.String | parseAnySimpleType(java.lang.String lexicalXSDAnySimpleType)
return lexicalXSDAnySimpleType;
// return (String)SimpleURType.theInstance._createValue( lexicalXSDAnySimpleType, null );
|
public byte[] | parseBase64Binary(java.lang.String lexicalXSDBase64Binary)
return _parseBase64Binary(lexicalXSDBase64Binary);
|
public boolean | parseBoolean(java.lang.String lexicalXSDBoolean)
return _parseBoolean(lexicalXSDBoolean);
|
public byte | parseByte(java.lang.String lexicalXSDByte)
return _parseByte(lexicalXSDByte);
|
public java.util.Calendar | parseDate(java.lang.String lexicalXSDDate)
return datatypeFactory.newXMLGregorianCalendar(lexicalXSDDate).toGregorianCalendar();
|
public java.util.Calendar | parseDateTime(java.lang.String lexicalXSDDateTime)
return _parseDateTime(lexicalXSDDateTime);
|
public java.math.BigDecimal | parseDecimal(java.lang.String content)
return _parseDecimal(content);
|
public double | parseDouble(java.lang.String lexicalXSDDouble)
return _parseDouble(lexicalXSDDouble);
|
public float | parseFloat(java.lang.String lexicalXSDFloat)
return _parseFloat(lexicalXSDFloat);
|
public byte[] | parseHexBinary(java.lang.String s)
final int len = s.length();
// "111" is not a valid hex encoding.
if( len%2 != 0 )
throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);
byte[] out = new byte[len/2];
for( int i=0; i<len; i+=2 ) {
int h = hexToBin(s.charAt(i ));
int l = hexToBin(s.charAt(i+1));
if( h==-1 || l==-1 )
throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);
out[i/2] = (byte)(h*16+l);
}
return out;
|
public int | parseInt(java.lang.String s)
return _parseInt(s);
|
public java.math.BigInteger | parseInteger(java.lang.String lexicalXSDInteger)
return _parseInteger(lexicalXSDInteger);
|
public long | parseLong(java.lang.String lexicalXSLong)
return _parseLong(lexicalXSLong);
|
public javax.xml.namespace.QName | parseQName(java.lang.String lexicalXSDQName, javax.xml.namespace.NamespaceContext nsc)
return _parseQName(lexicalXSDQName,nsc);
|
public short | parseShort(java.lang.String lexicalXSDShort)
return _parseShort(lexicalXSDShort);
|
public java.lang.String | parseString(java.lang.String lexicalXSDString)
return lexicalXSDString;
|
public java.util.Calendar | parseTime(java.lang.String lexicalXSDTime)
return datatypeFactory.newXMLGregorianCalendar(lexicalXSDTime).toGregorianCalendar();
|
public long | parseUnsignedInt(java.lang.String lexicalXSDUnsignedInt)
return _parseLong(lexicalXSDUnsignedInt);
|
public int | parseUnsignedShort(java.lang.String lexicalXSDUnsignedShort)
return _parseInt(lexicalXSDUnsignedShort);
|
public java.lang.String | printAnySimpleType(java.lang.String val)
return val;
|
public java.lang.String | printBase64Binary(byte[] val)
return _printBase64Binary(val);
|
public java.lang.String | printBoolean(boolean val)
return val?"true":"false";
|
public java.lang.String | printByte(byte val)
return _printByte(val);
|
public java.lang.String | printDate(java.util.Calendar val)
return CalendarFormatter.doFormat((new StringBuilder("%Y-%M-%D").append("%z")).toString(),val);
|
public java.lang.String | printDateTime(java.util.Calendar val)
return _printDateTime(val);
|
public java.lang.String | printDecimal(java.math.BigDecimal val)
return _printDecimal(val);
|
public java.lang.String | printDouble(double v)
return _printDouble(v);
|
public java.lang.String | printFloat(float v)
return _printFloat(v);
|
public java.lang.String | printHexBinary(byte[] data)
StringBuilder r = new StringBuilder(data.length*2);
for ( byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
|
public java.lang.String | printInt(int val)
return _printInt(val);
|
public java.lang.String | printInteger(java.math.BigInteger val)
return _printInteger(val);
|
public java.lang.String | printLong(long val)
return _printLong(val);
|
public java.lang.String | printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc)
return _printQName(val,nsc);
|
public java.lang.String | printShort(short val)
return _printShort(val);
|
public java.lang.String | printString(java.lang.String val)
// return StringType.theInstance.convertToLexicalValue( val, null );
return val;
|
public java.lang.String | printTime(java.util.Calendar val)
return CalendarFormatter.doFormat("%h:%m:%s%z",val);
|
public java.lang.String | printUnsignedInt(long val)
return _printLong(val);
|
public java.lang.String | printUnsignedShort(int val)
return String.valueOf(val);
|
private static java.lang.CharSequence | removeOptionalPlus(java.lang.CharSequence s)
int len = s.length();
if(len<=1 || s.charAt(0)!='+") return s;
s = s.subSequence(1,len);
char ch = s.charAt(0);
if('0"<=ch && ch<='9") return s;
if('."==ch ) return s;
throw new NumberFormatException();
|