/**
 * Determine the common suffix of two strings.
 * @param text1 First string.
 * @param text2 Second string.
 * @return The number of characters common to the end of each string.
 */
CFIndex diff_commonSuffix(CFStringRef text1, CFStringRef text2) {
  // Performance analysis: http://neil.fraser.name/news/2007/10/09/
  CFIndex text1_length = CFStringGetLength(text1);
  CFIndex text2_length = CFStringGetLength(text2);

  CFStringInlineBuffer text1_inlineBuffer, text2_inlineBuffer;
  CFStringInitInlineBuffer(text1, &text1_inlineBuffer, CFRangeMake(0, text1_length));
  CFStringInitInlineBuffer(text2, &text2_inlineBuffer, CFRangeMake(0, text2_length));

  UniChar char1, char2;
  CFIndex n = MIN(text1_length, text2_length);

  for (CFIndex i = 1; i <= n; i++) {
    char1 = CFStringGetCharacterFromInlineBuffer(&text1_inlineBuffer, (text1_length - i));
    char2 = CFStringGetCharacterFromInlineBuffer(&text2_inlineBuffer, (text2_length - i));

    if (char1 != char2) {
      return i - 1;
    }
  }
  return n;
}
示例#2
0
void stringGettingAtCharactersExample(void) {

    CFStringRef str;
    const UniChar *chars;

    show(CFSTR("------------------Character Manipulations---------------"));

    // Create some test CFString
    str = CFStringCreateWithCString(NULL, "Hello World", kCFStringEncodingASCII);

    show(CFSTR("Original String : %@"), str);

    // The fastest way to get the contents; this might return NULL though
    // depending on the system, the release, etc, so don't depend on it 
    // (unless you used CFStringCreateMutableWithExternalCharactersNoCopy())
    chars = CFStringGetCharactersPtr(str);

    // If that fails, you can try copying the UniChars out
    // either into some stack buffer or some allocated piece of memory...
    // Using the former is fine, but you need to know the size; the latter
    // always works but requires allocating some memory; not too efficient.
    if (chars == NULL) {
        CFIndex length = CFStringGetLength(str);
        UniChar *buffer = (UniChar*)malloc(length * sizeof(UniChar));
        CFStringGetCharacters(str, CFRangeMake(0, length), buffer);
        // Process the chars...
        free(buffer);
    }
    else
        show(CFSTR("Characters      : %@"), str);

    // You can use CFStringGetCharacterAtIndex() to get at the characters one at a time,
    // but doing a lot of characters this way might get slow...
    // An option is to use "inline buffer" functionality which mixes the convenience of
    // one-at-a-time char access with efficiency of bulk access
    {
        CFStringInlineBuffer inlineBuffer;
        CFIndex length = CFStringGetLength(str);
        CFIndex cnt;

        CFStringInitInlineBuffer(str, &inlineBuffer, CFRangeMake(0, length));

        for (cnt = 0; cnt < length; cnt++) {
            UniChar ch = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, cnt);
            // Process character...
	         (void)ch;   // Dummy processing to prevent compiler warning...
        }
    }
    
}
示例#3
0
static void printObjAsString(CFStringRef obj) {
	CFStringInlineBuffer buf;
	CFIndex len = CFStringGetLength(obj);
	CFStringInitInlineBuffer(obj, &buf, CFRangeMake(0, len));
	printf("\"");
	for (CFIndex i = 0; i < len; ++ i) {
		UniChar c = CFStringGetCharacterFromInlineBuffer(&buf, i);
		if (c == '"' || c == '\\')
			printf("\\%C", c);
		else if (c >= ' ' && c <= '\x7F')
			printf("%C", c);
		else if (c == '\t')
			printf("\\t");
		else if (c == '\n')
			printf("\\n");
		else
			printf("\\U%04x", c);
	}
	printf("\"");
}
__private_extern__ CFIndex CFPreferencesAppIntegerValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) {
    CFPropertyListRef value;
    CFIndex result;
    CFTypeID typeID = 0;
    Boolean valid;
    CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__);
    CFAssert1(key != NULL, __kCFLogAssertion, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__);

    value = CFPreferencesCopyAppValue(key, appName);
    if (!keyExistsAndHasValidFormat) {
        keyExistsAndHasValidFormat = &valid;
    }
    if (!value) {
        *keyExistsAndHasValidFormat = false;
        return 0;
    }
    typeID = CFGetTypeID(value);
    if (typeID == CFStringGetTypeID()) {
        SInt32 charIndex = 0;
        SInt32 intVal;
        CFStringInlineBuffer buf;
        Boolean success;
        CFStringInitInlineBuffer((CFStringRef)value, &buf, CFRangeMake(0, CFStringGetLength((CFStringRef)value)));
        success = __CFStringScanInteger(&buf, NULL, &charIndex, false, &intVal);
        *keyExistsAndHasValidFormat = (success && charIndex == CFStringGetLength((CFStringRef)value));
        result = (*keyExistsAndHasValidFormat) ? intVal : 0;
    } else if (typeID == CFNumberGetTypeID()) {
        *keyExistsAndHasValidFormat = !CFNumberIsFloatType((CFNumberRef)value);
        if (*keyExistsAndHasValidFormat) {
            CFNumberGetValue((CFNumberRef)value, kCFNumberCFIndexType, &result);
        } else {
            result = 0;
        }
    } else {
        // Unknown type
        result = 0;
        *keyExistsAndHasValidFormat = false;
    }
    CFRelease(value);
    return result;
}
/* There has got to be an easier way to do this.  For now we based this code
   on CFNetwork/Connection/URLResponse.cpp. */
static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) {
    /* The format of the cache control header is a comma-separated list, but
       each list element could be a key-value pair, with the value quoted and
       possibly containing a comma. */
    CFStringInlineBuffer inlineBuf;
    CFRange componentRange;
    CFIndex length = CFStringGetLength(cacheControlHeader);
    bool done = false;
    CFCharacterSetRef whitespaceSet = CFCharacterSetGetPredefined(kCFCharacterSetWhitespace);
    CFStringRef maxAgeValue = NULL;

    CFStringInitInlineBuffer(cacheControlHeader, &inlineBuf, CFRangeMake(0, length));
    componentRange.location = 0;

    while (!done) {
        bool inQuotes = false;
        bool foundComponentStart = false;
        CFIndex charIndex = componentRange.location;
        CFIndex componentEnd = -1;
        CFRange maxAgeRg;
        componentRange.length = 0;

        while (charIndex < length) {
            UniChar ch = CFStringGetCharacterFromInlineBuffer(&inlineBuf, charIndex);
            if (!inQuotes && ch == ',') {
                componentRange.length = charIndex - componentRange.location;
                break;
            }
            if (!CFCharacterSetIsCharacterMember(whitespaceSet, ch)) {
                if (!foundComponentStart) {
                    foundComponentStart = true;
                    componentRange.location = charIndex;
                } else {
                    componentEnd = charIndex;
                }
                if (ch == '\"') {
                    inQuotes = (inQuotes == false);
                }
            }
            charIndex ++;
        }

        if (componentEnd == -1) {
            componentRange.length = charIndex - componentRange.location;
        } else {
            componentRange.length = componentEnd - componentRange.location + 1;
        }

        if (charIndex == length) {
            /* Fell off the end; this is the last component. */
            done = true;
        }

        /* componentRange should now contain the range of the current
           component; trimmed of any whitespace. */

        /* We want to look for a max-age value. */
        if (!maxAgeValue && CFStringFindWithOptions(cacheControlHeader, CFSTR("max-age"), componentRange, kCFCompareCaseInsensitive | kCFCompareAnchored, &maxAgeRg)) {
            CFIndex equalIdx;
            CFIndex maxCompRg = componentRange.location + componentRange.length;
            for (equalIdx = maxAgeRg.location + maxAgeRg.length; equalIdx < maxCompRg; equalIdx ++) {
                UniChar equalCh = CFStringGetCharacterFromInlineBuffer(&inlineBuf, equalIdx);
                if (equalCh == '=') {
                    // Parse out max-age value
                    equalIdx ++;
                    while (equalIdx < maxCompRg && CFCharacterSetIsCharacterMember(whitespaceSet, CFStringGetCharacterAtIndex(cacheControlHeader, equalIdx))) {
                        equalIdx ++;
                    }
                    if (equalIdx < maxCompRg) {
                        maxAgeValue = CFStringCreateWithSubstring(kCFAllocatorDefault, cacheControlHeader, CFRangeMake(equalIdx, maxCompRg-equalIdx));
                    }
                } else if (!CFCharacterSetIsCharacterMember(whitespaceSet, equalCh)) {
                    // Not a valid max-age header; break out doing nothing
                    break;
                }
            }
        }

        if (!done && maxAgeValue) {
            done = true;
        }
        if (!done) {
            /* Advance to the next component; + 1 to get past the comma. */
            componentRange.location = charIndex + 1;
        }
    }

    return maxAgeValue;
}