Skip to content

Instantly share code, notes, and snippets.

@rahulvyas
Forked from farcaller/gist:719729
Created August 6, 2011 12:22
Show Gist options
  • Save rahulvyas/1129297 to your computer and use it in GitHub Desktop.
Save rahulvyas/1129297 to your computer and use it in GitHub Desktop.
NSString category for GSM7 encoding and GSM7/UCS-2BE string length evaluation
//
// 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