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 #include "platform_config.hpp"
14 #include <boost/filesystem/config.hpp>
15 #include <boost/filesystem/path_traits.hpp>
16 #include <boost/system/system_error.hpp>
17 #include <boost/smart_ptr/scoped_array.hpp>
18 #include <boost/assert.hpp>
20 #include <locale> // for codecvt_base::result
21 #include <cstring> // for strlen
22 #include <cwchar> // for wcslen
25 namespace pt
= boost::filesystem::path_traits
;
26 namespace fs
= boost::filesystem
;
27 namespace bs
= boost::system
;
29 //--------------------------------------------------------------------------------------//
31 //--------------------------------------------------------------------------------------//
33 #ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE
34 #define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256
39 BOOST_CONSTEXPR_OR_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
,
57 pt::codecvt_type
const& 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
, to
, to_end
, to_next
)) != std::codecvt_base::ok
)
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"));
77 target
.append(to
, to_next
);
80 //--------------------------------------------------------------------------------------//
81 // convert_aux const wchar_t* to string //
82 //--------------------------------------------------------------------------------------//
86 const wchar_t* from_end
,
87 char* to
, char* to_end
,
89 pt::codecvt_type
const& cvt
)
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)
98 std::mbstate_t state
= std::mbstate_t(); // perhaps unneeded, but cuts bug reports
99 const wchar_t* from_next
;
102 std::codecvt_base::result res
;
104 if ((res
= cvt
.out(state
, from
, from_end
, from_next
, to
, to_end
, to_next
)) != std::codecvt_base::ok
)
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"));
109 target
.append(to
, to_next
);
112 } // unnamed namespace
114 //--------------------------------------------------------------------------------------//
116 //--------------------------------------------------------------------------------------//
119 namespace filesystem
{
120 namespace path_traits
{
122 //--------------------------------------------------------------------------------------//
123 // convert const char* to wstring //
124 //--------------------------------------------------------------------------------------//
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
)
133 if (!from_end
) // null terminated
135 from_end
= from
+ std::strlen(from
);
138 if (from
== from_end
)
141 std::size_t buf_size
= (from_end
- from
) * 3; // perhaps too large, but that's OK
143 // dynamically allocate a buffer only if source is unusually large
144 if (buf_size
> default_codecvt_buf_size
)
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
);
151 wchar_t buf
[default_codecvt_buf_size
];
152 convert_aux(from
, from_end
, buf
, buf
+ default_codecvt_buf_size
, to
, cvt
);
156 //--------------------------------------------------------------------------------------//
157 // convert const wchar_t* to string //
158 //--------------------------------------------------------------------------------------//
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
)
167 if (!from_end
) // null terminated
169 from_end
= from
+ std::wcslen(from
);
172 if (from
== from_end
)
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.
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
182 // dynamically allocate a buffer only if source is unusually large
183 if (buf_size
> default_codecvt_buf_size
)
185 boost::scoped_array
< char > buf(new char[buf_size
]);
186 convert_aux(from
, from_end
, buf
.get(), buf
.get() + buf_size
, to
, cvt
);
190 char buf
[default_codecvt_buf_size
];
191 convert_aux(from
, from_end
, buf
, buf
+ default_codecvt_buf_size
, to
, cvt
);
195 } // namespace path_traits
196 } // namespace filesystem