名前(NSString)からNSStringEncodingを得る

せっかくMacをもっているんだから、Objective-C (Cocoa) を使ってみないともったいない気がしたんだ。

#import <Cocoa/Cocoa.h>
@interface Foo : NSObject {
  int val;
}
-init:(int) v;
-add:(int) v;
-(int) get;
@end

@implementation Foo
-init:(int) v
{
  val = v;
  return self;
}
-add:(int) v
{
  val += v;
  return self;
}
-(int) get
{
  return val;
}
@end

int main(void)
{
  Foo *f = [[Foo alloc] init:5];
  [f add:6];
  NSLog(@"%d", [f get]);
  [f relese];
  return 0;  

こんなObjective-Cのコードを初めて見たときには、メッセージ方式の呼び出し方や*1クラスのインターフェイス&実装の書き方に驚くとともに、
「うげー、なんじゃこりゃ」という不快感も感じた。
でもある程度読み書きしていると、だんだんと慣れてくるものだな。
ただ、Core Foundation 等のAPIや定数の名前の長さはどうにかして欲しい。。。タイプするのが面倒。


んで、今 NSString についていろいろやってみてたんだけど、エンコーディング名からNSStringEncodingを得る方法が少々面倒だったのでメモ。
もっといい方法があったら教えてください。

NSStringEncoding getEncodingFromName(const NSString *enc_name)
{
  CFStringEncoding cf_enc = CFStringConvertIANACharSetNameToEncoding((CFStringRef)enc_name);
  if (cf_enc == kCFStringEncodingInvalidId) {
    NSLog(@"error");
    return -1; 
  }
  return CFStringConvertEncodingToNSStringEncoding(cf_enc);
}

CFStringRef と NSString は特別な変換無しに相互変換可能だそうだ。これはかなり衝撃的だった。

NSString is “toll-free bridged” with its Core Foundation counterpart, CFString (see CFStringRef). This means that the Core Foundation type is interchangeable in function or method calls with the bridged Foundation object. Therefore, in a method where you see an NSString * parameter, you can pass a CFStringRef, and in a function where you see a CFStringRef parameter, you can pass an NSString instance (you cast one type to the other to suppress compiler warnings). This also applies to your concrete subclasses of NSString. See Interchangeable Data Types for more information on toll-free bridging.

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html


これでだいたい上手くいくんだけど、Shift_JIS, CP932周りがよくわからん。
enc_name に CP932 を渡すと 8 = NSShiftJISStringEncoding が返るんだが、Shift_JIS を渡すと 0x80000a01 が返る。
名前が食い違っているんだけど。。。
「〜」を enc_name=@"Shift_JIS" で解釈すると U+301C(WAVE DASH) で、enc_name=@"CP932" だと U+FF5E(FULLWIDTH TILDE) だった。

追記

~(チルダ)に関しても試してみた。
CP932(=8) だと U+007E(TILDE) だが、Shift_JIS(=0x80000a01) だと U+203E(OVERLINE) と解釈された。
これだからエンコーディングは嫌いなんだ!さっさとUTF-8なりに統一しちゃってくれ!

*1:しかもダックタイピング。対応するメソッドが無くても警告は出すけどコンパイルできちゃう