diff --git a/include/boost/nowide/convert.hpp b/include/boost/nowide/convert.hpp index 1855504..c4f102c 100644 --- a/include/boost/nowide/convert.hpp +++ b/include/boost/nowide/convert.hpp @@ -8,114 +8,11 @@ #ifndef BOOST_NOWIDE_CONVERT_HPP_INCLUDED #define BOOST_NOWIDE_CONVERT_HPP_INCLUDED -#include -#include -#include +#include #include namespace boost { namespace nowide { - /// - /// \brief Template function that converts a buffer of UTF sequences in range [source_begin,source_end) - /// to the output \a buffer of size \a buffer_size. - /// - /// In case of success a NULL terminated string is returned (buffer), otherwise 0 is returned. - /// - /// If there is not enough room in the buffer 0 is returned, and the content of the buffer is undefined. - /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER - /// - template - CharOut* basic_convert(CharOut* buffer, size_t buffer_size, const CharIn* source_begin, const CharIn* source_end) - { - CharOut* rv = buffer; - if(buffer_size == 0) - return 0; - buffer_size--; - while(source_begin != source_end) - { - using namespace detail::utf; - code_point c = utf_traits::template decode(source_begin, source_end); - if(c == illegal || c == incomplete) - { - c = BOOST_NOWIDE_REPLACEMENT_CHARACTER; - } - size_t width = utf_traits::width(c); - if(buffer_size < width) - { - rv = NULL; - break; - } - buffer = utf_traits::template encode(c, buffer); - buffer_size -= width; - } - *buffer++ = 0; - return rv; - } - - /// - /// \brief Template function that converts a buffer of UTF sequences in range [source_begin,source_end) and returns a string containing - /// converted value - /// - /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER - /// - template - std::basic_string basic_convert(const CharIn* begin, const CharIn* end) - { - std::basic_string result; - result.reserve(end - begin); - typedef std::back_insert_iterator > inserter_type; - inserter_type inserter(result); - using namespace detail::utf; - code_point c; - while(begin != end) - { - c = utf_traits::template decode(begin, end); - if(c == illegal || c == incomplete) - { - c = BOOST_NOWIDE_REPLACEMENT_CHARACTER; - } - utf_traits::template encode(c, inserter); - } - return result; - } - - /// \cond INTERNAL - namespace detail { - // - // wcslen defined only in C99... So we will not use it - // - template - const Char* basic_strend(const Char* s) - { - while(*s) - s++; - return s; - } - } // namespace detail - /// \endcond - - /// - /// \brief Template function that converts a string \a s from one type of UTF to another UTF and returns a string containing converted - /// value - /// - /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER - /// - template - std::basic_string basic_convert(std::basic_string const& s) - { - return basic_convert(s.c_str(), s.c_str() + s.size()); - } - /// - /// \brief Template function that converts a string \a s from one type of UTF to another UTF and returns a string containing converted - /// value - /// - /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER - /// - template - std::basic_string basic_convert(const CharIn* s) - { - return basic_convert(s, detail::basic_strend(s)); - } /// /// Convert NULL terminated UTF source string to NULL terminated \a output string of size at @@ -126,7 +23,7 @@ namespace nowide { /// inline char* narrow(char* output, size_t output_size, const wchar_t* source) { - return basic_convert(output, output_size, source, detail::basic_strend(source)); + return detail::convert_buffer(output, output_size, source, detail::strend(source)); } /// /// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at @@ -137,7 +34,7 @@ namespace nowide { /// inline char* narrow(char* output, size_t output_size, const wchar_t* begin, const wchar_t* end) { - return basic_convert(output, output_size, begin, end); + return detail::convert_buffer(output, output_size, begin, end); } /// /// Convert NULL terminated UTF source string to NULL terminated \a output string of size at @@ -148,7 +45,7 @@ namespace nowide { /// inline wchar_t* widen(wchar_t* output, size_t output_size, const char* source) { - return basic_convert(output, output_size, source, detail::basic_strend(source)); + return detail::convert_buffer(output, output_size, source, detail::strend(source)); } /// /// Convert UTF text in range [begin,end) to NULL terminated \a output string of size at @@ -159,7 +56,7 @@ namespace nowide { /// inline wchar_t* widen(wchar_t* output, size_t output_size, const char* begin, const char* end) { - return basic_convert(output, output_size, begin, end); + return detail::convert_buffer(output, output_size, begin, end); } /// @@ -169,7 +66,7 @@ namespace nowide { /// inline std::string narrow(const wchar_t* s) { - return basic_convert(s); + return detail::convert_string(s, detail::strend(s)); } /// /// Convert between UTF-8 and UTF-16 string @@ -178,7 +75,7 @@ namespace nowide { /// inline std::wstring widen(const char* s) { - return basic_convert(s); + return detail::convert_string(s, detail::strend(s)); } /// /// Convert between Wide - UTF-16/32 string and UTF-8 string @@ -187,7 +84,7 @@ namespace nowide { /// inline std::string narrow(const std::wstring& s) { - return basic_convert(s); + return detail::convert_string(s.c_str(), s.c_str() + s.size()); } /// /// Convert between UTF-8 and UTF-16 string @@ -196,7 +93,7 @@ namespace nowide { /// inline std::wstring widen(const std::string& s) { - return basic_convert(s); + return detail::convert_string(s.c_str(), s.c_str() + s.size()); } } // namespace nowide diff --git a/include/boost/nowide/detail/convert.hpp b/include/boost/nowide/detail/convert.hpp new file mode 100644 index 0000000..5e1ae64 --- /dev/null +++ b/include/boost/nowide/detail/convert.hpp @@ -0,0 +1,99 @@ +// +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// +// 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) +// +#ifndef BOOST_NOWIDE_DETAIL_CONVERT_HPP_INCLUDED +#define BOOST_NOWIDE_DETAIL_CONVERT_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost { +namespace nowide { + /// \cond INTERNAL + namespace detail { + /// + /// Convert a buffer of UTF sequences in the range [source_begin, source_end) from \tparam CharIn to \tparam CharOut + /// to the output \a buffer of size \a buffer_size. + /// + /// \return original buffer containing the NULL terminated string or NULL + /// + /// If there is not enough room in the buffer NULL is returned, and the content of the buffer is undefined. + /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER + /// + template + CharOut* convert_buffer(CharOut* buffer, size_t buffer_size, const CharIn* source_begin, const CharIn* source_end) + { + CharOut* rv = buffer; + if(buffer_size == 0) + return 0; + buffer_size--; + while(source_begin != source_end) + { + using namespace detail::utf; + code_point c = utf_traits::template decode(source_begin, source_end); + if(c == illegal || c == incomplete) + { + c = BOOST_NOWIDE_REPLACEMENT_CHARACTER; + } + size_t width = utf_traits::width(c); + if(buffer_size < width) + { + rv = NULL; + break; + } + buffer = utf_traits::template encode(c, buffer); + buffer_size -= width; + } + *buffer++ = 0; + return rv; + } + + /// + /// Convert the UTF sequences in range [begin, end) from \tparam CharIn to \tparam CharOut + /// and return it as a string + /// + /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER + /// + template + std::basic_string convert_string(const CharIn* begin, const CharIn* end) + { + std::basic_string result; + result.reserve(end - begin); + typedef std::back_insert_iterator > inserter_type; + inserter_type inserter(result); + using namespace detail::utf; + code_point c; + while(begin != end) + { + c = utf_traits::template decode(begin, end); + if(c == illegal || c == incomplete) + { + c = BOOST_NOWIDE_REPLACEMENT_CHARACTER; + } + utf_traits::template encode(c, inserter); + } + return result; + } + + /// Return the pointer to the first NULL value encountered by increasing s + /// Equivalent to `return s + strlen(s)` but more generic + template + const Char* strend(const Char* s) + { + while(*s) + s++; + return s; + } + + } // namespace detail + /// \endcond +} // namespace nowide +} // namespace boost + +#endif diff --git a/include/boost/nowide/stackstring.hpp b/include/boost/nowide/stackstring.hpp index 9fcfed9..4d7ede2 100644 --- a/include/boost/nowide/stackstring.hpp +++ b/include/boost/nowide/stackstring.hpp @@ -93,7 +93,7 @@ namespace nowide { output_char* convert(const input_char* input) { if(input) - return convert(input, detail::basic_strend(input)); + return convert(input, detail::strend(input)); clear(); return get(); } @@ -107,11 +107,11 @@ namespace nowide { if(space <= buffer_size) { data_ = buffer_; - basic_convert(buffer_, buffer_size, begin, end); + detail::convert_buffer(buffer_, buffer_size, begin, end); } else { data_ = new output_char[space]; - basic_convert(data_, space, begin, end); + detail::convert_buffer(data_, space, begin, end); } } return get();