• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
basic_string_literal()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 >
basic_string_literal(T (& p)[LenV],typename boost::enable_if_c<is_same<T,const value_type>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())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      */
basic_string_literal(basic_string_literal const & that)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      */
operator =(this_type const & that)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
operator =(T (& p)[LenV])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      */
operator ==(this_type const & that) const152     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      */
operator ==(const_pointer str) const162     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      */
operator ==(string_type const & that) const172     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      */
operator !=(this_type const & that) const183     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      */
operator !=(const_pointer str) const193     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      */
operator !=(string_type const & that) const203     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      */
operator <(this_type const & that) const214     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      */
operator <(const_pointer str) const224     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      */
operator <(string_type const & that) const234     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      */
operator <=(this_type const & that) const245     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      */
operator <=(const_pointer str) const255     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      */
operator <=(string_type const & that) const265     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      */
operator >(this_type const & that) const276     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      */
operator >(const_pointer str) const286     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      */
operator >(string_type const & that) const296     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      */
operator >=(this_type const & that) const307     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      */
operator >=(const_pointer str) const317     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      */
operator >=(string_type const & that) const327     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      */
operator [](size_type i) const339     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      */
at(size_type i) const351     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      */
c_str() const361     BOOST_CONSTEXPR const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
362     /*!
363      * \return Pointer to the beginning of the literal
364      */
data() const365     BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
366     /*!
367      * \return Length of the literal
368      */
size() const369     BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return m_Len; }
370     /*!
371      * \return Length of the literal
372      */
length() const373     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      */
empty() const378     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      */
begin() const386     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      */
end() const390     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      */
rbegin() const394     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      */
rend() const398     const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
399 
400     /*!
401      * \return STL string constructed from the literal
402      */
str() const403     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      */
clear()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      */
swap(this_type & that)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      */
assign(this_type const & that)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
assign(T (& p)[LenV])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      */
copy(value_type * str,size_type n,size_type pos=0) const479     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      */
compare(size_type pos,size_type n,const_pointer str,size_type len) const504     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      */
compare(size_type pos,size_type n,const_pointer str) const528     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      */
compare(size_type pos,size_type n,this_type const & that) const544     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      */
compare(const_pointer str,size_type len) const556     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      */
compare(const_pointer str) const567     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      */
compare(this_type const & that) const578     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
compare_internal(const_pointer pLeft,size_type LeftLen,const_pointer pRight,size_type RightLen)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 >
insert_fill_chars(std::basic_ostream<CharT,TraitsT> & strm,std::size_t n)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 >
insert_aligned(std::basic_ostream<CharT,TraitsT> & strm,const CharT * p,std::size_t size)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 >
operator <<(std::basic_ostream<CharT,StrmTraitsT> & strm,basic_string_literal<CharT,LitTraitsT> const & lit)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 >
swap(basic_string_literal<CharT,TraitsT> & left,basic_string_literal<CharT,TraitsT> & right)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
str_literal(T (& p)[LenV])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
str_literal(T (& p)[LenV])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_
712