Рекомендации по маршаллированной строке, которая может быть ASCII или UTF-16 - PullRequest
4 голосов
/ 29 июня 2010

Добро пожаловать на unsafe сушу.

Я делаю P / Invoke для устаревшей библиотеки, которая дает мне строку в C-стиле в виде 0 в виде неуправляемого байтового буфера неизвестной длины, которыйможет быть либо ASCII , либо UTF-16, но без указания каких-либо признаков, кроме самого потока байтов, который ...

. Сейчас у меня плохая схема, основанная напроверка на одиночные и двойные 0 байтов, чтобы решить, должен ли я создать управляемый String из Char* или SByte*.Схема явно ломается для каждой кодовой точки Unicode выше U+00FF.

Вот что у меня есть:

  • Адрес неуправляемого байтового буфера.
  • Неуправляемый байтовый буфер имеет неизвестную длину.
  • Неуправляемый байтовый буфер является либо строкой C в стиле C ASCII с 0 концом, либо строкой C в стиле UTF-16 с 0 терминалами.*

    Это то, что я хочу:

    • Создать правильный управляемый String из буфера неуправляемых байтов, будь то ASCII или UTF-16.

    Isэта проблема вообще решаема?

Ответы [ 3 ]

4 голосов
/ 01 июля 2010

Я не думаю, что это можно решить на 100%. Если в буфере содержится 6c 34 00 00 («l4»), это китайский знак для воды, или просто ASCII с более низкими L и 4? Но должно быть возможно угадать правильное "большую часть времени" в зависимости от конкретных строк.

Является ли UTF-16 младшим или (вероятно) старшим?

Наибольший риск - переполнение буфера. Например, если буфер начинается с 00, является ли это строкой ASCII нулевой длины или мы должны попытаться подготовить больше буфера, интерпретируя его как UTF-16BE?

2 голосов
/ 18 июля 2010

Эта проблема вообще решаема?

номер

Если вам известна длина строки (и что она четная), вы можете определить UTF-16 по наличию 00 байтов, дополняющих символы ISO-8859-1. (Даже в языке, не связанном с латинским алфавитом, все еще интенсивно используются пробел и новая строка ASCII.)

Но если вы зависите от нулевого завершения, это вам не поможет. Если вы ищете 00 00, вы можете косвенно сопоставить байт 00, который как раз оказывается сразу после нулевого терминатора. Хуже того, если в строке ASCII не двойное значение null завершено, вы будете проходить сразу за концом строки.

0 голосов
/ 29 июня 2010

Один из способов добавления уровня эвристики в простую схему обнаружения кодирования, основанную на проверке одиночных и двойных 0-байтов:

  1. Предположим, что маршализованный "контекст" из устаревшей библиотеки состоит из одной или нескольких строк.
  2. Если одна строка в таком контексте, вероятно, будет UTF-16, то все остальные строки в этом контексте также будут UTF-16.
  3. Таким образом, как только строка UTF-16 будет найдена с достаточно высокой степенью достоверности, смещение всех остальных обнаружений будет «вероятно, UTF-16».
  4. Если найдена строка «вероятно, не UTF-16», которая является строкой «определенно не UTF-8», то она также не может быть ASCII, поэтому установите ее как UTF-16.

Это даст гораздо более высокую скорость точно созданных управляемых String с.

...