Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / filesystem / src / path_traits.cpp
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
12 #ifndef BOOST_SYSTEM_NO_DEPRECATED
13 # define BOOST_SYSTEM_NO_DEPRECATED
14 #endif
15
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
23
24 namespace pt = boost::filesystem::path_traits;
25 namespace fs = boost::filesystem;
26 namespace bs = boost::system;
27
28 //--------------------------------------------------------------------------------------//
29 //                                  configuration                                       //
30 //--------------------------------------------------------------------------------------//
31
32 #ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE
33 # define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256
34 #endif
35
36 namespace {
37
38   const std::size_t default_codecvt_buf_size = BOOST_FILESYSTEM_CODECVT_BUF_SIZE;
39
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
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                    const pt::codecvt_type & cvt)
58   {
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
66     std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
67     const char* from_next;
68     wchar_t* to_next;
69
70     std::codecvt_base::result res;
71
72     if ((res=cvt.in(state, from, from_end, from_next,
73            to, to_end, to_next)) != std::codecvt_base::ok)
74     {
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"));
78     }
79     target.append(to, to_next);
80   }
81
82 //--------------------------------------------------------------------------------------//
83 //                      convert_aux const wchar_t* to string                           //
84 //--------------------------------------------------------------------------------------//
85
86   void convert_aux(
87                    const wchar_t* from,
88                    const wchar_t* from_end,
89                    char* to, char* to_end,
90                    std::string & target,
91                    const pt::codecvt_type & cvt)
92   {
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)
98     //          << std::endl;
99
100     std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
101     const wchar_t* from_next;
102     char* to_next;
103
104     std::codecvt_base::result res;
105
106     if ((res=cvt.out(state, from, from_end, from_next,
107            to, to_end, to_next)) != std::codecvt_base::ok)
108     {
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"));
112     }
113     target.append(to, to_next);
114   }
115
116 }  // unnamed namespace
117
118 //--------------------------------------------------------------------------------------//
119 //                                   path_traits                                        //
120 //--------------------------------------------------------------------------------------//
121
122 namespace boost { namespace filesystem { namespace path_traits {
123
124 //--------------------------------------------------------------------------------------//
125 //                          convert const char* to wstring                              //
126 //--------------------------------------------------------------------------------------//
127
128   BOOST_FILESYSTEM_DECL
129   void convert(const char* from,
130                 const char* from_end,    // 0 for null terminated MBCS
131                 std::wstring & to,
132                 const codecvt_type & cvt)
133   {
134     BOOST_ASSERT(from);
135
136     if (!from_end)  // null terminated
137     {
138       from_end = from + std::strlen(from);
139     }
140
141     if (from == from_end) return;
142
143     std::size_t buf_size = (from_end - from) * 3;  // perhaps too large, but that's OK
144
145     //  dynamically allocate a buffer only if source is unusually large
146     if (buf_size > default_codecvt_buf_size)
147     {
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);
150     }
151     else
152     {
153       wchar_t buf[default_codecvt_buf_size];
154       convert_aux(from, from_end, buf, buf+default_codecvt_buf_size, to, cvt);
155     }
156   }
157
158 //--------------------------------------------------------------------------------------//
159 //                         convert const wchar_t* to string                            //
160 //--------------------------------------------------------------------------------------//
161
162   BOOST_FILESYSTEM_DECL
163   void convert(const wchar_t* from,
164                 const wchar_t* from_end,  // 0 for null terminated MBCS
165                 std::string & to,
166                 const codecvt_type & cvt)
167   {
168     BOOST_ASSERT(from);
169
170     if (!from_end)  // null terminated
171     {
172       from_end = from + std::wcslen(from);
173     }
174
175     if (from == from_end) return;
176
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
183
184     //  dynamically allocate a buffer only if source is unusually large
185     if (buf_size > default_codecvt_buf_size)
186     {
187       boost::scoped_array< char > buf(new char [buf_size]);
188       convert_aux(from, from_end, buf.get(), buf.get()+buf_size, to, cvt);
189     }
190     else
191     {
192       char buf[default_codecvt_buf_size];
193       convert_aux(from, from_end, buf, buf+default_codecvt_buf_size, to, cvt);
194     }
195   }
196 }}} // namespace boost::filesystem::path_traits