Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:46

0001 //
0002 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // https://www.boost.org/LICENSE_1_0.txt
0006 
0007 #ifndef BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED
0008 #define BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED
0009 
0010 #include <boost/nowide/convert.hpp>
0011 #include <boost/nowide/utf/utf.hpp>
0012 #include <cassert>
0013 #include <cstring>
0014 
0015 namespace boost {
0016 namespace nowide {
0017 
0018     ///
0019     /// \brief A class that allows to create a temporary wide or narrow UTF strings from
0020     /// wide or narrow UTF source.
0021     ///
0022     /// It uses a stack buffer if the string is short enough
0023     /// otherwise allocates a buffer on the heap.
0024     ///
0025     /// Invalid UTF characters are replaced by the substitution character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER
0026     ///
0027     /// If a NULL pointer is passed to the constructor or convert method, NULL will be returned by c_str.
0028     /// Similarly a default constructed stackstring will return NULL on calling c_str.
0029     ///
0030     template<typename CharOut = wchar_t, typename CharIn = char, size_t BufferSize = 256>
0031     class basic_stackstring
0032     {
0033     public:
0034         /// Size of the stack buffer
0035         static const size_t buffer_size = BufferSize;
0036         /// Type of the output character (converted to)
0037         using output_char = CharOut;
0038         /// Type of the input character (converted from)
0039         using input_char = CharIn;
0040 
0041         /// Creates a NULL stackstring
0042         basic_stackstring()
0043         {
0044             buffer_[0] = 0;
0045         }
0046         /// Convert the NULL terminated string input and store in internal buffer
0047         /// If input is NULL, nothing will be stored
0048         explicit basic_stackstring(const input_char* input)
0049         {
0050             convert(input);
0051         }
0052         /// Convert the sequence [begin, end) and store in internal buffer
0053         /// If begin is NULL, nothing will be stored
0054         basic_stackstring(const input_char* begin, const input_char* end)
0055         {
0056             convert(begin, end);
0057         }
0058         /// Copy construct from other
0059         basic_stackstring(const basic_stackstring& other)
0060         {
0061             *this = other;
0062         }
0063         /// Copy assign from other
0064         basic_stackstring& operator=(const basic_stackstring& other)
0065         {
0066             if(this != &other)
0067             {
0068                 clear();
0069                 const size_t len = other.length();
0070                 if(other.uses_stack_memory())
0071                     data_ = buffer_;
0072                 else if(other.data_)
0073                     data_ = new output_char[len + 1];
0074                 else
0075                 {
0076                     data_ = nullptr;
0077                     return *this;
0078                 }
0079                 std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1));
0080             }
0081             return *this;
0082         }
0083 
0084         ~basic_stackstring()
0085         {
0086             clear();
0087         }
0088 
0089         /// Convert the NULL terminated string input and store in internal buffer
0090         /// If input is NULL, the current buffer will be reset to NULL
0091         output_char* convert(const input_char* input)
0092         {
0093             if(input)
0094                 return convert(input, input + utf::strlen(input));
0095             clear();
0096             return get();
0097         }
0098         /// Convert the sequence [begin, end) and store in internal buffer
0099         /// If begin is NULL, the current buffer will be reset to NULL
0100         output_char* convert(const input_char* begin, const input_char* end)
0101         {
0102             clear();
0103 
0104             if(begin)
0105             {
0106                 const size_t input_len = end - begin;
0107                 // Minimum size required: 1 output char per input char + trailing NULL
0108                 const size_t min_output_size = input_len + 1;
0109                 // If there is a chance the converted string fits on stack, try it
0110                 if(min_output_size <= buffer_size && utf::convert_buffer(buffer_, buffer_size, begin, end))
0111                     data_ = buffer_;
0112                 else
0113                 {
0114                     // Fallback: Allocate a buffer that is surely large enough on heap
0115                     // Max size: Every input char is transcoded to the output char with maximum with + trailing NULL
0116                     const size_t max_output_size = input_len * utf::utf_traits<output_char>::max_width + 1;
0117                     data_ = new output_char[max_output_size];
0118                     const bool success = utf::convert_buffer(data_, max_output_size, begin, end) == data_;
0119                     assert(success);
0120                     (void)success;
0121                 }
0122             }
0123             return get();
0124         }
0125         /// Return the converted, NULL-terminated string or NULL if no string was converted
0126         output_char* get()
0127         {
0128             return data_;
0129         }
0130         /// Return the converted, NULL-terminated string or NULL if no string was converted
0131         const output_char* get() const
0132         {
0133             return data_;
0134         }
0135         /// Reset the internal buffer to NULL
0136         void clear()
0137         {
0138             if(!uses_stack_memory())
0139                 delete[] data_;
0140             data_ = nullptr;
0141         }
0142         /// Swap lhs with rhs
0143         friend void swap(basic_stackstring& lhs, basic_stackstring& rhs)
0144         {
0145             if(lhs.uses_stack_memory())
0146             {
0147                 if(rhs.uses_stack_memory())
0148                 {
0149                     for(size_t i = 0; i < buffer_size; i++)
0150                         std::swap(lhs.buffer_[i], rhs.buffer_[i]);
0151                 } else
0152                 {
0153                     lhs.data_ = rhs.data_;
0154                     rhs.data_ = rhs.buffer_;
0155                     for(size_t i = 0; i < buffer_size; i++)
0156                         rhs.buffer_[i] = lhs.buffer_[i];
0157                 }
0158             } else if(rhs.uses_stack_memory())
0159             {
0160                 rhs.data_ = lhs.data_;
0161                 lhs.data_ = lhs.buffer_;
0162                 for(size_t i = 0; i < buffer_size; i++)
0163                     lhs.buffer_[i] = rhs.buffer_[i];
0164             } else
0165                 std::swap(lhs.data_, rhs.data_);
0166         }
0167 
0168     protected:
0169         /// True if the stack memory is used
0170         bool uses_stack_memory() const
0171         {
0172             return data_ == buffer_;
0173         }
0174         /// Return the current length of the string excluding the NULL terminator
0175         /// If NULL is stored returns NULL
0176         size_t length() const
0177         {
0178             if(!data_)
0179                 return 0;
0180             size_t len = 0;
0181             while(data_[len])
0182                 len++;
0183             return len;
0184         }
0185 
0186     private:
0187         output_char buffer_[buffer_size];
0188         output_char* data_ = nullptr;
0189     }; // basic_stackstring
0190 
0191     ///
0192     /// Convenience typedef
0193     ///
0194     using wstackstring = basic_stackstring<wchar_t, char, 256>;
0195     ///
0196     /// Convenience typedef
0197     ///
0198     using stackstring = basic_stackstring<char, wchar_t, 256>;
0199     ///
0200     /// Convenience typedef
0201     ///
0202     using wshort_stackstring = basic_stackstring<wchar_t, char, 16>;
0203     ///
0204     /// Convenience typedef
0205     ///
0206     using short_stackstring = basic_stackstring<char, wchar_t, 16>;
0207 
0208 } // namespace nowide
0209 } // namespace boost
0210 
0211 #endif