Переносимость программ между Windows и UNIX (wchar_t совместимость)

Все что не вошло в предыдущие темы
Аватара пользователя
Admin
Сообщения: 1
Зарегистрирован: 16 дек 2014, 08:17
Контактная информация:

Переносимость программ между Windows и UNIX (wchar_t совместимость)

Сообщение Admin » 01 мар 2015, 05:18

Здесь описан только один аспект совместимости приложений по wchar_t.
Размер 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 гость