Преобразование многобайтового массива символов в массив QChar

У меня есть два буфера (примеры размеров):

char c[512];
QChar q[256];

Предполагая, что «c» содержит многобайтовую строку символов (UTF-8). Мне нужно преобразовать его в последовательность QChar и поместить в «q». Думаю, хорошим примером того, что мне нужно, может быть MultiByteToWideChar.
ВАЖНО: эта операция не должна включать никаких явных или неявных выделений памяти, за исключением, может быть, дополнительных выделений в стеке. Пожалуйста, не отвечайте, если вы не уверены, что означает вышеизложенное.


person Pavele    schedule 05.04.2019    source источник
comment
Добро пожаловать в StackOverflow! Ваш вопрос вызывает у меня (и, думаю, у других тоже) вопрос: почему нет выделений? Это серьезно ограничивает использование любого Qt из-за того, что Qt использует PIMPL в большинстве классов.   -  person Martin Hennings    schedule 05.04.2019
comment
Кроме того, знаете ли вы кодек вашей многобайтовой строки? (Наверное, из-за фиксированных размеров массива в соотношении 2:1)   -  person Martin Hennings    schedule 05.04.2019
comment
Привет Мартин. Логичный вопрос. Здесь речь идет о фрагментации памяти и ее использовании при работе с высокой частотой кадров. Поэтому в конкретном случае PIMPL немного обременительна. Насчет кодеков - с этим Qt справляется (например при создании QString из QByteArray или const char*) больше ничего не хочу. Просто внешние заполнители. Windows API предоставляет такие функции, которые преобразуют широкие символы в многобайтовые строки и наоборот. Почему Qt не работает? (Или так?)   -  person Pavele    schedule 05.04.2019
comment
Я позволю себе не согласиться - Qt интерпретирует const char * как UTF-8, за исключением случаев, когда вы явно указываете обратное. Ваш массив символов может содержать 512 символов. В UTF-8 это будет до 512 QChars.   -  person Martin Hennings    schedule 05.04.2019
comment
Под многобайтностью вы, вероятно, подразумеваете текущую кодовую страницу ansi в Windows, не так ли? (большинство из них на самом деле однобайтовые :)) Похоже, не все знают этот термин, может быть, было бы лучше уточнить его в вопросе.   -  person max630    schedule 07.04.2019


Ответы (1)


QChar содержит ushort в качестве единственного члена, поэтому его размер равен sizeof(ushort).

В контексте QString он представляет "символы" UTF-16 (кодовые точки).

Так что здесь все дело в кодировке.

Если вы знаете, что ваш char const * представляет собой данные UTF-16 с тем же порядком байтов/порядком байтов, что и ваша система, просто скопируйте его:

memcpy(q, c, 512);

Если вы хотите инициализировать QString данными const char *, вы можете просто интерпретировать их как UTF-16, используя QString::fromRawData():

QString strFromData = QString::fromRawData(reinterpret_cast<QChar*>(c), 256);
// where 256 is sizeof(c) * sizeof(char) / sizeof(QChar)

Тогда вам даже не нужен массив QChar q[256].

Если вы знаете, что ваши данные имеют формат UTF-8, вам следует использовать QString::fromUtf8(), а затем просто получить доступ к внутренней памяти с помощью QString::constData().

Используя QString с UTF-8, я не знаю ни одного способа полностью предотвратить выделение кучи. Но упомянутый способ должен выделять только дважды: один раз для PIMPL QString, один раз для строковых данных UTF-16.


Если ваши входные данные закодированы как UTF-8, ответ Нет: вы не можете преобразовать их с помощью Qt.

Доказательство: просмотр исходного кода qtbase/src/ corelib/codecs/qutfcodec.cpp мы видим, что все функции для кодирования/декодирования создают новых QString/QByteArray экземпляров. Никакая функция не работает с двумя массивами, как в вашем вопросе.

person Martin Hennings    schedule 05.04.2019
comment
Спасибо, Мартин. Это было бы просто. Как насчет UTF-8? Думаю, хорошим примером того, что мне нужно, может быть MultiByteToWideChar (docs.microsoft.com/en-us/windows/desktop/api/stringapiset/) - person Pavele; 05.04.2019
comment
Спасибо, Мартин. Я думаю, это означает, что нет, нет никакого способа сделать это. - person Pavele; 08.04.2019
comment
Даже при использовании MultiByteToWideChar нужно указывать кодировку. - person Martin Hennings; 08.04.2019
comment
Я считаю, что либо ваши ограничения слишком жесткие, либо Qt не подходит для этой работы. Вероятно, вы могли бы выполнить преобразование с помощью Qt без выделения строк в куче, например. с QTextStream, но вам понадобится QTextCodec, и он снова будет создан в куче. - person Martin Hennings; 08.04.2019