2
0
mirror of https://github.com/boostorg/log.git synced 2026-01-28 19:22:16 +00:00
Files
log/src/code_conversion.cpp
Andrey Semashev 7d7b70e78b The default formatter has been rewritten to avoid using Boost.Phoenix.
This reduces compile times and binary sizes. It should also fix compilation with compilers not able to handle Boost.Phoenix (see #11200).

Also, date/time format has changed. The default formatter will produce dates with numeric months instead of abbreviated month names (see #8839).

The standard attribute value types supported by default parsed formatters now include char16_t and char32_t, when available. This required to add new code conversion routines.

Added Boost.PP sequences with the standard types. These are used to generate the corresponding type sequences, which is faster to compile than doing this with Boost.MPL.
2015-07-25 23:58:02 +03:00

209 lines
8.0 KiB
C++

/*
* Copyright Andrey Semashev 2007 - 2015.
* 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 code_conversion.cpp
* \author Andrey Semashev
* \date 08.11.2008
*
* \brief This header is the Boost.Log library implementation, see the library documentation
* at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
*/
#include <cstddef>
#include <locale>
#include <string>
#include <stdexcept>
#include <algorithm>
#include <boost/log/exceptions.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
BOOST_LOG_ANONYMOUS_NAMESPACE {
//! The function performs character conversion with the specified facet
template< typename LocalCharT >
inline std::codecvt_base::result convert(
std::codecvt< LocalCharT, char, std::mbstate_t > const& fac,
std::mbstate_t& state,
const char*& pSrcBegin,
const char* pSrcEnd,
LocalCharT*& pDstBegin,
LocalCharT* pDstEnd)
{
return fac.in(state, pSrcBegin, pSrcEnd, pSrcBegin, pDstBegin, pDstEnd, pDstBegin);
}
//! The function performs character conversion with the specified facet
template< typename LocalCharT >
inline std::codecvt_base::result convert(
std::codecvt< LocalCharT, char, std::mbstate_t > const& fac,
std::mbstate_t& state,
const LocalCharT*& pSrcBegin,
const LocalCharT* pSrcEnd,
char*& pDstBegin,
char* pDstEnd)
{
return fac.out(state, pSrcBegin, pSrcEnd, pSrcBegin, pDstBegin, pDstEnd, pDstBegin);
}
} // namespace
template< typename SourceCharT, typename TargetCharT, typename FacetT >
inline void code_convert(const SourceCharT* begin, const SourceCharT* end, std::basic_string< TargetCharT >& converted, FacetT const& fac)
{
typedef typename FacetT::state_type state_type;
TargetCharT converted_buffer[256];
state_type state = state_type();
while (begin != end)
{
TargetCharT* dest = converted_buffer;
std::codecvt_base::result res = convert(
fac,
state,
begin,
end,
dest,
dest + sizeof(converted_buffer) / sizeof(*converted_buffer));
switch (res)
{
case std::codecvt_base::ok:
// All characters were successfully converted
// NOTE: MSVC 11 also returns ok when the source buffer was only partially consumed, so we also check that the begin pointer has reached the end.
converted.append(converted_buffer, dest);
break;
case std::codecvt_base::partial:
// Some characters were converted, some were not
if (dest != converted_buffer)
{
// Some conversion took place, so it seems like
// the destination buffer might not have been long enough
converted.append(converted_buffer, dest);
// ...and go on for the next part
break;
}
else
{
// Nothing was converted, looks like the tail of the
// source buffer contains only part of the last character.
// Leave it as it is.
return;
}
case std::codecvt_base::noconv:
// Not possible, unless both character types are actually equivalent
converted.append(reinterpret_cast< const TargetCharT* >(begin), reinterpret_cast< const TargetCharT* >(end));
return;
default: // std::codecvt_base::error
BOOST_LOG_THROW_DESCR(conversion_error, "Could not convert character encoding");
}
}
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
}
// Note: MSVC 2015 (aka VC14) implement char16_t and char32_t types but not codecvt locale facets
#if !defined(BOOST_MSVC)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc)
{
std::string temp_str;
code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
}
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc)
{
code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc)
{
std::string temp_str;
code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc));
}
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_CHAR32_T)
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::locale const& loc)
{
std::string temp_str;
code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
}
//! The function converts one string to the character type of another
BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::locale const& loc)
{
std::string temp_str;
code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc));
code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc));
}
#endif
#endif // !defined(BOOST_MSVC)
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>