GsmAlphabetpublic class GsmAlphabet extends Object 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} |
Fields Summary |
---|
static final String | LOG_TAG | public static final byte | GSM_EXTENDED_ESCAPEThis 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 | private static int | sGsmSpaceChar | private static final android.util.SparseIntArray | charToGsm | private static final android.util.SparseIntArray | gsmToChar | private static final android.util.SparseIntArray | charToGsmExtended | private static final android.util.SparseIntArray | gsmExtendedToChar |
Methods Summary |
---|
public static int | charToGsm(char c)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
try {
return charToGsm(c, false);
} catch (EncodeException ex) {
// this should never happen
return sGsmSpaceChar;
}
| public static int | charToGsm(char c, boolean throwException)char to GSM alphabet char
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;
| public static int | charToGsmExtended(char c)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
int ret;
ret = charToGsmExtended.get(c, -1);
if (ret == -1) {
return sGsmSpaceChar;
}
return ret;
| public static int | countGsmSeptets(char c)Returns the count of 7-bit GSM alphabet characters
needed to represent this character. Counts unencodable char as 1 septet.
try {
return countGsmSeptets(c, false);
} catch (EncodeException ex) {
// This should never happen.
return 0;
}
| public static int | countGsmSeptets(char c, boolean throwsException)Returns the count of 7-bit GSM alphabet characters
needed to represent this character
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;
}
| public static int | countGsmSeptets(java.lang.CharSequence s)Returns the count of 7-bit GSM alphabet characters
needed to represent this string. Counts unencodable char as 1 septet.
try {
return countGsmSeptets(s, false);
} catch (EncodeException ex) {
// this should never happen
return 0;
}
| public static int | countGsmSeptets(java.lang.CharSequence s, boolean throwsException)Returns the count of 7-bit GSM alphabet characters
needed to represent this string.
int charIndex = 0;
int sz = s.length();
int count = 0;
while (charIndex < sz) {
count += countGsmSeptets(s.charAt(charIndex), throwsException);
charIndex++;
}
return count;
| public static int | findGsmSeptetLimitIndex(java.lang.String s, int start, int limit)Returns the index into s of the first character
after limit septets have been reached, starting at
index start . This is used when dividing messages
into units within the SMS message size 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;
| public static int | findLimitIndex(java.lang.String s, int start, int limit, int encodingType)Returns the index into s of the first character
after limit septets/octets have been reached
according to the encodingType , starting at
index start . This is used when dividing messages
units within the SMS message size limit.
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);
}
| public static int | findUCS2LimitIndex(java.lang.String s, int start, int limit)Returns the index into s of the first character
after limit octets have been reached, starting at
index start . This is used when dividing messages
in UCS2 encoding into units within the SMS message size limit.
int numCharToBeEncoded = s.length() - start;
return ((numCharToBeEncoded*2 > limit)? limit/2: numCharToBeEncoded) + start;
| public static java.lang.String | gsm7BitPackedToString(byte[] pdu, int offset, int lengthSeptets)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
return gsm7BitPackedToString(pdu, offset, lengthSeptets, 0);
| public static java.lang.String | gsm7BitPackedToString(byte[] pdu, int offset, int lengthSeptets, int numPaddingBits)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
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();
| public static java.lang.String | gsm8BitUnpackedToString(byte[] data, int offset, int length)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.
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();
| public static char | gsmExtendedToChar(int 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
int ret;
ret = gsmExtendedToChar.get(gsmChar, -1);
if (ret == -1) {
return ' ";
}
return (char)ret;
| public static char | gsmToChar(int gsmChar)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
return (char)gsmToChar.get(gsmChar, ' ");
| private static void | packSmsChar(byte[] packedChars, int bitOffset, int value)Pack a 7-bit char into its appropirate place in a byte array
int byteOffset = bitOffset / 8;
int shift = bitOffset % 8;
packedChars[++byteOffset] |= value << shift;
if (shift > 1) {
packedChars[++byteOffset] = (byte)(value >> (8 - shift));
}
| public static byte[] | stringToGsm7BitPacked(java.lang.String data)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.
return stringToGsm7BitPacked(data, 0, -1, 0, true);
| public static byte[] | stringToGsm7BitPacked(java.lang.String data, int dataOffset, int maxSeptets, int startingBitOffset, boolean throwException)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.
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;
| public static byte[] | stringToGsm7BitPackedWithHeader(java.lang.String data, byte[] header)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.
if (header == null || header.length == 0) {
return stringToGsm7BitPacked(data);
}
int headerBits = header.length * 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
System.arraycopy(header, 0, ret, 1, header.length);
return ret;
| public static byte[] | stringToGsm8BitPacked(java.lang.String s)Convert a string into an 8-bit unpacked GSM alphabet byte
array
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;
| public static void | stringToGsm8BitUnpackedField(java.lang.String s, byte[] dest, int offset, int length)Write a String into a GSM 8-bit unpacked field of
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;
}
|
|