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:
34  static const size_t buffer_size = BufferSize;
35  typedef CharOut output_char;
36  typedef CharIn input_char;
37 
38  basic_stackstring() : data_(NULL)
39  {
40  buffer_[0] = 0;
41  }
42  explicit basic_stackstring(const input_char* input) : data_(NULL)
43  {
44  convert(input);
45  }
46  basic_stackstring(const input_char* begin, const input_char* end) : data_(NULL)
47  {
48  convert(begin, end);
49  }
50 
51  basic_stackstring(const basic_stackstring& other) : data_(NULL)
52  {
53  *this = other;
54  }
55  basic_stackstring& operator=(const basic_stackstring& other)
56  {
57  if(this != &other)
58  {
59  clear();
60  const size_t len = other.length();
61  if(other.uses_stack_memory())
62  data_ = buffer_;
63  else if(other.data_)
64  data_ = new output_char[len + 1];
65  else
66  {
67  data_ = NULL;
68  return *this;
69  }
70  std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1));
71  }
72  return *this;
73  }
74 
76  {
77  clear();
78  }
79 
80  output_char* convert(const input_char* input)
81  {
82  if(input)
83  return convert(input, input + detail::strlen(input));
84  clear();
85  return get();
86  }
87  output_char* convert(const input_char* begin, const input_char* end)
88  {
89  clear();
90 
91  if(begin)
92  {
93  const size_t input_len = end - begin;
94  // Minimum size required: 1 output char per input char + trailing NULL
95  const size_t min_output_size = input_len + 1;
96  // If there is a chance the converted string fits on stack, try it
97  if(min_output_size <= buffer_size && detail::convert_buffer(buffer_, buffer_size, begin, end))
98  data_ = buffer_;
99  else
100  {
101  // Fallback: Allocate a buffer that is surely large enough on heap
102  // Max size: Every input char is transcoded to the output char with maximum with + trailing NULL
103  const size_t max_output_size = input_len * detail::utf::utf_traits<output_char>::max_width + 1;
104  data_ = new output_char[max_output_size];
105  const bool success = detail::convert_buffer(data_, max_output_size, begin, end) == data_;
106  assert(success);
107  (void)success;
108  }
109  }
110  return get();
111  }
113  output_char* get()
114  {
115  return data_;
116  }
118  const output_char* get() const
119  {
120  return data_;
121  }
122  void clear()
123  {
124  if(!uses_stack_memory())
125  delete[] data_;
126  data_ = NULL;
127  }
128 
129  friend void swap(basic_stackstring& lhs, basic_stackstring& rhs)
130  {
131  if(lhs.uses_stack_memory())
132  {
133  if(rhs.uses_stack_memory())
134  {
135  for(size_t i = 0; i < buffer_size; i++)
136  std::swap(lhs.buffer_[i], rhs.buffer_[i]);
137  } else
138  {
139  lhs.data_ = rhs.data_;
140  rhs.data_ = rhs.buffer_;
141  for(size_t i = 0; i < buffer_size; i++)
142  rhs.buffer_[i] = lhs.buffer_[i];
143  }
144  } else if(rhs.uses_stack_memory())
145  {
146  rhs.data_ = lhs.data_;
147  lhs.data_ = lhs.buffer_;
148  for(size_t i = 0; i < buffer_size; i++)
149  lhs.buffer_[i] = rhs.buffer_[i];
150  } else
151  std::swap(lhs.data_, rhs.data_);
152  }
153 
154  protected:
156  bool uses_stack_memory() const
157  {
158  return data_ == buffer_;
159  }
160  size_t length() const
161  {
162  if(!data_)
163  return 0;
164  size_t len = 0;
165  while(data_[len])
166  len++;
167  return len;
168  }
169 
170  private:
171  output_char buffer_[buffer_size];
172  output_char* data_;
173  }; // basic_stackstring
174 
191 
192 } // namespace nowide
193 } // namespace boost
194 
195 #endif
basic_stackstring< wchar_t, char, 256 > wstackstring
Definition: stackstring.hpp:178
bool uses_stack_memory() const
True if the stack memory is used.
Definition: stackstring.hpp:156
basic_stackstring< char, wchar_t, 16 > short_stackstring
Definition: stackstring.hpp:190
basic_stackstring< wchar_t, char, 16 > wshort_stackstring
Definition: stackstring.hpp:186
basic_stackstring< char, wchar_t, 256 > stackstring
Definition: stackstring.hpp:182
const output_char * get() const
Return the converted, NULL-terminated string or NULL if no string was converted.
Definition: stackstring.hpp:118
A class that allows to create a temporary wide or narrow UTF strings from wide or narrow UTF source.
Definition: stackstring.hpp:31
output_char * get()
Return the converted, NULL-terminated string or NULL if no string was converted.
Definition: stackstring.hpp:113