]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // filesystem path_traits.cpp --------------------------------------------------------// |
2 | ||
3 | // Copyright Beman Dawes 2008, 2009 | |
4 | ||
5 | // Distributed under the Boost Software License, Version 1.0. | |
6 | // See http://www.boost.org/LICENSE_1_0.txt | |
7 | ||
8 | // Library home page: http://www.boost.org/libs/filesystem | |
9 | ||
10 | //--------------------------------------------------------------------------------------// | |
11 | ||
20effc67 | 12 | #include "platform_config.hpp" |
7c673cae | 13 | |
1e59de90 | 14 | #include <boost/filesystem/config.hpp> |
7c673cae FG |
15 | #include <boost/filesystem/path_traits.hpp> |
16 | #include <boost/system/system_error.hpp> | |
1e59de90 TL |
17 | #include <boost/smart_ptr/scoped_array.hpp> |
18 | #include <boost/assert.hpp> | |
19 | #include <string> | |
20 | #include <locale> // for codecvt_base::result | |
21 | #include <cstring> // for strlen | |
22 | #include <cwchar> // for wcslen | |
23 | #include <cstddef> | |
7c673cae FG |
24 | |
25 | namespace pt = boost::filesystem::path_traits; | |
26 | namespace fs = boost::filesystem; | |
27 | namespace bs = boost::system; | |
28 | ||
29 | //--------------------------------------------------------------------------------------// | |
30 | // configuration // | |
31 | //--------------------------------------------------------------------------------------// | |
32 | ||
33 | #ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE | |
1e59de90 | 34 | #define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256 |
7c673cae FG |
35 | #endif |
36 | ||
37 | namespace { | |
38 | ||
1e59de90 | 39 | BOOST_CONSTEXPR_OR_CONST std::size_t default_codecvt_buf_size = BOOST_FILESYSTEM_CODECVT_BUF_SIZE; |
7c673cae FG |
40 | |
41 | //--------------------------------------------------------------------------------------// | |
42 | // // | |
43 | // The public convert() functions do buffer management, and then forward to the // | |
44 | // convert_aux() functions for the actual call to the codecvt facet. // | |
45 | // // | |
46 | //--------------------------------------------------------------------------------------// | |
47 | ||
48 | //--------------------------------------------------------------------------------------// | |
49 | // convert_aux const char* to wstring // | |
50 | //--------------------------------------------------------------------------------------// | |
51 | ||
1e59de90 TL |
52 | void convert_aux( |
53 | const char* from, | |
54 | const char* from_end, | |
55 | wchar_t* to, wchar_t* to_end, | |
56 | std::wstring& target, | |
57 | pt::codecvt_type const& cvt) | |
58 | { | |
7c673cae FG |
59 | //std::cout << std::hex |
60 | // << " from=" << std::size_t(from) | |
61 | // << " from_end=" << std::size_t(from_end) | |
62 | // << " to=" << std::size_t(to) | |
63 | // << " to_end=" << std::size_t(to_end) | |
64 | // << std::endl; | |
65 | ||
1e59de90 | 66 | std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports |
7c673cae FG |
67 | const char* from_next; |
68 | wchar_t* to_next; | |
69 | ||
70 | std::codecvt_base::result res; | |
71 | ||
1e59de90 | 72 | if ((res = cvt.in(state, from, from_end, from_next, to, to_end, to_next)) != std::codecvt_base::ok) |
7c673cae | 73 | { |
1e59de90 TL |
74 | //std::cout << " result is " << static_cast<int>(res) << std::endl; |
75 | BOOST_FILESYSTEM_THROW(bs::system_error(res, fs::codecvt_error_category(), "boost::filesystem::path codecvt to wstring")); | |
7c673cae | 76 | } |
92f5a8d4 | 77 | target.append(to, to_next); |
1e59de90 | 78 | } |
7c673cae FG |
79 | |
80 | //--------------------------------------------------------------------------------------// | |
81 | // convert_aux const wchar_t* to string // | |
82 | //--------------------------------------------------------------------------------------// | |
83 | ||
1e59de90 TL |
84 | void convert_aux( |
85 | const wchar_t* from, | |
86 | const wchar_t* from_end, | |
87 | char* to, char* to_end, | |
88 | std::string& target, | |
89 | pt::codecvt_type const& cvt) | |
90 | { | |
7c673cae FG |
91 | //std::cout << std::hex |
92 | // << " from=" << std::size_t(from) | |
93 | // << " from_end=" << std::size_t(from_end) | |
94 | // << " to=" << std::size_t(to) | |
95 | // << " to_end=" << std::size_t(to_end) | |
96 | // << std::endl; | |
97 | ||
1e59de90 | 98 | std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports |
7c673cae FG |
99 | const wchar_t* from_next; |
100 | char* to_next; | |
101 | ||
102 | std::codecvt_base::result res; | |
103 | ||
1e59de90 | 104 | if ((res = cvt.out(state, from, from_end, from_next, to, to_end, to_next)) != std::codecvt_base::ok) |
7c673cae | 105 | { |
1e59de90 TL |
106 | //std::cout << " result is " << static_cast<int>(res) << std::endl; |
107 | BOOST_FILESYSTEM_THROW(bs::system_error(res, fs::codecvt_error_category(), "boost::filesystem::path codecvt to string")); | |
7c673cae | 108 | } |
92f5a8d4 | 109 | target.append(to, to_next); |
1e59de90 | 110 | } |
92f5a8d4 | 111 | |
1e59de90 | 112 | } // unnamed namespace |
7c673cae FG |
113 | |
114 | //--------------------------------------------------------------------------------------// | |
115 | // path_traits // | |
116 | //--------------------------------------------------------------------------------------// | |
117 | ||
1e59de90 TL |
118 | namespace boost { |
119 | namespace filesystem { | |
120 | namespace path_traits { | |
7c673cae FG |
121 | |
122 | //--------------------------------------------------------------------------------------// | |
123 | // convert const char* to wstring // | |
124 | //--------------------------------------------------------------------------------------// | |
125 | ||
1e59de90 TL |
126 | BOOST_FILESYSTEM_DECL |
127 | void convert(const char* from, | |
128 | const char* from_end, // 0 for null terminated MBCS | |
129 | std::wstring& to, codecvt_type const& cvt) | |
130 | { | |
7c673cae FG |
131 | BOOST_ASSERT(from); |
132 | ||
1e59de90 | 133 | if (!from_end) // null terminated |
7c673cae | 134 | { |
1e59de90 | 135 | from_end = from + std::strlen(from); |
7c673cae FG |
136 | } |
137 | ||
1e59de90 TL |
138 | if (from == from_end) |
139 | return; | |
7c673cae | 140 | |
1e59de90 | 141 | std::size_t buf_size = (from_end - from) * 3; // perhaps too large, but that's OK |
7c673cae FG |
142 | |
143 | // dynamically allocate a buffer only if source is unusually large | |
144 | if (buf_size > default_codecvt_buf_size) | |
145 | { | |
1e59de90 TL |
146 | boost::scoped_array< wchar_t > buf(new wchar_t[buf_size]); |
147 | convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, cvt); | |
7c673cae FG |
148 | } |
149 | else | |
150 | { | |
1e59de90 TL |
151 | wchar_t buf[default_codecvt_buf_size]; |
152 | convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, cvt); | |
7c673cae | 153 | } |
1e59de90 | 154 | } |
7c673cae FG |
155 | |
156 | //--------------------------------------------------------------------------------------// | |
157 | // convert const wchar_t* to string // | |
158 | //--------------------------------------------------------------------------------------// | |
159 | ||
1e59de90 TL |
160 | BOOST_FILESYSTEM_DECL |
161 | void convert(const wchar_t* from, | |
162 | const wchar_t* from_end, // 0 for null terminated MBCS | |
163 | std::string& to, codecvt_type const& cvt) | |
164 | { | |
7c673cae FG |
165 | BOOST_ASSERT(from); |
166 | ||
1e59de90 | 167 | if (!from_end) // null terminated |
7c673cae | 168 | { |
1e59de90 | 169 | from_end = from + std::wcslen(from); |
7c673cae FG |
170 | } |
171 | ||
1e59de90 TL |
172 | if (from == from_end) |
173 | return; | |
7c673cae FG |
174 | |
175 | // The codecvt length functions may not be implemented, and I don't really | |
176 | // understand them either. Thus this code is just a guess; if it turns | |
177 | // out the buffer is too small then an error will be reported and the code | |
178 | // will have to be fixed. | |
1e59de90 TL |
179 | std::size_t buf_size = (from_end - from) * 4; // perhaps too large, but that's OK |
180 | buf_size += 4; // encodings like shift-JIS need some prefix space | |
7c673cae FG |
181 | |
182 | // dynamically allocate a buffer only if source is unusually large | |
183 | if (buf_size > default_codecvt_buf_size) | |
184 | { | |
1e59de90 TL |
185 | boost::scoped_array< char > buf(new char[buf_size]); |
186 | convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, cvt); | |
7c673cae FG |
187 | } |
188 | else | |
189 | { | |
1e59de90 TL |
190 | char buf[default_codecvt_buf_size]; |
191 | convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, cvt); | |
7c673cae | 192 | } |
1e59de90 TL |
193 | } |
194 | ||
195 | } // namespace path_traits | |
196 | } // namespace filesystem | |
197 | } // namespace boost |