]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright Andrey Semashev 2007 - 2016. | |
3 | * Distributed under the Boost Software License, Version 1.0. | |
4 | * (See accompanying file LICENSE_1_0.txt or copy at | |
5 | * http://www.boost.org/LICENSE_1_0.txt) | |
6 | */ | |
7 | /*! | |
8 | * \file string_literal.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 24.06.2007 | |
11 | * | |
12 | * The header contains implementation of a constant string literal wrapper. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ | |
17 | ||
18 | #include <cstddef> | |
19 | #include <stdexcept> | |
20 | #include <iosfwd> | |
21 | #include <ios> // std::streamsize | |
22 | #include <string> | |
23 | #include <iterator> | |
24 | #include <boost/throw_exception.hpp> | |
25 | #include <boost/type_traits/is_same.hpp> | |
26 | #include <boost/log/detail/config.hpp> | |
27 | #include <boost/log/utility/string_literal_fwd.hpp> | |
28 | #include <boost/log/detail/sfinae_tools.hpp> | |
29 | #include <boost/log/detail/header.hpp> | |
30 | ||
31 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
32 | #pragma once | |
33 | #endif | |
34 | ||
35 | namespace boost { | |
36 | ||
37 | BOOST_LOG_OPEN_NAMESPACE | |
38 | ||
39 | /*! | |
40 | * \brief String literal wrapper | |
41 | * | |
42 | * The \c basic_string_literal is a thin wrapper around a constant string literal. | |
43 | * It provides interface similar to STL strings, but because of read-only nature | |
44 | * of string literals, lacks ability to modify string contents. However, | |
45 | * \c basic_string_literal objects can be assigned to and cleared. | |
46 | * | |
47 | * The main advantage of this class comparing to other string classes is that | |
48 | * it doesn't dynamically allocate memory and therefore is fast, thin and exception safe. | |
49 | */ | |
50 | template< typename CharT, typename TraitsT > | |
51 | class basic_string_literal | |
52 | { | |
53 | //! Self type | |
54 | typedef basic_string_literal< CharT, TraitsT > this_type; | |
55 | ||
56 | public: | |
57 | typedef CharT value_type; | |
58 | typedef TraitsT traits_type; | |
59 | ||
60 | typedef std::size_t size_type; | |
61 | typedef std::ptrdiff_t difference_type; | |
62 | typedef const value_type* const_pointer; | |
63 | typedef value_type const& const_reference; | |
64 | typedef const value_type* const_iterator; | |
65 | typedef std::reverse_iterator< const_iterator > const_reverse_iterator; | |
66 | ||
67 | //! Corresponding STL string type | |
68 | typedef std::basic_string< value_type, traits_type > string_type; | |
69 | ||
70 | private: | |
71 | //! Pointer to the beginning of the literal | |
72 | const_pointer m_pStart; | |
73 | //! Length | |
74 | size_type m_Len; | |
75 | ||
76 | //! Empty string literal to support \c clear | |
77 | #if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS) | |
78 | static constexpr value_type g_EmptyString[1] = { 0 }; | |
79 | #else | |
80 | static const value_type g_EmptyString[1]; | |
81 | #endif | |
82 | ||
83 | public: | |
84 | /*! | |
85 | * Constructor | |
86 | * | |
87 | * \post <tt>empty() == true</tt> | |
88 | */ | |
89 | BOOST_CONSTEXPR basic_string_literal() BOOST_NOEXCEPT : m_pStart(g_EmptyString), m_Len(0) { } | |
90 | ||
91 | /*! | |
92 | * Constructor from a string literal | |
93 | * | |
94 | * \post <tt>*this == p</tt> | |
95 | * \param p A zero-terminated constant sequence of characters | |
96 | */ | |
97 | template< typename T, size_type LenV > | |
98 | BOOST_CONSTEXPR basic_string_literal(T(&p)[LenV] | |
99 | //! \cond | |
100 | , typename boost::enable_if_c< is_same< T, const value_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy() | |
101 | //! \endcond | |
102 | ) BOOST_NOEXCEPT | |
103 | : m_pStart(p), m_Len(LenV - 1) | |
104 | { | |
105 | } | |
106 | ||
107 | /*! | |
108 | * Copy constructor | |
109 | * | |
110 | * \post <tt>*this == that</tt> | |
111 | * \param that Source literal to copy string from | |
112 | */ | |
113 | BOOST_CONSTEXPR basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {} | |
114 | ||
115 | /*! | |
116 | * Assignment operator | |
117 | * | |
118 | * \post <tt>*this == that</tt> | |
119 | * \param that Source literal to copy string from | |
120 | */ | |
121 | BOOST_CXX14_CONSTEXPR this_type& operator= (this_type const& that) BOOST_NOEXCEPT | |
122 | { | |
123 | return assign(that); | |
124 | } | |
125 | /*! | |
126 | * Assignment from a string literal | |
127 | * | |
128 | * \post <tt>*this == p</tt> | |
129 | * \param p A zero-terminated constant sequence of characters | |
130 | */ | |
131 | template< typename T, size_type LenV > | |
132 | BOOST_CXX14_CONSTEXPR | |
133 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
134 | typename boost::enable_if_c< | |
135 | is_same< T, const value_type >::value, | |
136 | this_type& | |
137 | >::type | |
138 | #else | |
139 | this_type& | |
140 | #endif // BOOST_LOG_DOXYGEN_PASS | |
141 | operator= (T(&p)[LenV]) BOOST_NOEXCEPT | |
142 | { | |
143 | return assign(p); | |
144 | } | |
145 | ||
146 | /*! | |
147 | * Lexicographical comparison (equality) | |
148 | * | |
149 | * \param that Comparand | |
150 | * \return \c true if the comparand string equals to this string, \c false otherwise | |
151 | */ | |
152 | bool operator== (this_type const& that) const BOOST_NOEXCEPT | |
153 | { | |
154 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) == 0); | |
155 | } | |
156 | /*! | |
157 | * Lexicographical comparison (equality) | |
158 | * | |
159 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
160 | * \return \c true if the comparand string equals to this string, \c false otherwise | |
161 | */ | |
162 | bool operator== (const_pointer str) const BOOST_NOEXCEPT | |
163 | { | |
164 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) == 0); | |
165 | } | |
166 | /*! | |
167 | * Lexicographical comparison (equality) | |
168 | * | |
169 | * \param that Comparand | |
170 | * \return \c true if the comparand string equals to this string, \c false otherwise | |
171 | */ | |
172 | bool operator== (string_type const& that) const BOOST_NOEXCEPT | |
173 | { | |
174 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0); | |
175 | } | |
176 | ||
177 | /*! | |
178 | * Lexicographical comparison (inequality) | |
179 | * | |
180 | * \param that Comparand | |
181 | * \return \c true if the comparand string is not equal to this string, \c false otherwise | |
182 | */ | |
183 | bool operator!= (this_type const& that) const BOOST_NOEXCEPT | |
184 | { | |
185 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) != 0); | |
186 | } | |
187 | /*! | |
188 | * Lexicographical comparison (inequality) | |
189 | * | |
190 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
191 | * \return \c true if the comparand string is not equal to this string, \c false otherwise | |
192 | */ | |
193 | bool operator!= (const_pointer str) const BOOST_NOEXCEPT | |
194 | { | |
195 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) != 0); | |
196 | } | |
197 | /*! | |
198 | * Lexicographical comparison (inequality) | |
199 | * | |
200 | * \param that Comparand | |
201 | * \return \c true if the comparand string is not equal to this string, \c false otherwise | |
202 | */ | |
203 | bool operator!= (string_type const& that) const BOOST_NOEXCEPT | |
204 | { | |
205 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) != 0); | |
206 | } | |
207 | ||
208 | /*! | |
209 | * Lexicographical comparison (less ordering) | |
210 | * | |
211 | * \param that Comparand | |
212 | * \return \c true if this string is less than the comparand, \c false otherwise | |
213 | */ | |
214 | bool operator< (this_type const& that) const BOOST_NOEXCEPT | |
215 | { | |
216 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) < 0); | |
217 | } | |
218 | /*! | |
219 | * Lexicographical comparison (less ordering) | |
220 | * | |
221 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
222 | * \return \c true if this string is less than the comparand, \c false otherwise | |
223 | */ | |
224 | bool operator< (const_pointer str) const BOOST_NOEXCEPT | |
225 | { | |
226 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) < 0); | |
227 | } | |
228 | /*! | |
229 | * Lexicographical comparison (less ordering) | |
230 | * | |
231 | * \param that Comparand | |
232 | * \return \c true if this string is less than the comparand, \c false otherwise | |
233 | */ | |
234 | bool operator< (string_type const& that) const BOOST_NOEXCEPT | |
235 | { | |
236 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0); | |
237 | } | |
238 | ||
239 | /*! | |
240 | * Lexicographical comparison (less or equal ordering) | |
241 | * | |
242 | * \param that Comparand | |
243 | * \return \c true if this string is less or equal to the comparand, \c false otherwise | |
244 | */ | |
245 | bool operator<= (this_type const& that) const BOOST_NOEXCEPT | |
246 | { | |
247 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) <= 0); | |
248 | } | |
249 | /*! | |
250 | * Lexicographical comparison (less or equal ordering) | |
251 | * | |
252 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
253 | * \return \c true if this string is less or equal to the comparand, \c false otherwise | |
254 | */ | |
255 | bool operator<= (const_pointer str) const BOOST_NOEXCEPT | |
256 | { | |
257 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) <= 0); | |
258 | } | |
259 | /*! | |
260 | * Lexicographical comparison (less or equal ordering) | |
261 | * | |
262 | * \param that Comparand | |
263 | * \return \c true if this string is less or equal to the comparand, \c false otherwise | |
264 | */ | |
265 | bool operator<= (string_type const& that) const BOOST_NOEXCEPT | |
266 | { | |
267 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) <= 0); | |
268 | } | |
269 | ||
270 | /*! | |
271 | * Lexicographical comparison (greater ordering) | |
272 | * | |
273 | * \param that Comparand | |
274 | * \return \c true if this string is greater than the comparand, \c false otherwise | |
275 | */ | |
276 | bool operator> (this_type const& that) const BOOST_NOEXCEPT | |
277 | { | |
278 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) > 0); | |
279 | } | |
280 | /*! | |
281 | * Lexicographical comparison (greater ordering) | |
282 | * | |
283 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
284 | * \return \c true if this string is greater than the comparand, \c false otherwise | |
285 | */ | |
286 | bool operator> (const_pointer str) const BOOST_NOEXCEPT | |
287 | { | |
288 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) > 0); | |
289 | } | |
290 | /*! | |
291 | * Lexicographical comparison (greater ordering) | |
292 | * | |
293 | * \param that Comparand | |
294 | * \return \c true if this string is greater than the comparand, \c false otherwise | |
295 | */ | |
296 | bool operator> (string_type const& that) const BOOST_NOEXCEPT | |
297 | { | |
298 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0); | |
299 | } | |
300 | ||
301 | /*! | |
302 | * Lexicographical comparison (greater or equal ordering) | |
303 | * | |
304 | * \param that Comparand | |
305 | * \return \c true if this string is greater or equal to the comparand, \c false otherwise | |
306 | */ | |
307 | bool operator>= (this_type const& that) const BOOST_NOEXCEPT | |
308 | { | |
309 | return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) >= 0); | |
310 | } | |
311 | /*! | |
312 | * Lexicographical comparison (greater or qual ordering) | |
313 | * | |
314 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
315 | * \return \c true if this string is greater or equal to the comparand, \c false otherwise | |
316 | */ | |
317 | bool operator>= (const_pointer str) const BOOST_NOEXCEPT | |
318 | { | |
319 | return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) >= 0); | |
320 | } | |
321 | /*! | |
322 | * Lexicographical comparison (greater or equal ordering) | |
323 | * | |
324 | * \param that Comparand | |
325 | * \return \c true if this string is greater or equal to the comparand, \c false otherwise | |
326 | */ | |
327 | bool operator>= (string_type const& that) const BOOST_NOEXCEPT | |
328 | { | |
329 | return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) >= 0); | |
330 | } | |
331 | ||
332 | /*! | |
333 | * Subscript operator | |
334 | * | |
335 | * \pre <tt>i < size()</tt> | |
336 | * \param i Requested character index | |
337 | * \return Constant reference to the requested character | |
338 | */ | |
339 | BOOST_CONSTEXPR const_reference operator[] (size_type i) const BOOST_NOEXCEPT | |
340 | { | |
341 | return m_pStart[i]; | |
342 | } | |
343 | /*! | |
344 | * Checked subscript | |
345 | * | |
346 | * \param i Requested character index | |
347 | * \return Constant reference to the requested character | |
348 | * | |
349 | * \b Throws: An <tt>std::exception</tt>-based exception if index \a i is out of string boundaries | |
350 | */ | |
351 | const_reference at(size_type i) const | |
352 | { | |
353 | if (BOOST_UNLIKELY(i >= m_Len)) | |
354 | BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range")); | |
355 | return m_pStart[i]; | |
356 | } | |
357 | ||
358 | /*! | |
359 | * \return Pointer to the beginning of the literal | |
360 | */ | |
361 | BOOST_CONSTEXPR const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; } | |
362 | /*! | |
363 | * \return Pointer to the beginning of the literal | |
364 | */ | |
365 | BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return m_pStart; } | |
366 | /*! | |
367 | * \return Length of the literal | |
368 | */ | |
369 | BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return m_Len; } | |
370 | /*! | |
371 | * \return Length of the literal | |
372 | */ | |
373 | BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return m_Len; } | |
374 | ||
375 | /*! | |
376 | * \return \c true if the literal is an empty string, \c false otherwise | |
377 | */ | |
378 | BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT | |
379 | { | |
380 | return (m_Len == 0); | |
381 | } | |
382 | ||
383 | /*! | |
384 | * \return Iterator that points to the first character of the literal | |
385 | */ | |
386 | BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; } | |
387 | /*! | |
388 | * \return Iterator that points after the last character of the literal | |
389 | */ | |
390 | BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; } | |
391 | /*! | |
392 | * \return Reverse iterator that points to the last character of the literal | |
393 | */ | |
394 | const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } | |
395 | /*! | |
396 | * \return Reverse iterator that points before the first character of the literal | |
397 | */ | |
398 | const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } | |
399 | ||
400 | /*! | |
401 | * \return STL string constructed from the literal | |
402 | */ | |
403 | string_type str() const | |
404 | { | |
405 | return string_type(m_pStart, m_Len); | |
406 | } | |
407 | ||
408 | /*! | |
409 | * The method clears the literal | |
410 | * | |
411 | * \post <tt>empty() == true</tt> | |
412 | */ | |
413 | BOOST_CXX14_CONSTEXPR void clear() BOOST_NOEXCEPT | |
414 | { | |
415 | m_pStart = g_EmptyString; | |
416 | m_Len = 0; | |
417 | } | |
418 | /*! | |
419 | * The method swaps two literals | |
420 | */ | |
421 | BOOST_CXX14_CONSTEXPR void swap(this_type& that) BOOST_NOEXCEPT | |
422 | { | |
423 | const_pointer p = m_pStart; | |
424 | m_pStart = that.m_pStart; | |
425 | that.m_pStart = p; | |
426 | ||
427 | size_type l = m_Len; | |
428 | m_Len = that.m_Len; | |
429 | that.m_Len = l; | |
430 | } | |
431 | ||
432 | /*! | |
433 | * Assignment from another literal | |
434 | * | |
435 | * \post <tt>*this == that</tt> | |
436 | * \param that Source literal to copy string from | |
437 | */ | |
438 | BOOST_CXX14_CONSTEXPR this_type& assign(this_type const& that) BOOST_NOEXCEPT | |
439 | { | |
440 | m_pStart = that.m_pStart; | |
441 | m_Len = that.m_Len; | |
442 | return *this; | |
443 | } | |
444 | /*! | |
445 | * Assignment from another literal | |
446 | * | |
447 | * \post <tt>*this == p</tt> | |
448 | * \param p A zero-terminated constant sequence of characters | |
449 | */ | |
450 | template< typename T, size_type LenV > | |
451 | BOOST_CXX14_CONSTEXPR | |
452 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
453 | typename boost::enable_if_c< | |
454 | is_same< T, const value_type >::value, | |
455 | this_type& | |
456 | >::type | |
457 | #else | |
458 | this_type& | |
459 | #endif // BOOST_LOG_DOXYGEN_PASS | |
460 | assign(T(&p)[LenV]) BOOST_NOEXCEPT | |
461 | { | |
462 | m_pStart = p; | |
463 | m_Len = LenV - 1; | |
464 | return *this; | |
465 | } | |
466 | ||
467 | /*! | |
468 | * The method copies the literal or its portion to an external buffer | |
469 | * | |
470 | * \pre <tt>pos <= size()</tt> | |
471 | * \param str Pointer to the external buffer beginning. Must not be NULL. | |
472 | * The buffer must have enough capacity to accommodate the requested number of characters. | |
473 | * \param n Maximum number of characters to copy | |
474 | * \param pos Starting position to start copying from | |
475 | * \return Number of characters copied | |
476 | * | |
477 | * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. | |
478 | */ | |
479 | size_type copy(value_type* str, size_type n, size_type pos = 0) const | |
480 | { | |
481 | if (BOOST_UNLIKELY(pos > m_Len)) | |
482 | BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range")); | |
483 | ||
484 | size_type len = m_Len - pos; | |
485 | if (len > n) | |
486 | len = n; | |
487 | traits_type::copy(str, m_pStart + pos, len); | |
488 | return len; | |
489 | } | |
490 | ||
491 | /*! | |
492 | * Lexicographically compares the argument string to a part of this string | |
493 | * | |
494 | * \pre <tt>pos <= size()</tt> | |
495 | * \param pos Starting position within this string to perform comparison to | |
496 | * \param n Length of the substring of this string to perform comparison to | |
497 | * \param str Comparand. Must point to a sequence of characters, must not be NULL. | |
498 | * \param len Number of characters in the sequence \a str. | |
499 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
500 | * a positive value if this string is greater than the comparand. | |
501 | * | |
502 | * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. | |
503 | */ | |
504 | int compare(size_type pos, size_type n, const_pointer str, size_type len) const | |
505 | { | |
506 | if (BOOST_UNLIKELY(pos > m_Len)) | |
507 | BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range")); | |
508 | ||
509 | size_type compare_size = m_Len - pos; | |
510 | if (compare_size > len) | |
511 | compare_size = len; | |
512 | if (compare_size > n) | |
513 | compare_size = n; | |
514 | return compare_internal(m_pStart + pos, compare_size, str, compare_size); | |
515 | } | |
516 | /*! | |
517 | * Lexicographically compares the argument string to a part of this string | |
518 | * | |
519 | * \pre <tt>pos <= size()</tt> | |
520 | * \param pos Starting position within this string to perform comparison to | |
521 | * \param n Length of the substring of this string to perform comparison to | |
522 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
523 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
524 | * a positive value if this string is greater than the comparand. | |
525 | * | |
526 | * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. | |
527 | */ | |
528 | int compare(size_type pos, size_type n, const_pointer str) const BOOST_NOEXCEPT | |
529 | { | |
530 | return compare(pos, n, str, traits_type::length(str)); | |
531 | } | |
532 | /*! | |
533 | * Lexicographically compares the argument string literal to a part of this string | |
534 | * | |
535 | * \pre <tt>pos <= size()</tt> | |
536 | * \param pos Starting position within this string to perform comparison to | |
537 | * \param n Length of the substring of this string to perform comparison to | |
538 | * \param that Comparand | |
539 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
540 | * a positive value if this string is greater than the comparand. | |
541 | * | |
542 | * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. | |
543 | */ | |
544 | int compare(size_type pos, size_type n, this_type const& that) const BOOST_NOEXCEPT | |
545 | { | |
546 | return compare(pos, n, that.c_str(), that.size()); | |
547 | } | |
548 | /*! | |
549 | * Lexicographically compares the argument string to this string | |
550 | * | |
551 | * \param str Comparand. Must point to a sequence of characters, must not be NULL. | |
552 | * \param len Number of characters in the sequence \a str. | |
553 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
554 | * a positive value if this string is greater than the comparand. | |
555 | */ | |
556 | int compare(const_pointer str, size_type len) const BOOST_NOEXCEPT | |
557 | { | |
558 | return compare(0, m_Len, str, len); | |
559 | } | |
560 | /*! | |
561 | * Lexicographically compares the argument string to this string | |
562 | * | |
563 | * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. | |
564 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
565 | * a positive value if this string is greater than the comparand. | |
566 | */ | |
567 | int compare(const_pointer str) const BOOST_NOEXCEPT | |
568 | { | |
569 | return compare(0, m_Len, str, traits_type::length(str)); | |
570 | } | |
571 | /*! | |
572 | * Lexicographically compares the argument string to this string | |
573 | * | |
574 | * \param that Comparand | |
575 | * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, | |
576 | * a positive value if this string is greater than the comparand. | |
577 | */ | |
578 | int compare(this_type const& that) const BOOST_NOEXCEPT | |
579 | { | |
580 | return compare(0, m_Len, that.c_str(), that.size()); | |
581 | } | |
582 | ||
583 | private: | |
584 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
585 | //! Internal comparison implementation | |
586 | static int compare_internal(const_pointer pLeft, size_type LeftLen, const_pointer pRight, size_type RightLen) BOOST_NOEXCEPT | |
587 | { | |
588 | if (pLeft != pRight) | |
589 | { | |
590 | const int result = traits_type::compare(pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen)); | |
591 | if (result != 0) | |
592 | return result; | |
593 | } | |
594 | return LeftLen < RightLen ? -1 : (LeftLen > RightLen ? 1 : 0); | |
595 | } | |
596 | #endif // BOOST_LOG_DOXYGEN_PASS | |
597 | }; | |
598 | ||
599 | #if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS) | |
600 | template< typename CharT, typename TraitsT > | |
601 | constexpr typename basic_string_literal< CharT, TraitsT >::value_type | |
602 | basic_string_literal< CharT, TraitsT >::g_EmptyString[1]; | |
603 | #else | |
604 | template< typename CharT, typename TraitsT > | |
605 | const typename basic_string_literal< CharT, TraitsT >::value_type | |
606 | basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 }; | |
607 | #endif | |
608 | ||
609 | namespace aux { | |
610 | ||
611 | template< typename CharT, typename TraitsT > | |
612 | inline void insert_fill_chars(std::basic_ostream< CharT, TraitsT >& strm, std::size_t n) | |
613 | { | |
614 | enum { chunk_size = 8 }; | |
615 | CharT fill_chars[chunk_size]; | |
616 | const CharT filler = strm.fill(); | |
617 | for (unsigned int i = 0; i < chunk_size; ++i) | |
618 | fill_chars[i] = filler; | |
619 | for (; n >= chunk_size && strm.good(); n -= chunk_size) | |
620 | strm.write(fill_chars, static_cast< std::size_t >(chunk_size)); | |
621 | if (n > 0 && strm.good()) | |
622 | strm.write(fill_chars, n); | |
623 | } | |
624 | ||
625 | template< typename CharT, typename TraitsT > | |
626 | void insert_aligned(std::basic_ostream< CharT, TraitsT >& strm, const CharT* p, std::size_t size) | |
627 | { | |
628 | const std::size_t alignment_size = static_cast< std::size_t >(strm.width()) - size; | |
629 | const bool align_left = (strm.flags() & std::basic_ostream< CharT, TraitsT >::adjustfield) == std::basic_ostream< CharT, TraitsT >::left; | |
630 | if (align_left) | |
631 | { | |
632 | strm.write(p, size); | |
633 | if (strm.good()) | |
634 | aux::insert_fill_chars(strm, alignment_size); | |
635 | } | |
636 | else | |
637 | { | |
638 | aux::insert_fill_chars(strm, alignment_size); | |
639 | if (strm.good()) | |
640 | strm.write(p, size); | |
641 | } | |
642 | } | |
643 | ||
644 | } // namespace aux | |
645 | ||
646 | //! Output operator | |
647 | template< typename CharT, typename StrmTraitsT, typename LitTraitsT > | |
648 | inline std::basic_ostream< CharT, StrmTraitsT >& operator<< ( | |
649 | std::basic_ostream< CharT, StrmTraitsT >& strm, basic_string_literal< CharT, LitTraitsT > const& lit) | |
650 | { | |
651 | if (strm.good()) | |
652 | { | |
653 | const std::size_t size = lit.size(); | |
654 | const std::size_t w = static_cast< std::size_t >(strm.width()); | |
655 | if (w <= size) | |
656 | strm.write(lit.c_str(), static_cast< std::streamsize >(size)); | |
657 | else | |
658 | aux::insert_aligned(strm, lit.c_str(), lit.size()); | |
659 | strm.width(0); | |
660 | } | |
661 | return strm; | |
662 | } | |
663 | ||
664 | //! External swap | |
665 | template< typename CharT, typename TraitsT > | |
666 | inline BOOST_CXX14_CONSTEXPR void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT | |
667 | { | |
668 | left.swap(right); | |
669 | } | |
670 | ||
671 | //! Creates a string literal wrapper from a constant string literal | |
672 | #ifdef BOOST_LOG_USE_CHAR | |
673 | template< typename T, std::size_t LenV > | |
674 | inline BOOST_CONSTEXPR | |
675 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
676 | typename boost::enable_if_c< | |
677 | is_same< T, const char >::value, | |
678 | string_literal | |
679 | >::type | |
680 | #else | |
681 | basic_string_literal< T > | |
682 | #endif // BOOST_LOG_DOXYGEN_PASS | |
683 | str_literal(T(&p)[LenV]) BOOST_NOEXCEPT | |
684 | { | |
685 | return string_literal(p); | |
686 | } | |
687 | #endif | |
688 | ||
689 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
690 | ||
691 | #ifdef BOOST_LOG_USE_WCHAR_T | |
692 | template< typename T, std::size_t LenV > | |
693 | inline BOOST_CONSTEXPR typename boost::enable_if_c< | |
694 | is_same< T, const wchar_t >::value, | |
695 | wstring_literal | |
696 | >::type | |
697 | str_literal(T(&p)[LenV]) BOOST_NOEXCEPT | |
698 | { | |
699 | return wstring_literal(p); | |
700 | } | |
701 | #endif | |
702 | ||
703 | #endif // BOOST_LOG_DOXYGEN_PASS | |
704 | ||
705 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
706 | ||
707 | } // namespace boost | |
708 | ||
709 | #include <boost/log/detail/footer.hpp> | |
710 | ||
711 | #endif // BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ |