Я скручиваю метод класса, который преобразует UTF8 символ в его представительную кодовую точку Unicode. Вот мои кандидаты в прототипы:
static uint32_t Utf8ToWStr( uint8_t Byte1, uint8_t Byte2 = 0x00,
uint8_t Byte3 = 0x00, uint8_t Byte4 = 0x00,
uint8_t Byte5 = 0x00, uint8_t Byte6 = 0x00);
static uint32_t Utf8ToWStr(const std::vector<uint8_t> & Bytes);
В моих приложениях;
Byte1
будет единственным ненулевым байтом примерно в 90% случаев.
Byte1
а также Byte2
будут единственными ненулевыми байтами примерно в 9% случаев.
Byte1
, Byte2
а также Byte3
будет единственным ненулевым байтом менее 1% времени.
Byte4
, Byte5
а также Byte6
почти всегда будет ноль.
Какой прототип мне лучше выбрать по скорости?
Наверное, нет.
Подумайте о коде, вызывающем эту функцию — им, вероятно, придется перепрыгнуть через огромные обручи, чтобы использовать ее:
uint8_t c1 = *cursor++;
uint8_t c2 = 0;
uint8_t c3 = 0;
uint8_t c4 = 0;
uint8_t c5 = 0;
uint8_t c6 = 0;
if(c1 >= 0x80)
c2 = *cursor++;
if(c1 >= 0xc0)
c3 = *cursor++;
if(c1 >= 0xe0)
c4 = *cursor++;
if(c1 >= 0xf0)
c5 = *cursor++;
if(c1 >= 0xf8)
c6 = *cursor++;
uint32_t wch = Utf8ToWStr(c1, c2, c3, c4, c5, c6);
Я искренне сомневаюсь, что этот интерфейс полезен.
Мой обычный интерфейс для преобразования процедур
bool utf8_to_wchar(uint8_t const *&cursor, uint8_t const *end, uint32_t &result);
Возвращаемое значение используется для передачи ошибок (например, как ваша функция будет реагировать на параметры (0x81, 0x00)
?
И последнее, но не менее важное: вы можете захотеть иметь режим, который определяет, должна ли денормализованная UTF-8 выдавать ошибку — из POV безопасности рекомендуется запретить кодирование. U+003F
как 0x80 0x3f
,
Я бы использовал
// if you want it as simple as possible
typedef uint8_t data_t[6];
или же
// if you like C++11
typedef std::array<uint8_t, 6> data_t;
или же
// if it should be extensible
typedef struct { uint8_t data[6]; } data_t;
указать на природу фиксированной длины входных данных во время компиляции. Таким образом, вы сэкономите много времени на вводе функции.
Использование вектора переменной длины мне как-то показало бы, что может быть больше или меньше или пустых данных.
std :: vector, вероятно, медленнее, потому что он хранит эти байты в куче и выделяет для них память.
Вы также можете просто передать указатель на байтовый массив или использовать std :: array при использовании C ++ 11.