iconvを使ってNSDataからNSStringを生成する

Oreyonで使ったコードはこんな感じです。元ネタあるような気がするので思い出したら追記

#include <iconv.h>
#include <errno.h>

#define __iconvBufferLength 1024

+(NSString *)stringWithData:(NSData *)data iconvEncoding:(NSString *)encodingString {
	iconv_t descriptor = iconv_open("UTF-16//IGNORE", [encodingString UTF8String]);
	size_t inbytesleft = [data length];
	char* inbuf = (char*)[data bytes];
	
	size_t outbytesleft;
	char* outbuf = malloc(__iconvBufferLength);
	char* outbyteslength = NULL;
	NSMutableString *resultString = [NSMutableString string];
	errno = E2BIG;
	
	while (errno == E2BIG) {
		outbytesleft = __iconvBufferLength;
		outbyteslength = outbuf;
		errno = 0;
		iconv(descriptor, &inbuf, &inbytesleft, &outbyteslength, &outbytesleft);
		if (errno == EILSEQ || errno == EINVAL) break;
		NSString *part = [[[NSString alloc] initWithBytes:outbuf
						  length:__iconvBufferLength-outbytesleft
												 encoding:NSUTF16StringEncoding] autorelease];
		[resultString appendString:part];
	}
	iconv_close(descriptor);
	free(outbuf);
	
	return resultString;
}

追記:使い方

多分リンカフラグ要ります。http://d.hatena.ne.jp/RNatori/20090601
呼び出すとき、encodingStringにはiconvに渡すエンコードのタイプを表す文字列を渡します。
具体的には、@"UTF-8"だの@"EUC-JP"だの@"CP932"だの@"SHIFT-JIS"だのですね。ターミナルでiconv --listして出てくるのはだいたいiPhoneでも使える…んじゃないかな

  • エラーの際にdouble freeになってったぽいのでこっそり改訂
  • ループのたびにmallocとfreeを繰り返してたのでこっそり改訂