org.restcomm.protocols.ss7.map.datacoding.GSMCharset Maven / Gradle / Ivy
/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.restcomm.protocols.ss7.map.datacoding;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import org.restcomm.protocols.ss7.map.api.datacoding.NationalLanguageIdentifier;
/**
*
* The encoding/decoding of 7 bits characters in USSD strings is used doing GSMCharset.
*
*
*
* For further details look at GSM 03.38 Specs
*
*
* @author amit bhayani
* @author sergey vetyutnev
*
*/
public class GSMCharset extends Charset {
public static final String GSM_CANONICAL_NAME = "GSM";
protected static final float averageCharsPerByte = 8 / 7f;
protected static final float maxCharsPerByte = 2f;
protected static final float averageBytesPerChar = 2f;
protected static final float maxBytesPerChar = 2f;
protected static final int BUFFER_SIZE = 256;
public static final byte ESCAPE = 0x1B;
protected int[] mainTable;
protected int[] extensionTable;
public GSMCharset(String canonicalName, String[] aliases) {
this(canonicalName, aliases, BYTE_TO_CHAR_DefaultAlphabet, BYTE_TO_CHAR_DefaultAlphabetExtentionTable);
}
public GSMCharset(String canonicalName, String[] aliases, int[] mainTable, int[] extentionTable) {
super(canonicalName, aliases);
this.mainTable = mainTable;
this.extensionTable = extentionTable;
}
public GSMCharset(String canonicalName, String[] aliases,
NationalLanguageIdentifier nationalLanguageLockingShiftIdentifier,
NationalLanguageIdentifier nationalLanguageSingleShiftIdentifier) {
super(canonicalName, aliases);
// TODO: after implementing National Language Shift Tables make here selection depending on nationalLanguageIdentifier
// nationalLanguageLockingShift and nationalLanguageIdentifierSingleShift can be ==null
if (nationalLanguageLockingShiftIdentifier == null) {
this.mainTable = BYTE_TO_CHAR_DefaultAlphabet;
} else {
switch (nationalLanguageLockingShiftIdentifier) {
case Urdu:
this.mainTable = BYTE_TO_CHAR_UrduAlphabet;
break;
default:
this.mainTable = BYTE_TO_CHAR_DefaultAlphabet;
break;
}
}
if (nationalLanguageSingleShiftIdentifier == null) {
this.extensionTable = BYTE_TO_CHAR_DefaultAlphabetExtentionTable;
} else
switch (nationalLanguageSingleShiftIdentifier) {
case Urdu:
this.extensionTable = BYTE_TO_CHAR_UrduAlphabetExtentionTable;
break;
default:
this.extensionTable = BYTE_TO_CHAR_DefaultAlphabetExtentionTable;
break;
}
}
@Override
public boolean contains(Charset cs) {
return this.getClass().isInstance(cs);
}
@Override
public CharsetDecoder newDecoder() {
return new GSMCharsetDecoder(this, averageCharsPerByte, maxCharsPerByte);
}
@Override
public CharsetEncoder newEncoder() {
return new GSMCharsetEncoder(this, averageBytesPerChar, maxBytesPerChar);
}
/**
* Returns true if all characters in data String is included in main and extension encoding tables of the GSM7 charset
*
* @param data
* @return
*/
public boolean checkAllCharsCanBeEncoded(String data) {
return checkAllCharsCanBeEncoded(data, this.mainTable, this.extensionTable);
}
/**
* Returns true if all characters in data String is included in main and extension encoding tables of the GSM7 charset
*
* @param data
* @return
*/
public static boolean checkAllCharsCanBeEncoded(String data, int[] mainTable, int[] extentionTable) {
if (data == null)
return true;
if (mainTable == null)
return false;
for (int i1 = 0; i1 < data.length(); i1++) {
char c = data.charAt(i1);
boolean found = false;
for (int i = 0; i < mainTable.length; i++) {
if (mainTable[i] == c) {
found = true;
break;
}
}
if (!found && extentionTable != null) {
for (int i = 0; i < extentionTable.length; i++) {
if (c != 0 && extentionTable[i] == c) {
found = true;
break;
}
}
}
if (!found)
return false;
}
return true;
}
/**
* Returns a count in characters / septets of the data String after which the String will be GSM7 style encoded. For all
* characters from the extension character table two bytes will be reserved. For all characters from the main character
* table or which are not present in main or extension character tables one byte will be reserved.
*
* @param data
* @return
*/
public int checkEncodedDataLengthInChars(String data) {
return checkEncodedDataLengthInChars(data, this.mainTable, this.extensionTable);
}
/**
* Returns a count in characters / septets of the data String after which the String will be GSM7 style encoded. For all
* characters from the extension character table two bytes will be reserved. For all characters from the main character
* table or which are not present in main or extension character tables one byte will be reserved.
*
* @param data
* @return
*/
public static int checkEncodedDataLengthInChars(String data, int[] mainTable, int[] extentionTable) {
if (data == null)
return 0;
if (mainTable == null)
return 0;
int cnt = 0;
for (int i1 = 0; i1 < data.length(); i1++) {
char c = data.charAt(i1);
boolean found = false;
for (int i = 0; i < mainTable.length; i++) {
if (mainTable[i] == c) {
found = true;
cnt++;
break;
}
}
if (!found && extentionTable != null) {
for (int i = 0; i < extentionTable.length; i++) {
if (c != 0 && extentionTable[i] == c) {
found = true;
cnt += 2;
break;
}
}
}
if (!found)
cnt++;
}
return cnt;
}
/**
* Calculates how many octets encapsulate the provides septets count.
*
* @param data
* @return
*/
public static int septetsToOctets(int septCnt) {
int byteCnt = (septCnt + 1) * 7 / 8;
return byteCnt;
}
/**
* Calculates how many septets are encapsulated in the provides octets count.
*
* @param data
* @return
*/
public static int octetsToSeptets(int byteCnt) {
int septCnt = (byteCnt * 8 - 1) / 7 + 1;
return septCnt;
}
/**
* Slicing of a data String into substrings that fits to characters / septets count in charCount parameter.
*
* @param data
* @return
*/
public String[] sliceString(String data, int charCount) {
return sliceString(data, charCount, this.mainTable, this.extensionTable);
}
/**
* Slicing of a data String into substrings that fits to characters / septets count in charCount parameter.
*
* @param data
* @return
*/
public static String[] sliceString(String data, int charCount, int[] mainTable, int[] extentionTable) {
if (data == null)
return null;
if (mainTable == null)
return null;
ArrayList res = new ArrayList();
StringBuilder sb = new StringBuilder();
int chCnt = 0;
for (int i1 = 0; i1 < data.length(); i1++) {
char c = data.charAt(i1);
boolean found = false;
for (int i = 0; i < mainTable.length; i++) {
if (mainTable[i] == c) {
found = true;
chCnt++;
if (chCnt > charCount) {
chCnt = 1;
res.add(sb.toString());
sb = new StringBuilder();
}
sb.append(c);
break;
}
}
if (!found && extentionTable != null) {
for (int i = 0; i < extentionTable.length; i++) {
if (extentionTable[i] == c) {
found = true;
chCnt += 2;
if (chCnt > charCount) {
chCnt = 2;
res.add(sb.toString());
sb = new StringBuilder();
}
sb.append(c);
break;
}
}
}
if (!found) {
chCnt++;
if (chCnt > charCount) {
chCnt = 1;
res.add(sb.toString());
sb = new StringBuilder();
}
sb.append(c);
}
}
res.add(sb.toString());
String[] arr = new String[res.size()];
res.toArray(arr);
return arr;
}
// Look at http://www.unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT
public static final int[] BYTE_TO_CHAR_DefaultAlphabet = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5, 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9,
0x03A0, 0x03A8, 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023,
0x00A4, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031,
0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
0x00A1, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D,
0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4,
0x00D6, 0x00D1, 0x00DC, 0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 };
public static final int[] BYTE_TO_CHAR_DefaultAlphabetExtentionTable = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x000C, 0x0000, 0x0000, 0x000D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x005E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x007B, 0x007D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x005C,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x005B, 0x007E,
0x005D, 0x0000, 0x007C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20AC, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, };
public static final int[] BYTE_TO_CHAR_UrduAlphabet = { 0x0627, 0x0622, 0x0628, 0x067B, 0x0680, 0x067E, 0x06A6, 0x062A,
0x06C2, 0x067F, 0x000A, 0x0679, 0x067D, 0x000D, 0x067A, 0x067C, 0x062B, 0x062C, 0x0681, 0x0684, 0x0683, 0x0685,
0x0686, 0x0687, 0x062D, 0x062E, 0x062F, 0x00A0, 0x068C, 0x0688, 0x0689, 0x068A, 0x0020, 0x0021, 0x068F, 0x068D,
0x0630, 0x0631, 0x0691, 0x0693, 0x0028, 0x0029, 0x0699, 0x0632, 0x002C, 0x0696, 0x002E, 0x0698, 0x0030, 0x0031,
0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x069A, 0x0633, 0x0634, 0x003F,
0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x0641, 0x0642, 0x06A9, 0x06AA, 0x06AB, 0x06AF, 0x06B3, 0x06B1, 0x0644,
0x0645, 0x0646, 0x06BA, 0x06BB, 0x06BC, 0x0648, 0x06C4, 0x06D5, 0x06C1, 0x06BE, 0x0621, 0x06CC, 0x06D0, 0x06D2,
0x064D, 0x0650, 0x064F, 0x0657, 0x0657, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x0655, 0x0651, 0x0653, 0x0656, 0x0670 };
public static final int[] BYTE_TO_CHAR_UrduAlphabetExtentionTable = { 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00BF, 0x0022,
0x00A4, 0x0025, 0x0026, 0x0027, 0x000C, 0x002A, 0x002B, 0x000D, 0x002D, 0x002F, 0x003C, 0x003D, 0x003E, 0x00A1,
0x005E, 0x00A1, 0x005F, 0x0023, 0x002A, 0x0600, 0x0601, 0x0000, 0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5,
0x06F6, 0x06F7, 0x06F8, 0x06F9, 0x060C, 0x060D, 0x007B, 0x007D, 0x060E, 0x060F, 0x0610, 0x0611, 0x0612, 0x005C,
0x0613, 0x0614, 0x061B, 0x061F, 0x0640, 0x0652, 0x0658, 0x066B, 0x066C, 0x0672, 0x0673, 0x06CD, 0x005B, 0x007E,
0x005D, 0x06D4, 0x007C, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B,
0x004C, 0x004E, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20AC, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, };
}