/* * XCTrack - XContest Live Tracking client for J2ME devices * Copyright (C) 2009 Petr Chromec <petr@xcontest.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.xcontest.live; import java.io.UnsupportedEncodingException; public final class UTF8 { public static final byte[] encode(String str) { try { return str.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { return encodeSlow(str); } } public static final String decode(byte[] bytes) { return decode(bytes,0,bytes.length); } public static final String decode(byte[] bytes, int off, int len) { try { return new String(bytes,off,len,"utf-8"); } catch (UnsupportedEncodingException e) { return decodeSlow(bytes, off, len); } } private static final byte[] encodeSlow(String str) { int len = 0; char[] chars = new char[str.length()]; byte[] out; str.getChars(0, str.length(), chars, 0); for (int i = 0; i < chars.length; i ++) { if (chars[i] < 0x80) len ++; else if (chars[i] < 0x800) len += 2; else len += 3; } out = new byte[len]; int pos = 0; for (int i = 0; i < chars.length; i ++) { int ch = (int)chars[i]; if (ch < 0x80) { out[pos] = (byte)ch; pos ++; } else if (ch < 0x800) { out[pos] = (byte)(192 | (ch>>6)); out[pos+1] = (byte)(128 | (ch&63)); pos += 2; } else { out[pos] = (byte)(224 | (ch>>12)); out[pos+1] = (byte)(128 | ((ch>>6)&63)); out[pos+2] = (byte)(128 | (ch&63)); pos += 3; } } return out; } private static final String decodeSlow(byte[] bytes, int off, int len) { int cnt = 0; int pos = 0; while (pos < len) { int b = (int)bytes[off+pos]; if (b < 0) b += 256; if ((b & 0x80) == 0) pos ++; else if ((b >> 5) == 6) pos += 2; else if ((b >> 4) == 14) pos += 3; else pos ++; // ? cnt ++; } char[] chars = new char[cnt]; cnt = 0; pos = 0; while (pos < len) { int b = bytes[off+pos]; if (b < 0) b += 256; if (b < 0x80) { chars[cnt] = (char)b; pos ++; } else if ((b >> 5) == 6) { int b2 = pos+1 < len ? bytes[off+pos+1] : 128; chars[cnt] = (char)(((b&31)<<6)|(b2&63)); pos += 2; } else if ((b >> 4) == 14) { int b2 = pos+1 < len ? bytes[off+pos+1] : 128; int b3 = pos+2 < len ? bytes[off+pos+2] : 128; chars[cnt] = (char)(((b&15)<<12)|((b2&63)<<6)|(b3&63)); pos += 3; } else { // error or 4byte utf-8 sequence (not representable in UCS2 chars[cnt] = '?'; pos ++; } cnt ++; } return new String(chars); } }