Изменения API MultiByteToWideChar в Vista - PullRequest
2 голосов
/ 10 августа 2010

Мне нужна опция для преобразования строки в широкую строку с двумя различными режимами:

  1. Игнорировать недопустимые символы
  2. Прервать преобразование, если встречается недопустимый символ:

В Windows XP я мог бы сделать это:

bool ignore_illegal; // input

DWORD flags = ignore_illegal ? 0 : MB_ERR_INVALID_CHARS;

SetLastError(0);

int res = MultiByteToWideChar(CP_UTF8,flags,"test\xFF\xFF test",-1,buf,sizeof(buf));
int err = GetLastError();

std::cout << "result = " << res << " get last error = " << err; 

Теперь, в XP, если игнорировать недопустимые символы истины, я получу:

result = 10 get last error = 0

А в случае игнорирования недопустимы символыfalse Я получаю

result = 0 get last error = 1113 // invalid code

Итак, при достаточно большом буфере достаточно проверить результат! = 0;

Согласно документации http://msdn.microsoft.com/en-us/library/dd319072(VS.85).aspx есть изменения API, так какэто меняется на Vista?

Ответы [ 2 ]

3 голосов
/ 15 августа 2010

Я думаю, что он заменяет недопустимые единицы кода символом замены (U + FFFD), как это предусмотрено стандартом Unicode.Следующий код

#define STRICT
#define UNICODE
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <cstdlib>
#include <iostream>
#include <iomanip>


void test(bool ignore_illegal) {
    const DWORD flags = ignore_illegal ? 0 : MB_ERR_INVALID_CHARS;
    WCHAR buf[0x100];
    SetLastError(0);
    const int res = MultiByteToWideChar(CP_UTF8, flags, "test\xFF\xFF test", -1, buf, sizeof buf);
    const DWORD err = GetLastError();
    std::cout << "ignore_illegal = " << std::boolalpha << ignore_illegal
        << ", result = " << std::dec << res
        << ", last error = " << err
        << ", fifth code unit = " << std::hex << static_cast<unsigned int>(buf[5])
        << std::endl;
}


int main() {
    test(false);
    test(true);
    std::system("pause");
}

выдает следующий вывод в моей системе Windows 7:

ignore_illegal = false, result = 0, last error = 1113, fifth code unit = fffd
ignore_illegal = true, result = 12, last error = 0, fifth code unit = fffd

Таким образом, коды ошибок остаются прежними, но длина уменьшается на два, указывая на двакодовые точки замены, которые были вставлены.Если вы запускаете мой код на XP, пятая кодовая точка должна быть U + 0020 (символ пробела), если две недопустимые единицы кода были удалены.

0 голосов
/ 10 августа 2010
WCHAR *pstrRet = NULL;

int nLen = MultiByteToWideChar(CP_UTF8, 0, pstrTemp2, -1, NULL, 0);

pstrRet = new WCHAR[nLen];

int nConv = MultiByteToWideChar(CP_UTF8, 0, pstrTemp2, -1, pstrRet, nLen);

if (nConv == nLen)

{

// Success! pstrRet should be the wide char equivelant of pstrTemp2

}

if (pstrRet)

delete[] pstrRet;

Я думаю, что так оно и есть на Vista, найденном на каком-то форуме :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...