Диапазон токенов CFStringTokenizer в C-строке UTF8 - PullRequest
1 голос
/ 29 декабря 2011

Я использую CFStringTokenizer, чтобы разбить загрузку текста на слова, но у меня возникают трудности при соединении с любой кодировкой, используемой CFString и UTF8.Учтите это:

NSString *theString = @"Lorem ipsum dolor sit amet!";

const char *theCString = [theString cStringUsingEncoding:NSUTF8StringEncoding];

tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, 
                                    (__bridge CFStringRef)theString, 
                                    CFRangeMake(0, [theString length]), 
                                    kCFStringTokenizerUnitWordBoundary, 
                                    locale);

while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) != kCFStringTokenizerTokenNone) {
    tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
    memcpy(resultPtr, theCString+tokenRange.location, tokenRange.length);
}

К сожалению, диапазон, сообщаемый токенизатором, неверен при попытке чтения из строки C, если встречаются какие-либо не-ascii символы.Как я могу получить правильный диапазон от токенизатора, чтобы можно было извлечь правильные символы из моей строки C?

Чтобы уточнить, вещи memcpy немного сложнее, чем выше, и необходимы для производительностина моем целевом устройстве, iPhone.Так что я даже не могу ничего сделать, как создать подстроку CFString и преобразовать ее, мне нужен диапазон в строке C.Есть ли способ сделать это без переопределения различных библиотек границ слов, чтобы заставить его работать в различных локалях, с которыми мне нужно работать?(это как можно больше, поэтому я не могу просто перебрать поиск '' к сожалению ..)

Алек

1 Ответ

1 голос
/ 29 декабря 2011

NSStrings и CFStrings работают в UTF-16, а не в UTF-8, но это не настоящая проблема.

У вашего кода две проблемы:

  1. Вы предполагаете, что индексы строки C соответствуют индексам исходной строки.
  2. Вы копируете и конвертируете всю строку в строку C UTF-8 одновременно.

# 1 является причиной несоответствия диапазона, а # 2 вызывает потенциально высокое использование памяти в зависимости от длины и содержимого строки. (UTF-8 может занимать до четырех байтов на символ в некоторых алфавитах, а затем добавлять один для терминатора строки C.)

Вы можете решить обе эти проблемы за одно изменение.

Создать NSMutableData для хранения вывода. Для каждого токена установите длину данных равную length диапазона; затем скажите строке, чтобы получить байты в требуемом диапазоне в нужной кодировке и сохранить их в буфере данных mutableBytes. NSString имеет метод с очень длинным селектором (кратко getBytes:::::::), который вы захотите использовать для этого.

Так как вы используете диапазон, относящийся к строке исключительно со строкой, нет никакого совпадения индекса / диапазона, и каждый токен будет выводиться правильно.

Если вам действительно нужна строка C, вы можете установить длину данных равной length + 1 диапазона, а затем установить последний байт на '\0' с отдельным назначением после получения байтов токена. (Без отдельного присвоения байт может содержать предыдущее значение.)

...