blob: b0b79765c12cc750a39d0fc778c12ab4027f7247 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.luni.util;
import java.io.ByteArrayOutputStream;
import java.io.UTFDataFormatException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.TimeZone;
public final class Util {
private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
private static String[] MONTHS = new String[] { "January", "February",
"March", "April", "May", "June", "July", "August", "September",
"October", "November", "December" };
private static final String defaultEncoding;
static {
String encoding = System.getProperty("os.encoding");
if (encoding != null) {
try {
"".getBytes(encoding);
} catch (Throwable t) {
encoding = null;
}
}
defaultEncoding = encoding;
}
/**
* Get bytes from String using default encoding; default encoding can
* be changed via "os.encoding" property
* @param name input String
* @return byte array
*/
public static byte[] getBytes(String name) {
if (defaultEncoding != null) {
try {
return name.getBytes(defaultEncoding);
} catch (java.io.UnsupportedEncodingException e) {
}
}
return name.getBytes();
}
/**
* Get bytes from String with UTF8 encoding
* @param name
* input String
* @return byte array
*/
public static byte[] getUTF8Bytes(String name) {
try {
return name.getBytes("UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
return getBytes(name);
}
}
public static String toString(byte[] bytes) {
if (defaultEncoding != null) {
try {
return new String(bytes, 0, bytes.length, defaultEncoding);
} catch (java.io.UnsupportedEncodingException e) {
}
}
return new String(bytes, 0, bytes.length);
}
public static String toUTF8String(byte[] bytes) {
return toUTF8String(bytes, 0, bytes.length);
}
public static String toString(byte[] bytes, int offset, int length) {
if (defaultEncoding != null) {
try {
return new String(bytes, offset, length, defaultEncoding);
} catch (java.io.UnsupportedEncodingException e) {
}
}
return new String(bytes, offset, length);
}
public static String toUTF8String(byte[] bytes, int offset, int length) {
try {
return new String(bytes, offset, length, "UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
return toString(bytes, offset, length);
}
}
/**
* Answers the millisecond value of the date and time parsed from the
* specified String. Many date/time formats are recognized
*
* @param string
* the String to parse
* @return the millisecond value parsed from the String
*/
public static long parseDate(String string) {
int offset = 0, length = string.length(), state = 0;
int year = -1, month = -1, date = -1;
int hour = -1, minute = -1, second = -1;
final int PAD = 0, LETTERS = 1, NUMBERS = 2;
StringBuilder buffer = new StringBuilder();
while (offset <= length) {
char next = offset < length ? string.charAt(offset) : '\r';
offset++;
int nextState;
if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
nextState = LETTERS;
else if (next >= '0' && next <= '9')
nextState = NUMBERS;
else if (" ,-:\r\t".indexOf(next) == -1)
throw new IllegalArgumentException();
else
nextState = PAD;
if (state == NUMBERS && nextState != NUMBERS) {
int digit = Integer.parseInt(buffer.toString());
buffer.setLength(0);
if (digit >= 70) {
if (year != -1
|| (next != ' ' && next != ',' && next != '\r'))
throw new IllegalArgumentException();
year = digit;
} else if (next == ':') {
if (hour == -1)
hour = digit;
else if (minute == -1)
minute = digit;
else
throw new IllegalArgumentException();
} else if (next == ' ' || next == ',' || next == '-'
|| next == '\r') {
if (hour != -1 && minute == -1)
minute = digit;
else if (minute != -1 && second == -1)
second = digit;
else if (date == -1)
date = digit;
else if (year == -1)
year = digit;
else
throw new IllegalArgumentException();
} else if (year == -1 && month != -1 && date != -1)
year = digit;
else
throw new IllegalArgumentException();
} else if (state == LETTERS && nextState != LETTERS) {
String text = buffer.toString().toUpperCase();
buffer.setLength(0);
if (text.length() < 3)
throw new IllegalArgumentException();
if (parse(text, WEEKDAYS) != -1) {
} else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
} else if (text.equals("GMT")) {
} else
throw new IllegalArgumentException();
}
if (nextState == LETTERS || nextState == NUMBERS)
buffer.append(next);
state = nextState;
}
if (year != -1 && month != -1 && date != -1) {
if (hour == -1)
hour = 0;
if (minute == -1)
minute = 0;
if (second == -1)
second = 0;
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
int current = cal.get(Calendar.YEAR) - 80;
if (year < 100) {
year += current / 100 * 100;
if (year < current)
year += 100;
}
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DATE, date);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime().getTime();
}
throw new IllegalArgumentException();
}
private static int parse(String string, String[] array) {
int length = string.length();
for (int i = 0; i < array.length; i++) {
if (string.regionMatches(true, 0, array[i], 0, length))
return i;
}
return -1;
}
public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
throws UTFDataFormatException {
return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
}
public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
int utfSize) throws UTFDataFormatException {
int count = 0, s = 0, a;
while (count < utfSize) {
if ((out[s] = (char) buf[offset + count++]) < '\u0080')
s++;
else if (((a = out[s]) & 0xe0) == 0xc0) {
if (count >= utfSize)
throw new UTFDataFormatException(Msg.getString("K0062",
count));
int b = buf[count++];
if ((b & 0xC0) != 0x80)
throw new UTFDataFormatException(Msg.getString("K0062",
(count - 1)));
out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
} else if ((a & 0xf0) == 0xe0) {
if (count + 1 >= utfSize)
throw new UTFDataFormatException(Msg.getString("K0063",
(count + 1)));
int b = buf[count++];
int c = buf[count++];
if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
throw new UTFDataFormatException(Msg.getString("K0064",
(count - 2)));
out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
} else {
throw new UTFDataFormatException(Msg.getString("K0065",
(count - 1)));
}
}
return new String(out, 0, s);
}
/**
* '%' and two following hex digit characters are converted to the
* equivalent byte value. All other characters are passed through
* unmodified. e.g. "ABC %24%25" -> "ABC $%"
*
* @param s
* java.lang.String The encoded string.
* @return java.lang.String The decoded version.
*/
public static String decode(String s, boolean convertPlus) {
return decode(s, convertPlus, null);
}
/**
* '%' and two following hex digit characters are converted to the
* equivalent byte value. All other characters are passed through
* unmodified. e.g. "ABC %24%25" -> "ABC $%"
*
* @param s
* java.lang.String The encoded string.
* @param encoding
* the specified encoding
* @return java.lang.String The decoded version.
*/
public static String decode(String s, boolean convertPlus, String encoding) {
if (!convertPlus && s.indexOf('%') == -1)
return s;
StringBuilder result = new StringBuilder(s.length());
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int i = 0; i < s.length();) {
char c = s.charAt(i);
if (convertPlus && c == '+')
result.append(' ');
else if (c == '%') {
out.reset();
do {
if (i + 2 >= s.length())
throw new IllegalArgumentException(Msg.getString(
"K01fe", i));
int d1 = Character.digit(s.charAt(i + 1), 16);
int d2 = Character.digit(s.charAt(i + 2), 16);
if (d1 == -1 || d2 == -1)
throw new IllegalArgumentException(Msg.getString(
"K01ff", s.substring(i, i + 3), String
.valueOf(i)));
out.write((byte) ((d1 << 4) + d2));
i += 3;
} while (i < s.length() && s.charAt(i) == '%');
if (encoding == null) {
result.append(out.toString());
} else {
try {
result.append(out.toString(encoding));
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
}
continue;
} else
result.append(c);
i++;
}
return result.toString();
}
public static String toASCIILowerCase(String s) {
int len = s.length();
StringBuilder buffer = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if ('A' <= c && c <= 'Z') {
buffer.append((char) (c + ('a' - 'A')));
} else {
buffer.append(c);
}
}
return buffer.toString();
}
public static String toASCIIUpperCase(String s) {
int len = s.length();
StringBuilder buffer = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if ('a' <= c && c <= 'z') {
buffer.append((char) (c - ('a' - 'A')));
} else {
buffer.append(c);
}
}
return buffer.toString();
}
}