1 // filesystem path_traits.cpp --------------------------------------------------------//
3 // Copyright Beman Dawes 2008, 2009
5 // Distributed under the Boost Software License, Version 1.0.
6 // See http://www.boost.org/LICENSE_1_0.txt
8 // Library home page: http://www.boost.org/libs/filesystem
10 //--------------------------------------------------------------------------------------//
12 #ifndef BOOST_SYSTEM_NO_DEPRECATED
13 # define BOOST_SYSTEM_NO_DEPRECATED
16 #include <boost/filesystem/config.hpp>
17 #include <boost/filesystem/path_traits.hpp>
18 #include <boost/system/system_error.hpp>
19 #include <boost/scoped_array.hpp>
20 #include <locale> // for codecvt_base::result
21 #include <cstring> // for strlen
22 #include <cwchar> // for wcslen
24 namespace pt
= boost::filesystem::path_traits
;
25 namespace fs
= boost::filesystem
;
26 namespace bs
= boost::system
;
28 //--------------------------------------------------------------------------------------//
30 //--------------------------------------------------------------------------------------//
32 #ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE
33 # define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256
38 const std::size_t default_codecvt_buf_size
= BOOST_FILESYSTEM_CODECVT_BUF_SIZE
;
41 //--------------------------------------------------------------------------------------//
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. //
46 //--------------------------------------------------------------------------------------//
48 //--------------------------------------------------------------------------------------//
49 // convert_aux const char* to wstring //
50 //--------------------------------------------------------------------------------------//
55 wchar_t* to
, wchar_t* to_end
,
56 std::wstring
& target
,
57 const pt::codecvt_type
& cvt
)
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)
66 std::mbstate_t state
= std::mbstate_t(); // perhaps unneeded, but cuts bug reports
67 const char* from_next
;
70 std::codecvt_base::result res
;
72 if ((res
=cvt
.in(state
, from
, from_end
, from_next
,
73 to
, to_end
, to_next
)) != std::codecvt_base::ok
)
75 //std::cout << " result is " << static_cast<int>(res) << std::endl;
76 BOOST_FILESYSTEM_THROW(bs::system_error(res
, fs::codecvt_error_category(),
77 "boost::filesystem::path codecvt to wstring"));
79 target
.append(to
, to_next
);
82 //--------------------------------------------------------------------------------------//
83 // convert_aux const wchar_t* to string //
84 //--------------------------------------------------------------------------------------//
88 const wchar_t* from_end
,
89 char* to
, char* to_end
,
91 const pt::codecvt_type
& cvt
)
93 //std::cout << std::hex
94 // << " from=" << std::size_t(from)
95 // << " from_end=" << std::size_t(from_end)
96 // << " to=" << std::size_t(to)
97 // << " to_end=" << std::size_t(to_end)
100 std::mbstate_t state
= std::mbstate_t(); // perhaps unneeded, but cuts bug reports
101 const wchar_t* from_next
;
104 std::codecvt_base::result res
;
106 if ((res
=cvt
.out(state
, from
, from_end
, from_next
,
107 to
, to_end
, to_next
)) != std::codecvt_base::ok
)
109 //std::cout << " result is " << static_cast<int>(res) << std::endl;
110 BOOST_FILESYSTEM_THROW(bs::system_error(res
, fs::codecvt_error_category(),
111 "boost::filesystem::path codecvt to string"));
113 target
.append(to
, to_next
);
116 } // unnamed namespace
118 //--------------------------------------------------------------------------------------//
120 //--------------------------------------------------------------------------------------//
122 namespace boost
{ namespace filesystem
{ namespace path_traits
{
124 //--------------------------------------------------------------------------------------//
125 // convert const char* to wstring //
126 //--------------------------------------------------------------------------------------//
128 BOOST_FILESYSTEM_DECL
129 void convert(const char* from
,
130 const char* from_end
, // 0 for null terminated MBCS
132 const codecvt_type
& cvt
)
136 if (!from_end
) // null terminated
138 from_end
= from
+ std::strlen(from
);
141 if (from
== from_end
) return;
143 std::size_t buf_size
= (from_end
- from
) * 3; // perhaps too large, but that's OK
145 // dynamically allocate a buffer only if source is unusually large
146 if (buf_size
> default_codecvt_buf_size
)
148 boost::scoped_array
< wchar_t > buf(new wchar_t [buf_size
]);
149 convert_aux(from
, from_end
, buf
.get(), buf
.get()+buf_size
, to
, cvt
);
153 wchar_t buf
[default_codecvt_buf_size
];
154 convert_aux(from
, from_end
, buf
, buf
+default_codecvt_buf_size
, to
, cvt
);
158 //--------------------------------------------------------------------------------------//
159 // convert const wchar_t* to string //
160 //--------------------------------------------------------------------------------------//
162 BOOST_FILESYSTEM_DECL
163 void convert(const wchar_t* from
,
164 const wchar_t* from_end
, // 0 for null terminated MBCS
166 const codecvt_type
& cvt
)
170 if (!from_end
) // null terminated
172 from_end
= from
+ std::wcslen(from
);
175 if (from
== from_end
) return;
177 // The codecvt length functions may not be implemented, and I don't really
178 // understand them either. Thus this code is just a guess; if it turns
179 // out the buffer is too small then an error will be reported and the code
180 // will have to be fixed.
181 std::size_t buf_size
= (from_end
- from
) * 4; // perhaps too large, but that's OK
182 buf_size
+= 4; // encodings like shift-JIS need some prefix space
184 // dynamically allocate a buffer only if source is unusually large
185 if (buf_size
> default_codecvt_buf_size
)
187 boost::scoped_array
< char > buf(new char [buf_size
]);
188 convert_aux(from
, from_end
, buf
.get(), buf
.get()+buf_size
, to
, cvt
);
192 char buf
[default_codecvt_buf_size
];
193 convert_aux(from
, from_end
, buf
, buf
+default_codecvt_buf_size
, to
, cvt
);
196 }}} // namespace boost::filesystem::path_traits