| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed 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 com.android.internal.telephony; |
| |
| import android.telephony.SmsMessage; |
| import android.util.SparseIntArray; |
| |
| import android.util.Log; |
| |
| /** |
| * This class implements the character set mapping between |
| * the GSM SMS 7-bit alphabet specifed in TS 23.038 6.2.1 |
| * and UTF-16 |
| * |
| * {@hide} |
| */ |
| public class GsmAlphabet { |
| static final String LOG_TAG = "GSM"; |
| |
| |
| |
| //***** Constants |
| |
| /** |
| * This escapes extended characters, and when present indicates that the |
| * following character should |
| * be looked up in the "extended" table |
| * |
| * gsmToChar(GSM_EXTENDED_ESCAPE) returns 0xffff |
| */ |
| |
| public static final byte GSM_EXTENDED_ESCAPE = 0x1B; |
| |
| |
| /** |
| * char to GSM alphabet char |
| * Returns ' ' in GSM alphabet if there's no possible match |
| * Returns GSM_EXTENDED_ESCAPE if this character is in the extended table |
| * In this case, you must call charToGsmExtended() for the value that |
| * should follow GSM_EXTENDED_ESCAPE in the GSM alphabet string |
| */ |
| public static int |
| charToGsm(char c) { |
| try { |
| return charToGsm(c, false); |
| } catch (EncodeException ex) { |
| // this should never happen |
| return sGsmSpaceChar; |
| } |
| } |
| |
| /** |
| * char to GSM alphabet char |
| * @param throwException If true, throws EncodeException on invalid char. |
| * If false, returns GSM alphabet ' ' char. |
| * |
| * Returns GSM_EXTENDED_ESCAPE if this character is in the extended table |
| * In this case, you must call charToGsmExtended() for the value that |
| * should follow GSM_EXTENDED_ESCAPE in the GSM alphabet string |
| */ |
| |
| public static int |
| charToGsm(char c, boolean throwException) throws EncodeException { |
| int ret; |
| |
| ret = charToGsm.get(c, -1); |
| |
| if (ret == -1) { |
| ret = charToGsmExtended.get(c, -1); |
| |
| if (ret == -1) { |
| if (throwException) { |
| throw new EncodeException(c); |
| } else { |
| return sGsmSpaceChar; |
| } |
| } else { |
| return GSM_EXTENDED_ESCAPE; |
| } |
| } |
| |
| return ret; |
| |
| } |
| |
| |
| /** |
| * char to extended GSM alphabet char |
| * |
| * Extended chars should be escaped with GSM_EXTENDED_ESCAPE |
| * |
| * Returns ' ' in GSM alphabet if there's no possible match |
| * |
| */ |
| public static int |
| charToGsmExtended(char c) { |
| int ret; |
| |
| ret = charToGsmExtended.get(c, -1); |
| |
| if (ret == -1) { |
| return sGsmSpaceChar; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * Converts a character in the GSM alphabet into a char |
| * |
| * if GSM_EXTENDED_ESCAPE is passed, 0xffff is returned. In this case, |
| * the following character in the stream should be decoded with |
| * gsmExtendedToChar() |
| * |
| * If an unmappable value is passed (one greater than 127), ' ' is returned |
| */ |
| |
| public static char |
| gsmToChar(int gsmChar) { |
| return (char)gsmToChar.get(gsmChar, ' '); |
| } |
| |
| /** |
| * Converts a character in the extended GSM alphabet into a char |
| * |
| * if GSM_EXTENDED_ESCAPE is passed, ' ' is returned since no second |
| * extension page has yet been defined (see Note 1 in table 6.2.1.1 of |
| * TS 23.038 v7.00) |
| * |
| * If an unmappable value is passed , ' ' is returned |
| */ |
| |
| public static char |
| gsmExtendedToChar(int gsmChar) { |
| int ret; |
| |
| ret = gsmExtendedToChar.get(gsmChar, -1); |
| |
| if (ret == -1) { |
| return ' '; |
| } |
| |
| return (char)ret; |
| } |
| |
| /** |
| * Converts a String into a byte array containing the 7-bit packed |
| * GSM Alphabet representation of the string. If a header is provided, |
| * this is included in the returned byte array and padded to a septet |
| * boundary. |
| * |
| * Unencodable chars are encoded as spaces |
| * |
| * Byte 0 in the returned byte array is the count of septets used, |
| * including the header and header padding. The returned byte array is |
| * the minimum size required to store the packed septets. The returned |
| * array cannot contain more than 255 septets. |
| * |
| * @param data The text string to encode. |
| * @param header Optional header (includeing length byte) that precedes |
| * the encoded data, padded to septet boundary. |
| * @return Byte array containing header and encoded data. |
| */ |
| public static byte[] stringToGsm7BitPackedWithHeader(String data, byte[] header) |
| throws EncodeException { |
| |
| if (header == null || header.length == 0) { |
| return stringToGsm7BitPacked(data); |
| } |
| |
| int headerBits = (header.length + 1) * 8; |
| int headerSeptets = headerBits / 7; |
| headerSeptets += (headerBits % 7) > 0 ? 1 : 0; |
| |
| int sz = data.length(); |
| int septetCount; |
| septetCount = countGsmSeptets(data, true) + headerSeptets; |
| |
| byte[] ret = stringToGsm7BitPacked(data, 0, septetCount, |
| (headerSeptets*7), true); |
| |
| // Paste in the header |
| ret[1] = (byte)header.length; |
| System.arraycopy(header, 0, ret, 2, header.length); |
| return ret; |
| } |
| |
| /** |
| * Converts a String into a byte array containing |
| * the 7-bit packed GSM Alphabet representation of the string. |
| * |
| * Unencodable chars are encoded as spaces |
| * |
| * Byte 0 in the returned byte array is the count of septets used |
| * The returned byte array is the minimum size required to store |
| * the packed septets. The returned array cannot contain more than 255 |
| * septets. |
| * |
| * @param data the data string to endcode |
| * @throws EncodeException if String is too large to encode |
| */ |
| public static byte[] stringToGsm7BitPacked(String data) |
| throws EncodeException { |
| return stringToGsm7BitPacked(data, 0, -1, 0, true); |
| } |
| |
| /** |
| * Converts a String into a byte array containing |
| * the 7-bit packed GSM Alphabet representation of the string. |
| * |
| * Byte 0 in the returned byte array is the count of septets used |
| * The returned byte array is the minimum size required to store |
| * the packed septets. The returned array cannot contain more than 255 |
| * septets. |
| * |
| * @param data the text to convert to septets |
| * @param dataOffset the character offset in data to start the encoding from |
| * @param maxSeptets the maximum number of septets to convert, or -1 for no |
| * enforced maximum. |
| * @param startingBitOffset the number of padding bits to put before |
| * the start of the first septet at the begining of the array |
| * @param throwException If true, throws EncodeException on invalid char. |
| * If false, replaces unencodable char with GSM alphabet space char. |
| * |
| * @throws EncodeException if String is too large to encode |
| */ |
| public static byte[] stringToGsm7BitPacked(String data, int dataOffset, |
| int maxSeptets, int startingBitOffset, boolean throwException) |
| throws EncodeException { |
| |
| int sz = data.length(); |
| int septetCount; |
| if (maxSeptets == -1) { |
| septetCount = countGsmSeptets(data, true); |
| } else { |
| septetCount = maxSeptets; |
| } |
| |
| if(septetCount > 0xff) { |
| throw new EncodeException("Payload cannot exceed " + Short.MAX_VALUE |
| + " septets"); |
| } |
| |
| // Enough for all the septets and the length 2 byte prefix |
| byte[] ret = new byte[1 + (((septetCount * 7) + 7) / 8)]; |
| |
| int bitOffset = startingBitOffset; |
| int septets = startingBitOffset/7; |
| for (int i = dataOffset; i < sz && septets < septetCount; i++, bitOffset += 7) { |
| char c = data.charAt(i); |
| |
| int v = GsmAlphabet.charToGsm(c, throwException); |
| if (v == GSM_EXTENDED_ESCAPE) { |
| // Lookup the extended char |
| v = GsmAlphabet.charToGsmExtended(c); |
| |
| packSmsChar(ret, bitOffset, GSM_EXTENDED_ESCAPE); |
| bitOffset += 7; |
| septets++; |
| } |
| |
| packSmsChar(ret, bitOffset, v); |
| septets++; |
| } |
| |
| // See check for > 0xff above |
| ret[0] = (byte)septets; |
| |
| return ret; |
| } |
| |
| /** |
| * Pack a 7-bit char into its appropirate place in a byte array |
| * |
| * @param bitOffset the bit offset that the septet should be packed at |
| * (septet index * 7) |
| */ |
| private static void |
| packSmsChar(byte[] packedChars, int bitOffset, int value) { |
| int byteOffset = bitOffset / 8; |
| int shift = bitOffset % 8; |
| |
| packedChars[++byteOffset] |= value << shift; |
| |
| if (shift > 1) { |
| packedChars[++byteOffset] = (byte)(value >> (8 - shift)); |
| } |
| } |
| |
| /** |
| * Convert a GSM alphabet 7 bit packed string (SMS string) into a |
| * {@link java.lang.String}. |
| * |
| * See TS 23.038 6.1.2.1 for SMS Character Packing |
| * |
| * @param pdu the raw data from the pdu |
| * @param offset the byte offset of |
| * @param lengthSeptets string length in septets, not bytes |
| * @return String representation or null on decoding exception |
| */ |
| public static String gsm7BitPackedToString(byte[] pdu, int offset, |
| int lengthSeptets) { |
| return gsm7BitPackedToString(pdu, offset, lengthSeptets, 0); |
| } |
| |
| /** |
| * Convert a GSM alphabet 7 bit packed string (SMS string) into a |
| * {@link java.lang.String}. |
| * |
| * See TS 23.038 6.1.2.1 for SMS Character Packing |
| * |
| * @param pdu the raw data from the pdu |
| * @param offset the byte offset of |
| * @param lengthSeptets string length in septets, not bytes |
| * @param numPaddingBits the number of padding bits before the start of the |
| * string in the first byte |
| * @return String representation or null on decoding exception |
| */ |
| public static String gsm7BitPackedToString(byte[] pdu, int offset, |
| int lengthSeptets, int numPaddingBits) { |
| StringBuilder ret = new StringBuilder(lengthSeptets); |
| boolean prevCharWasEscape; |
| |
| try { |
| prevCharWasEscape = false; |
| |
| for (int i = 0 ; i < lengthSeptets ; i++) { |
| int bitOffset = (7 * i) + numPaddingBits; |
| |
| int byteOffset = bitOffset / 8; |
| int shift = bitOffset % 8; |
| int gsmVal; |
| |
| gsmVal = (0x7f & (pdu[offset + byteOffset] >> shift)); |
| |
| // if it crosses a byte boundry |
| if (shift > 1) { |
| // set msb bits to 0 |
| gsmVal &= 0x7f >> (shift - 1); |
| |
| gsmVal |= 0x7f & (pdu[offset + byteOffset + 1] << (8 - shift)); |
| } |
| |
| if (prevCharWasEscape) { |
| ret.append(GsmAlphabet.gsmExtendedToChar(gsmVal)); |
| prevCharWasEscape = false; |
| } else if (gsmVal == GSM_EXTENDED_ESCAPE) { |
| prevCharWasEscape = true; |
| } else { |
| ret.append(GsmAlphabet.gsmToChar(gsmVal)); |
| } |
| } |
| } catch (RuntimeException ex) { |
| Log.e(LOG_TAG, "Error GSM 7 bit packed: ", ex); |
| return null; |
| } |
| |
| return ret.toString(); |
| } |
| |
| |
| /** |
| * Convert a GSM alphabet string that's stored in 8-bit unpacked |
| * format (as it often appears in SIM records) into a String |
| * |
| * Field may be padded with trailing 0xff's. The decode stops |
| * at the first 0xff encountered. |
| */ |
| public static String |
| gsm8BitUnpackedToString(byte[] data, int offset, int length) { |
| boolean prevWasEscape; |
| StringBuilder ret = new StringBuilder(length); |
| |
| prevWasEscape = false; |
| for (int i = offset ; i < offset + length ; i++) { |
| // Never underestimate the pain that can be caused |
| // by signed bytes |
| int c = data[i] & 0xff; |
| |
| if (c == 0xff) { |
| break; |
| } else if (c == GSM_EXTENDED_ESCAPE) { |
| if (prevWasEscape) { |
| // Two escape chars in a row |
| // We treat this as a space |
| // See Note 1 in table 6.2.1.1 of TS 23.038 v7.00 |
| ret.append(' '); |
| prevWasEscape = false; |
| } else { |
| prevWasEscape = true; |
| } |
| } else { |
| if (prevWasEscape) { |
| ret.append((char)gsmExtendedToChar.get(c, ' ')); |
| } else { |
| ret.append((char)gsmToChar.get(c, ' ')); |
| } |
| prevWasEscape = false; |
| } |
| } |
| |
| return ret.toString(); |
| } |
| |
| /** |
| * Convert a string into an 8-bit unpacked GSM alphabet byte |
| * array |
| */ |
| public static byte[] |
| stringToGsm8BitPacked(String s) { |
| byte[] ret; |
| |
| int septets = 0; |
| |
| septets = countGsmSeptets(s); |
| |
| // Enough for all the septets and the length byte prefix |
| ret = new byte[septets]; |
| |
| stringToGsm8BitUnpackedField(s, ret, 0, ret.length); |
| |
| return ret; |
| } |
| |
| |
| /** |
| * Write a String into a GSM 8-bit unpacked field of |
| * @param length size at @param offset in @param dest |
| * |
| * Field is padded with 0xff's, string is truncated if necessary |
| */ |
| |
| public static void |
| stringToGsm8BitUnpackedField(String s, byte dest[], int offset, int length) { |
| int outByteIndex = offset; |
| |
| // Septets are stored in byte-aligned octets |
| for (int i = 0, sz = s.length() |
| ; i < sz && (outByteIndex - offset) < length |
| ; i++ |
| ) { |
| char c = s.charAt(i); |
| |
| int v = GsmAlphabet.charToGsm(c); |
| |
| if (v == GSM_EXTENDED_ESCAPE) { |
| // make sure we can fit an escaped char |
| if (! (outByteIndex + 1 - offset < length)) { |
| break; |
| } |
| |
| dest[outByteIndex++] = GSM_EXTENDED_ESCAPE; |
| |
| v = GsmAlphabet.charToGsmExtended(c); |
| } |
| |
| dest[outByteIndex++] = (byte)v; |
| } |
| |
| // pad with 0xff's |
| while((outByteIndex - offset) < length) { |
| dest[outByteIndex++] = (byte)0xff; |
| } |
| } |
| |
| /** |
| * Returns the count of 7-bit GSM alphabet characters |
| * needed to represent this character. Counts unencodable char as 1 septet. |
| */ |
| public static int |
| countGsmSeptets(char c) { |
| try { |
| return countGsmSeptets(c, false); |
| } catch (EncodeException ex) { |
| // This should never happen. |
| return 0; |
| } |
| } |
| |
| /** |
| * Returns the count of 7-bit GSM alphabet characters |
| * needed to represent this character |
| * @param throwsException If true, throws EncodeException if unencodable |
| * char. Otherwise, counts invalid char as 1 septet |
| */ |
| public static int |
| countGsmSeptets(char c, boolean throwsException) throws EncodeException { |
| if (charToGsm.get(c, -1) != -1) { |
| return 1; |
| } |
| |
| if (charToGsmExtended.get(c, -1) != -1) { |
| return 2; |
| } |
| |
| if (throwsException) { |
| throw new EncodeException(c); |
| } else { |
| // count as a space char |
| return 1; |
| } |
| } |
| |
| /** |
| * Returns the count of 7-bit GSM alphabet characters |
| * needed to represent this string. Counts unencodable char as 1 septet. |
| */ |
| public static int |
| countGsmSeptets(CharSequence s) { |
| try { |
| return countGsmSeptets(s, false); |
| } catch (EncodeException ex) { |
| // this should never happen |
| return 0; |
| } |
| } |
| |
| /** |
| * Returns the count of 7-bit GSM alphabet characters |
| * needed to represent this string. |
| * @param throwsException If true, throws EncodeException if unencodable |
| * char. Otherwise, counts invalid char as 1 septet |
| */ |
| public static int |
| countGsmSeptets(CharSequence s, boolean throwsException) throws EncodeException { |
| int charIndex = 0; |
| int sz = s.length(); |
| int count = 0; |
| |
| while (charIndex < sz) { |
| count += countGsmSeptets(s.charAt(charIndex), throwsException); |
| charIndex++; |
| } |
| |
| return count; |
| } |
| |
| /** |
| * Returns the index into <code>s</code> of the first character |
| * after <code>limit</code> septets have been reached, starting at |
| * index <code>start</code>. This is used when dividing messages |
| * into units within the SMS message size limit. |
| * |
| * @param s source string |
| * @param start index of where to start counting septets |
| * @param limit maximum septets to include, |
| * e.g. <code>MAX_USER_DATA_SEPTETS</code> |
| * @return index of first character that won't fit, or the length |
| * of the entire string if everything fits |
| */ |
| public static int |
| findGsmSeptetLimitIndex(String s, int start, int limit) { |
| int accumulator = 0; |
| int size = s.length(); |
| |
| for (int i = start; i < size; i++) { |
| accumulator += countGsmSeptets(s.charAt(i)); |
| if (accumulator > limit) { |
| return i; |
| } |
| } |
| return size; |
| } |
| |
| /** |
| * Returns the index into <code>s</code> of the first character |
| * after <code>limit</code> octets have been reached, starting at |
| * index <code>start</code>. This is used when dividing messages |
| * in UCS2 encoding into units within the SMS message size limit. |
| * |
| * @param s source string |
| * @param start index of where to start counting septets |
| * @param limit maximum septets to include, |
| * e.g. <code>MAX_USER_DATA_BYTES</code> |
| * @return index of first character that won't fit, or the length |
| * of the entire string if everything fits |
| */ |
| public static int |
| findUCS2LimitIndex(String s, int start, int limit) { |
| int numCharToBeEncoded = s.length() - start; |
| return ((numCharToBeEncoded*2 > limit)? limit/2: numCharToBeEncoded) + start; |
| } |
| |
| /** |
| * Returns the index into <code>s</code> of the first character |
| * after <code>limit</code> septets/octets have been reached |
| * according to the <code>encodingType</code>, starting at |
| * index <code>start</code>. This is used when dividing messages |
| * units within the SMS message size limit. |
| * |
| * @param s source string |
| * @param start index of where to start counting septets |
| * @param limit maximum septets to include, |
| * e.g. <code>MAX_USER_DATA_BYTES</code> |
| * @return index of first character that won't fit, or the length |
| * of the entire string if everything fits |
| */ |
| public static int |
| findLimitIndex(String s, int start, int limit, int encodingType) throws EncodeException { |
| if (encodingType == SmsMessage.ENCODING_7BIT) { |
| return findGsmSeptetLimitIndex(s, start, limit); |
| } |
| else if (encodingType == SmsMessage.ENCODING_16BIT) { |
| return findUCS2LimitIndex(s, start, limit); |
| } |
| else { |
| throw new EncodeException("Unsupported encoding type: " + encodingType); |
| } |
| } |
| |
| // Set in the static initializer |
| private static int sGsmSpaceChar; |
| |
| private static final SparseIntArray charToGsm = new SparseIntArray(); |
| private static final SparseIntArray gsmToChar = new SparseIntArray(); |
| private static final SparseIntArray charToGsmExtended = new SparseIntArray(); |
| private static final SparseIntArray gsmExtendedToChar = new SparseIntArray(); |
| |
| static { |
| int i = 0; |
| |
| charToGsm.put('@', i++); |
| charToGsm.put('\u00a3', i++); |
| charToGsm.put('$', i++); |
| charToGsm.put('\u00a5', i++); |
| charToGsm.put('\u00e8', i++); |
| charToGsm.put('\u00e9', i++); |
| charToGsm.put('\u00f9', i++); |
| charToGsm.put('\u00ec', i++); |
| charToGsm.put('\u00f2', i++); |
| charToGsm.put('\u00c7', i++); |
| charToGsm.put('\n', i++); |
| charToGsm.put('\u00d8', i++); |
| charToGsm.put('\u00f8', i++); |
| charToGsm.put('\r', i++); |
| charToGsm.put('\u00c5', i++); |
| charToGsm.put('\u00e5', i++); |
| |
| charToGsm.put('\u0394', i++); |
| charToGsm.put('_', i++); |
| charToGsm.put('\u03a6', i++); |
| charToGsm.put('\u0393', i++); |
| charToGsm.put('\u039b', i++); |
| charToGsm.put('\u03a9', i++); |
| charToGsm.put('\u03a0', i++); |
| charToGsm.put('\u03a8', i++); |
| charToGsm.put('\u03a3', i++); |
| charToGsm.put('\u0398', i++); |
| charToGsm.put('\u039e', i++); |
| charToGsm.put('\uffff', i++); |
| charToGsm.put('\u00c6', i++); |
| charToGsm.put('\u00e6', i++); |
| charToGsm.put('\u00df', i++); |
| charToGsm.put('\u00c9', i++); |
| |
| charToGsm.put(' ', i++); |
| charToGsm.put('!', i++); |
| charToGsm.put('"', i++); |
| charToGsm.put('#', i++); |
| charToGsm.put('\u00a4', i++); |
| charToGsm.put('%', i++); |
| charToGsm.put('&', i++); |
| charToGsm.put('\'', i++); |
| charToGsm.put('(', i++); |
| charToGsm.put(')', i++); |
| charToGsm.put('*', i++); |
| charToGsm.put('+', i++); |
| charToGsm.put(',', i++); |
| charToGsm.put('-', i++); |
| charToGsm.put('.', i++); |
| charToGsm.put('/', i++); |
| |
| charToGsm.put('0', i++); |
| charToGsm.put('1', i++); |
| charToGsm.put('2', i++); |
| charToGsm.put('3', i++); |
| charToGsm.put('4', i++); |
| charToGsm.put('5', i++); |
| charToGsm.put('6', i++); |
| charToGsm.put('7', i++); |
| charToGsm.put('8', i++); |
| charToGsm.put('9', i++); |
| charToGsm.put(':', i++); |
| charToGsm.put(';', i++); |
| charToGsm.put('<', i++); |
| charToGsm.put('=', i++); |
| charToGsm.put('>', i++); |
| charToGsm.put('?', i++); |
| |
| charToGsm.put('\u00a1', i++); |
| charToGsm.put('A', i++); |
| charToGsm.put('B', i++); |
| charToGsm.put('C', i++); |
| charToGsm.put('D', i++); |
| charToGsm.put('E', i++); |
| charToGsm.put('F', i++); |
| charToGsm.put('G', i++); |
| charToGsm.put('H', i++); |
| charToGsm.put('I', i++); |
| charToGsm.put('J', i++); |
| charToGsm.put('K', i++); |
| charToGsm.put('L', i++); |
| charToGsm.put('M', i++); |
| charToGsm.put('N', i++); |
| charToGsm.put('O', i++); |
| |
| charToGsm.put('P', i++); |
| charToGsm.put('Q', i++); |
| charToGsm.put('R', i++); |
| charToGsm.put('S', i++); |
| charToGsm.put('T', i++); |
| charToGsm.put('U', i++); |
| charToGsm.put('V', i++); |
| charToGsm.put('W', i++); |
| charToGsm.put('X', i++); |
| charToGsm.put('Y', i++); |
| charToGsm.put('Z', i++); |
| charToGsm.put('\u00c4', i++); |
| charToGsm.put('\u00d6', i++); |
| charToGsm.put('\u0147', i++); |
| charToGsm.put('\u00dc', i++); |
| charToGsm.put('\u00a7', i++); |
| |
| charToGsm.put('\u00bf', i++); |
| charToGsm.put('a', i++); |
| charToGsm.put('b', i++); |
| charToGsm.put('c', i++); |
| charToGsm.put('d', i++); |
| charToGsm.put('e', i++); |
| charToGsm.put('f', i++); |
| charToGsm.put('g', i++); |
| charToGsm.put('h', i++); |
| charToGsm.put('i', i++); |
| charToGsm.put('j', i++); |
| charToGsm.put('k', i++); |
| charToGsm.put('l', i++); |
| charToGsm.put('m', i++); |
| charToGsm.put('n', i++); |
| charToGsm.put('o', i++); |
| |
| charToGsm.put('p', i++); |
| charToGsm.put('q', i++); |
| charToGsm.put('r', i++); |
| charToGsm.put('s', i++); |
| charToGsm.put('t', i++); |
| charToGsm.put('u', i++); |
| charToGsm.put('v', i++); |
| charToGsm.put('w', i++); |
| charToGsm.put('x', i++); |
| charToGsm.put('y', i++); |
| charToGsm.put('z', i++); |
| charToGsm.put('\u00e4', i++); |
| charToGsm.put('\u00f6', i++); |
| charToGsm.put('\u00f1', i++); |
| charToGsm.put('\u00fc', i++); |
| charToGsm.put('\u00e0', i++); |
| |
| |
| charToGsmExtended.put('\f', 10); |
| charToGsmExtended.put('^', 20); |
| charToGsmExtended.put('{', 40); |
| charToGsmExtended.put('}', 41); |
| charToGsmExtended.put('\\', 47); |
| charToGsmExtended.put('[', 60); |
| charToGsmExtended.put('~', 61); |
| charToGsmExtended.put(']', 62); |
| charToGsmExtended.put('|', 64); |
| charToGsmExtended.put('\u20ac', 101); |
| |
| int size = charToGsm.size(); |
| for (int j=0; j<size; j++) { |
| gsmToChar.put(charToGsm.valueAt(j), charToGsm.keyAt(j)); |
| } |
| |
| size = charToGsmExtended.size(); |
| for (int j=0; j<size; j++) { |
| gsmExtendedToChar.put(charToGsmExtended.valueAt(j), charToGsmExtended.keyAt(j)); |
| } |
| |
| |
| sGsmSpaceChar = charToGsm.get(' '); |
| } |
| |
| |
| } |