18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "gsm.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** UTILITIES
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbyte_t
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_int_to_bcdi( int  value )
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (byte_t)((value / 10) | ((value % 10) << 4));
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_int_from_bcdi( byte_t  val )
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  ret = 0;
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((val & 0xf0) <= 0x90)
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = (val >> 4);
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((val & 0x0f) <= 0x90)
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret |= (val % 0xf)*10;
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_bcdi_to_ascii( cbytes_t  bcd, int  bcdlen, bytes_t  dst )
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static byte_t  bcdichars[14] = "0123456789*#,N";
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = 0;
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  shift  = 0;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (bcdlen > 0) {
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = (bcd[0] >> shift) & 0xf;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == 0xf && bcdlen == 1)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 14) {
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst) dst[result] = bcdichars[c];
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += 1;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bcdlen --;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift += 4;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 8) {
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bcd++;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 0;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_bcdi_from_ascii( cbytes_t  ascii, int  asciilen, bytes_t  dst )
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end    = ascii + asciilen;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = 0;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       phase  = 0x01;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (ascii < end) {
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *ascii++;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == '*')
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 11;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '#')
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 12;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == ',')
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 13;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == 'N')
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 14;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c -= '0';
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((unsigned)c >= 10)
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        phase = (phase << 4) | c;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (phase & 0x100) {
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst) dst[result] = (byte_t) phase;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += 1;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phase   = 0x01;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (phase != 0x01) {
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst) dst[result] = (byte_t)( phase | 0xf0 );
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 1;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hexchar_to_int( char  c )
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((unsigned)(c - '0') < 10)
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return c - '0';
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((unsigned)(c - 'a') < 6)
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 10 + (c - 'a');
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((unsigned)(c - 'A') < 6)
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 10 + (c - 'A');
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hexchar_to_int0( char  c )
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  ret = gsm_hexchar_to_int(c);
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (ret < 0) ? 0 : ret;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex2_to_byte( const char*  hex )
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  hi = gsm_hexchar_to_int(hex[0]);
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  lo = gsm_hexchar_to_int(hex[1]);
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hi < 0 || lo < 0)
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ( (hi << 4) | lo );
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex4_to_short( const char*  hex )
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  hi = gsm_hex2_to_byte(hex);
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  lo = gsm_hex2_to_byte(hex+2);
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hi < 0 || lo < 0)
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ((hi << 8) | lo);
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex2_to_byte0( const char*  hex )
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  hi = gsm_hexchar_to_int0(hex[0]);
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  lo = gsm_hexchar_to_int0(hex[1]);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (byte_t)( (hi << 4) | lo );
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex_from_byte( char*  hex, int val )
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char  hexdigits[] = "0123456789abcdef";
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hex[0] = hexdigits[(val >> 4) & 15];
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hex[1] = hexdigits[val & 15];
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex_from_short( char*  hex, int  val )
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_hex_from_byte( hex,   (val >> 8) );
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_hex_from_byte( hex+2, val );
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** HEX
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex_to_bytes0( cbytes_t  hex, int  hexlen, bytes_t  dst )
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < hexlen/2; nn++ ) {
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[nn] = (byte_t) gsm_hex2_to_byte0( (const char*)hex+2*nn );
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen & 1) {
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[nn] = gsm_hexchar_to_int0( hex[2*nn] ) << 4;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex_to_bytes( cbytes_t  hex, int  hexlen, bytes_t  dst )
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen & 1)  /* must be even */
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < hexlen/2; nn++ ) {
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = gsm_hex2_to_byte( (const char*)hex+2*nn );
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0) return -1;
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[nn] = (byte_t) c;
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return hexlen/2;
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_hex_from_bytes( char*  hex, cbytes_t  src, int  srclen )
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < srclen; nn++) {
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gsm_hex_from_byte( hex + 2*nn, src[nn] );
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** ROPES
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_init( GsmRope  rope )
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->data  = NULL;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos   = 0;
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->max   = 0;
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->error = 0;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_init_alloc( GsmRope  rope, int  count )
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->data  = rope->data0;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos   = 0;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->max   = sizeof(rope->data0);
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->error = 0;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->data = calloc( count, 1 );
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->max  = count;
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rope->data == NULL) {
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rope->error = 1;
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rope->max   = 0;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_done( GsmRope  rope )
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = rope->error;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rope->data && rope->data != rope->data0)
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free(rope->data);
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->data  = NULL;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos   = 0;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->max   = 0;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->error = 0;
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbytes_t
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_done_acquire( GsmRope  rope, int  *psize )
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t  result = rope->data;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *psize = rope->pos;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (result == rope->data0) {
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = malloc(  rope->pos );
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (result != NULL)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy( result, rope->data, rope->pos );
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_ensure( GsmRope  rope, int  new_count )
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rope->data != NULL) {
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       old_max  = rope->max;
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bytes_t   old_data = rope->data == rope->data0 ? NULL : rope->data;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       new_max  = old_max;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bytes_t   new_data;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (new_max < new_count) {
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            new_max += (new_max >> 1) + 4;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_data = realloc( old_data, new_max );
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (new_data == NULL) {
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rope->error = 1;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->data = new_data;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->max  = new_max;
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->max = new_count;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_can_grow( GsmRope  rope, int  count )
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!rope->data || rope->error)
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rope->pos + count > rope->max)
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rope->data == NULL)
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rope->max = rope->pos + count;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (rope->error ||
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 gsm_rope_ensure( rope, rope->pos + count ) < 0)
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add_c( GsmRope  rope,  char  c )
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_rope_can_grow(rope, 1)) {
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rope->data[ rope->pos ] = (byte_t) c;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos += 1;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add( GsmRope  rope, const void*  buf, int  buflen )
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_rope_can_grow(rope, buflen)) {
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy( rope->data + rope->pos, (const char*)buf, buflen );
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos += buflen;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid*
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_reserve( GsmRope  rope, int  count )
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void*  result = NULL;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_rope_can_grow(rope, count))
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rope->data != NULL)
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result = rope->data + rope->pos;
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rope->pos += count;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* skip a given number of Unicode characters in a utf-8 byte string */
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcbytes_t
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_skip( cbytes_t   utf8,
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           cbytes_t   utf8end,
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           int        count)
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p   = utf8;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end = utf8end;
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; count > 0; count-- ) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p >= end)
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = *p++;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c > 128) {
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80)
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p++;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  p;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic __inline__ int
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_next( cbytes_t  *pp, cbytes_t  end )
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p      = *pp;
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p < end) {
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c= *p++;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p ++;
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = c;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pp    = p;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project__inline__ int
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_write( bytes_t  utf8, int  offset, int  v )
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (v < 128) {
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 1;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (utf8)
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset] = (byte_t) v;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (v < 0x800) {
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 2;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (utf8) {
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+0] = (byte_t)( 0xc0 | (v >> 6) );
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+1] = (byte_t)( 0x80 | (v & 0x3f) );
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (v < 0x10000) {
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 3;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (utf8) {
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+0] = (byte_t)( 0xe0 |  (v >> 12) );
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+1] = (byte_t)( 0x80 | ((v >> 6) & 0x3f) );
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+2] = (byte_t)( 0x80 |  (v & 0x3f) );
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 4;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (utf8) {
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+0] = (byte_t)( 0xf0 | ((v >> 18) & 0x7) );
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+1] = (byte_t)( 0x80 | ((v >> 12) & 0x3f) );
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+2] = (byte_t)( 0x80 | ((v >> 6) & 0x3f) );
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8[offset+3] = (byte_t)( 0x80 |  (v & 0x3f) );
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic __inline__ int
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectucs2_write( bytes_t  ucs2, int  offset, int  v )
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ucs2) {
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ucs2[offset+0] = (byte_t) (v >> 8);
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ucs2[offset+1] = (byte_t) (v);
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 2;
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_check( cbytes_t   p, int  utf8len )
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end    = p + utf8len;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = 0;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p) {
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (p < end) {
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  c = *p++;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (c >= 128) {
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  len;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((c & 0xe0) == 0xc0) {
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    len = 1;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else if ((c & 0xf0) == 0xe0) {
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    len = 2;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else if ((c & 0xf8) == 0xf0) {
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    len = 3;
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Exit;  /* malformed utf-8 */
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (p+len > end) /* string too short */
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Exit;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for ( ; len > 0; len--, p++ ) {
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((p[0] & 0xc0) != 0x80)
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto Exit;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 1;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** UCS2 to UTF8
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* convert a UCS2 string into a UTF8 byte string, assumes 'buf' is correctly sized */
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectucs2_to_utf8( cbytes_t  ucs2,
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              int       ucs2len,
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              bytes_t   buf )
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = 0;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < ucs2len; ucs2 += 2, nn++) {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c= (ucs2[0] << 8) | ucs2[1];
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += utf8_write(buf, result, c);
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* count the number of UCS2 chars contained in a utf8 byte string */
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_to_ucs2( cbytes_t  utf8,
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              int       utf8len,
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              bytes_t   ucs2 )
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p      = utf8;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end    = p + utf8len;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = 0;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end) {
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next(&p, end);
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0)
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += ucs2_write(ucs2, result, c);
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result/2;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** GSM ALPHABET
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  GSM_7BITS_ESCAPE   0x1b
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  GSM_7BITS_UNKNOWN  0
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const unsigned short   gsm7bits_to_unicode[128] = {
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  '@', 0xa3,  '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project0x394,  '_',0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,0x3a3,0x398,0x39e,    0, 0xc6, 0xe6, 0xdf, 0xc9,
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  ' ',  '!',  '"',  '#', 0xa4,  '%',  '&', '\'',  '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0xa1,  'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z', 0xc4, 0xd6,0x147, 0xdc, 0xa7,
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0xbf,  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0,
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const unsigned short  gsm7bits_extend_to_unicode[128] = {
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\f',   0,   0,   0,   0,   0,
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0, '^',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,   0,   0,   0, '{', '}',   0,   0,   0,   0,   0,'\\',
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, '[', '~', ']',   0,
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  '|',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,0x20ac, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectunichar_to_gsm7( int  unicode )
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < 128; nn++) {
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (gsm7bits_to_unicode[nn] == unicode) {
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return nn;
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectunichar_to_gsm7_extend( int  unichar )
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < 128; nn++) {
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (gsm7bits_extend_to_unicode[nn] == unichar) {
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return nn;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return the number of septets needed to encode a unicode charcode */
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectunichar_to_gsm7_count( int  unicode )
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nn = unichar_to_gsm7(unicode);
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn >= 0)
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nn = unichar_to_gsm7_extend(unicode);
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn >= 0)
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 2;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcbytes_t
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_skip_gsm7( cbytes_t  utf8, cbytes_t  utf8end, int  gsm7len )
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p   = utf8;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end = utf8end;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (gsm7len >0) {
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t  q = p;
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       c = utf8_next( &q, end );
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       len;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0)
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = unichar_to_gsm7_count( c );
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len == 0)  /* unknown chars are replaced by spaces */
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = 1;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len > gsm7len)
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gsm7len -= len;
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p        = q;
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  p;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_check_gsm7( cbytes_t  utf8,
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 int       utf8len )
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  utf8end = utf8 + utf8len;
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (utf8 < utf8end) {
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &utf8, utf8end );
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (unichar_to_gsm7_count(c) == 0)
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_from_gsm7( cbytes_t  src,
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int       septet_offset,
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int       septet_count,
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                bytes_t   utf8 )
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  shift   = (septet_offset & 7);
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  escaped = 0;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result  = 0;
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    src += (septet_offset >> 3);
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; septet_count > 0; septet_count-- )
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = (src[0] >> shift) & 0x7f;
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  v;
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift > 1) {
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = ((src[1] << (8-shift)) | c) & 0x7f;
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (escaped) {
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            v = gsm7bits_extend_to_unicode[c];
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (c == GSM_7BITS_ESCAPE) {
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escaped = 1;
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto NextSeptet;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            v = gsm7bits_to_unicode[c];
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += utf8_write( utf8, result, v );
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NextSeptet:
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift += 7;
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift >= 8) {
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift -= 8;
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            src   += 1;
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_from_gsm8( cbytes_t  src, int  count, bytes_t  utf8 )
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result  = 0;
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  escaped = 0;
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; count > 0; count-- )
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *src++;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == 0xff)
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == GSM_7BITS_ESCAPE) {
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (escaped) { /* two escape characters => one space */
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = 0x20;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                escaped = 0;
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                escaped = 1;
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                continue;
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (c >= 0x80) {
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c       = 0x20;
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                escaped = 0;
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (escaped) {
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = gsm7bits_extend_to_unicode[c];
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = gsm7bits_to_unicode[c];
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += utf8_write( utf8, result, c );
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* convert a GSM 7-bit message into a unicode character array
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the 'dst' array must contain at least 160 chars. the function
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * returns the number of characters decoded
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * assumes the 'dst' array has at least septet_count items, returns the
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * number of unichars really written
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectucs2_from_gsm7( bytes_t   ucs2,
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cbytes_t  src,
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int       septet_offset,
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int       septet_count )
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const unsigned char*  p     = src + (septet_offset >> 3);
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                   shift = (septet_offset & 7);
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                   escaped = 0;
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                   result  = 0;
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; septet_count > 0; septet_count-- )
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned  val  = (p[0] >> shift) & 0x7f;
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift > 1)
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (val | (p[1] << (8-shift))) & 0x7f;
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (escaped) {
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  c = gsm7bits_to_unicode[val];
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += ucs2_write(ucs2, result, c);
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escaped = 0;
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (val == GSM_7BITS_ESCAPE) {
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escaped = 1;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = gsm7bits_extend_to_unicode[val];
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (val == 0)
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = 0x20;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += ucs2_write( ucs2, result, val );
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result/2;
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* count the number of septets required to write a utf8 string */
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_to_gsm7_count( cbytes_t  utf8, int  utf8len )
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  utf8end = utf8 + utf8len;
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result  = 0;
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while ( utf8 < utf8end ) {
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  len;
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &utf8, utf8end );
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0)
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = unichar_to_gsm7_count(c);
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len == 0)    /* replace non-representables with space */
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = 1;
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += len;
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t   dst;
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned  pad;
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       bits;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       offset;
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} BWriterRec, *BWriter;
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbwriter_init( BWriter  writer, bytes_t  dst, int  start )
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  shift = start & 7;
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->dst    = dst + (start >> 3);
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->pad    = 0;
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->bits   = shift;
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->offset = start;
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift > 0) {
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->pad  = writer->dst[0] & ~(0xFF << shift);
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbwriter_add7( BWriter  writer, unsigned  value )
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->pad  |= (unsigned)(value << writer->bits);
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->bits += 7;
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (writer->bits >= 8) {
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->dst[0] = (byte_t)writer->pad;
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->bits  -= 8;
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->pad  >>= 8;
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->dst   += 1;
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    writer->offset += 7;
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbwriter_done( BWriter  writer )
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (writer->bits > 0) {
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->dst[0] = (byte_t)writer->pad;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->pad    = 0;
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->bits   = 0;
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        writer->dst   += 1;
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return writer->offset;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* convert a utf8 string to a gsm7 byte string - return the number of septets written */
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_to_gsm7( cbytes_t  utf8, int  utf8len, bytes_t  dst, int offset )
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const unsigned char*  utf8end = utf8 + utf8len;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BWriterRec            writer[1];
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dst == NULL)
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return utf8_to_gsm7_count(utf8, utf8len);
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bwriter_init( writer, dst, offset );
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while ( utf8 < utf8end ) {
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &utf8, utf8end );
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0)
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nn = unichar_to_gsm7(c);
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn >= 0) {
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bwriter_add7( writer, nn );
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nn = unichar_to_gsm7_extend(c);
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn >= 0) {
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bwriter_add7( writer, GSM_7BITS_ESCAPE );
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bwriter_add7( writer, nn );
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unknown => replaced by space */
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bwriter_add7( writer, 0x20 );
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  bwriter_done( writer );
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_to_gsm8( cbytes_t  utf8, int  utf8len, bytes_t  dst )
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const unsigned char*  utf8end = utf8 + utf8len;
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                   result  = 0;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while ( utf8 < utf8end ) {
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &utf8, utf8end );
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 0)
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nn = unichar_to_gsm7(c);
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn >= 0) {
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst)
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst[result] = (byte_t)nn;
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += 1;
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nn = unichar_to_gsm7_extend(c);
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn >= 0) {
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst) {
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst[result+0] = (byte_t) GSM_7BITS_ESCAPE;
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst[result+1] = (byte_t) nn;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result += 2;
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unknown => space */
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst)
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst[result] = 0x20;
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 1;
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectucs2_to_gsm7( cbytes_t  ucs2, int  ucs2len, bytes_t  dst, int offset )
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const unsigned char*  ucs2end = ucs2 + ucs2len*2;
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BWriterRec            writer[1];
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bwriter_init( writer, dst, offset );
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while ( ucs2 < ucs2end ) {
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *ucs2++;
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < 128; nn++) {
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( gsm7bits_to_unicode[nn] == c ) {
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                bwriter_add7( writer, nn );
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto NextUnicode;
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < 128; nn++) {
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( gsm7bits_extend_to_unicode[nn] == c ) {
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                bwriter_add7( writer, GSM_7BITS_ESCAPE );
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                bwriter_add7( writer, nn );
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto NextUnicode;
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unknown */
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bwriter_add7( writer, 0x20 );
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NextUnicode:
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ;
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  bwriter_done( writer );
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectucs2_to_gsm8( cbytes_t  ucs2, int  ucs2len, bytes_t  dst )
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const unsigned char*  ucs2end = ucs2 + ucs2len*2;
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t               dst0    = dst;
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while ( ucs2 < ucs2end ) {
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *ucs2++;
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < 128; nn++) {
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( gsm7bits_to_unicode[nn] == c ) {
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *dst++ = (byte_t)nn;
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto NextUnicode;
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < 128; nn++) {
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( gsm7bits_extend_to_unicode[nn] == c ) {
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst[0] = (byte_t) GSM_7BITS_ESCAPE;
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst[1] = (byte_t) nn;
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dst   += 2;
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto NextUnicode;
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unknown */
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *dst++ = 0x20;
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NextUnicode:
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ;
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (dst - dst0);
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_bcdnum_to_ascii( cbytes_t  bcd, int  count, bytes_t  dst )
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = 0;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  shift  = 0;
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (count > 0) {
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = (bcd[0] >> shift) & 0xf;
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == 15 && count == 1)  /* ignore trailing 0xf */
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 14)
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 0;
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst) dst[result] = "0123456789*#,N"[c];
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 1;
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift += 4;
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 8) {
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 0;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bcd += 1;
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_bcdnum_from_ascii( cbytes_t  ascii, int  asciilen, bytes_t  dst )
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end = ascii + asciilen;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result   = 0;
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  phase = 0x01;
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (ascii < end) {
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *ascii++;
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == '*')
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 10;
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '#')
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 11;
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == ',')
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 12;
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == 'N')
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = 13;
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c -= '0';
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((unsigned)c >= 10U)
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        phase   = (phase << 4) | c;
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 1;
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (phase & 0x100) {
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst) dst[result/2] = (byte_t) phase;
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phase   = 0x01;
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (result & 1) {
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst) dst[result/2] = (byte_t)(phase | 0xf0);
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** ADN: Abbreviated Dialing Number
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_FOOTER_SIZE     14
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_NUMBER_LENGTH   0
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_TON_NPI         1
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_NUMBER_START    2
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_NUMBER_END      11
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_CAPABILITY_ID   12
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  ADN_OFFSET_EXTENSION_ID    13
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* see 10.5.1 of 3GPP 51.011 */
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsim_adn_alpha_to_utf8( cbytes_t  alpha, cbytes_t  end, bytes_t  dst )
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = 0;
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ignore trailing 0xff */
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (alpha < end && end[-1] == 0xff)
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        end--;
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (alpha >= end)
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (alpha[0] == 0x80) { /* UCS/2 source encoding */
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        alpha += 1;
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = ucs2_to_utf8( alpha, (end-alpha)/2, dst );
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  is_ucs2 = 0;
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  len = 0, base = 0;
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (alpha+3 <= end && alpha[0] == 0x81) {
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_ucs2 = 1;
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len     = alpha[1];
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            base    = alpha[2] << 7;
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            alpha  += 3;
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (len > end-alpha)
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = end-alpha;
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (alpha+4 <= end && alpha[0] == 0x82) {
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_ucs2 = 1;
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len     = alpha[1];
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            base    = (alpha[2] << 8) | alpha[3];
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            alpha  += 4;
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (len > end-alpha)
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = end-alpha;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_ucs2) {
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            end = alpha + len;
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (alpha < end) {
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  c = alpha[0];
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c >= 0x80) {
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    result += utf8_write(dst, result, base + (c & 0x7f));
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    alpha  += 1;
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* GSM character set */
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    int   count;
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (count = 0; alpha+count < end && alpha[count] < 128; count++)
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ;
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    result += utf8_from_gsm8(alpha, count, (dst ? dst+result : NULL));
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    alpha  += count;
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result = utf8_from_gsm8(alpha, end-alpha, dst);
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsim_adn_alpha_from_utf8( cbytes_t  utf8, int  utf8len, bytes_t  dst )
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   result = 0;
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (utf8_check_gsm7(utf8, utf8len)) {
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* GSM 7-bit compatible, encode directly as 8-bit string */
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = utf8_to_gsm8(utf8, utf8len, dst);
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* otherwise, simply try UCS-2 encoding, nothing more serious at the moment */
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst) {
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst[0] = 0x80;
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = 1 + utf8_to_ucs2(utf8, utf8len, dst ? (dst+1) : NULL)*2;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsim_adn_record_from_bytes( SimAdnRecord  rec, cbytes_t  data, int  len )
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end    = data + len;
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  footer = end - ADN_FOOTER_SIZE;
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       num_len;
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rec->adn.alpha[0]  = 0;
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rec->adn.number[0] = 0;
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rec->ext_record    = 0xff;
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < ADN_FOOTER_SIZE)
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* alpha is optional */
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > ADN_FOOTER_SIZE) {
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t  dataend = data + len - ADN_FOOTER_SIZE;
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       count   = sim_adn_alpha_to_utf8(data, dataend, NULL);
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count > sizeof(rec->adn.alpha)-1)  /* too long */
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sim_adn_alpha_to_utf8(data, dataend, rec->adn.alpha);
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rec->adn.alpha[count] = 0;
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    num_len = footer[ADN_OFFSET_NUMBER_LENGTH];
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (num_len > 11)
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* decode TON and number to ASCII, NOTE: this is lossy !! */
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      ton    = footer[ADN_OFFSET_TON_NPI];
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bytes_t  number = (bytes_t) rec->adn.number;
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      len    = sizeof(rec->adn.number)-1;
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      count;
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ton != 0x81 && ton != 0x91)
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ton == 0x91) {
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *number++ = '+';
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len      -= 1;
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count = gsm_bcdnum_to_ascii( footer + ADN_OFFSET_NUMBER_START,
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     num_len*2, number );
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        number[count] = 0;
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsim_adn_record_to_bytes( SimAdnRecord  rec, bytes_t   data, int  datalen )
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t   end    = data + datalen;
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t   footer = end - ADN_FOOTER_SIZE;
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       ton    = 0x81;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  number = (cbytes_t) rec->adn.number;
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (number[0] == '+') {
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ton     = 0x91;
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        number += 1;
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    footer[0] = (strlen((const char*)number)+1)/2 + 1;
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXX: TODO */
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1221