All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.smpp.charset.Gsm7BitCharset Maven / Gradle / Ivy

The newest version!
package org.smpp.charset;

import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.util.HashMap;

import java.util.logging.Logger;

/**
 * A Charset implementation for Gsm 7-bit default and extended character set
 * See GSM 03.38
 * 
 * @author Sverker Abrahamsson
 * @version $Id: Gsm7BitCharset.java 90 2011-04-19 22:07:52Z sverkera $
 */
public class Gsm7BitCharset extends Charset {

	private boolean debug = false;
	
	// HashMap's used for encoding and decoding
	protected static HashMap defaultEncodeMap = new HashMap();
	protected static HashMap defaultDecodeMap = new HashMap();
	protected static HashMap extEncodeMap = new HashMap();
	protected static HashMap extDecodeMap = new HashMap();
	
	// Data to populate the hashmaps with
	private static final Object[][] gsmCharacters = { 
		{ "@",      new Byte((byte) 0x00) },
		{ "£",      new Byte((byte) 0x01) },
		{ "$",      new Byte((byte) 0x02) },
		{ "¥",      new Byte((byte) 0x03) },
		{ "è",      new Byte((byte) 0x04) },
		{ "é",      new Byte((byte) 0x05) },
		{ "ù",      new Byte((byte) 0x06) },
		{ "ì",      new Byte((byte) 0x07) },
		{ "ò",      new Byte((byte) 0x08) },
		{ "Ç",      new Byte((byte) 0x09) },
		{ "\n",     new Byte((byte) 0x0a) },
		{ "Ø",      new Byte((byte) 0x0b) },
		{ "ø",      new Byte((byte) 0x0c) },
		{ "\r",     new Byte((byte) 0x0d) },
		{ "Å",      new Byte((byte) 0x0e) },
		{ "å",      new Byte((byte) 0x0f) },
		{ "\u0394", new Byte((byte) 0x10) },
		{ "_",      new Byte((byte) 0x11) },
		{ "\u03A6", new Byte((byte) 0x12) },
		{ "\u0393", new Byte((byte) 0x13) },
		{ "\u039B", new Byte((byte) 0x14) },
		{ "\u03A9", new Byte((byte) 0x15) },
		{ "\u03A0", new Byte((byte) 0x16) },
		{ "\u03A8", new Byte((byte) 0x17) },
		{ "\u03A3", new Byte((byte) 0x18) },
		{ "\u0398", new Byte((byte) 0x19) },
		{ "\u039E", new Byte((byte) 0x1a) },
		{ "\u001B", new Byte((byte) 0x1b) }, // 27 is Escape character
		{ "Æ",      new Byte((byte) 0x1c) },
		{ "æ",      new Byte((byte) 0x1d) },
		{ "ß",      new Byte((byte) 0x1e) },
		{ "É",      new Byte((byte) 0x1f) },
		{ "\u0020", new Byte((byte) 0x20) },
		{ "!",      new Byte((byte) 0x21) },
		{ "\"",     new Byte((byte) 0x22) },
		{ "#",      new Byte((byte) 0x23) },
		{ "¤",      new Byte((byte) 0x24) },
		{ "%",      new Byte((byte) 0x25) },
		{ "&",      new Byte((byte) 0x26) },
		{ "'",      new Byte((byte) 0x27) },
		{ "(",      new Byte((byte) 0x28) },
		{ ")",      new Byte((byte) 0x29) },
		{ "*",      new Byte((byte) 0x2a) },
		{ "+",      new Byte((byte) 0x2b) },
		{ ",",      new Byte((byte) 0x2c) },
		{ "-",      new Byte((byte) 0x2d) },
		{ ".",      new Byte((byte) 0x2e) },
		{ "/",      new Byte((byte) 0x2f) },
		{ "0",      new Byte((byte) 0x30) },
		{ "1",      new Byte((byte) 0x31) },
		{ "2",      new Byte((byte) 0x32) },
		{ "3",      new Byte((byte) 0x33) },
		{ "4",      new Byte((byte) 0x34) },
		{ "5",      new Byte((byte) 0x35) },
		{ "6",      new Byte((byte) 0x36) },
		{ "7",      new Byte((byte) 0x37) },
		{ "8",      new Byte((byte) 0x38) },
		{ "9",      new Byte((byte) 0x39) },
		{ ":",      new Byte((byte) 0x3a) },
		{ ";",      new Byte((byte) 0x3b) },
		{ "<",      new Byte((byte) 0x3c) },
		{ "=",      new Byte((byte) 0x3d) },
		{ ">",      new Byte((byte) 0x3e) },
		{ "?",      new Byte((byte) 0x3f) },
		{ "¡",      new Byte((byte) 0x40) },
		{ "A",      new Byte((byte) 0x41) },
		{ "B",      new Byte((byte) 0x42) },
		{ "C",      new Byte((byte) 0x43) },
		{ "D",      new Byte((byte) 0x44) },
		{ "E",      new Byte((byte) 0x45) },
		{ "F",      new Byte((byte) 0x46) },
		{ "G",      new Byte((byte) 0x47) },
		{ "H",      new Byte((byte) 0x48) },
		{ "I",      new Byte((byte) 0x49) },
		{ "J",      new Byte((byte) 0x4a) },
		{ "K",      new Byte((byte) 0x4b) },
		{ "L",      new Byte((byte) 0x4c) },
		{ "M",      new Byte((byte) 0x4d) },
		{ "N",      new Byte((byte) 0x4e) },
		{ "O",      new Byte((byte) 0x4f) },
		{ "P",      new Byte((byte) 0x50) },
		{ "Q",      new Byte((byte) 0x51) },
		{ "R",      new Byte((byte) 0x52) },
		{ "S",      new Byte((byte) 0x53) },
		{ "T",      new Byte((byte) 0x54) },
		{ "U",      new Byte((byte) 0x55) },
		{ "V",      new Byte((byte) 0x56) },
		{ "W",      new Byte((byte) 0x57) },
		{ "X",      new Byte((byte) 0x58) },
		{ "Y",      new Byte((byte) 0x59) },
		{ "Z",      new Byte((byte) 0x5a) },
		{ "Ä",      new Byte((byte) 0x5b) },
		{ "Ö",      new Byte((byte) 0x5c) },
		{ "Ñ",      new Byte((byte) 0x5d) },
		{ "Ü",      new Byte((byte) 0x5e) },
		{ "§",      new Byte((byte) 0x5f) },
		{ "¿",      new Byte((byte) 0x60) },
		{ "a",      new Byte((byte) 0x61) },
		{ "b",      new Byte((byte) 0x62) },
		{ "c",      new Byte((byte) 0x63) },
		{ "d",      new Byte((byte) 0x64) },
		{ "e",      new Byte((byte) 0x65) },
		{ "f",      new Byte((byte) 0x66) },
		{ "g",      new Byte((byte) 0x67) },
		{ "h",      new Byte((byte) 0x68) },
		{ "i",      new Byte((byte) 0x69) },
		{ "j",      new Byte((byte) 0x6a) },
		{ "k",      new Byte((byte) 0x6b) },
		{ "l",      new Byte((byte) 0x6c) },
		{ "m",      new Byte((byte) 0x6d) },
		{ "n",      new Byte((byte) 0x6e) },
		{ "o",      new Byte((byte) 0x6f) },
		{ "p",      new Byte((byte) 0x70) },
		{ "q",      new Byte((byte) 0x71) },
		{ "r",      new Byte((byte) 0x72) },
		{ "s",      new Byte((byte) 0x73) },
		{ "t",      new Byte((byte) 0x74) },
		{ "u",      new Byte((byte) 0x75) },
		{ "v",      new Byte((byte) 0x76) },
		{ "w",      new Byte((byte) 0x77) },
		{ "x",      new Byte((byte) 0x78) },
		{ "y",      new Byte((byte) 0x79) },
		{ "z",      new Byte((byte) 0x7a) },
		{ "ä",      new Byte((byte) 0x7b) },
		{ "ö",      new Byte((byte) 0x7c) },
		{ "ñ",      new Byte((byte) 0x7d) },
		{ "ü",      new Byte((byte) 0x7e) },
		{ "à",      new Byte((byte) 0x7f) }
	};

	private static final Object[][] gsmExtensionCharacters = { 
		{ "\n", new Byte((byte) 0x0a) },
		{ "^",  new Byte((byte) 0x14) },
		{ " ",  new Byte((byte) 0x1b) }, // reserved for future extensions
		{ "{",  new Byte((byte) 0x28) },
		{ "}",  new Byte((byte) 0x29) },
		{ "\\", new Byte((byte) 0x2f) },
		{ "[",  new Byte((byte) 0x3c) },
		{ "~",  new Byte((byte) 0x3d) },
		{ "]",  new Byte((byte) 0x3e) },
		{ "|",  new Byte((byte) 0x40) },
		{ "€",  new Byte((byte) 0x65) }
	};

	private static Logger logger = Logger.getLogger(Gsm7BitCharset.class.getName());
	
	// static section that populates the encode and decode HashMap objects
	static {
		// default alphabet
		int len = gsmCharacters.length;
		for (int i = 0; i < len; i++) {
			Object[] map = gsmCharacters[i];
			defaultEncodeMap.put((String) map[0], (Byte) map[1]);
			defaultDecodeMap.put((Byte) map[1], (String) map[0]);
		}

		// extended alphabet
		len = gsmExtensionCharacters.length;
		for (int i = 0; i < len; i++) {
			Object[] map = gsmExtensionCharacters[i];
			extEncodeMap.put((String) map[0], (Byte) map[1]);
			extDecodeMap.put((Byte) map[1], (String) map[0]);
		}
	}

	/**
	 * Constructor for the Gsm7Bit charset.  Call the superclass
	 * constructor to pass along the name(s) we'll be known by.
	 * Then save a reference to the delegate Charset.
	 */
	protected Gsm7BitCharset(String canonical, String[] aliases) {
		super(canonical, aliases);
	}

	// ----------------------------------------------------------

	/**
	 * Called by users of this Charset to obtain an encoder.
	 * This implementation instantiates an instance of a private class
	 * (defined below) and passes it an encoder from the base Charset.
	 */
	public CharsetEncoder newEncoder() {
		return new Gsm7BitEncoder(this);
	}

	/**
	 * Called by users of this Charset to obtain a decoder.
	 * This implementation instantiates an instance of a private class
	 * (defined below) and passes it a decoder from the base Charset.
	 */
	public CharsetDecoder newDecoder() {
		return new Gsm7BitDecoder(this);
	}

	/**
	 * This method must be implemented by concrete Charsets.  We always
	 * say no, which is safe.
	 */
	public boolean contains(Charset cs) {
		return (false);
	}

	/**
	 * The encoder implementation for the Gsm7Bit Charset.
	 * This class, and the matching decoder class below, should also
	 * override the "impl" methods, such as implOnMalformedInput() and
	 * make passthrough calls to the baseEncoder object.  That is left
	 * as an exercise for the hacker.
	 */
	private class Gsm7BitEncoder extends CharsetEncoder {

		/**
		 * Constructor, call the superclass constructor with the
		 * Charset object and the encodings sizes from the
		 * delegate encoder.
		 */
		Gsm7BitEncoder(Charset cs) {
			super(cs, 1, 2);
		}

		/**
		 * Implementation of the encoding loop.
		 */
		protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) {
			CoderResult cr = CoderResult.UNDERFLOW;

			while (cb.hasRemaining()) {
				if (!bb.hasRemaining()) {
					cr = CoderResult.OVERFLOW;
					break;
				}
				char ch = cb.get();

				// first check the default alphabet
				Byte b = (Byte) defaultEncodeMap.get("" + ch);
				if(debug)
					logger.finest("Encoding ch " + ch + " to byte " + b);
				if (b != null) {
					bb.put((byte) b.byteValue());
				} else {
					// check extended alphabet
					b = (Byte) extEncodeMap.get("" + ch);
					if(debug)
						logger.finest("Trying extended map to encode ch " + ch + " to byte " + b);
					if (b != null) {
						// since the extended character set takes two bytes 
						// we have to check that there is enough space left
						if (bb.remaining() < 2) {
							// go back one step
							cb.position(cb.position() - 1);
							cr = CoderResult.OVERFLOW;
							break;
						}
						// all ok, add it to the buffer
						bb.put((byte) 0x1b);
						bb.put((byte) b.byteValue());
					} else {
						// no match found, send a ?
						b = new Byte((byte) 0x3F);
						bb.put((byte) b.byteValue());
					}
				}
			}
			return cr;
		}
	}

	// --------------------------------------------------------

	/**
	 * The decoder implementation for the Gsm 7Bit Charset.
	 */
	private class Gsm7BitDecoder extends CharsetDecoder {

		/**
		 * Constructor, call the superclass constructor with the
		 * Charset object and pass alon the chars/byte values
		 * from the delegate decoder.
		 */
		Gsm7BitDecoder(Charset cs) {
			super(cs, 1, 1);
		}

		/**
		 * Implementation of the decoding loop.
		 */
		protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb) {
			CoderResult cr = CoderResult.UNDERFLOW;

			while (bb.hasRemaining()) {
				if (!cb.hasRemaining()) {
					cr = CoderResult.OVERFLOW;
					break;
				}
				byte b = bb.get();

				// first check the default alphabet
				if(debug)
					logger.finest("Looking up byte " + b);
				String s = (String) defaultDecodeMap.get(new Byte(b));
				if (s != null) {
					char ch = s.charAt(0);
					if (ch != '\u001B') {
						if(debug)
							logger.finest("Found string " + s);
						cb.put(ch);
					} else {
						if(debug)
							logger.finest("Found escape character");
						// check the extended alphabet
						if (bb.hasRemaining()) {
							b = bb.get();
							s = (String) extDecodeMap.get(new Byte(b));
							if (s != null) {
								if(debug)
									logger.finest("Found extended string " + s);
								ch = s.charAt(0);
								cb.put(ch);
							} else {
								cb.put('?');
							}
						}
					}
				} else {
					cb.put('?');
				}
			}
			return cr;
		}
	}
}

/*
 * $Log: not supported by cvs2svn $
 * Revision 1.2  2006/03/09 16:24:14  sverkera
 * Removed compiler and javadoc warnings
 *
 * Revision 1.1  2003/09/30 09:02:09  sverkera
 * Added implementation for GSM 7Bit charset
 *
 */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy