]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2009 Daniel James | |
3 | ||
4 | Use, modification and distribution is subject to the Boost Software | |
5 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
6 | http://www.boost.org/LICENSE_1_0.txt) | |
7 | =============================================================================*/ | |
8 | ||
9 | #include <boost/program_options.hpp> | |
10 | #include <iostream> | |
11 | #include "native_text.hpp" | |
12 | #include "utils.hpp" | |
13 | #include "files.hpp" | |
14 | ||
15 | #if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS | |
16 | #include <boost/scoped_ptr.hpp> | |
17 | #include <windows.h> | |
18 | #include <io.h> | |
19 | #include <fcntl.h> | |
20 | #endif | |
21 | ||
22 | #if QUICKBOOK_CYGWIN_PATHS | |
23 | #include <boost/scoped_array.hpp> | |
24 | #include <boost/program_options/errors.hpp> | |
25 | #include <sys/cygwin.h> | |
26 | #endif | |
27 | ||
28 | namespace quickbook { | |
29 | namespace detail { | |
30 | namespace { | |
31 | bool ms_errors = false; | |
32 | } | |
33 | ||
34 | void set_ms_errors(bool x) { | |
35 | ms_errors = x; | |
36 | } | |
37 | ||
38 | // This is used for converting paths to UTF-8 on cygin. | |
39 | // Might be better not to use a windows | |
40 | #if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS | |
41 | namespace { | |
42 | std::string to_utf8(std::wstring const& x) | |
43 | { | |
44 | int buffer_count = WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0); | |
45 | ||
46 | if (!buffer_count) | |
47 | throw conversion_error("Error converting wide string to utf-8."); | |
48 | ||
49 | boost::scoped_ptr<char> buffer(new char[buffer_count]); | |
50 | ||
51 | if (!WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0, 0)) | |
52 | throw conversion_error("Error converting wide string to utf-8."); | |
53 | ||
54 | return std::string(buffer.get()); | |
55 | } | |
56 | ||
57 | std::wstring from_utf8(boost::string_ref text) | |
58 | { | |
59 | std::string x(text.begin(), text.end()); | |
60 | int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0); | |
61 | ||
62 | if (!buffer_count) | |
63 | throw conversion_error("Error converting utf-8 to wide string."); | |
64 | ||
65 | boost::scoped_ptr<wchar_t> buffer(new wchar_t[buffer_count]); | |
66 | ||
67 | if (!MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count)) | |
68 | throw conversion_error("Error converting utf-8 to wide string."); | |
69 | ||
70 | return std::wstring(buffer.get()); | |
71 | } | |
72 | } | |
73 | #endif | |
74 | ||
75 | #if QUICKBOOK_WIDE_PATHS | |
76 | std::string command_line_to_utf8(command_line_string const& x) | |
77 | { | |
78 | return to_utf8(x); | |
79 | } | |
80 | #else | |
81 | std::string command_line_to_utf8(command_line_string const& x) | |
82 | { | |
83 | return x; | |
84 | } | |
85 | #endif | |
86 | ||
87 | #if QUICKBOOK_WIDE_PATHS | |
88 | fs::path generic_to_path(boost::string_ref x) | |
89 | { | |
90 | return fs::path(from_utf8(x)); | |
91 | } | |
92 | ||
93 | std::string path_to_generic(fs::path const& x) | |
94 | { | |
95 | return to_utf8(x.generic_wstring()); | |
96 | } | |
97 | #else | |
98 | fs::path generic_to_path(boost::string_ref x) | |
99 | { | |
100 | return fs::path(x.begin(), x.end()); | |
101 | } | |
102 | ||
103 | std::string path_to_generic(fs::path const& x) | |
104 | { | |
105 | return x.generic_string(); | |
106 | } | |
107 | ||
108 | #endif | |
109 | ||
110 | ||
111 | #if QUICKBOOK_CYGWIN_PATHS | |
112 | fs::path command_line_to_path(command_line_string const& path) | |
113 | { | |
114 | cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_W | CCP_RELATIVE; | |
115 | ||
116 | ssize_t size = cygwin_conv_path(flags, path.c_str(), NULL, 0); | |
117 | ||
118 | if (size < 0) | |
119 | throw conversion_error("Error converting cygwin path to windows."); | |
120 | ||
121 | boost::scoped_array<char> result(new char[size]); | |
122 | void* ptr = result.get(); | |
123 | ||
124 | if(cygwin_conv_path(flags, path.c_str(), ptr, size)) | |
125 | throw conversion_error("Error converting cygwin path to windows."); | |
126 | ||
127 | return fs::path(static_cast<wchar_t*>(ptr)); | |
128 | } | |
129 | ||
130 | ostream::string path_to_stream(fs::path const& path) | |
131 | { | |
132 | cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE; | |
133 | ||
134 | ssize_t size = cygwin_conv_path(flags, path.native().c_str(), NULL, 0); | |
135 | ||
136 | if (size < 0) | |
137 | throw conversion_error("Error converting windows path to cygwin."); | |
138 | ||
139 | boost::scoped_array<char> result(new char[size]); | |
140 | ||
141 | if(cygwin_conv_path(flags, path.native().c_str(), result.get(), size)) | |
142 | throw conversion_error("Error converting windows path to cygwin."); | |
143 | ||
144 | return std::string(result.get()); | |
145 | } | |
146 | #else | |
147 | fs::path command_line_to_path(command_line_string const& path) | |
148 | { | |
149 | return fs::path(path); | |
150 | } | |
151 | ||
152 | #if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS | |
153 | ostream::string path_to_stream(fs::path const& path) | |
154 | { | |
155 | return path.string(); | |
156 | } | |
157 | #else | |
158 | ostream::string path_to_stream(fs::path const& path) | |
159 | { | |
160 | return path.native(); | |
161 | } | |
162 | #endif | |
163 | ||
164 | #endif // QUICKBOOK_CYGWIN_PATHS | |
165 | ||
166 | #if QUICKBOOK_WIDE_STREAMS | |
167 | ||
168 | void initialise_output() | |
169 | { | |
170 | if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT); | |
171 | if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT); | |
172 | } | |
173 | ||
174 | void write_utf8(ostream::base_ostream& out, boost::string_ref x) | |
175 | { | |
176 | out << from_utf8(x); | |
177 | } | |
178 | ||
179 | ostream& out() | |
180 | { | |
181 | static ostream x(std::wcout); | |
182 | return x; | |
183 | } | |
184 | ||
185 | namespace | |
186 | { | |
187 | inline ostream& error_stream() | |
188 | { | |
189 | static ostream x(std::wcerr); | |
190 | return x; | |
191 | } | |
192 | } | |
193 | ||
194 | #else | |
195 | ||
196 | void initialise_output() | |
197 | { | |
198 | } | |
199 | ||
200 | void write_utf8(ostream::base_ostream& out, boost::string_ref x) | |
201 | { | |
202 | out << x; | |
203 | } | |
204 | ||
205 | ostream& out() | |
206 | { | |
207 | static ostream x(std::cout); | |
208 | return x; | |
209 | } | |
210 | ||
211 | namespace | |
212 | { | |
213 | inline ostream& error_stream() | |
214 | { | |
215 | static ostream x(std::clog); | |
216 | return x; | |
217 | } | |
218 | } | |
219 | ||
220 | #endif | |
221 | ||
222 | ostream& outerr() | |
223 | { | |
224 | return error_stream() << "Error: "; | |
225 | } | |
226 | ||
227 | ostream& outerr(fs::path const& file, int line) | |
228 | { | |
229 | if (line >= 0) | |
230 | { | |
231 | if (ms_errors) | |
232 | return error_stream() << path_to_stream(file) << "(" << line << "): error: "; | |
233 | else | |
234 | return error_stream() << path_to_stream(file) << ":" << line << ": error: "; | |
235 | } | |
236 | else | |
237 | { | |
238 | return error_stream() << path_to_stream(file) << ": error: "; | |
239 | } | |
240 | } | |
241 | ||
242 | ostream& outerr(file_ptr const& f, string_iterator pos) | |
243 | { | |
244 | return outerr(f->path, f->position_of(pos).line); | |
245 | } | |
246 | ||
247 | ostream& outwarn(fs::path const& file, int line) | |
248 | { | |
249 | if (line >= 0) | |
250 | { | |
251 | if (ms_errors) | |
252 | return error_stream() << path_to_stream(file) << "(" << line << "): warning: "; | |
253 | else | |
254 | return error_stream() << path_to_stream(file) << ":" << line << ": warning: "; | |
255 | } | |
256 | else | |
257 | { | |
258 | return error_stream() << path_to_stream(file) << ": warning: "; | |
259 | } | |
260 | } | |
261 | ||
262 | ostream& outwarn(file_ptr const& f, string_iterator pos) | |
263 | { | |
264 | return outwarn(f->path, f->position_of(pos).line); | |
265 | } | |
266 | ||
267 | ostream& ostream::operator<<(char c) { | |
268 | assert(c > 0 && c <= 127); | |
269 | base << c; | |
270 | return *this; | |
271 | } | |
272 | ||
273 | inline bool check_ascii(char const* x) { | |
274 | for(;*x;++x) if(*x <= 0 || *x > 127) return false; | |
275 | return true; | |
276 | } | |
277 | ||
278 | ostream& ostream::operator<<(char const* x) { | |
279 | assert(check_ascii(x)); | |
280 | base << x; | |
281 | return *this; | |
282 | } | |
283 | ||
284 | ostream& ostream::operator<<(std::string const& x) { | |
285 | write_utf8(base, x); | |
286 | return *this; | |
287 | } | |
288 | ||
289 | ostream& ostream::operator<<(boost::string_ref x) { | |
290 | write_utf8(base, x); | |
291 | return *this; | |
292 | } | |
293 | ||
294 | ostream& ostream::operator<<(int x) { | |
295 | base << x; | |
296 | return *this; | |
297 | } | |
298 | ||
299 | ostream& ostream::operator<<(unsigned int x) { | |
300 | base << x; | |
301 | return *this; | |
302 | } | |
303 | ||
304 | ostream& ostream::operator<<(long x) { | |
305 | base << x; | |
306 | return *this; | |
307 | } | |
308 | ||
309 | ostream& ostream::operator<<(unsigned long x) { | |
310 | base << x; | |
311 | return *this; | |
312 | } | |
313 | ||
314 | #if !defined(BOOST_NO_LONG_LONG) | |
315 | ostream& ostream::operator<<(long long x) { | |
316 | base << x; | |
317 | return *this; | |
318 | } | |
319 | ||
320 | ostream& ostream::operator<<(unsigned long long x) { | |
321 | base << x; | |
322 | return *this; | |
323 | } | |
324 | #endif | |
325 | ||
326 | ostream& ostream::operator<<(fs::path const& x) { | |
327 | base << path_to_stream(x); | |
328 | return *this; | |
329 | } | |
330 | ||
331 | ostream& ostream::operator<<(base_ostream& (*x)(base_ostream&)) { | |
332 | base << x; | |
333 | return *this; | |
334 | } | |
335 | ||
336 | ostream& ostream::operator<<(base_ios& (*x)(base_ios&)) { | |
337 | base << x; | |
338 | return *this; | |
339 | } | |
340 | }} |