home link download back number special issue

HMDT - Special Issue / CoreFoundation の秘密 / String Services - 可変長文字列の作り方


- String Servcies -
可変長文字列の作り方

ここでは可変長文字列の作り方を見るぜ。定数文字列固定文字列はそれぞれ前の項を参照のこと。

可変長文字列を作る API

CFString では可変長の文字列 CFMutableString をサポートしている。このインスタンスを作るのは、次の 3 つの API。

  • CFStringCreateMutable
  • CFStringCreateMutableCopy
  • CFStringCreateMutableWithExternalCharactersNoCopy

この 3 つから CFMutableString を作るための関数 __CFStringCreateMutableFunnel() を呼び出しているんだ。こいつの定義はこれ。

CoreFoundation/String.subporj/CFString.c
CoreFoundation/string.subproj/CFString.c
CF_INLINE CFMutableStringRef  __CFStringCreateMutableFunnel(
                CFAllocatorRef alloc, 
                CFIndex maxLength, 
                UInt32 additionalInfoBits)

引数には文字列の長さ maxLength はあるけど、文字列データがないことに注意。つまり、空文字列しか作らないんだ。

__CFStringCreateMutableFunnel() の実装

__CFStringCreateMutableFunnel() は空文字列しか作らない。だから、固定文字列のインスタンスを作る __CFStringCreateImmutableFunnel3() と比べると、非常に簡単だ。固定文字列を作るときは、あらかじめ渡された文字列データが C 文字列か Pascal 文字列か判断しないといけなかったし、Unicode にエンコードしてやらないといけなかった。でもここではそれがないんだよね。

というわけで、実装を見てみよう。とても短い。

CoreFoundation/String.subproj/CFString.c
CF_INLINE CFMutableStringRef  __CFStringCreateMutableFunnel(
                CFAllocatorRef alloc, 
                CFIndex maxLength, 
                UInt32 additionalInfoBits) 
{
    CFMutableStringRef str;
    Boolean hasExternalContentsAllocator = 
            (additionalInfoBits & __kCFHasContentsAllocator) ? true : false;

    if (alloc == NULL) alloc = __CFGetDefaultAllocator();

    // Note that if there is an externalContentsAllocator, 
    // then we also have the storage for the string allocator...
    /* インスタンスを作成 */
    str = (CFMutableStringRef)_CFRuntimeCreateInstance(
             alloc, 
             __kCFStringTypeID, 
             sizeof(void *) + sizeof(UInt32) * 3 + 
                 (hasExternalContentsAllocator ? sizeof(CFAllocatorRef) : 0), 
             NULL);
    if (str) {
        if (__CFOASafe) __CFSetLastAllocationEventName(
                        str, "CFString (mutable)");

        /* _info ビットを設定 */
        __CFStrSetInfoBits(str, __kCFIsMutable | additionalInfoBits);
        str->variants.externalMutable.buffer = NULL;
        __CFStrSetExplicitLength(str, 0);
        str->variants.externalMutable.gapEtc = 0;
        if (maxLength != 0) __CFStrSetIsFixed(str);
        __CFStrSetDesiredCapacity(
                str, (maxLength == 0) ? DEFAULTMINCAPACITY : maxLength);
        __CFStrSetCapacity(str, 0);
    }
    return str;
}

インスタンスを作成して、_info ビットを設定するぐらいだ。インスタンスの大きさは、CFStringCreateMutable() の引数の値による。

(Nov. 23, 2002)


Home | Link | Download | Back Number | Speciall Issue

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

HMDT