My Project
fixed_string.hpp
1 #pragma once
2 //-----------------------------------------------------------------------------
3 // Class: FixedString on stack, based on boost fixed_string (which is rejected by boost).
4 // Authors: Modified by LiXizhi
5 // Emails: LiXizhi@yeah.net
6 // Company: ParaEngine corporation
7 // Date: 2008.6.20
8 // Desc:
9 // This class manages a fixed-size, null-terminated string buffer. It is meant
10 // to be allocated on the stack, and it makes no use of the heap internally. In
11 // most cases you'll just want to use a std::string, but when you need to
12 // avoid the heap, you can use this class instead.
13 //
14 // Methods are provided to read the null-terminated buffer and to append data
15 // to the buffer, and once the buffer fills-up, it simply discards any extra
16 // append calls.
17 //
18 // Since this object clips if the internal fixed buffer is exceeded, it is
19 // appropriate for exception handlers where the heap may be corrupted. Fixed
20 // buffers that overflow onto the heap are provided by StackString. (see stack_container.hpp).
21 //-----------------------------------------------------------------------------
22 // (C) Copyright 2003-2004: Reece H. Dunn
23 //
24 // Safe string operations
25 //
26 // Original by Reece H. Dunn.
27 // Modified by J. Nagle.
28 //
29 //
30 // The templated class fixed_string<size> is provided for
31 // declaring fixed size strings that do not use "new", and
32 // the abstract base class fixed_string_base is provided
33 // for references to fixed_string of any size.
34 //
35 // These classes are intended to be safe against store-type buffer
36 // overflows.
37 // All storing subscripts must be checked.
38 // Non-const char* pointers must not be returned.
39 //
40 // The usual STL operations are to be provided for fixed_string,
41 // along with the classic C string operations.
42 //
43 // Direct replacement of C strings with fixed_string should
44 // either work correctly or result in compile errors.
45 //
46 #include <cstring>
47 #include <stddef.h>
48 #include <stdarg.h>
49 #include <stdexcept>
50 #include <string>
51 
52 namespace ParaEngine
53 {
54  // Abstract base class for templated strings.
55  // This can be passed to functions, regardless of size.
56  template <class T>
58  {
59  public:
60  virtual std::size_t capacity() const = 0;
61  virtual std::size_t size() = 0;
62  virtual const T* c_str() const = 0;
63  virtual T* data() = 0;
64  virtual void copy(const T * s ) = 0;
65  virtual void clear() = 0;
66  virtual void append(const T* s) = 0;
67  virtual T& operator[](std::size_t ix) = 0;
68  virtual const T& operator[](std::size_t ix) const = 0;
69 
70  typedef T* iterator;
71  typedef const T* const_iterator;
72  // Implemented functions without direct equivalents at the fixed_string level.
73  fixed_string_base<T>& operator=(const fixed_string_base<T>& s)
74  { copy(s.c_str()); return(*this); }
75  fixed_string_base<T>& operator=(const T* s)
76  { copy(s); return(*this); }
77  int comp(fixed_string_base<T>& s1,
78  const fixed_string_base<T>& s2)
79  { s1.comp(s2.c_str()); return(s1); }
80  bool operator==(const fixed_string_base<T>& s)
81  { return(comp(s) == 0); }
82  bool operator==(const T* s)
83  { return(comp(s) == 0); }
84  };
85  //
86  // class fixed_string
87  //
88  // Generic template class for fixed size strings.
89  //
90  // One extra space is always allocated for a trailing null.
91  // But only calls to c_str guarantee that the trailing
92  // null will be present.
93  //
94  template< class T, std::size_t N>
96  : public fixed_string_base<T>
97  {
98  public:
99  typedef typename fixed_string_base<T>::iterator iterator;
100  typedef typename fixed_string_base<T>::const_iterator const_iterator;
101 
102  private:
103  T m_str[N+1]; // the data
104  int m_len; // length, not including trailing null
105  // -1 if unknown
106  private:
107  void update_len() // update length if necessary
108  { if (m_len >= 0) return; // length needs no update
109  for (m_len = 0; m_len < N && m_str[m_len]; m_len++)
110  {} // count
111  m_str[m_len] = 0;
112  }
113 
114  void invalidate_len() // invalidate length. String has changed
115  { m_len = -1;
116  }
117 
118  public:
119  fixed_string() // default constructor
120  :
121  m_len(0)
122  {
123  m_str[0] = 0; // initially null
124  m_str[N] = 0; // last must always be a null
125  }
126 
127  fixed_string(const T* s)// constructor from string
128  :
129  m_len(0)
130  {
131  m_str[0] = 0; // initially null
132  m_str[N] = 0; // last must always be a null
133  copy(s); // copy input
134  }
135 
136 
137  fixed_string(std::size_t cnt, T ch) // constructor from char
138  :
139  m_len(0)
140  {
141  m_str[0] = 0; // initially null
142  m_str[N] = 0; // last must always be a null
143  while (cnt--)
144  this->operator +=(ch); // append N copies of char
145  }
146 
147  public: // access
148  T* data() // access to raw data - unsafe
149  { invalidate_len(); // invalidates length count
150  return(m_str);
151  }
152  const T* c_str() const
153  { // "Virtual constness" - must update length info and trailing null
154  fixed_string<T,N>* s =
155  const_cast<fixed_string<T,N>* > (this);
156  s->update_len();
157  s->m_str[m_len] = 0;
158  return( m_str );
159  }
160 
161  std::size_t capacity() const
162  {
163  return(N);
164  }
165 
166  std::size_t size()
167  {
168  update_len();
169  return(m_len);
170  }
171 
172  void clear()
173  {
174  m_len = 0;
175  m_str[0] = 0;
176  }
177 
178  void operator+=(const T& ch)
179  {
180  update_len();
181  if (m_len >= N-1)
182  throw(std::length_error("fixed_string +=")); // fails
183  m_str[m_len] = ch;
184  m_len++;
185  m_str[m_len] = 0;
186  }
187  // Subscripting.
188  // Note that you can address the extra space for the trailing
189  // null, so that the classic "for (int i=0; s[i]; i++) will work.
190  public:
191  T& operator[](std::size_t ix)
192  {
193  invalidate_len();
194  if (ix <= N)
195  return(m_str[ix]); // normal case
196  throw(std::length_error("fixed_string []")); // fails
197  }
198 
199  const T& operator[](std::size_t ix) const
200  {
201  if (ix <= N)
202  return(m_str[ix]); // normal case
203  throw(std::length_error("fixed_string []")); // fails
204  }
205 
206  public: // iterators, unchecked
207  iterator begin() { return(&m_str[0]); }
208  const iterator begin() const { return(&m_str[0]); }
209  iterator end() { return(begin() + size() + 1); }
210  const iterator end() const { return(begin() + size() + 1); }
211 
212  public: // copy
213  void copy(const fixed_string_base<T>& s)
214  {
215  copy(s.c_str());
216  }
217 
218  void copy(const T* s)
219  {
220  clear();
221  append(s); // inefficient, test only
222  }
223 
224 
225  public: // append
226  void append(const fixed_string_base<T>& s)
227  {
228  append(s.c_str());
229  }
230 
231  void append(const T* s)
232  {
233  for (int i=0; s[i] !=0; i++)
234  {
235  *this += s[i];
236  }
237  }
238  public: // comparison
239  inline int comp(const char* s) const
240  {
241  return(compare(c_str(),s)); // from char_traits
242  }
243  inline int comp(const fixed_string_base<T>& s) const
244  {
245  return(compare(c_str(),s,c_str())); // from char_traits
246  }
247  };
248 } // ParaEngine
249 
different physics engine has different winding order.
Definition: EventBinding.h:32
Definition: fixed_string.hpp:95
Definition: fixed_string.hpp:57