Boost.Nowide
stackstring.hpp
1 //
2 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #ifndef BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED
9 #define BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED
10 
11 #include <boost/nowide/convert.hpp>
12 #include <cassert>
13 #include <cstring>
14 
15 namespace boost {
16 namespace nowide {
17 
30  template<typename CharOut = wchar_t, typename CharIn = char, size_t BufferSize = 256>
32  {
33  public:
35  static const size_t buffer_size = BufferSize;
37  typedef CharOut output_char;
39  typedef CharIn input_char;
40 
42  basic_stackstring() : data_(NULL)
43  {
44  buffer_[0] = 0;
45  }
48  explicit basic_stackstring(const input_char* input) : data_(NULL)
49  {
50  convert(input);
51  }
54  basic_stackstring(const input_char* begin, const input_char* end) : data_(NULL)
55  {
56  convert(begin, end);
57  }
59  basic_stackstring(const basic_stackstring& other) : data_(NULL)
60  {
61  *this = other;
62  }
65  {
66  if(this != &other)
67  {
68  clear();
69  const size_t len = other.length();
70  if(other.uses_stack_memory())
71  data_ = buffer_;
72  else if(other.data_)
73  data_ = new output_char[len + 1];
74  else
75  {
76  data_ = NULL;
77  return *this;
78  }
79  std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1));
80  }
81  return *this;
82  }
83 
85  {
86  clear();
87  }
88 
92  {
93  if(input)
94  return convert(input, input + detail::strlen(input));
95  clear();
96  return get();
97  }
100  output_char* convert(const input_char* begin, const input_char* end)
101  {
102  clear();
103 
104  if(begin)
105  {
106  const size_t input_len = end - begin;
107  // Minimum size required: 1 output char per input char + trailing NULL
108  const size_t min_output_size = input_len + 1;
109  // If there is a chance the converted string fits on stack, try it
110  if(min_output_size <= buffer_size && detail::convert_buffer(buffer_, buffer_size, begin, end))
111  data_ = buffer_;
112  else
113  {
114  // Fallback: Allocate a buffer that is surely large enough on heap
115  // Max size: Every input char is transcoded to the output char with maximum with + trailing NULL
116  const size_t max_output_size = input_len * detail::utf::utf_traits<output_char>::max_width + 1;
117  data_ = new output_char[max_output_size];
118  const bool success = detail::convert_buffer(data_, max_output_size, begin, end) == data_;
119  assert(success);
120  (void)success;
121  }
122  }
123  return get();
124  }
127  {
128  return data_;
129  }
131  const output_char* get() const
132  {
133  return data_;
134  }
136  void clear()
137  {
138  if(!uses_stack_memory())
139  delete[] data_;
140  data_ = NULL;
141  }
143  friend void swap(basic_stackstring& lhs, basic_stackstring& rhs)
144  {
145  if(lhs.uses_stack_memory())
146  {
147  if(rhs.uses_stack_memory())
148  {
149  for(size_t i = 0; i < buffer_size; i++)
150  std::swap(lhs.buffer_[i], rhs.buffer_[i]);
151  } else
152  {
153  lhs.data_ = rhs.data_;
154  rhs.data_ = rhs.buffer_;
155  for(size_t i = 0; i < buffer_size; i++)
156  rhs.buffer_[i] = lhs.buffer_[i];
157  }
158  } else if(rhs.uses_stack_memory())
159  {
160  rhs.data_ = lhs.data_;
161  lhs.data_ = lhs.buffer_;
162  for(size_t i = 0; i < buffer_size; i++)
163  lhs.buffer_[i] = rhs.buffer_[i];
164  } else
165  std::swap(lhs.data_, rhs.data_);
166  }
167 
168  protected:
170  bool uses_stack_memory() const
171  {
172  return data_ == buffer_;
173  }
176  size_t length() const
177  {
178  if(!data_)
179  return 0;
180  size_t len = 0;
181  while(data_[len])
182  len++;
183  return len;
184  }
185 
186  private:
187  output_char buffer_[buffer_size];
188  output_char* data_;
189  }; // basic_stackstring
190 
207 
208 } // namespace nowide
209 } // namespace boost
210 
211 #endif
basic_stackstring(const input_char *input)
Definition: stackstring.hpp:48
basic_stackstring< wchar_t, char, 256 > wstackstring
Definition: stackstring.hpp:194
bool uses_stack_memory() const
True if the stack memory is used.
Definition: stackstring.hpp:170
basic_stackstring< char, wchar_t, 16 > short_stackstring
Definition: stackstring.hpp:206
basic_stackstring(const basic_stackstring &other)
Copy construct from other.
Definition: stackstring.hpp:59
basic_stackstring< wchar_t, char, 16 > wshort_stackstring
Definition: stackstring.hpp:202
basic_stackstring & operator=(const basic_stackstring &other)
Copy assign from other.
Definition: stackstring.hpp:64
static const size_t buffer_size
Size of the stack buffer.
Definition: stackstring.hpp:35
void clear()
Reset the internal buffer to NULL.
Definition: stackstring.hpp:136
basic_stackstring(const input_char *begin, const input_char *end)
Definition: stackstring.hpp:54
output_char * convert(const input_char *begin, const input_char *end)
Definition: stackstring.hpp:100
basic_stackstring< char, wchar_t, 256 > stackstring
Definition: stackstring.hpp:198
const output_char * get() const
Return the converted, NULL-terminated string or NULL if no string was converted.
Definition: stackstring.hpp:131
size_t length() const
Definition: stackstring.hpp:176
output_char * convert(const input_char *input)
Definition: stackstring.hpp:91
A class that allows to create a temporary wide or narrow UTF strings from wide or narrow UTF source.
Definition: stackstring.hpp:31
basic_stackstring()
Creates a NULL stackstring.
Definition: stackstring.hpp:42
output_char * get()
Return the converted, NULL-terminated string or NULL if no string was converted.
Definition: stackstring.hpp:126
friend void swap(basic_stackstring &lhs, basic_stackstring &rhs)
Swap lhs with rhs.
Definition: stackstring.hpp:143
CharOut output_char
Type of the output character (converted to)
Definition: stackstring.hpp:37
CharIn input_char
Type of the input character (converted from)
Definition: stackstring.hpp:39