Эксперт С++
8711 / 4256 / 947
Регистрация: 15.11.2014
Сообщений: 9,653
1

[mingw] не видит <codecvt>

31.01.2016, 21:50. Показов 2257. Ответов 10
Метки нет (Все метки)

всем привет.

есть библиотека, которая изначально разрабатывалась в msvc2013.
к библиотеке есть требование - кросс-платформа,
и отсутствие внешних зависимостей.

то есть, нельзя подтягивать буст,
и подобные тяжеловесные вещи.

казалось бы - никаких левых зависимостей,
стандартная библиотека во все поля.
однако, при попытке портануться на mingw (942, что идет в коробке с qt5.5.1),
вылезла проблема:

для работы понадобилось выполнять преобразования кодировок текста.
наиболее актуальным является конвертация utf8 <----> unicode

что в коде выглядит,
как преобразование std::string <----> std::wstring

что бы было понятнее,
проиллюстрирую этот момент:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// cmdconv.h
 
#pragma once
 
namespace cmd{
 
// =======================================================================
// =======================================================================
 
    namespace multibyte {
        std::string  convert(const wchar_t* s);
        std::wstring convert(const char*    s);
        std::string  convert(const std::wstring& s);
        std::wstring convert(const std::string&  s);
    }// namespace multibyte 
 
    namespace utf8 {
        std::string  convert(const std::wstring& s);
        std::wstring convert(const std::string&  s);
    }// namespace utf8 
 
    namespace stdlocal {
 
        std::string convert(
            const wchar_t* s,
            const size_t len,
            const std::locale& loc = std::locale(),
            const char default_char = '?'
        );
        std::string convert(
            const wchar_t* s, 
            const std::locale& loc = std::locale(""), 
            const char default_char = '?'
        );
        std::string convert(
            const std::wstring& s, 
            const std::locale& loc = std::locale(""), 
            const char default_char = '?'
        );
        std::wstring convert(
            const char* s,
            const std::locale& loc = std::locale("")
        );
        std::wstring convert(
            const std::string& s, 
            const std::locale& loc = std::locale("") 
        );
        std::wstring convert(
            const char* s, 
            const size_t len, 
            const std::locale& loc = std::locale()
        );
 
    } //namespace stdlocal 
 
// =======================================================================
// =======================================================================
 
}//namespace cmd
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//cmdconv.cpp
 
#include "precompiled.h"
 
#include <cmd/cmdconv.h>
 
namespace cmd{
 
// =======================================================================
// =======================================================================
 
    namespace multibyte {
 
        std::string convert(const std::wstring& s)
            { return convert( s.c_str() ); }
        std::wstring convert(const std::string& s)
            { return convert(s.c_str()); }
 
        std::string convert(const wchar_t* s)
        { 
            const size_t len = wcslen(s);
            std::string result(len,'\0');
 
            #ifdef _MSC_VER
                size_t count = 0;
                const auto size_ = result.size();
                wcstombs_s(&count, &result[0], size_, s, size_ );
            #else
                std::mbstate_t state = std::mbstate_t();
                std::wcsrtombs( &result[0], &s, result.size(), &state);
            #endif
 
            return result;
        }
 
        std::wstring convert(const char* s)
        { 
            std::mbstate_t state  = std::mbstate_t(); 
        
            size_t len;
            wchar_t wc[4] = {};
            std::wstring result;
            const char* end = s + std::strlen(s);
        
            //TODO: remove warning:
            //conversion to 'size_t {aka unsigned int}' from 'int' 
            //may change the sign of the result [-Wsign-conversion] 
            while ((len = std::mbrtowc(wc, s, end - s, &state)) > 0 )
            {
                result += wc; s += len;
                for (auto& ch: wc)  ch = L'\0';
            }
            return result;
        }
    }//namespace multibyte
 
 
    namespace utf8 {
        
    #if defined(__MINGW__) || defined(__MINGW32__)
    
    // no support
    
    #else
 
        std::string convert(const std::wstring& s)
        { 
            typedef std::codecvt_utf8<wchar_t>
                convert_typeX;
            std::wstring_convert<convert_typeX,wchar_t>
                converterX;
            return converterX.to_bytes(s);
        }
        std::wstring convert(const std::string&  s)
        { 
            typedef std::codecvt_utf8<wchar_t>
                convert_typeX;
            std::wstring_convert<convert_typeX,wchar_t>
                converterX;
            return converterX.from_bytes(s);
        }
    #endif
            
    }//namespace utf8 
 
    namespace stdlocal {
 
        std::wstring convert(const char* first, const size_t len, const std::locale& loc)
        {
            if(len == 0)
                return std::wstring();
 
            const std::ctype<wchar_t>& facet =
                std::use_facet< std::ctype<wchar_t> >(loc);
 
            const char* last = first + len;
 
            std::wstring result(len, L'\0');
 
            facet.widen(first, last, &result[0]);
            return result;
        }
 
        std::string convert(
            const wchar_t* first,
            const size_t len,
            const std::locale& loc,
            const char default_char
        )
        {
            if(len == 0)
                return std::string();
 
            const std::ctype<wchar_t>& facet =
                std::use_facet<std::ctype<wchar_t> >(loc);
 
            const wchar_t* last  = first + len;
 
            std::string result( len, default_char );
            facet.narrow( first, last, default_char, &result[0] );
            return result;
        }
 
        std::string  convert( const wchar_t* s, const std::locale& loc, const char default_char )
            { return convert(s, std::wcslen(s), loc, default_char); }
        std::string  convert(const std::wstring& s, const std::locale& loc, const char default_char)
            { return convert(s.c_str(), s.length(), loc, default_char);  }
        std::wstring convert( const char* s, const std::locale& loc)
            { return convert(s, std::strlen(s), loc); }
        std::wstring convert( const std::string& s, const std::locale& loc)
            { return convert(s.c_str(), s.length(), loc); }
 
    }//namespace stdlocal
 
// =======================================================================
// =======================================================================
 
}//namespace cmd


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//precompiled.h
 
#pragma once
 
#pragma message("PRECOMPILE CMDCONV HEADER ...")
 
#include <cassert>
 
#if defined(__MINGW__) || defined(__MINGW32__)
    #include <stdexcept>
    #include <cstring>
    #include <locale>
#else
 
    //TODO: No such file or directory
    // WTF ????
    #include <codecvt>
#endif
 
#include <string>
оказывается, mingw не умеет юникод!
он вообще не знает ни о каких
C++
1
#include <codecvt>
гугл не утешителен.
в основном советуют смотреть в сторону boost.


но я себе этого позволить не могу.

какие могут быть обходные пути?
или как можно заставить работать мои конвертеры?
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.01.2016, 21:50
Ответы с готовыми решениями:

MinGW не видит класс thread
MinGW не видит класс thread,в то время как заголовочный файл thread подключается без проблем.При...

Компилятор MinGW в NetBeans не видит класс потока (thread)
Версия NetBeans - 8.0.2 компилятор - MinGW Суть проблемы в следующем - использую NetBeans для...

Может ли MinGW x64 компилить приложения x32? Или нужно для этого отдельно ещё MinGW х32 качать?
Просто решил поиграться с CodeLite.

Mingw-w64 MinGW TDM-GCC
Всем привет. Хочу понять, существует ли принципиальная разница между Mingw-w64, MinGW и...

10
Don't worry, be happy
17686 / 10433 / 2015
Регистрация: 27.09.2012
Сообщений: 26,282
Записей в блоге: 1
31.01.2016, 22:08 2
Цитата Сообщение от hoggy Посмотреть сообщение
оказывается, mingw не умеет юникод!
Насколько я помню,
mingw даже нестандартные локали не умеет в std::locale.
Плюется исключениями
1
Эксперт С++
4978 / 3085 / 456
Регистрация: 10.11.2010
Сообщений: 11,164
Записей в блоге: 10
01.02.2016, 19:34 3
Я несколько раз пытался проделать подобное в MinGW 5.2.0 но ни разу не получал нужного результата. Насколько я помню, опыты почти всегда оканчивались исключением.
На тот момент я видел только один выход - преобразование вручную.
1
683 / 296 / 96
Регистрация: 04.07.2014
Сообщений: 834
02.02.2016, 15:17 4
Цитата Сообщение от hoggy Посмотреть сообщение
какие могут быть обходные пути?
или как можно заставить работать мои конвертеры?
Для платформ без поддержки codecvt использовать реализации на базе boost/icu
0
Эксперт С++
8711 / 4256 / 947
Регистрация: 15.11.2014
Сообщений: 9,653
02.02.2016, 18:20  [ТС] 5
111111111

Цитата Сообщение от AlexVRud Посмотреть сообщение
Для платформ без поддержки codecvt использовать реализации на базе boost/icu
Цитата Сообщение от hoggy Посмотреть сообщение
и отсутствие внешних зависимостей.
то есть, нельзя подтягивать буст,
и подобные тяжеловесные вещи.
0
683 / 296 / 96
Регистрация: 04.07.2014
Сообщений: 834
02.02.2016, 20:51 6
Цитата Сообщение от hoggy Посмотреть сообщение
кросс-платформа,
и
wstring, codecvt, locale
уже не совместимы. Например в CentOS 7 gcc 4.8, при этом ещё никуда не ушел CentOS 6.

Даже Qt не стал заморачиваться и воспользовался ICU. Одно дело, когда отказываются от непредсказуемого boost. Но когда вместо icu/zlib/openssl/... начинают лепить свои велосипеды,....
0
Эксперт С++
4978 / 3085 / 456
Регистрация: 10.11.2010
Сообщений: 11,164
Записей в блоге: 10
02.02.2016, 21:00 7
Цитата Сообщение от AlexVRud Посмотреть сообщение
уже не совместимы.
o_O
0
683 / 296 / 96
Регистрация: 04.07.2014
Сообщений: 834
02.02.2016, 21:36 8
Цитата Сообщение от castaway Посмотреть сообщение
o_O
  1. wchar_t может иметь размер в 8,16,32 бита на разных платформах
  2. #include <codecvt> - много ли где отработает?
  3. locale - Russian_Russia/ru_RU/??? не говоря о различных реализациях, и их отсутствия напрочь на большинстве платформ.
0
Эксперт С++
4978 / 3085 / 456
Регистрация: 10.11.2010
Сообщений: 11,164
Записей в блоге: 10
02.02.2016, 21:46 9
1. ссылку можно?
2. не понял что вы имели в виду
3. не понял что вы имели в виду

Все нюансы должна предусмотреть стандартная библиотека C++. Иначе она не была бы стандартной.
0
Don't worry, be happy
17686 / 10433 / 2015
Регистрация: 27.09.2012
Сообщений: 26,282
Записей в блоге: 1
02.02.2016, 22:08 10
Цитата Сообщение от castaway Посмотреть сообщение
1. ссылку можно?
На винде 2 байта, на лине 4 байта.
Цитата Сообщение от castaway Посмотреть сообщение
3. не понял что вы имели в виду
названия локалей везде свои.
1
1441 / 1322 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
03.02.2016, 11:03 11
Цитата Сообщение от AlexVRud Посмотреть сообщение
Даже Qt не стал заморачиваться и воспользовался ICU
Вот в Qt они заморочились как и в Boost.Поддерживается не только ICU, но libiconv
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.02.2016, 11:03
Помогаю со студенческими работами здесь

MinGW, при установке ошибка: unpacking mingw-get-0.6.2-mingw32-beta-20131004-1-bin.tar.xz
Добрый день, форумчане! Недавно начал изучать Си, решил попрактиковаться. В качестве компилятора не...

WD3200AAJB-00J3A0 то НЕ видит, то видит BIOS, USB-to-IDE/SATA видит всегда
День добрый. Есть HDD WD3200AAJB-00J3A0. Проблема в том, что его перестал видеть BIOS. Иногда...

BIOS видит HDD. Windows, Acronis не видит. Live UBUNTU видит
Нужно вытащить данные с неисправного жесткого диска. HDD 2.5&quot; Toshiba 160 Gb Sata. BIOS видит...

HDD-видит BIOS, видит диспетчер устройст, но не видит система
Ну что же, вечер добрый товарищи. Возникла такая проблема, описываю все по-порядку. -Купил...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru