NVIDIA Iray: Base API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
string.h
Go to the documentation of this file.
1 //*****************************************************************************
2 // Copyright 1986, 2014 NVIDIA Corporation. All rights reserved.
3 //*****************************************************************************
9 //*****************************************************************************
10 
11 #ifndef MI_BASE_STRING_H
12 #define MI_BASE_STRING_H
13 
14 #include <mi/base/config.h>
15 #include <mi/base/assert.h>
16 #include <mi/base/types.h>
17 #include <mi/base/iallocator.h>
19 #include <cstring>
20 
21 #ifdef MI_COMPILER_MSC
22 #pragma warning( push )
23 #pragma warning( disable : 4996 )
24 #endif
25 
26 namespace mi {
27 
28 namespace base {
29 
40 class String {
50 public:
51  typedef char value_type;
52  typedef Size size_type;
54 
55  typedef char& reference;
56  typedef const char& const_reference;
57  typedef char* pointer;
58  typedef const char* const_pointer;
59 
60  typedef pointer iterator;
62 
63  static const Size npos = Size(-1);
64 
67  static const Size SHORT_SIZE = 24;
68 
69 private:
70 
71  // Length of the string.
72  Size m_length;
73 
74  // Pointer to allocator object
75  IAllocator *m_allocator;
76 
77  // Pointer to the string.
78  char *m_string;
79 
80  // Buffer for strings allocated on the stack.
81  char m_short_string_buffer[SHORT_SIZE];
82 
83  // Allocates size many bytes. Throws an exception if allocation fails.
84  char* allocate( Size size)
85  {
86  char* p = reinterpret_cast<char*>(m_allocator->malloc( size));
87  if ( ! p)
88  throw std::bad_alloc();
89  return p;
90  }
91 
92  // Deallocates the memory \p buf, which must be allocated with the
93  // \c allocate function. \p buf may be zero, in which case nothing is
94  // deallocated.
95  // static void deallocate( char* buf) { delete[] buf; } // OLD
96  void deallocate( char* buf) { m_allocator->free(buf); }
97 
98 public:
99 
101  inline String()
102  : m_length(0),
103  m_allocator( Default_allocator::get_instance()),
104  m_string(m_short_string_buffer)
105  {
106  m_short_string_buffer[0] = '\0';
107  }
108 
109  inline String( IAllocator* allocator)
110  : m_length(0),
111  m_allocator( allocator),
112  m_string(m_short_string_buffer)
113  {
114  mi_base_assert( allocator != 0);
115  m_short_string_buffer[0] = '\0';
116  }
117 
119  // TODO: Add a variant with an allocator arg
120  inline String( const char* str)
121  : m_allocator( Default_allocator::get_instance())
122  {
123  if(str) {
124  m_length = static_cast<Size>(MISTD::strlen(str));
125  if(m_length < SHORT_SIZE) {
126  MISTD::strcpy(m_short_string_buffer,str);
127  m_string = m_short_string_buffer;
128  } else {
129  m_string = allocate( m_length + 1);
130  MISTD::strcpy(m_string,str);
131  m_short_string_buffer[0] = '\0';
132  }
133  } else {
134  m_length = 0;
135  m_string = m_short_string_buffer;
136  m_short_string_buffer[0] = '\0';
137  }
138  }
139 
141  // TODO: Add a variant with an allocator arg
142  inline String( const String& str)
143  : m_allocator( Default_allocator::get_instance())
144  {
145  m_length = str.length();
146  if(m_length < SHORT_SIZE) {
147  MISTD::strcpy(m_short_string_buffer, str.m_short_string_buffer);
148  m_string = m_short_string_buffer;
149  } else {
150  m_string = allocate( m_length + 1);
151  MISTD::strcpy(m_string, str.m_string);
152  m_short_string_buffer[0] = '\0';
153  }
154  }
155 
157  inline String& operator=( const String& str)
158  {
159  if ( this != & str) {
160  m_length = str.length();
161  if(m_string != m_short_string_buffer)
162  deallocate( m_string);
163  if(m_length < SHORT_SIZE) {
164  MISTD::strcpy(m_short_string_buffer, str.m_short_string_buffer);
165  m_string = m_short_string_buffer;
166  } else {
167  m_string = allocate( m_length + 1);
168  MISTD::strcpy(m_string, str.m_string);
169  m_short_string_buffer[0] = '\0';
170  }
171  }
172  return *this;
173  }
174 
176  inline ~String()
177  {
178  if(m_string != m_short_string_buffer)
179  deallocate( m_string);
180  }
181 
184  inline bool empty() const
185  {
186  return m_length == Size(0);
187  }
188 
191  inline Size size() const
192  {
193  return m_length;
194  }
195 
198  inline Size length() const
199  {
200  return m_length;
201  }
202 
205  inline const char* c_str() const
206  {
207  return m_string;
208  }
209 
213  inline const char& operator[] ( Size i) const
214  {
215  mi_base_assert_msg(i <= size(), "precondition");
216  return m_string[i];
217  }
218 
223  inline char& operator[] ( Size i)
224  {
225  mi_base_assert_msg(i <= size(), "precondition");
226  return m_string[i];
227  }
228 
230  inline String& operator+= ( const String& str)
231  {
232  Size nl = length() + str.length();
233  if(nl < SHORT_SIZE) {
234  MISTD::strcat(m_short_string_buffer, str.m_short_string_buffer);
235  } else {
236  char *result = allocate( nl+1);
237  MISTD::strcpy(result, m_string);
238  MISTD::strcat(result, str.m_string);
239  if(m_string != m_short_string_buffer)
240  deallocate( m_string);
241  m_string = result;
242  m_short_string_buffer[0] = '\0';
243  }
244  m_length = nl;
245  return *this;
246  }
247 };
248 
250 inline bool operator==(
251  const String &left, // The left argument.
252  const String &right) // The right argument.
253 {
254  return (left.length() == right.length())
255  && !MISTD::strcmp(left.c_str(),right.c_str());
256 }
257 
259 inline bool operator!=(
260  const String &left, // The left argument.
261  const String &right) // The right argument.
262 {
263  return !(left == right);
264 }
265 
267 inline bool operator<(
268  const String &left, // The left argument.
269  const String &right) // The right argument.
270 {
271  return MISTD::strcmp(left.c_str(),right.c_str()) < 0;
272 }
273 
275 inline bool operator<=(
276  const String &left, // The left argument.
277  const String &right) // The right argument.
278 {
279  return MISTD::strcmp(left.c_str(),right.c_str()) <= 0;
280 }
281 
283 inline bool operator>=(
284  const String &left, // The left argument.
285  const String &right) // The right argument.
286 {
287  return 0 <= MISTD::strcmp(left.c_str(),right.c_str());
288 }
289 
291 inline bool operator>(
292  const String &left, // The left argument.
293  const String &right) // The right argument.
294 {
295  return 0 < MISTD::strcmp(left.c_str(),right.c_str());
296 }
297 
300  const String &left, // The left argument.
301  const String &right) // The right argument.
302 {
303 
304  String result(left);
305  result += right;
306  return result;
307 }
308 
309  // end group mi_base_string
311 
312 } // namespace base
313 } // namespace mi
314 
315 #ifdef MI_COMPILER_MSC
316 #pragma warning( pop )
317 #endif
318 
319 #endif // MI_BASE_STRING_H