712 lines
24 KiB
C++
712 lines
24 KiB
C++
/*
|
|
* Copyright Andrey Semashev 2007 - 2016.
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
/*!
|
|
* \file string_literal.hpp
|
|
* \author Andrey Semashev
|
|
* \date 24.06.2007
|
|
*
|
|
* The header contains implementation of a constant string literal wrapper.
|
|
*/
|
|
|
|
#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
|
|
#define BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
|
|
|
|
#include <cstddef>
|
|
#include <stdexcept>
|
|
#include <iosfwd>
|
|
#include <ios> // std::streamsize
|
|
#include <string>
|
|
#include <iterator>
|
|
#include <boost/throw_exception.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <boost/log/detail/config.hpp>
|
|
#include <boost/log/utility/string_literal_fwd.hpp>
|
|
#include <boost/log/detail/sfinae_tools.hpp>
|
|
#include <boost/log/detail/header.hpp>
|
|
|
|
#ifdef BOOST_HAS_PRAGMA_ONCE
|
|
#pragma once
|
|
#endif
|
|
|
|
namespace boost {
|
|
|
|
BOOST_LOG_OPEN_NAMESPACE
|
|
|
|
/*!
|
|
* \brief String literal wrapper
|
|
*
|
|
* The \c basic_string_literal is a thin wrapper around a constant string literal.
|
|
* It provides interface similar to STL strings, but because of read-only nature
|
|
* of string literals, lacks ability to modify string contents. However,
|
|
* \c basic_string_literal objects can be assigned to and cleared.
|
|
*
|
|
* The main advantage of this class comparing to other string classes is that
|
|
* it doesn't dynamically allocate memory and therefore is fast, thin and exception safe.
|
|
*/
|
|
template< typename CharT, typename TraitsT >
|
|
class basic_string_literal
|
|
{
|
|
//! Self type
|
|
typedef basic_string_literal< CharT, TraitsT > this_type;
|
|
|
|
public:
|
|
typedef CharT value_type;
|
|
typedef TraitsT traits_type;
|
|
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef const value_type* const_pointer;
|
|
typedef value_type const& const_reference;
|
|
typedef const value_type* const_iterator;
|
|
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
|
|
|
|
//! Corresponding STL string type
|
|
typedef std::basic_string< value_type, traits_type > string_type;
|
|
|
|
private:
|
|
//! Pointer to the beginning of the literal
|
|
const_pointer m_pStart;
|
|
//! Length
|
|
size_type m_Len;
|
|
|
|
//! Empty string literal to support \c clear
|
|
#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
|
|
static constexpr value_type g_EmptyString[1] = { 0 };
|
|
#else
|
|
static const value_type g_EmptyString[1];
|
|
#endif
|
|
|
|
public:
|
|
/*!
|
|
* Constructor
|
|
*
|
|
* \post <tt>empty() == true</tt>
|
|
*/
|
|
BOOST_CONSTEXPR basic_string_literal() BOOST_NOEXCEPT : m_pStart(g_EmptyString), m_Len(0) { }
|
|
|
|
/*!
|
|
* Constructor from a string literal
|
|
*
|
|
* \post <tt>*this == p</tt>
|
|
* \param p A zero-terminated constant sequence of characters
|
|
*/
|
|
template< typename T, size_type LenV >
|
|
BOOST_CONSTEXPR basic_string_literal(T(&p)[LenV]
|
|
//! \cond
|
|
, typename boost::enable_if_c< is_same< T, const value_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
|
|
//! \endcond
|
|
) BOOST_NOEXCEPT
|
|
: m_pStart(p), m_Len(LenV - 1)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* Copy constructor
|
|
*
|
|
* \post <tt>*this == that</tt>
|
|
* \param that Source literal to copy string from
|
|
*/
|
|
BOOST_CONSTEXPR basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {}
|
|
|
|
/*!
|
|
* Assignment operator
|
|
*
|
|
* \post <tt>*this == that</tt>
|
|
* \param that Source literal to copy string from
|
|
*/
|
|
BOOST_CXX14_CONSTEXPR this_type& operator= (this_type const& that) BOOST_NOEXCEPT
|
|
{
|
|
return assign(that);
|
|
}
|
|
/*!
|
|
* Assignment from a string literal
|
|
*
|
|
* \post <tt>*this == p</tt>
|
|
* \param p A zero-terminated constant sequence of characters
|
|
*/
|
|
template< typename T, size_type LenV >
|
|
BOOST_CXX14_CONSTEXPR
|
|
#ifndef BOOST_LOG_DOXYGEN_PASS
|
|
typename boost::enable_if_c<
|
|
is_same< T, const value_type >::value,
|
|
this_type&
|
|
>::type
|
|
#else
|
|
this_type&
|
|
#endif // BOOST_LOG_DOXYGEN_PASS
|
|
operator= (T(&p)[LenV]) BOOST_NOEXCEPT
|
|
{
|
|
return assign(p);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (equality)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if the comparand string equals to this string, \c false otherwise
|
|
*/
|
|
bool operator== (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) == 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (equality)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if the comparand string equals to this string, \c false otherwise
|
|
*/
|
|
bool operator== (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) == 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (equality)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if the comparand string equals to this string, \c false otherwise
|
|
*/
|
|
bool operator== (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (inequality)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if the comparand string is not equal to this string, \c false otherwise
|
|
*/
|
|
bool operator!= (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) != 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (inequality)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if the comparand string is not equal to this string, \c false otherwise
|
|
*/
|
|
bool operator!= (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) != 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (inequality)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if the comparand string is not equal to this string, \c false otherwise
|
|
*/
|
|
bool operator!= (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) != 0);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (less ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is less than the comparand, \c false otherwise
|
|
*/
|
|
bool operator< (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) < 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (less ordering)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if this string is less than the comparand, \c false otherwise
|
|
*/
|
|
bool operator< (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) < 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (less ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is less than the comparand, \c false otherwise
|
|
*/
|
|
bool operator< (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (less or equal ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is less or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator<= (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) <= 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (less or equal ordering)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if this string is less or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator<= (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) <= 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (less or equal ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is less or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator<= (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) <= 0);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (greater ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is greater than the comparand, \c false otherwise
|
|
*/
|
|
bool operator> (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) > 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (greater ordering)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if this string is greater than the comparand, \c false otherwise
|
|
*/
|
|
bool operator> (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) > 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (greater ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is greater than the comparand, \c false otherwise
|
|
*/
|
|
bool operator> (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0);
|
|
}
|
|
|
|
/*!
|
|
* Lexicographical comparison (greater or equal ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator>= (this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) >= 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (greater or qual ordering)
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator>= (const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) >= 0);
|
|
}
|
|
/*!
|
|
* Lexicographical comparison (greater or equal ordering)
|
|
*
|
|
* \param that Comparand
|
|
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
|
|
*/
|
|
bool operator>= (string_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) >= 0);
|
|
}
|
|
|
|
/*!
|
|
* Subscript operator
|
|
*
|
|
* \pre <tt>i < size()</tt>
|
|
* \param i Requested character index
|
|
* \return Constant reference to the requested character
|
|
*/
|
|
BOOST_CONSTEXPR const_reference operator[] (size_type i) const BOOST_NOEXCEPT
|
|
{
|
|
return m_pStart[i];
|
|
}
|
|
/*!
|
|
* Checked subscript
|
|
*
|
|
* \param i Requested character index
|
|
* \return Constant reference to the requested character
|
|
*
|
|
* \b Throws: An <tt>std::exception</tt>-based exception if index \a i is out of string boundaries
|
|
*/
|
|
const_reference at(size_type i) const
|
|
{
|
|
if (BOOST_UNLIKELY(i >= m_Len))
|
|
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range"));
|
|
return m_pStart[i];
|
|
}
|
|
|
|
/*!
|
|
* \return Pointer to the beginning of the literal
|
|
*/
|
|
BOOST_CONSTEXPR const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
|
|
/*!
|
|
* \return Pointer to the beginning of the literal
|
|
*/
|
|
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
|
|
/*!
|
|
* \return Length of the literal
|
|
*/
|
|
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return m_Len; }
|
|
/*!
|
|
* \return Length of the literal
|
|
*/
|
|
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return m_Len; }
|
|
|
|
/*!
|
|
* \return \c true if the literal is an empty string, \c false otherwise
|
|
*/
|
|
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
|
|
{
|
|
return (m_Len == 0);
|
|
}
|
|
|
|
/*!
|
|
* \return Iterator that points to the first character of the literal
|
|
*/
|
|
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; }
|
|
/*!
|
|
* \return Iterator that points after the last character of the literal
|
|
*/
|
|
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; }
|
|
/*!
|
|
* \return Reverse iterator that points to the last character of the literal
|
|
*/
|
|
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
|
/*!
|
|
* \return Reverse iterator that points before the first character of the literal
|
|
*/
|
|
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
|
|
|
/*!
|
|
* \return STL string constructed from the literal
|
|
*/
|
|
string_type str() const
|
|
{
|
|
return string_type(m_pStart, m_Len);
|
|
}
|
|
|
|
/*!
|
|
* The method clears the literal
|
|
*
|
|
* \post <tt>empty() == true</tt>
|
|
*/
|
|
BOOST_CXX14_CONSTEXPR void clear() BOOST_NOEXCEPT
|
|
{
|
|
m_pStart = g_EmptyString;
|
|
m_Len = 0;
|
|
}
|
|
/*!
|
|
* The method swaps two literals
|
|
*/
|
|
BOOST_CXX14_CONSTEXPR void swap(this_type& that) BOOST_NOEXCEPT
|
|
{
|
|
const_pointer p = m_pStart;
|
|
m_pStart = that.m_pStart;
|
|
that.m_pStart = p;
|
|
|
|
size_type l = m_Len;
|
|
m_Len = that.m_Len;
|
|
that.m_Len = l;
|
|
}
|
|
|
|
/*!
|
|
* Assignment from another literal
|
|
*
|
|
* \post <tt>*this == that</tt>
|
|
* \param that Source literal to copy string from
|
|
*/
|
|
BOOST_CXX14_CONSTEXPR this_type& assign(this_type const& that) BOOST_NOEXCEPT
|
|
{
|
|
m_pStart = that.m_pStart;
|
|
m_Len = that.m_Len;
|
|
return *this;
|
|
}
|
|
/*!
|
|
* Assignment from another literal
|
|
*
|
|
* \post <tt>*this == p</tt>
|
|
* \param p A zero-terminated constant sequence of characters
|
|
*/
|
|
template< typename T, size_type LenV >
|
|
BOOST_CXX14_CONSTEXPR
|
|
#ifndef BOOST_LOG_DOXYGEN_PASS
|
|
typename boost::enable_if_c<
|
|
is_same< T, const value_type >::value,
|
|
this_type&
|
|
>::type
|
|
#else
|
|
this_type&
|
|
#endif // BOOST_LOG_DOXYGEN_PASS
|
|
assign(T(&p)[LenV]) BOOST_NOEXCEPT
|
|
{
|
|
m_pStart = p;
|
|
m_Len = LenV - 1;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* The method copies the literal or its portion to an external buffer
|
|
*
|
|
* \pre <tt>pos <= size()</tt>
|
|
* \param str Pointer to the external buffer beginning. Must not be NULL.
|
|
* The buffer must have enough capacity to accommodate the requested number of characters.
|
|
* \param n Maximum number of characters to copy
|
|
* \param pos Starting position to start copying from
|
|
* \return Number of characters copied
|
|
*
|
|
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
|
|
*/
|
|
size_type copy(value_type* str, size_type n, size_type pos = 0) const
|
|
{
|
|
if (BOOST_UNLIKELY(pos > m_Len))
|
|
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range"));
|
|
|
|
size_type len = m_Len - pos;
|
|
if (len > n)
|
|
len = n;
|
|
traits_type::copy(str, m_pStart + pos, len);
|
|
return len;
|
|
}
|
|
|
|
/*!
|
|
* Lexicographically compares the argument string to a part of this string
|
|
*
|
|
* \pre <tt>pos <= size()</tt>
|
|
* \param pos Starting position within this string to perform comparison to
|
|
* \param n Length of the substring of this string to perform comparison to
|
|
* \param str Comparand. Must point to a sequence of characters, must not be NULL.
|
|
* \param len Number of characters in the sequence \a str.
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*
|
|
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
|
|
*/
|
|
int compare(size_type pos, size_type n, const_pointer str, size_type len) const
|
|
{
|
|
if (BOOST_UNLIKELY(pos > m_Len))
|
|
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range"));
|
|
|
|
size_type compare_size = m_Len - pos;
|
|
if (compare_size > len)
|
|
compare_size = len;
|
|
if (compare_size > n)
|
|
compare_size = n;
|
|
return compare_internal(m_pStart + pos, compare_size, str, compare_size);
|
|
}
|
|
/*!
|
|
* Lexicographically compares the argument string to a part of this string
|
|
*
|
|
* \pre <tt>pos <= size()</tt>
|
|
* \param pos Starting position within this string to perform comparison to
|
|
* \param n Length of the substring of this string to perform comparison to
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*
|
|
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
|
|
*/
|
|
int compare(size_type pos, size_type n, const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return compare(pos, n, str, traits_type::length(str));
|
|
}
|
|
/*!
|
|
* Lexicographically compares the argument string literal to a part of this string
|
|
*
|
|
* \pre <tt>pos <= size()</tt>
|
|
* \param pos Starting position within this string to perform comparison to
|
|
* \param n Length of the substring of this string to perform comparison to
|
|
* \param that Comparand
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*
|
|
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
|
|
*/
|
|
int compare(size_type pos, size_type n, this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return compare(pos, n, that.c_str(), that.size());
|
|
}
|
|
/*!
|
|
* Lexicographically compares the argument string to this string
|
|
*
|
|
* \param str Comparand. Must point to a sequence of characters, must not be NULL.
|
|
* \param len Number of characters in the sequence \a str.
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*/
|
|
int compare(const_pointer str, size_type len) const BOOST_NOEXCEPT
|
|
{
|
|
return compare(0, m_Len, str, len);
|
|
}
|
|
/*!
|
|
* Lexicographically compares the argument string to this string
|
|
*
|
|
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*/
|
|
int compare(const_pointer str) const BOOST_NOEXCEPT
|
|
{
|
|
return compare(0, m_Len, str, traits_type::length(str));
|
|
}
|
|
/*!
|
|
* Lexicographically compares the argument string to this string
|
|
*
|
|
* \param that Comparand
|
|
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
|
|
* a positive value if this string is greater than the comparand.
|
|
*/
|
|
int compare(this_type const& that) const BOOST_NOEXCEPT
|
|
{
|
|
return compare(0, m_Len, that.c_str(), that.size());
|
|
}
|
|
|
|
private:
|
|
#ifndef BOOST_LOG_DOXYGEN_PASS
|
|
//! Internal comparison implementation
|
|
static int compare_internal(const_pointer pLeft, size_type LeftLen, const_pointer pRight, size_type RightLen) BOOST_NOEXCEPT
|
|
{
|
|
if (pLeft != pRight)
|
|
{
|
|
const int result = traits_type::compare(pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen));
|
|
if (result != 0)
|
|
return result;
|
|
}
|
|
return LeftLen < RightLen ? -1 : (LeftLen > RightLen ? 1 : 0);
|
|
}
|
|
#endif // BOOST_LOG_DOXYGEN_PASS
|
|
};
|
|
|
|
#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
|
|
template< typename CharT, typename TraitsT >
|
|
constexpr typename basic_string_literal< CharT, TraitsT >::value_type
|
|
basic_string_literal< CharT, TraitsT >::g_EmptyString[1];
|
|
#else
|
|
template< typename CharT, typename TraitsT >
|
|
const typename basic_string_literal< CharT, TraitsT >::value_type
|
|
basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 };
|
|
#endif
|
|
|
|
namespace aux {
|
|
|
|
template< typename CharT, typename TraitsT >
|
|
inline void insert_fill_chars(std::basic_ostream< CharT, TraitsT >& strm, std::size_t n)
|
|
{
|
|
enum { chunk_size = 8 };
|
|
CharT fill_chars[chunk_size];
|
|
const CharT filler = strm.fill();
|
|
for (unsigned int i = 0; i < chunk_size; ++i)
|
|
fill_chars[i] = filler;
|
|
for (; n >= chunk_size && strm.good(); n -= chunk_size)
|
|
strm.write(fill_chars, static_cast< std::size_t >(chunk_size));
|
|
if (n > 0 && strm.good())
|
|
strm.write(fill_chars, n);
|
|
}
|
|
|
|
template< typename CharT, typename TraitsT >
|
|
void insert_aligned(std::basic_ostream< CharT, TraitsT >& strm, const CharT* p, std::size_t size)
|
|
{
|
|
const std::size_t alignment_size = static_cast< std::size_t >(strm.width()) - size;
|
|
const bool align_left = (strm.flags() & std::basic_ostream< CharT, TraitsT >::adjustfield) == std::basic_ostream< CharT, TraitsT >::left;
|
|
if (align_left)
|
|
{
|
|
strm.write(p, size);
|
|
if (strm.good())
|
|
aux::insert_fill_chars(strm, alignment_size);
|
|
}
|
|
else
|
|
{
|
|
aux::insert_fill_chars(strm, alignment_size);
|
|
if (strm.good())
|
|
strm.write(p, size);
|
|
}
|
|
}
|
|
|
|
} // namespace aux
|
|
|
|
//! Output operator
|
|
template< typename CharT, typename StrmTraitsT, typename LitTraitsT >
|
|
inline std::basic_ostream< CharT, StrmTraitsT >& operator<< (
|
|
std::basic_ostream< CharT, StrmTraitsT >& strm, basic_string_literal< CharT, LitTraitsT > const& lit)
|
|
{
|
|
if (strm.good())
|
|
{
|
|
const std::size_t size = lit.size();
|
|
const std::size_t w = static_cast< std::size_t >(strm.width());
|
|
if (w <= size)
|
|
strm.write(lit.c_str(), static_cast< std::streamsize >(size));
|
|
else
|
|
aux::insert_aligned(strm, lit.c_str(), lit.size());
|
|
strm.width(0);
|
|
}
|
|
return strm;
|
|
}
|
|
|
|
//! External swap
|
|
template< typename CharT, typename TraitsT >
|
|
inline BOOST_CXX14_CONSTEXPR void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT
|
|
{
|
|
left.swap(right);
|
|
}
|
|
|
|
//! Creates a string literal wrapper from a constant string literal
|
|
#ifdef BOOST_LOG_USE_CHAR
|
|
template< typename T, std::size_t LenV >
|
|
inline BOOST_CONSTEXPR
|
|
#ifndef BOOST_LOG_DOXYGEN_PASS
|
|
typename boost::enable_if_c<
|
|
is_same< T, const char >::value,
|
|
string_literal
|
|
>::type
|
|
#else
|
|
basic_string_literal< T >
|
|
#endif // BOOST_LOG_DOXYGEN_PASS
|
|
str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
|
|
{
|
|
return string_literal(p);
|
|
}
|
|
#endif
|
|
|
|
#ifndef BOOST_LOG_DOXYGEN_PASS
|
|
|
|
#ifdef BOOST_LOG_USE_WCHAR_T
|
|
template< typename T, std::size_t LenV >
|
|
inline BOOST_CONSTEXPR typename boost::enable_if_c<
|
|
is_same< T, const wchar_t >::value,
|
|
wstring_literal
|
|
>::type
|
|
str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
|
|
{
|
|
return wstring_literal(p);
|
|
}
|
|
#endif
|
|
|
|
#endif // BOOST_LOG_DOXYGEN_PASS
|
|
|
|
BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
|
|
|
} // namespace boost
|
|
|
|
#include <boost/log/detail/footer.hpp>
|
|
|
|
#endif // BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
|