Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
со строками в Линуксе нужно работать в кодировке UTF-8 и в типе std::string, а в Windows строки должны быть в Юникоде (тип std::wstring). Почему? Потому что это by design операционных систем. Хранить строки в std::wstring в Линуксе крайне накладно, поскольку один символ wchar_t занимает 4 байта (в Windows — 2 байта),Разве это бидезигн? Можно и там и там как угодно работать, как сами ниже говорите — в линуксе строки можно же и в wchar_t хранить. В винде sdk/api он двухбайтовый, потому что там исторически сложилось так с древних времён ещё, хотя это неправильно. И там в этих двух байтах просто символы UTF-16 хранятся (либо если UTF-16 символ окажется четырёхбайтовым, то в двух wchar_t ). UTF-8 здесь и ниже по тексту — это же просто вопрос кодирования юникода, а выбор строки, чаров итд — вопрос хранения самих символов. Вы намеренно смешиваете понятия (ровно как и понятия «в винде строки в юникоде» и «в линуксе строки в utf-8»), либо я не понимаю чего-то тут?
Статья называется «кроссплатформенная работа со строками», а не то как писать «100% кроссплатформенное приложение».
Плюс, как в таком случае делать операции вида «заменить три последних символа»? Все с помощью boost.locale?
Для QString и ICU это будут методы QString и UnicodeString. В случае использования boost.locale это будут внешние методы над строками, что сильно затруднит чтение кода.
Для Windows при минимальном использовании WinAPI/COM/whatever таких «внешних выходов» будет дофига и больше. ИМХО, это будет архитектурное решение, порождающее избыточное количество кода, который не имеет отношения к решаемой задачи а служит клеем между абстракциями. Как показывает практика, такой код труднее читать и поддерживать — тривиально больше кода.
public class MyKewlInputStream(const std::wstring&)
defined by system-specific implementation
WideString wsFileName(fileName.c_str());
PMString pmFileName = PMString(wsFileName);
IDFile idFileName;
FileUtils::PMStringToIDFile(pmFileName, idFileName);
InterfacePtr<IPMStream> stream(StreamUtil::CreateFileStreamWriteLazy(
idFileName, kOpenOut | kOpenTrunc));
// Наконец-то у нас что-то system specific InDesign API и можно с этим работать
#ifdef WINDOWS
// клятый фотошоп нам подсунул под виндой UTF16Char*
uint16* result = fSpec->mReference;
numUtf16 = (uint32)wcslen((const wchar_t*)result);
// для остроты ощущений это все еще в Java сунем
jstring filePath = env->NewString(result, numUtf16);
...
#else
// а под маком Fork aka FSIORefNum, добро пожаловать в отладчик
CFStringRef path = FSRefToCFString(&fSpec->mReference);
uint32 numUtf16 = (uint32)CFStringGetLength(path);
UniChar* result = nil;
if(numUtf16 > 0) {
result = new UniChar[numUtf16+1];
CFRange rangeToCopy;
rangeToCopy.location = 0;
rangeToCopy.length = numUtf16;
CFStringGetCharacters(path, rangeToCopy, result);
// для остроты ощущений это все еще в Java сунем
jstring filePath = env->NewString(result, numUtf16);
...
}
CFRelease(path);
#endif
nsresult GetAsText(
const nsACString &aCharset,
const char* aData,
PRUint32 dataLength,
nsAString& aResult)
{
nsresult rv;
nsCAutoString charsetGuess = aCharset;
nsCAutoString charset;
nsCOMPtr<nsICharsetAlias> alias = do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = alias->GetPreferred(charsetGuess, charset);
NS_ENSURE_SUCCESS(rv, rv);
...
}
(обратите внимание — в 10-строчнике мы видим 3 разных ns*String и const char* до кучи)typedef char utf8_char;
class utf8_char_traits: public std::char_traits<utf8_char> {};
typedef std::basic_string<utf8_char, utf8_char_traits> utf8_string;
Кроссплатформенная работа со строками на C++