Переносимость программ между Windows и UNIX (wchar_t совместимость)
- Admin
- Сообщения: 1
- Зарегистрирован: 16 дек 2014, 08:17
- Контактная информация:
Переносимость программ между Windows и UNIX (wchar_t совместимость)
Здесь описан только один аспект совместимости приложений по wchar_t.
Размер wchar_t различается для этих платформ. В Windows wchar_t = 2 байтам, в UNIX - 4-м.
Для g++(clang++) можно использовать опцию -fshort-wchar, чтобы принудительно задать для wchar_t размер 2 байта. Но это еще не все. Строковые функции в стандартной библиотеке UNIX скомпилированы для 4-х байтового условия, и следовательно будут не совместимы с вашими 2-х байтовыми строками. Выход - подмена библиотечных функций. Как это сделать для С-функций и STL-string показано ниже.
I. Подмена строковых функций.
Используем наследование.
Объявление:
Реализация:
Использование функций в поиске или сортировке.
II. Подмена класса wstring из STL
Здесь необходимо переопределить char_traits в классе basic_string.
Использование.
Такой подход обеспечивает хорошую переносимость программ между разными платформами.
Размер wchar_t различается для этих платформ. В Windows wchar_t = 2 байтам, в UNIX - 4-м.
Для g++(clang++) можно использовать опцию -fshort-wchar, чтобы принудительно задать для wchar_t размер 2 байта. Но это еще не все. Строковые функции в стандартной библиотеке UNIX скомпилированы для 4-х байтового условия, и следовательно будут не совместимы с вашими 2-х байтовыми строками. Выход - подмена библиотечных функций. Как это сделать для С-функций и STL-string показано ниже.
I. Подмена строковых функций.
Используем наследование.
Объявление:
Код: Выделить всё
struct wstr
{
static size_t strlen(const wchar_t* str);
static int strcmp(const wchar_t* str1, const wchar_t* str2);
static wchar_t* strcpy(wchar_t* dst, const wchar_t* src);
…
// Описывать нужно только те функции, которые используются в программе.
};
Реализация:
Код: Выделить всё
size_t wstr::strlen(const wchar_t* str)
{
wchar_t *ptr = (wchar_t*)str;
while (*ptr != 0)
ptr++;
return ptr - str;
}
int wstr::strcmp(const wchar_t* str1, const wchar_t* str2)
{
while (*str1 || *str2)
{
if (*str1 < *str2)
return -1;
if (*str1 > *str2)
return 1;
++str1, ++str2;
}
return 0;
}
wchar_t* wstr::strcpy(wchar_t* dst, const wchar_t* src)
{
wchar_t *ptr = (wchar_t*)dst;
while (*src != 0)
*ptr++ = *src++;
*ptr = 0;
return dst;
}
Использование функций в поиске или сортировке.
Код: Выделить всё
class MyClass : public wstr
{
public:
…
private:
int static compare(const char **arg1, const char **arg2);
int static wcompare(const wchar_t **arg1, const wchar_t **arg2);
};
int MyClass::compare(const char **arg1, const char **arg2)
{
return ::strcmp((char*)arg1, (char*)arg2); // вызов стандартной ANSI-функции
}
int MyClass::wcompare(const wchar_t **arg1, const wchar_t **arg2)
{
return strcmp((wchar_t*)arg1, (wchar_t*)arg2); // вызов подмененной функции
}
II. Подмена класса wstring из STL
Здесь необходимо переопределить char_traits в классе basic_string.
Код: Выделить всё
#include <string>
namespace wstr
{
using namespace std;
struct uchar_traits : public char_traits<wchar_t>
{
static void assign(wchar_t& _c1, const wchar_t& _c2)
{
_c1 = _c2;
}
static bool eq(wchar_t _c1, wchar_t _c2)
{
return _c1 == _c2;
}
static bool lt(wchar_t _c1, wchar_t _c2)
{
return _c1 < _c2;
}
static int compare(const wchar_t* _s1, const wchar_t* _s2, size_t n)
{
while( n-- != 0 )
{
if( *_s1 < *_s2 )
return -1;
if( *_s1 > *_s2 )
return 1;
++_s1; ++_s2;
}
return 0;
}
static size_t length(const wchar_t* _s)
{
const wchar_t* _p = _s;
while ( *_p )
++_p;
return ( _p - _s );
}
static const wchar_t* find(const wchar_t* _s, int n, wchar_t _a)
{
while( n-- > 0 && *_s != _a )
++_s;
return _s;
}
static wchar_t* move(wchar_t* _s1, const wchar_t* _s2, size_t _n)
{
return (wchar_t*) memmove(_s1, _s2, _n * sizeof(wchar_t));
}
static wchar_t* copy(wchar_t* _s1, const wchar_t* _s2, size_t _n)
{
return (wchar_t*) memcpy(_s1, _s2, _n * sizeof(wchar_t));
}
static wchar_t* assign(wchar_t* _s, size_t _n, wchar_t _a)
{
for ( wchar_t* _p = _s; _p < _s + _n; ++_p )
assign(*_p, _a);
return _s;
}
static wchar_t to_char_type(const int_type& _c)
{
return wchar_t(_c);
}
static int_type to_int_type(const wchar_t& _c)
{
return int_type(_c);
}
};
typedef basic_string<wchar_t, uchar_traits> wstring;
wostream& operator<<(wostream& os, const wstring& str)
{
return os.write(str.data(), str.size());
}
}
Использование.
Код: Выделить всё
wstr::wstring s1 = L"Hello";
wstr::wstring s2 = L"Hello";
if(s1 == s2)
{
std::wcout << s1 << L" and " << s2 << L" are equal. size=" << s1.size() << std::endl ;
}
Такой подход обеспечивает хорошую переносимость программ между разными платформами.
Вернуться в «О жизни за рамками путешествий»
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость