File: XADStringIconv.m

package info (click to toggle)
unar 1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,664 kB
  • sloc: ansic: 52,939; objc: 39,563; cpp: 4,074; makefile: 99; perl: 10
file content (131 lines) | stat: -rw-r--r-- 3,304 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * This implementation does not really work much at all, because iconv is horrible. Use ICU instead.
 */

#import "XADString.h"

#import <iconv.h>

#define MaxEncodingNameLength 128

static void IconvNameForEncodingName(char *cstr,NSString *name);

@implementation XADString (PlatformSpecific)

+(NSString *)stringForData:(NSData *)data encodingName:(NSString *)encoding
{
	char encbuf[MaxEncodingNameLength+1];
	IconvNameForEncodingName(encbuf,encoding);

	iconv_t ic=iconv_open("UCS-2-INTERNAL",encbuf);
	if(ic==(iconv_t)(-1)) return nil;

	char *inptr=(char *)[data bytes]; // iconv is horrible and doesn't declare its input as const.
	size_t inlen=[data length];

	uint16_t chars[1024];
	NSMutableString *string=[NSMutableString string];

	while(inlen)
	{
		char *outptr=(char *)&chars;
		size_t outlen=sizeof(chars)/sizeof(*chars)-1;
		if(iconv(ic,&inptr,&inlen,&outptr,&outlen)==-1)
		{
			if(errno!=E2BIG) return nil;
		}

		*(uint16_t *)outptr=0;
		[string appendFormat:@"%S",chars];
	}

	return [NSString stringWithString:string];
}

+(NSData *)dataForString:(NSString *)string encodingName:(NSString *)encoding
{
	char encbuf[MaxEncodingNameLength+1];
	IconvNameForEncodingName(encbuf,encoding);

	iconv_t ic=iconv_open(encbuf,"UCS-2-INTERNAL");
	if(ic==(iconv_t)(-1)) return nil;

	int numchars=[string length];
	unichar chars[numchars];
	[string getCharacters:chars range:NSMakeRange(0,numchars)];
	char *inptr=(char *)chars;
	size_t inlen=numchars*2;

	char bytes[1024];
	NSMutableData *data=[NSMutableData data];

	while(inlen)
	{
		char *outptr=bytes;
		size_t outlen=sizeof(bytes);

		if(iconv(ic,&inptr,&inlen,&outptr,&outlen)==-1)
		{
			if(errno!=E2BIG) return nil;
		}

		[data appendBytes:bytes length:outptr-bytes];
	}

	return [NSData dataWithData:data];
}

+(NSArray *)availableEncodingNames
{
}

static void IconvNameForEncodingName(char *cstr,NSString *name)
{
	static NSDictionary *replacementdictionary=nil;
	if(!replacementdictionary) replacementdictionary=[[NSDictionary alloc] initWithObjectsAndKeys:
	// Try to map normal names to weird iconv ones. Apparently these vary from implementation
	// to implementation though and this will be all wrong anyway. Sheesh.
	@"MACCENTRALEUROPE",@"x-mac-centraleurroman",
	@"MACICELAND",@"x-mac-icelandic",
	@"MACCROATIAN",@"x-mac-croatian",
	@"MACROMANIA",@"x-mac-romanian",
	@"MACCYRILLIC",@"x-mac-cyrillic",
	@"MACUKRAINE",@"x-mac-ukrainian",
	@"MACGREEK",@"x-mac-greek",
	@"MACTURKISH",@"x-mac-turkish",
	@"MACHEBREW",@"x-mac-hebrew",
	@"MACARABIC",@"x-mac-arabic",
	@"MACTHAI",@"x-mac-thai",
	// Still unknown:
	//x-mac-japanese
	//x-mac-trad-chinese
	//x-mac-korean
	//x-mac-devanagari
	//x-mac-gurmukhi
	//x-mac-gujarati
	//x-mac-simp-chinese
	//x-mac-tibetan
	//x-mac-symbol
	//x-mac-dingbats
	//x-mac-celtic
	//x-mac-gaelic
	//x-mac-farsi
	//x-mac-inuit
	//x-mac-roman-latin1
	nil];

	name=[name lowercaseString];

	NSString *replacement=[replacementdictionary objectForKey:name];
	if(replacement) name=replacement;

	NSAutoreleasePool *pool=[NSAutoreleasePool new];
	NSData *data=[name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
	int length=[data length];
	if(length>MaxEncodingNameLength) length=MaxEncodingNameLength;
	memcpy(cstr,[data bytes],length);
	cstr[length]=0;
	[pool release];
}

@end