Jamoma API  0.6.0.a19
TTString.h
1 /*
2  Jamoma Class for representing strings
3  Copyright © 2012, Timothy Place & Théo Delahogue
4 
5  License: This code is licensed under the terms of the "New BSD License"
6  http://creativecommons.org/licenses/BSD/
7  */
8 
9 #ifndef __TT_STRING_H__
10 #define __TT_STRING_H__
11 
12 #include "TTBase.h"
13 
14 
15 /****************************************************************************************************/
16 // Class Specification
17 
18 /** The TTString class is used to represent a string.
19  We cannot safely pass std::string across lib boundaries, particularly on Windows.
20  We also don't want to simply pass naked C-Strings for a whole host of reasons.
21 
22  In many cases we try to mimic the interface of std::string for ease of compatibility.
23 
24 
25  FROM http://cboard.cprogramming.com/cplusplus-programming/86598-std-vector-char-vs-std-string.html
26  1. std::string has a huge number of string-related functions which make it easy to manipulate strings.
27  2. std::vector, on the other hand, is guaranteed to be contiguous in memory -- that is, &data[x + 1] = &data[x] + sizeof(data[x]).
28  std::string has NO guarantee that it is contiguous in memory.
29  So, for example, say you're using an API call that fills a character buffer.
30  You'd need to use the vector, not the string.
31 
32  @seealso TTSymbol
33 */
34 class TTString : public std::vector<char> {
35 
36 public:
37 
38  /** Constructor */
39  TTString(const char *aCString = "")
40  {
41  assign(aCString);
42  }
43 
44 
45  TTString(const std::string& aStdString)
46  {
47  assign(aStdString);
48  }
49 
50 
51  TTString(std::vector<char>::iterator begin, std::vector<char>::iterator end)
52  {
53  TTPtrSizedInt newsize = (end - begin);
54 
55  reserve(newsize+16);
56  for (std::vector<char>::iterator c = begin; c != end; ++c) {
57  push_back(*c);
58  }
59 
60  // In some cases the range has NULL termination included, in other cases not.
61  // In these cases we need to correct the size of the string to match the C-String.
62  // If we don't then two strings with identical contents (e.g. "foo" and "foo") will hash to different values.
63  // If then looked-up in the symbol table we corrupt the symbol table with two entries for the same string!
64  TTBoolean resized = NO;
65 
66  for (TTPtrSizedInt i=newsize-1; i>0; i--) {
67  if (at(i) != 0) {
68  resize(i+1);
69  resized = YES;
70  break;
71  }
72  }
73  if (!resized)
74  resize(newsize); // ensure NULL termination
75  }
76 
77  /** Destructor */
79  {}
80 
81 
82  /** Return a pointer to the internal C-string */
83  const char* c_str() const
84  {
85  return &this->at(0);
86  }
87 
88 
89  /** Cast to a C-string. */
90  operator const char*() const
91  {
92  //return mData;
93  return &this->at(0);
94  }
95 
96 
97  /** Assign from a C-string. */
98  TTString& operator = (const char* aCString)
99  {
100  assign(aCString);
101  return *this;
102  }
103 
104 
105  /** Assign from a std::string. */
106  TTString& operator = (std::string& aStdString)
107  {
108  assign(aStdString);
109  return *this;
110  }
111 
112 
113  /** Assign from a simple char. */
114  TTString& operator = (const char aChar)
115  {
116  resize(1);
117  at(0) = aChar;
118  return *this;
119  }
120 
121 
122  /** Overload to assign from a C-string. */
123  void assign(const char* aCString, size_t length=0)
124  {
125  if (length == 0) // no length defined, so check the c-string in the traditional way
126  length = strlen(aCString);
127 
128  if ((length+1) >= capacity())
129  reserve(length+16);
130 
131  resize(length);
132  memcpy(&this->at(0), aCString, length);
133  }
134 
135 
136  /** Assign from a std::string. */
137  void assign(const std::string& aStdString)
138  {
139  assign(aStdString.c_str(), aStdString.length());
140  }
141 
142 
143  /** Find out the length of a string. */
144  size_t size() const
145  {
146  return std::vector<char>::size() - 1;
147  }
148 
149 
150  /** Find out the length of a string. */
151  size_t length() const
152  {
153  return size();
154  }
155 
156 
157  // because when size() == 0 there is still a char (null terminator) in the vector, we have to override this
158  bool empty() const
159  {
160  return size() == 0;
161  }
162 
163  /** Allocate memory for the string. */
164  void resize(size_t newSize)
165  {
166  std::vector<char>::resize(newSize + 1);
167  this->at(newSize) = 0; // NULL terminate for safety
168  }
169 
170 
171  template<class T>
172  TTString& operator += (const T& arg)
173  {
174  append(arg);
175  return (*this);
176  }
177 
178 
179  template<class T>
180  TTString& operator += (const TTString& anotherString)
181  {
182  append(anotherString.c_str(), anotherString.length());
183  return (*this);
184  }
185 
186 
187  template<class T>
188  TTString& operator += (const std::string& aStdString)
189  {
190  append(aStdString.c_str(), aStdString.length());
191  return (*this);
192  }
193 
194 
195  /** Append / Concatenate */
196  void append(const char *str, size_t length=0)
197  {
198  if (!str)
199  return;
200 
201  if (length == 0)
202  length = strlen(str);
203 
204  size_t oldSize = size();
205  size_t newSize = oldSize + length;
206 
207  if (newSize >= capacity())
208  reserve(newSize + 256);
209 
210  resize(newSize);
211  memcpy(&this->at(oldSize), str, length);
212  }
213 
214 
215  void append(const char aChar)
216  {
217  char s[2];
218 
219  snprintf(s, 2, "%c", aChar);
220  append(s);
221  }
222 
223 
224  void append(int anInt)
225  {
226  char s[16];
227 
228  snprintf(s, 16, "%i", anInt);
229  append(s);
230  }
231 
232 
233  void append(unsigned int aUInt)
234  {
235  char s[16];
236 
237  snprintf(s, 16, "%u", aUInt);
238  append(s);
239  }
240 
241 
242  void append(float aFloat)
243  {
244  char s[16];
245 
246  snprintf(s, 16, "%f", aFloat);
247  append(s);
248  }
249 
250 
251  void append(double aDouble)
252  {
253  char s[16];
254 
255  snprintf(s, 16, "%lf", aDouble);
256  append(s);
257  }
258 
259 
260  template<class T>
261  TTString operator + (const T& arg)
262  {
263  TTString result = *this; // Make a copy of myself
264  result += arg; // Use += to add arg to the copy.
265  return result;
266  }
267 
268 
269  bool operator == (const char *cString) const
270  {
271  const TTString s(cString);
272  return (*this) == s;
273  }
274 
275  bool operator == (const TTString &other) const
276  {
277  return *dynamic_cast<const std::vector<char>*>(this) == *dynamic_cast<const std::vector<char>*>(&other);
278  }
279 
280 
281  bool operator != (const char *cString) const
282  {
283  return !(*this == cString);
284  }
285 
286  bool operator != (const TTString &other) const
287  {
288  return !(*this == other);
289  }
290 
291 
292  /** Return the index of the first instance of a specified char in the string.
293  @param aChar The char for which to search
294  @param from A position in the string from which to begin the search. By default it starts at the beginning (0)
295  */
296  size_t find_first_of(const char aChar, size_t from = 0)
297  {
298  TTBoolean found = NO;
299  size_t i;
300 
301  for (i=from; i<size(); i++) {
302  if (at(i) == aChar) {
303  found = YES;
304  break;
305  }
306  }
307  if (found)
308  return i;
309  else
310  return -1;
311  }
312 
313  /** Return the index of the last instance of a specified char in the string.
314  @param aChar The char for which to search
315  */
316  size_t find_last_of(const char aChar)
317  {
318  TTBoolean found = NO;
319  size_t i, j;
320 
321  j = size() - 1;
322 
323  for (i=0; i<size(); i++) {
324  if (at(j) == aChar) {
325  found = YES;
326  break;
327  } else {
328  j--;
329  }
330  }
331  if (found)
332  return j;
333  else
334  return -1;
335  }
336 
337 
338  /** Returns a string object with its contents initialized to a substring of the current object.
339  @param pos Position of a character in the current string object to be used as starting character for the substring.
340  @param n Length of the substring.
341  */
342  TTString substr (size_t pos = 0, size_t n = 1) const
343  {
344  TTString substring;
345  size_t i;
346 
347  if (pos+n > size()) // If the size is too large and thus the range extends past the end of the string...
348  n = size() - pos; // we limit the range to end at the end of the string.
349 
350  substring.reserve(n+16);
351  substring.resize(n);
352  for (i=0; i<n; i++) {
353  substring[i] = (*this)[pos + i];
354  if (pos+i >= size())
355  break;
356  }
357  return substring;
358  }
359 
360 
361  // This avoids a warning in GCC 4.7 about ambiguity between using an int vs. a size_t where
362  // the int could also be considered an index into a char array
363  char& operator[] (const int index)
364  {
365  return this->at(index);
366  }
367 
368 
369  // NOTE: we do not export TTString because it is defined in a header as a subclass of a stl template
370  // but we do want to export this method, which is not defined inline so that we don't pick up a direct
371  // dependency on Mersenne Twister
372  /** Replace contents with a pseudo-random string. */
373  void TTFOUNDATION_EXPORT random();
374 
375 
376 
377 // TTBoolean toTTInt32( const TTString & str, TTInt32 & convertedInt )
378  TTBoolean toTTInt32(TTInt32& convertedInt) const
379  {
380  char * pEnd;
381 
382  convertedInt = strtol(c_str(), &pEnd, 10);
383  return *pEnd == 0;
384  }
385 
386  // TTBoolean toTTUInt32( const TTString & str, TTInt32 & convertedUInt )
387  TTBoolean toTTUInt32(TTUInt32& convertedUInt) const
388  {
389  char * pEnd;
390 
391  convertedUInt = strtoul(c_str(), &pEnd, 10);
392 
393  // is the last letter is a 'u' ?
394  return *pEnd == 'u' && pEnd == (c_str() + length() - 1);
395  }
396 
397  /* note : isTTFloat32 works only because the TTInt32 case is matched before
398  see in TTValue::fromString method
399  */
400 // TTBoolean toTTFloat32( const TTString & str, TTFloat32 & convertedFloat )
401  TTBoolean toTTFloat32(TTFloat32& convertedFloat) const
402  {
403  char * pEnd;
404 
405  convertedFloat = strtod(c_str(), &pEnd);
406  return *pEnd == 0;
407  }
408 
409 };
410 
411 
412 /** Iterator for using STL algorithms with TTString. */
413 typedef TTString::iterator TTStringIter;
414 
415 
416 /** Expose TTString for use in std output streams. */
417 template <class charT, class traits>
418 std::basic_ostream <charT, traits>& operator<< (std::basic_ostream <charT, traits>& stream, const TTString& aString)
419 {
420  return stream << aString.c_str();
421 }
422 
423 
424 // Only providing this for use in the Foundation itself at the moment
425 // (on OS 10.8 with Xcode 4.4 and compiling with clang for the Ruby extension, this code cause compile problems)
426 #ifdef TTFOUNDATION_EXPORTS
427 
428 
429 /** Provide overload of std::hash so that TTString can be used the same as std::string for std::map et al. */
430 
431 #if defined( __clang__ )
432 
433 // GCC and Clang provide different (cryptic) ways of adding custom types to the c++ hashing classes
434 // The GCC version is based on code from StackOverflow
435 // The Clang version is based on the code for std::string from libc ( on the mac these are installed @ /usr/lib/c++/v1/ )
436 
437 #include <functional>
438 namespace std
439 {
440  template <>
441  //struct hash<TTString> : public __hash_base<size_t, TTString>
442  struct hash<TTString> //: public __hash_node<size_t, TTString>
443  {
444  public:
445  size_t operator()(const TTString& __val) const noexcept
446  {
447  return __do_string_hash(__val.data(), __val.data() + __val.size());
448  }
449  };
450 }
451 
452 #elif defined( TT_PLATFORM_WIN )
453 namespace std
454 {
455 // namespace tr1
456 // {
457  template <>
458  struct hash<TTString> : public unary_function<TTString, size_t>
459  {
460  public:
461  size_t operator()(const TTString& self) const
462  {
463  size_t hashkey = _Hash_seq((const unsigned char*)self.data(), self.size()); //std::hash(self.data(), self.size());
464  //cout << "HASH: " << self.data() << " with size: " << self.size() << " = " << hashkey << endl;
465  return hashkey;
466  }
467  };
468 // }
469 }
470 
471 #else // gcc 4.7
472 
473 namespace std
474 {
475  template <>
476  struct hash<TTString>
477  {
478  public:
479 
480  size_t operator()(const TTString& self) const
481  {
482  size_t hashkey = std::_Hash_impl::hash(self.data(), self.size());
483  return hashkey;
484  }
485 
486  };
487 }
488 
489 #endif // ifdef clang etc...
490 
491 #endif // TTFOUNDATION_EXPORTS
492 
493 
494 #endif // __TT_STRING_H__
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
const char * c_str() const
Return a pointer to the internal C-string.
Definition: TTString.h:83
STL namespace.
void assign(const char *aCString, size_t length=0)
Overload to assign from a C-string.
Definition: TTString.h:123
Jamoma's lowest-level base class and related infrastructure.
~TTString()
Destructor.
Definition: TTString.h:78
float TTFloat32
32 bit floating point number
Definition: TTBase.h:187
void TTFOUNDATION_EXPORT random()
Replace contents with a pseudo-random string.
Definition: TTString.cpp:13
TTString & operator=(const char *aCString)
Assign from a C-string.
Definition: TTString.h:98
void assign(const std::string &aStdString)
Assign from a std::string.
Definition: TTString.h:137
TTString substr(size_t pos=0, size_t n=1) const
Returns a string object with its contents initialized to a substring of the current object...
Definition: TTString.h:342
size_t length() const
Find out the length of a string.
Definition: TTString.h:151
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
size_t find_last_of(const char aChar)
Return the index of the last instance of a specified char in the string.
Definition: TTString.h:316
long TTPtrSizedInt
An integer that is the same size as a pointer.
Definition: TTBase.h:240
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
void append(const char *str, size_t length=0)
Append / Concatenate.
Definition: TTString.h:196
size_t size() const
Find out the length of a string.
Definition: TTString.h:144
size_t find_first_of(const char aChar, size_t from=0)
Return the index of the first instance of a specified char in the string.
Definition: TTString.h:296
The TTString class is used to represent a string.
Definition: TTString.h:34
TTString(const char *aCString="")
Constructor.
Definition: TTString.h:39
void resize(size_t newSize)
Allocate memory for the string.
Definition: TTString.h:164