-
-
Save rahulvyas/1129297 to your computer and use it in GitHub Desktop.
NSString category for GSM7 encoding and GSM7/UCS-2BE string length evaluation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSString+SMSCount.m | |
// SmsProsto | |
// | |
// Created by Farcaller on 28.11.10. | |
// Copyright 2010 Codeneedle LLC. All rights reserved. | |
// | |
#import "NSString+SMSCount.h" | |
#include <iconv.h> | |
#include <errno.h> | |
static int gsm7_wctomb(unichar *r, unichar wc) | |
{ | |
unsigned char s1, s2; | |
s1 = (wc & 0xff00) >> 8; | |
s2 = wc & 0x00ff; | |
if( s1 == 0x00 ) { | |
if( s2 == 0xA || s2 == 0xD || | |
(s2 >= 0x20 && s2 <= 0x23 ) || (s2 >= 0x25 && s2 <= 0x3f) | |
|| (s2 >= 0x41 && s2 <= 0x5A) || (s2 >= 0x61 && s2 <= 0x7A) ) { | |
*r = s2; | |
return 1; | |
} else { | |
switch( s2 ) { | |
case 0x24: *r = 0x02; return 1; | |
case 0x40: *r = 0x00; return 1; | |
case 0x5b: *r = 0x1b3c; return 2; | |
case 0x5c: *r = 0x1b2f; return 2; | |
case 0x5d: *r = 0x1b3e; return 2; | |
case 0x5e: *r = 0x1b14; return 2; | |
case 0x5f: *r = 0x11; return 1; | |
case 0x7b: *r = 0x1b28; return 2; | |
case 0x7c: *r = 0x1b40; return 2; | |
case 0x7d: *r = 0x1b29; return 2; | |
case 0x7e: *r = 0x1b3d; return 2; | |
case 0xa3: *r = 0x01; return 1; | |
case 0xa4: *r = 0x24; return 1; | |
case 0xa5: *r = 0x03; return 1; | |
case 0xa7: *r = 0x5f; return 1; | |
case 0xb0: *r = 0x24; return 1; | |
case 0xbf: *r = 0x60; return 1; | |
case 0xc5: *r = 0x0e; return 1; | |
case 0xc6: *r = 0x1c; return 1; | |
case 0xc7: *r = 0x09; return 1; | |
case 0xc9: *r = 0x1f; return 1; | |
case 0xc4: *r = 0x5b; return 1; | |
case 0xd1: *r = 0x5d; return 1; | |
case 0xd6: *r = 0x5c; return 1; | |
case 0xd8: *r = 0x0b; return 1; | |
case 0xdc: *r = 0x5e; return 1; | |
case 0xdf: *r = 0x1e; return 1; | |
case 0xe0: *r = 0x7f; return 1; | |
case 0xe4: *r = 0x7b; return 1; | |
case 0xe5: *r = 0x0f; return 1; | |
case 0xe6: *r = 0x1d; return 1; | |
case 0xe7: *r = 0x09; return 1; | |
case 0xe8: *r = 0x04; return 1; | |
case 0xe9: *r = 0x05; return 1; | |
case 0xec: *r = 0x07; return 1; | |
case 0xf1: *r = 0x7d; return 1; | |
case 0xf2: *r = 0x08; return 1; | |
case 0xf6: *r = 0x7c; return 1; | |
case 0xf8: *r = 0x0c; return 1; | |
case 0xf9: *r = 0x06; return 1; | |
case 0xfc: *r = 0x7e; return 1; | |
/* one way mappings */ | |
case 0xc0: *r = 0x41; return 1; | |
case 0xc1: *r = 0x41; return 1; | |
case 0xc2: *r = 0x41; return 1; | |
case 0xc3: *r = 0x41; return 1; | |
case 0xc8: *r = 0x45; return 1; | |
case 0xca: *r = 0x45; return 1; | |
case 0xcb: *r = 0x45; return 1; | |
case 0xcc: *r = 0x49; return 1; | |
case 0xcd: *r = 0x49; return 1; | |
case 0xce: *r = 0x49; return 1; | |
case 0xcf: *r = 0x49; return 1; | |
case 0xd2: *r = 0x4f; return 1; | |
case 0xd3: *r = 0x4f; return 1; | |
case 0xd4: *r = 0x4f; return 1; | |
case 0xd5: *r = 0x4f; return 1; | |
case 0xd9: *r = 0x55; return 1; | |
case 0xda: *r = 0x55; return 1; | |
case 0xdb: *r = 0x55; return 1; | |
case 0xdd: *r = 0x59; return 1; | |
case 0xe1: *r = 0x61; return 1; | |
case 0xe2: *r = 0x61; return 1; | |
case 0xe3: *r = 0x61; return 1; | |
case 0xea: *r = 0x65; return 1; | |
case 0xeb: *r = 0x65; return 1; | |
case 0xed: *r = 0x69; return 1; | |
case 0xee: *r = 0x69; return 1; | |
case 0xef: *r = 0x69; return 1; | |
case 0xf3: *r = 0x6f; return 1; | |
case 0xf4: *r = 0x6f; return 1; | |
case 0xf5: *r = 0x6f; return 1; | |
case 0xfa: *r = 0x75; return 1; | |
case 0xfb: *r = 0x75; return 1; | |
case 0xfd: *r = 0x79; return 1; | |
case 0xff: *r = 0x79; return 1; | |
} | |
} | |
return -1; | |
} else if( s1 == 0x20 ) { | |
if( s2 == 0xac ) { | |
*r = 0x1b65; return 2; | |
} | |
} else if( s1 == 0x03 ) { | |
switch( s2 ) { | |
case 0x94: *r = 0x10; return 1; | |
case 0xa6: *r = 0x12; return 1; | |
case 0x93: *r = 0x13; return 1; | |
case 0x9b: *r = 0x14; return 1; | |
case 0xa9: *r = 0x15; return 1; | |
case 0xa0: *r = 0x16; return 1; | |
case 0xa8: *r = 0x17; return 1; | |
case 0xa3: *r = 0x18; return 1; | |
case 0x98: *r = 0x19; return 1; | |
case 0x9e: *r = 0x1a; return 1; | |
case 0x91: *r = 0x41; return 1; | |
case 0x92: *r = 0x42; return 1; | |
case 0x95: *r = 0x45; return 1; | |
case 0x97: *r = 0x48; return 1; | |
case 0x99: *r = 0x49; return 1; | |
case 0x9a: *r = 0x4b; return 1; | |
case 0x9c: *r = 0x4d; return 1; | |
case 0x9d: *r = 0x4e; return 1; | |
case 0x9f: *r = 0x4f; return 1; | |
case 0xa1: *r = 0x50; return 1; | |
case 0xa4: *r = 0x54; return 1; | |
case 0xa5: *r = 0x55; return 1; | |
case 0xa7: *r = 0x58; return 1; | |
case 0x96: *r = 0x5a; return 1; | |
} | |
return -1; | |
} | |
return 0; | |
}; | |
@implementation NSString (SMSCount) | |
- (NSUInteger)smsLength | |
{ | |
char *b = (char*)[self GSM7String]; | |
if(b) { | |
int l = strlen(b); | |
free(b); | |
return l; | |
} else { | |
// can't encode, fallback to UCS-2BE | |
return [self length]*2; | |
} | |
} | |
- (const char *)GSM7String | |
{ | |
char *ret = NULL; | |
NSUInteger len = [self length]; | |
unichar *ibuf = malloc(len*sizeof(unichar)); | |
assert(ibuf); | |
char *obuf = malloc(len*sizeof(unichar)); | |
assert(obuf); | |
bzero(obuf, len*sizeof(unichar)); | |
NSRange r; | |
r.length = len; | |
r.location = 0; | |
[self getCharacters:ibuf range:r]; | |
for(int i=0, j=0; i<len; ++i) { | |
unichar ic = ibuf[i]; | |
unichar oc = 0; | |
int l = gsm7_wctomb(&oc, ic); | |
if(l < 1) | |
goto final; | |
unsigned char s1 = (oc & 0xff00) >> 8; | |
unsigned char s2 = oc & 0x00ff; | |
if(s1) { | |
obuf[j++] = s1; | |
} | |
obuf[j++] = s2; | |
} | |
ret = strdup(obuf); | |
final: | |
free(ibuf); | |
free(obuf); | |
return ret; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment