unicode -> ansi средствами STL

Тема в разделе "LANGS.C", создана пользователем _DEN_, 20 июн 2009.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Средствами локали и стримов можно сконвертить ansi -> unicode через std::wstringstream << char const*. Обратный вывод (std::stringstream << wchar_t const*) выводит в стрим значение указателя. std::wstring сливаться в char-поток не хочет. Можно ли как-то сконвертить unicode -> ansi средствами STL?
     
  2. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    std::wstring w=L"111";
    std::string s(w->begin(),w->end());
     
  3. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Мда, и после этого у нас не любят индусов ;)

    Код (Text):
    1. wstring ws;
    2. string s;
    3. s.resize(ws.size());
    4. std::transform(ws.begin(), ws.end(), s.begin(), wctob);
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    GoldFinch

    А чо уж сразу не
    std::wstring w=L"111";
    std::string s = (std::string&)w;

    ?

    J0E

    wctob() не подходит - он не умеет работать с локалью, а мне нужно уметь.
     
  5. nobodyzzz

    nobodyzzz New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2005
    Сообщения:
    475
    http://www.mkssoftware.com/docs/man3/wctob.3.asp
     
  6. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Что бы уметь, учись... читать стандарт:

    7.11.1.1/2
    The setlocale function selects the appropriate portion of the program’s locale as
    specified by the category and locale arguments. The setlocale function may be
    used to change or query the program’s entire current locale or portions thereof. The value
    LC_ALL for category names the program’s entire locale; the other values for
    category name only a portion of the program’s locale. LC_COLLATE affects the
    behavior of the strcoll and strxfrm functions. LC_CTYPE affects the behavior of
    the character handling functions and the multibyte and wide character functions.

    LC_MONETARY affects the monetary formatting information returned by the
    localeconv function. LC_NUMERIC affects the decimal-point character for the
    formatted input/output functions and the string conversion functions, as well as the
    nonmonetary formatting information returned by the localeconv function. LC_TIME
    affects the behavior of the strftime and wcsftime functions.

    Или гуглить:
    http://www.google.com/search?q=LC_CTYPE+wctob

    Или смотреть сорцы:
    Код (Text):
    1. extern "C" int __cdecl wctob(
    2.     wint_t wchar
    3. )
    4. {
    5.     if (wchar == WEOF)
    6.     {
    7.         return (EOF);
    8.     }
    9.     else
    10.     {
    11.         /* check for one-byte translation */
    12.         int retValue = -1;
    13.         char buf[MB_LEN_MAX];
    14.         errno_t e;
    15.  
    16.         e = _wcrtomb_s_l(&retValue, buf, MB_LEN_MAX, wchar, NULL, NULL);
    17.         if (e == 0 && retValue == 1)
    18.         {
    19.             return buf[0];
    20.         }
    21.         return EOF;
    22.     }
    23. }
    24.  
    25. /***
    26. *errno_t _wcrtomb_s_l() - Helper function to convert wide character to multibyte character.
    27. *
    28. *Purpose:
    29. *       Convert a wide character into the equivalent multi-byte character,
    30. *       according to the specified LC_CTYPE category, or the current locale.
    31. *       [ANSI].
    32. *
    33. *       NOTE:  Currently, the C libraries support the "C" locale only.
    34. *              Non-C locale support now available under _INTL switch.
    35. *Entry:
    36. *       int *pRetValue      = the number of chars written (-1 in error case)
    37. *       char *dst           = pointer to multibyte character
    38. *       size_t sizeInBytes  = size of the destinarion buffer
    39. *       wchar_t wchar       = source wide character
    40. *       mbstate_t *pst      = pointer to state (not used)
    41. *       _locale_t plocinfo  = locale info
    42. *
    43. *Exit:
    44. *       Returns:
    45. *       Value of errno if errors, 0 otherwise. *pRetValue is set to -1 in error case.
    46. *
    47. *Exceptions:
    48. *
    49. *******************************************************************************/
    50.  
    51. static errno_t __cdecl _wcrtomb_s_l (
    52.     int *pRetValue,
    53.     char *dst,
    54.     size_t sizeInBytes,
    55.     wchar_t wchar,
    56.     mbstate_t *pst,
    57.     _locale_t plocinfo
    58. )
    59. {
    60.     _ASSERTE (dst != NULL && sizeInBytes > 0);
    61.  
    62.     _LocaleUpdate _loc_update(plocinfo);
    63.     _ASSERTE (_loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 || _loc_update.GetLocaleT()->locinfo->mb_cur_max == 2);
    64.     if(pst!=NULL)
    65.     {
    66.         *pst=0;
    67.     }
    68.  
    69.     if ( _loc_update.GetLocaleT()->locinfo->lc_handle[LC_CTYPE] == _CLOCALEHANDLE )
    70.     {
    71.         if ( wchar > 255 )  /* validate high byte */
    72.         {
    73.             errno = EILSEQ;
    74.             if (pRetValue != NULL)
    75.             {
    76.                 *pRetValue = -1;
    77.             }
    78.             return errno;
    79.         }
    80.  
    81.         *dst = (char) wchar;
    82.         if (pRetValue != NULL)
    83.         {
    84.             *pRetValue = 1;
    85.         }
    86.         return 0;
    87.     }
    88.     else
    89.     {
    90.         int size;
    91.         BOOL defused = 0;
    92.  
    93.         if ( ((size = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage,
    94.                                           0,
    95.                                           &wchar,
    96.                                           1,
    97.                                           dst,
    98.                                           (int)sizeInBytes,
    99.                                           NULL,
    100.                                           &defused)) == 0) ||
    101.                 (defused) )
    102.         {
    103.             errno = EILSEQ;
    104.             if (pRetValue != NULL)
    105.             {
    106.                 *pRetValue = -1;
    107.             }
    108.             return errno;
    109.         }
    110.  
    111.         if (pRetValue != NULL)
    112.         {
    113.             *pRetValue = size;
    114.         }
    115.         return 0;
    116.     }
    117. }
    А то нашел идола MSDN. Там про btowc тоже интересно "The output of this function is affected by the current LC_TYPE locale". Верь ему больше.

    P.S. В новой STL будет wstring_convert

    P.P.S. Не бангалорьте operator=() когда есть конструктор :\
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    nobodyzzz
    J0E

    Не катит. Многопоточность.


    При чем тут MSDN-то?
     
  8. nobodyzzz

    nobodyzzz New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2005
    Сообщения:
    475
    _DEN_
    _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); ?
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    nobodyzzz

    Не катит. Кроссплатформенность :)
     
  10. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Катит:

    Код (Text):
    1. std::string to_ansi(std::wstring const& wstr, std::locale const& loc)
    2. {
    3.     std::string str;
    4.     str.resize(wstr.length());
    5.  
    6.     std::wstringstream stream;
    7.     stream.imbue(loc);
    8.  
    9.     std::transform(wstr.begin(), wstr.end(), str.begin(), boost::bind(&std::wstringstream::narrow, &stream, _1, 0));
    10.  
    11.     return str;
    12. }
     
  11. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Вот что мне нравится, _DEN_ сначала спросит а потом сам все и сделает ))

    Тока в таком виде bind тож не катит, кросплатформенность ;-( http://www.gotw.ca/gotw/064.htm

    И много поточность не кросплатформенна пока что.

    Хотя МС позаботились:
    Код (Text):
    1. class _LocaleUpdate
    2. {
    3.     _locale_tstruct localeinfo;
    4.     _ptiddata ptd;
    5.     bool updated;
    6.     public:
    7.     _LocaleUpdate(_locale_t plocinfo)
    8.         : updated(false)
    9.     {
    10.         if (plocinfo == NULL)
    11.         {
    12.             ptd = _getptd();
    13.             localeinfo.locinfo = ptd->ptlocinfo;
    14.             localeinfo.mbcinfo = ptd->ptmbcinfo;
    15.  
    16.             __UPDATE_LOCALE(ptd, localeinfo.locinfo);
    17.             __UPDATE_MBCP(ptd, localeinfo.mbcinfo);
    18.             if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT))
    19.             {
    20.                 ptd->_ownlocale |= _PER_THREAD_LOCALE_BIT;
    21.                 updated = true;
    22.             }
    23.         }
    24.         else
    25.         {
    26.             localeinfo=*plocinfo;
    27.         }
    28.     }
    29.     ~_LocaleUpdate()
    30.     {
    31.         if (updated)
    32.             ptd->_ownlocale = ptd->_ownlocale & ~_PER_THREAD_LOCALE_BIT;
    33.     }
    34.     _locale_t GetLocaleT()
    35.     {
    36.         return &localeinfo;
    37.     }
    38. };
    А MSDN при том что откуда бы ты еще взял "не умеет работать с локалью", в остальных дока про это есть а там нет )
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Ну во-первых, в моем примере и нет конкурирующих точек (общих данных), чтобы возникали проблемы с многопоточностью.

    А во-вторых, не понял - в чем проблема с boost::bind?
     
  13. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Ну так е-мое, если не я, то кто? )))
     
  14. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Проблемы с многопоточностью в том, что средствами С++ нельзя создать тред кросплатформенным способом ))

    Про проблемы с байндом написано у Саттера, непонятен англ. что ли? Стандарт не запрещает реализации std::wstringstream иметь несколько функций narrow с разными сигнатурами. Хотя я сам не редко кладу на это болт ))
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Я позволяю себе считать, что boost::thread - кроссплатформенный способ.

    Насчет Саттера - с первого прочтения не понял в чем именно проблемы. Ну значит std::transform простро заменяется на цикл и все щясливы.