string_literal.hpp 24 KB

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