File indexing completed on 2025-01-18 09:42:46
0001
0002
0003
0004
0005
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
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template<typename CharOut = wchar_t, typename CharIn = char, size_t BufferSize = 256>
0031 class basic_stackstring
0032 {
0033 public:
0034
0035 static const size_t buffer_size = BufferSize;
0036
0037 using output_char = CharOut;
0038
0039 using input_char = CharIn;
0040
0041
0042 basic_stackstring()
0043 {
0044 buffer_[0] = 0;
0045 }
0046
0047
0048 explicit basic_stackstring(const input_char* input)
0049 {
0050 convert(input);
0051 }
0052
0053
0054 basic_stackstring(const input_char* begin, const input_char* end)
0055 {
0056 convert(begin, end);
0057 }
0058
0059 basic_stackstring(const basic_stackstring& other)
0060 {
0061 *this = other;
0062 }
0063
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
0090
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
0099
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
0108 const size_t min_output_size = input_len + 1;
0109
0110 if(min_output_size <= buffer_size && utf::convert_buffer(buffer_, buffer_size, begin, end))
0111 data_ = buffer_;
0112 else
0113 {
0114
0115
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
0126 output_char* get()
0127 {
0128 return data_;
0129 }
0130
0131 const output_char* get() const
0132 {
0133 return data_;
0134 }
0135
0136 void clear()
0137 {
0138 if(!uses_stack_memory())
0139 delete[] data_;
0140 data_ = nullptr;
0141 }
0142
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
0170 bool uses_stack_memory() const
0171 {
0172 return data_ == buffer_;
0173 }
0174
0175
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 };
0190
0191
0192
0193
0194 using wstackstring = basic_stackstring<wchar_t, char, 256>;
0195
0196
0197
0198 using stackstring = basic_stackstring<char, wchar_t, 256>;
0199
0200
0201
0202 using wshort_stackstring = basic_stackstring<wchar_t, char, 16>;
0203
0204
0205
0206 using short_stackstring = basic_stackstring<char, wchar_t, 16>;
0207
0208 }
0209 }
0210
0211 #endif