home link download back number special issue

HMDT - Special Issue / CoreFoundation の秘密 / String Services - 構造を見るための前提


- String Servcies -
構造を見るための前提

CFString ってのは CoreFoundation で文字列を扱うためのオブジェクトだ。プログラミングにおける文字列の扱いってのは、歴史的に見てやっかいな問題を多数かかえているよね。たとえば、エンコーディング、たとえばフォーマット、たとえば 1 byte 圏と 2 byte 圏の意識の差。もちろん、パフォーマンスも重要。

それらのことを解決するため、CFString の構造は巧妙に(複雑に)できている。そいつを理解するための前提をちょっと書いてみた。

CFString のフォーマット

CFString は次の 3 つのフォーマットを取り扱うんだ。

  • C string
  • Pascal string
  • Unicode characters

C string は、終端が NULL である char の配列、Pascal string は、先頭に配列の長さが代入されている char の配列、と定義できる。これらに加えて、Unicode の配列も取り扱う。Pascal string が含まれているところが、Mac プラットフォームだな。

で、CFString は基本的には Unicode の配列とみなせる。「基本的」にはな。ユーザからはそうやって取り扱えるんだけど、実体は異なっていることがあるんだ。メモリ節約のために、ASCII キャラクタ用には 8 bit しかメモリを確保しないことがある。また、1 つの CFString インスタンスに対して、1 つながりのメモリを確保しないこともある。だから、文字列にアクセスするときに、先頭ポインタを取り出して、そこからたぐってアクセスする、ということは推奨されない。そこんとこ注意。

CFStringRef と CFMutableStringRef

CFString には、CFStringRef と CFMutableStringRef っていう 2 つのオブジェクトがあるんだ。

CoreFoundation/String.subproj/CFBase.h
typedef const struct __CFString * CFStringRef;
typedef struct __CFString * CFMutableStringRef;

CFStringRef は固定長文字列、CFMutableStringRef は可変長文字列。どちらも同じ __CFString* のことだけど、もちろん内部では異なっている。CFStringRef の方が効率がいいので、使える場合はできるだけ CFStringRef を使うことをすすめるよ。

Copy と NoCopy

CFString のインスタンスを作る時に、自前のバッファを持つか、外部のバッファを参照するかどうか設定することができる。

自前のバッファを持つときは、必要なサイズのメモリを確保する。初期の文字列が与えられてるときは、それをコピーする。この場合は、このインスタンスを解放した時に、バッファも解放されるよ。

外部のバッファを参照するときは、メモリも確保しないしコピーもしない。効率はいいけど、外部バッファを自分で管理する必要あり。インスタンスを解放しても、外部バッファはそのままだよ。

というのが前提。一言で言うと、「8 bit か 16 bit の配列(混在可)で、固定長か可変長で、長さ情報が埋め込まれているかもしれなくて、内部か外部にバッファがある」ってことだ。なんでもありだな、おい。これを 1 つの構造体で実現しようとするから、けっこう無茶がある。次の節で詳しく見るぜ。

(Nov. 11, 2002)


Home | Link | Download | Back Number | Speciall Issue

mailto: mkino@xd5.so-net.ne.jp

HMDT