File Coverage

blib/lib/Device/Gsm/Charset.pm
Criterion Covered Total %
statement 47 78 60.2
branch 25 36 69.4
condition 2 15 13.3
subroutine 6 8 75.0
pod 0 4 0.0
total 80 141 56.7


line stmt bran cond sub pod time code
1             # Device::Gsm::Charset - GSM0338 <=> ASCII charset conversion module
2             # Copyright (C) 2004-2015 Cosimo Streppone, cosimo@cpan.org
3             #
4             # This program is free software; you can redistribute it and/or modify
5             # it only under the terms of Perl itself.
6             #
7             # This program is distributed in the hope that it will be useful,
8             # but WITHOUT ANY WARRANTY; without even the implied warranty of
9             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10             # Perl licensing terms for details.
11              
12             package Device::Gsm::Charset;
13             $VERSION = $Device::Gsm::VERSION;
14              
15 12     12   13622 use strict;
  12         13  
  12         292  
16 12     12   37 use constant NPC7 => 0x3F;
  12         12  
  12         593  
17 12     12   41 use constant NPC8 => 0x3F;
  12         11  
  12         392  
18 12     12   36 use constant ESCAPE => 0x1B;
  12         9  
  12         9583  
19              
20             # The following is the GSM 3.38 standard charset, as shown
21             # on some Siemens documentation found on the internet
22              
23             #my $gsm_charset = join('',
24             # '@»$»»»»»»»'."\n".'»»'."\r".'»»»', # 16
25             # '»»»»»»»»»»»»ß»»',
26             # ' !"# %&‘()*+,-./',
27             # '0123456789:;<=>?',
28             # '-ABCDEFGHIJKLMNO',
29             # 'PQRSTUVWXYZÄֻܻ',
30             # '¨abcdefghijklmno',
31             # 'pqrstuvwxyzäö»ü»'
32             #);
33              
34             #
35             # These conversion tables are taken from pduconv 0.1 library
36             # by Mats Engstrom . See also:
37             # http://www.mikrocontroller.net/attachment/104082/pduconv.c
38             # and
39             # https://github.com/rdmeneze/SMSBox-PIC/tree/master/source/pdu_conv
40             #
41             # Un grazie a Stefano!
42             #
43              
44             @Device::Gsm::Charset::GSM0338_TO_ISO8859 = (
45             64, # 0 @ COMMERCIAL AT */
46             163, # 1 £ POUND SIGN */
47             36, # 2 $ DOLLAR SIGN */
48             165, # 3 ¥ YEN SIGN */
49             232, # 4 è LATIN SMALL LETTER E WITH GRAVE */
50             233, # 5 é LATIN SMALL LETTER E WITH ACUTE */
51             249, # 6 ù LATIN SMALL LETTER U WITH GRAVE */
52             236, # 7 ì LATIN SMALL LETTER I WITH GRAVE */
53             242, # 8 ò LATIN SMALL LETTER O WITH GRAVE */
54             199, # 9 Ç LATIN CAPITAL LETTER C WITH CEDILLA */
55             10, # 10 LINE FEED */
56             216, # 11 Ø LATIN CAPITAL LETTER O WITH STROKE */
57             248, # 12 ø LATIN SMALL LETTER O WITH STROKE */
58             13, # 13 CARRIAGE RETURN */
59             197, # 14 Å LATIN CAPITAL LETTER A WITH RING ABOVE */
60             229, # 15 å LATIN SMALL LETTER A WITH RING ABOVE */
61             NPC8, # 16 GREEK CAPITAL LETTER DELTA */
62             95, # 17 _ LOW LINE */
63             NPC8, # 18 GREEK CAPITAL LETTER PHI */
64             NPC8, # 19 GREEK CAPITAL LETTER GAMMA */
65             NPC8, # 20 GREEK CAPITAL LETTER LAMBDA */
66             NPC8, # 21 GREEK CAPITAL LETTER OMEGA */
67             NPC8, # 22 GREEK CAPITAL LETTER PI */
68             NPC8, # 23 GREEK CAPITAL LETTER PSI */
69             NPC8, # 24 GREEK CAPITAL LETTER SIGMA */
70             NPC8, # 25 GREEK CAPITAL LETTER THETA */
71             NPC8, # 26 GREEK CAPITAL LETTER XI */
72             27, # 27 ESCAPE TO EXTENSION TABLE */
73             198, # 28 Æ LATIN CAPITAL LETTER AE */
74             230, # 29 æ LATIN SMALL LETTER AE */
75             223, # 30 ß LATIN SMALL LETTER SHARP S (German) */
76             201, # 31 É LATIN CAPITAL LETTER E WITH ACUTE */
77             32, # 32 SPACE */
78             33, # 33 ! EXCLAMATION MARK */
79             34, # 34 " QUOTATION MARK */
80             35, # 35 # NUMBER SIGN */
81             164, # 36 ¤ CURRENCY SIGN */
82             37, # 37 % PERCENT SIGN */
83             38, # 38 & AMPERSAND */
84             39, # 39 ' APOSTROPHE */
85             40, # 40 ( LEFT PARENTHESIS */
86             41, # 41 ) RIGHT PARENTHESIS */
87             42, # 42 * ASTERISK */
88             43, # 43 + PLUS SIGN */
89             44, # 44 , COMMA */
90             45, # 45 - HYPHEN-MINUS */
91             46, # 46 . FULL STOP */
92             47, # 47 / SOLIDUS (SLASH) */
93             48, # 48 0 DIGIT ZERO */
94             49, # 49 1 DIGIT ONE */
95             50, # 50 2 DIGIT TWO */
96             51, # 51 3 DIGIT THREE */
97             52, # 52 4 DIGIT FOUR */
98             53, # 53 5 DIGIT FIVE */
99             54, # 54 6 DIGIT SIX */
100             55, # 55 7 DIGIT SEVEN */
101             56, # 56 8 DIGIT EIGHT */
102             57, # 57 9 DIGIT NINE */
103             58, # 58 : COLON */
104             59, # 59 ; SEMICOLON */
105             60, # 60 < LESS-THAN SIGN */
106             61, # 61 = EQUALS SIGN */
107             62, # 62 > GREATER-THAN SIGN */
108             63, # 63 ? QUESTION MARK */
109             161, # 64 ¡ INVERTED EXCLAMATION MARK */
110             65, # 65 A LATIN CAPITAL LETTER A */
111             66, # 66 B LATIN CAPITAL LETTER B */
112             67, # 67 C LATIN CAPITAL LETTER C */
113             68, # 68 D LATIN CAPITAL LETTER D */
114             69, # 69 E LATIN CAPITAL LETTER E */
115             70, # 70 F LATIN CAPITAL LETTER F */
116             71, # 71 G LATIN CAPITAL LETTER G */
117             72, # 72 H LATIN CAPITAL LETTER H */
118             73, # 73 I LATIN CAPITAL LETTER I */
119             74, # 74 J LATIN CAPITAL LETTER J */
120             75, # 75 K LATIN CAPITAL LETTER K */
121             76, # 76 L LATIN CAPITAL LETTER L */
122             77, # 77 M LATIN CAPITAL LETTER M */
123             78, # 78 N LATIN CAPITAL LETTER N */
124             79, # 79 O LATIN CAPITAL LETTER O */
125             80, # 80 P LATIN CAPITAL LETTER P */
126             81, # 81 Q LATIN CAPITAL LETTER Q */
127             82, # 82 R LATIN CAPITAL LETTER R */
128             83, # 83 S LATIN CAPITAL LETTER S */
129             84, # 84 T LATIN CAPITAL LETTER T */
130             85, # 85 U LATIN CAPITAL LETTER U */
131             86, # 86 V LATIN CAPITAL LETTER V */
132             87, # 87 W LATIN CAPITAL LETTER W */
133             88, # 88 X LATIN CAPITAL LETTER X */
134             89, # 89 Y LATIN CAPITAL LETTER Y */
135             90, # 90 Z LATIN CAPITAL LETTER Z */
136             196, # 91 Ä LATIN CAPITAL LETTER A WITH DIAERESIS */
137             214, # 92 Ö LATIN CAPITAL LETTER O WITH DIAERESIS */
138             209, # 93 Ñ LATIN CAPITAL LETTER N WITH TILDE */
139             220, # 94 Ü LATIN CAPITAL LETTER U WITH DIAERESIS */
140             167, # 95 § SECTION SIGN */
141             191, # 96 ¿ INVERTED QUESTION MARK */
142             97, # 97 a LATIN SMALL LETTER A */
143             98, # 98 b LATIN SMALL LETTER B */
144             99, # 99 c LATIN SMALL LETTER C */
145             100, # 100 d LATIN SMALL LETTER D */
146             101, # 101 e LATIN SMALL LETTER E */
147             102, # 102 f LATIN SMALL LETTER F */
148             103, # 103 g LATIN SMALL LETTER G */
149             104, # 104 h LATIN SMALL LETTER H */
150             105, # 105 i LATIN SMALL LETTER I */
151             106, # 106 j LATIN SMALL LETTER J */
152             107, # 107 k LATIN SMALL LETTER K */
153             108, # 108 l LATIN SMALL LETTER L */
154             109, # 109 m LATIN SMALL LETTER M */
155             110, # 110 n LATIN SMALL LETTER N */
156             111, # 111 o LATIN SMALL LETTER O */
157             112, # 112 p LATIN SMALL LETTER P */
158             113, # 113 q LATIN SMALL LETTER Q */
159             114, # 114 r LATIN SMALL LETTER R */
160             115, # 115 s LATIN SMALL LETTER S */
161             116, # 116 t LATIN SMALL LETTER T */
162             117, # 117 u LATIN SMALL LETTER U */
163             118, # 118 v LATIN SMALL LETTER V */
164             119, # 119 w LATIN SMALL LETTER W */
165             120, # 120 x LATIN SMALL LETTER X */
166             121, # 121 y LATIN SMALL LETTER Y */
167             122, # 122 z LATIN SMALL LETTER Z */
168             228, # 123 ä LATIN SMALL LETTER A WITH DIAERESIS */
169             246, # 124 ö LATIN SMALL LETTER O WITH DIAERESIS */
170             241, # 125 ñ LATIN SMALL LETTER N WITH TILDE */
171             252, # 126 ü LATIN SMALL LETTER U WITH DIAERESIS */
172             224, # 127 à LATIN SMALL LETTER A WITH GRAVE */
173              
174             # 12 27 10 FORM FEED
175             # 94 27 20 ^ CIRCUMFLEX ACCENT
176             # 123 27 40 { LEFT CURLY BRACKET
177             # 125 27 41 } RIGHT CURLY BRACKET
178             # 92 27 47 \ REVERSE SOLIDUS (BACKSLASH)
179             # 91 27 60 [ LEFT SQUARE BRACKET
180             # 126 27 61 ~ TILDE
181             # 93 27 62 ] RIGHT SQUARE BRACKET
182             # 124 27 64 | VERTICAL BAR */
183             );
184              
185             #my $gsm_charset = join '' => map chr => @GSM0338_TO_ISO8859;
186              
187             @Device::Gsm::Charset::ISO8859_TO_GSM0338 = (
188             NPC7, # 0 null [NUL] */
189             NPC7, # 1 start of heading [SOH] */
190             NPC7, # 2 start of text [STX] */
191             NPC7, # 3 end of text [ETX] */
192             NPC7, # 4 end of transmission [EOT] */
193             NPC7, # 5 enquiry [ENQ] */
194             NPC7, # 6 acknowledge [ACK] */
195             NPC7, # 7 bell [BEL] */
196             NPC7, # 8 backspace [BS] */
197             NPC7, # 9 horizontal tab [HT] */
198             10, # 10 line feed [LF] */
199             NPC7, # 11 vertical tab [VT] */
200             10 + 256, # 12 form feed [FF] */
201             13, # 13 carriage return [CR] */
202             NPC7, # 14 shift out [SO] */
203             NPC7, # 15 shift in [SI] */
204             NPC7, # 16 data link escape [DLE] */
205             NPC7, # 17 device control 1 [DC1] */
206             NPC7, # 18 device control 2 [DC2] */
207             NPC7, # 19 device control 3 [DC3] */
208             NPC7, # 20 device control 4 [DC4] */
209             NPC7, # 21 negative acknowledge [NAK] */
210             NPC7, # 22 synchronous idle [SYN] */
211             NPC7, # 23 end of trans. block [ETB] */
212             NPC7, # 24 cancel [CAN] */
213             NPC7, # 25 end of medium [EM] */
214             NPC7, # 26 substitute [SUB] */
215             NPC7, # 27 escape [ESC] */
216             NPC7, # 28 file separator [FS] */
217             NPC7, # 29 group separator [GS] */
218             NPC7, # 30 record separator [RS] */
219             NPC7, # 31 unit separator [US] */
220             32, # 32 space */
221             33, # 33 ! exclamation mark */
222             34, # 34 " double quotation mark */
223             35, # 35 # number sign */
224             2, # 36 $ dollar sign */
225             37, # 37 % percent sign */
226             38, # 38 & ampersand */
227             39, # 39 ' apostrophe */
228             40, # 40 ( left parenthesis */
229             41, # 41 ) right parenthesis */
230             42, # 42 * asterisk */
231             43, # 43 + plus sign */
232             44, # 44 , comma */
233             45, # 45 - hyphen */
234             46, # 46 . period */
235             47, # 47 / slash, */
236             48, # 48 0 digit 0 */
237             49, # 49 1 digit 1 */
238             50, # 50 2 digit 2 */
239             51, # 51 3 digit 3 */
240             52, # 52 4 digit 4 */
241             53, # 53 5 digit 5 */
242             54, # 54 6 digit 6 */
243             55, # 55 7 digit 7 */
244             56, # 56 8 digit 8 */
245             57, # 57 9 digit 9 */
246             58, # 58 : colon */
247             59, # 59 ; semicolon */
248             60, # 60 < less-than sign */
249             61, # 61 = equal sign */
250             62, # 62 > greater-than sign */
251             63, # 63 ? question mark */
252             0, # 64 @ commercial at sign */
253             65, # 65 A uppercase A */
254             66, # 66 B uppercase B */
255             67, # 67 C uppercase C */
256             68, # 68 D uppercase D */
257             69, # 69 E uppercase E */
258             70, # 70 F uppercase F */
259             71, # 71 G uppercase G */
260             72, # 72 H uppercase H */
261             73, # 73 I uppercase I */
262             74, # 74 J uppercase J */
263             75, # 75 K uppercase K */
264             76, # 76 L uppercase L */
265             77, # 77 M uppercase M */
266             78, # 78 N uppercase N */
267             79, # 79 O uppercase O */
268             80, # 80 P uppercase P */
269             81, # 81 Q uppercase Q */
270             82, # 82 R uppercase R */
271             83, # 83 S uppercase S */
272             84, # 84 T uppercase T */
273             85, # 85 U uppercase U */
274             86, # 86 V uppercase V */
275             87, # 87 W uppercase W */
276             88, # 88 X uppercase X */
277             89, # 89 Y uppercase Y */
278             90, # 90 Z uppercase Z */
279             60 + 256, # 91 [ left square bracket */
280             47 + 256, # 92 \ backslash */
281             62 + 256, # 93 ] right square bracket */
282             20 + 256, # 94 ^ circumflex accent */
283             17, # 95 _ underscore */
284             -39, # 96 ` back apostrophe */
285             97, # 97 a lowercase a */
286             98, # 98 b lowercase b */
287             99, # 99 c lowercase c */
288             100, # 100 d lowercase d */
289             101, # 101 e lowercase e */
290             102, # 102 f lowercase f */
291             103, # 103 g lowercase g */
292             104, # 104 h lowercase h */
293             105, # 105 i lowercase i */
294             106, # 106 j lowercase j */
295             107, # 107 k lowercase k */
296             108, # 108 l lowercase l */
297             109, # 109 m lowercase m */
298             110, # 110 n lowercase n */
299             111, # 111 o lowercase o */
300             112, # 112 p lowercase p */
301             113, # 113 q lowercase q */
302             114, # 114 r lowercase r */
303             115, # 115 s lowercase s */
304             116, # 116 t lowercase t */
305             117, # 117 u lowercase u */
306             118, # 118 v lowercase v */
307             119, # 119 w lowercase w */
308             120, # 120 x lowercase x */
309             121, # 121 y lowercase y */
310             122, # 122 z lowercase z */
311             40 + 256, # 123 { left brace */
312             64 + 256, # 124 | vertical bar */
313             41 + 256, # 125 } right brace */
314             61 + 256, # 126 ~ tilde accent */
315             NPC7, # 127 delete [DEL] */
316             NPC7, # 128 */
317             NPC7, # 129 */
318             -39, # 130 low left rising single quote */
319             -102, # 131 lowercase italic f */
320             -34, # 132 low left rising double quote */
321             NPC7, # 133 low horizontal ellipsis */
322             NPC7, # 134 dagger mark */
323             NPC7, # 135 double dagger mark */
324             NPC7, # 136 letter modifying circumflex */
325             NPC7, # 137 per thousand (mille) sign */
326             -83, # 138 uppercase S caron or hacek */
327             -39, # 139 left single angle quote mark */
328             -214, # 140 uppercase OE ligature */
329             NPC7, # 141 */
330             NPC7, # 142 */
331             NPC7, # 143 */
332             NPC7, # 144 */
333             -39, # 145 left single quotation mark */
334             -39, # 146 right single quote mark */
335             -34, # 147 left double quotation mark */
336             -34, # 148 right double quote mark */
337             -42, # 149 round filled bullet */
338             -45, # 150 en dash */
339             -45, # 151 em dash */
340             -39, # 152 small spacing tilde accent */
341             NPC7, # 153 trademark sign */
342             -115, # 154 lowercase s caron or hacek */
343             -39, # 155 right single angle quote mark */
344             -111, # 156 lowercase oe ligature */
345             NPC7, # 157 */
346             NPC7, # 158 */
347             -89, # 159 uppercase Y dieresis or umlaut */
348             -32, # 160   non-breaking space */
349             64, # 161 ¡ inverted exclamation mark */
350             -99, # 162 ¢ cent sign */
351             1, # 163 £ pound sterling sign */
352             36, # 164 ¤ general currency sign */
353             3, # 165 ¥ yen sign */
354             -33, # 166 ¦ broken vertical bar */
355             95, # 167 § section sign */
356             -34, # 168 ¨ spacing dieresis or umlaut */
357             NPC7, # 169 © copyright sign */
358             NPC7, # 170 ª feminine ordinal indicator */
359             -60, # 171 « left (double) angle quote */
360             NPC7, # 172 ¬ logical not sign */
361             -45, # 173 ­ soft hyphen */
362             NPC7, # 174 ® registered trademark sign */
363             NPC7, # 175 ¯ spacing macron (long) accent */
364             NPC7, # 176 ° degree sign */
365             NPC7, # 177 ± plus-or-minus sign */
366             -50, # 178 ² superscript 2 */
367             -51, # 179 ³ superscript 3 */
368             -39, # 180 ´ spacing acute accent */
369             -117, # 181 µ micro sign */
370             NPC7, # 182 ¶ paragraph sign, pilcrow sign */
371             NPC7, # 183 · middle dot, centered dot */
372             NPC7, # 184 ¸ spacing cedilla */
373             -49, # 185 ¹ superscript 1 */
374             NPC7, # 186 º masculine ordinal indicator */
375             -62, # 187 » right (double) angle quote (guillemet) */
376             NPC7, # 188 ¼ fraction 1/4 */
377             NPC7, # 189 ½ fraction 1/2 */
378             NPC7, # 190 ¾ fraction 3/4 */
379             96, # 191 ¿ inverted question mark */
380             -65, # 192 À uppercase A grave */
381             -65, # 193 Á uppercase A acute */
382             -65, # 194 Â uppercase A circumflex */
383             -65, # 195 Ã uppercase A tilde */
384             91, # 196 Ä uppercase A dieresis or umlaut */
385             14, # 197 Å uppercase A ring */
386             28, # 198 Æ uppercase AE ligature */
387             9, # 199 Ç uppercase C cedilla */
388             -31, # 200 È uppercase E grave */
389             31, # 201 É uppercase E acute */
390             -31, # 202 Ê uppercase E circumflex */
391             -31, # 203 Ë uppercase E dieresis or umlaut */
392             -73, # 204 Ì uppercase I grave */
393             -73, # 205 Í uppercase I acute */
394             -73, # 206 Î uppercase I circumflex */
395             -73, # 207 Ï uppercase I dieresis or umlaut */
396             -68, # 208 Ð uppercase ETH */
397             93, # 209 Ñ uppercase N tilde */
398             -79, # 210 Ò uppercase O grave */
399             -79, # 211 Ó uppercase O acute */
400             -79, # 212 Ô uppercase O circumflex */
401             -79, # 213 Õ uppercase O tilde */
402             92, # 214 Ö uppercase O dieresis or umlaut */
403             -42, # 215 × multiplication sign */
404             11, # 216 Ø uppercase O slash */
405             -85, # 217 Ù uppercase U grave */
406             -85, # 218 Ú uppercase U acute */
407             -85, # 219 Û uppercase U circumflex */
408             94, # 220 Ü uppercase U dieresis or umlaut */
409             -89, # 221 Ý uppercase Y acute */
410             NPC7, # 222 Þ uppercase THORN */
411             30, # 223 ß lowercase sharp s, sz ligature */
412             127, # 224 à lowercase a grave */
413             -97, # 225 á lowercase a acute */
414             -97, # 226 â lowercase a circumflex */
415             -97, # 227 ã lowercase a tilde */
416             123, # 228 ä lowercase a dieresis or umlaut */
417             15, # 229 å lowercase a ring */
418             29, # 230 æ lowercase ae ligature */
419             -9, # 231 ç lowercase c cedilla */
420             4, # 232 è lowercase e grave */
421             5, # 233 é lowercase e acute */
422             -101, # 234 ê lowercase e circumflex */
423             -101, # 235 ë lowercase e dieresis or umlaut */
424             7, # 236 ì lowercase i grave */
425             -7, # 237 í lowercase i acute */
426             -105, # 238 î lowercase i circumflex */
427             -105, # 239 ï lowercase i dieresis or umlaut */
428             NPC7, # 240 ð lowercase eth */
429             125, # 241 ñ lowercase n tilde */
430             8, # 242 ò lowercase o grave */
431             -111, # 243 ó lowercase o acute */
432             -111, # 244 ô lowercase o circumflex */
433             -111, # 245 õ lowercase o tilde */
434             124, # 246 ö lowercase o dieresis or umlaut */
435             -47, # 247 ÷ division sign */
436             12, # 248 ø lowercase o slash */
437             6, # 249 ù lowercase u grave */
438             -117, # 250 ú lowercase u acute */
439             -117, # 251 û lowercase u circumflex */
440             126, # 252 ü lowercase u dieresis or umlaut */
441             -121, # 253 ý lowercase y acute */
442             NPC7, # 254 þ lowercase thorn */
443             -121 # 255 ÿ lowercase y dieresis or umlaut */
444             );
445              
446             sub iso8859_to_gsm0338 {
447 384     384 0 56638 my $ascii = shift;
448 384 50 33     1254 return '' if !defined $ascii || $ascii eq '';
449              
450 384         266 my $gsm = '';
451 384         241 my $n = 0;
452 384         540 for (; $n < length($ascii); $n++) {
453 489         452 my $ch_ascii = ord(substr($ascii, $n, 1));
454 489         353 my $ch_gsm = $Device::Gsm::Charset::ISO8859_TO_GSM0338[$ch_ascii];
455              
456             # Is this a "replaced" char?
457 489 100       517 if ($ch_gsm <= 0xFF) {
458 480         337 $ch_gsm = abs($ch_gsm);
459             }
460             else {
461              
462             # Prepend an escape char for extended char
463 9         9 $gsm .= chr(ESCAPE);
464              
465             # Encode extended char
466 9         9 $ch_gsm -= 256;
467             }
468              
469             #warn('char ['.$ch_ascii.'] => ['.$ch_gsm.']');
470 489         802 $gsm .= chr($ch_gsm);
471             }
472 384         532 return $gsm;
473             }
474              
475             sub gsm0338_to_iso8859 {
476 398     398 0 262 my $gsm = shift;
477 398 50 33     990 return '' if !defined $gsm || $gsm eq '';
478              
479 398         261 my $ascii = '';
480 398         231 my $n = 0;
481              
482 398         495 for (; $n < length($gsm); $n++) {
483              
484 1127         876 my $c = ord(substr($gsm, $n, 1));
485              
486             # Extended charset ?
487 1127 100       1062 if ($c == ESCAPE) { # "escape extended mode"
488 14         10 $n++;
489 14         16 $c = ord(substr($gsm, $n, 1));
490 14 100       57 if ($c == 0x0A) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
491 1         2 $ascii .= chr(12);
492             }
493             elsif ($c == 0x14) {
494 2         5 $ascii .= '^';
495             }
496             elsif ($c == 0x28) {
497 1         2 $ascii .= '{';
498             }
499             elsif ($c == 0x29) {
500 1         2 $ascii .= '}';
501             }
502             elsif ($c == 0x2F) {
503 2         5 $ascii .= '\\';
504             }
505             elsif ($c == 0x3C) {
506 2         4 $ascii .= '[';
507             }
508             elsif ($c == 0x3D) {
509 1         3 $ascii .= '~';
510             }
511             elsif ($c == 0x3E) {
512 2         4 $ascii .= ']';
513             }
514             elsif ($c == 0x40) {
515 1         2 $ascii .= '|';
516             }
517             elsif ($c == 0x65) { # 'e'
518 1         3 $ascii .= chr(164)
519             ; # iso_8859_15 EURO SIGN or iso_8859_1 CURRENCY_SIGN
520             }
521             else {
522 0         0 $ascii .= chr(NPC8); # Non printable
523             }
524              
525             }
526             else {
527              
528             # Standard GSM 3.38 encoding
529 1113         1875 $ascii .= chr($Device::Gsm::Charset::GSM0338_TO_ISO8859[$c]);
530             }
531              
532             #warn('gsm char ['.$c.'] converted to ascii ['.ord(substr($ascii,-1)).']');
533             }
534              
535 398         804 return $ascii;
536             }
537              
538             sub gsm0338_length {
539 0     0 0   my $ascii = shift;
540 0           my $gsm0338_length = 0;
541 0           my $n = 0;
542 0           for (; $n < length($ascii); $n++) {
543 0           my $ch_ascii = ord(substr($ascii, $n, 1));
544 0           my $ch_gsm = $Device::Gsm::Charset::ISO8859_TO_GSM0338[$ch_ascii];
545              
546             # Is this a "replaced" char?
547 0 0         if ($ch_gsm <= 0xFF) {
548 0           $gsm0338_length++;
549             }
550             else {
551 0           $gsm0338_length += 2;
552             }
553             }
554 0           return $gsm0338_length;
555             }
556              
557             sub gsm0338_split {
558 0     0 0   my $ascii = shift;
559 0 0 0       return '' if !defined $ascii || $ascii eq '';
560 0           my @parts;
561             my $part;
562 0           my $chars_count = 0;
563 0           my $ascii_length = length($ascii);
564 0           while ($ascii_length) {
565 0           my $ch_ascii = substr($ascii, 0, 1);
566 0           my $ch_gsm
567             = $Device::Gsm::Charset::ISO8859_TO_GSM0338[ ord($ch_ascii) ];
568 0 0 0       if ($chars_count < 153 and $ch_gsm <= 0xFF) {
    0 0        
569 0           $part .= $ch_ascii;
570 0           $chars_count++;
571 0           $ascii = substr($ascii, 1, $ascii_length--);
572             }
573             elsif ($chars_count < 152 and $ch_gsm > 0xFF) {
574 0           $part .= $ch_ascii;
575 0           $chars_count += 2;
576 0           $ascii = substr($ascii, 1, $ascii_length--);
577             }
578             else {
579 0           push(@parts, $part);
580 0           $part = '';
581 0           $chars_count = 0;
582             }
583             }
584 0           push(@parts, $part);
585 0           return (@parts);
586             }
587             1;
588              
589             __END__