// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. // // Redistribution and use in source and binary forms, with or without modifica- // tion, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <log4cplus/helpers/stringhelper.h> #include <log4cplus/helpers/loglog.h> #include <cstdlib> #include <cstring> #include <cwchar> #include <cassert> #include <vector> namespace log4cplus { namespace helpers { void clear_mbstate (std::mbstate_t & mbs); #if defined (LOG4CPLUS_WORKING_C_LOCALE) static void tostring_internal (std::string & result, wchar_t const * src, std::size_t size) { std::vector<char> result_buf (MB_CUR_MAX); wchar_t const * src_it = src; wchar_t const * const src_end_it = src + size; std::mbstate_t mbs; clear_mbstate (mbs); result.clear (); result.reserve (size + size / 3 + 1); while (src_it != src_end_it) { std::size_t ret = std::wcrtomb (&result_buf[0], *src_it, &mbs); if (ret == static_cast<std::size_t>(-1)) { result.push_back ('?'); clear_mbstate (mbs); ++src_it; } else { result.append (result_buf.begin (), result_buf.begin () + ret); ++src_it; } } } std::string tostring (const std::wstring & src) { std::string ret; tostring_internal (ret, src.c_str (), src.size ()); return ret; } std::string tostring (wchar_t const * src) { assert (src); std::string ret; tostring_internal (ret, src, std::wcslen (src)); return ret; } static void towstring_internal (std::wstring & result, char const * src, std::size_t size) { char const * src_it = src; char const * const src_end_it = src + size; std::mbstate_t mbs; clear_mbstate (mbs); result.clear (); result.reserve (size); while (src_it != src_end_it) { std::size_t const n = size - (src - src_it); wchar_t result_char; std::size_t ret = std::mbrtowc (&result_char, src_it, n, &mbs); if (ret > 0) { result.push_back (result_char); src_it += ret; } else { result.push_back (ret == 0 ? L'\0' : L'?') ; clear_mbstate (mbs); ++src_it; } } } std::wstring towstring (const std::string& src) { std::wstring ret; towstring_internal (ret, src.c_str (), src.size ()); return ret; } std::wstring towstring (char const * src) { assert (src); std::wstring ret; towstring_internal (ret, src, std::strlen (src)); return ret; } #endif // LOG4CPLUS_WORKING_C_LOCALE } // namespace helpers } // namespace log4cplus