StrLib.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // This code is in the public domain -- Ignacio Castaño <castano@gmail.com>
  2. #pragma once
  3. #ifndef NV_CORE_STRING_H
  4. #define NV_CORE_STRING_H
  5. #include "Debug.h"
  6. #include "Hash.h" // hash
  7. //#include <string.h> // strlen, etc.
  8. #if NV_OS_WIN32
  9. #define NV_PATH_SEPARATOR '\\'
  10. #else
  11. #define NV_PATH_SEPARATOR '/'
  12. #endif
  13. namespace nv
  14. {
  15. NVCORE_API uint strHash(const char * str, uint h) NV_PURE;
  16. /// String hash based on Bernstein's hash.
  17. inline uint strHash(const char * data, uint h = 5381)
  18. {
  19. uint i = 0;
  20. while(data[i] != 0) {
  21. h = (33 * h) ^ uint(data[i]);
  22. i++;
  23. }
  24. return h;
  25. }
  26. template <> struct Hash<const char *> {
  27. uint operator()(const char * str) const { return strHash(str); }
  28. };
  29. NVCORE_API uint strLen(const char * str) NV_PURE; // Asserts on NULL strings.
  30. NVCORE_API int strDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
  31. NVCORE_API int strCaseDiff(const char * s1, const char * s2) NV_PURE; // Asserts on NULL strings.
  32. NVCORE_API bool strEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
  33. NVCORE_API bool strCaseEqual(const char * s1, const char * s2) NV_PURE; // Accepts NULL strings.
  34. template <> struct Equal<const char *> {
  35. bool operator()(const char * a, const char * b) const { return strEqual(a, b); }
  36. };
  37. NVCORE_API bool strBeginsWith(const char * dst, const char * prefix) NV_PURE;
  38. NVCORE_API bool strEndsWith(const char * dst, const char * suffix) NV_PURE;
  39. NVCORE_API void strCpy(char * dst, uint size, const char * src);
  40. NVCORE_API void strCpy(char * dst, uint size, const char * src, uint len);
  41. NVCORE_API void strCat(char * dst, uint size, const char * src);
  42. NVCORE_API const char * strSkipWhiteSpace(const char * str);
  43. NVCORE_API char * strSkipWhiteSpace(char * str);
  44. NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
  45. NVCORE_API bool isNumber(const char * str) NV_PURE;
  46. /* @@ Implement these two functions and modify StringBuilder to use them?
  47. NVCORE_API void strFormat(const char * dst, const char * fmt, ...);
  48. NVCORE_API void strFormatList(const char * dst, const char * fmt, va_list arg);
  49. template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) __attribute__((format (printf, 2, 3)));
  50. template <size_t count> void strFormatSafe(char (&buffer)[count], const char *fmt, ...) {
  51. va_list args;
  52. va_start(args, fmt);
  53. strFormatList(buffer, count, fmt, args);
  54. va_end(args);
  55. }
  56. template <size_t count> void strFormatListSafe(char (&buffer)[count], const char *fmt, va_list arg) {
  57. va_list tmp;
  58. va_copy(tmp, args);
  59. strFormatList(buffer, count, fmt, tmp);
  60. va_end(tmp);
  61. }*/
  62. template <int count> void strCpySafe(char (&buffer)[count], const char *src) {
  63. strCpy(buffer, count, src);
  64. }
  65. template <int count> void strCatSafe(char (&buffer)[count], const char * src) {
  66. strCat(buffer, count, src);
  67. }
  68. /// String builder.
  69. class NVCORE_CLASS StringBuilder
  70. {
  71. public:
  72. StringBuilder();
  73. explicit StringBuilder( uint size_hint );
  74. StringBuilder(const char * str);
  75. StringBuilder(const char * str, uint len);
  76. StringBuilder(const StringBuilder & other);
  77. ~StringBuilder();
  78. StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
  79. StringBuilder & formatList( const char * format, va_list arg );
  80. StringBuilder & append(char c);
  81. StringBuilder & append(const char * str);
  82. StringBuilder & append(const char * str, uint len);
  83. StringBuilder & append(const StringBuilder & str);
  84. StringBuilder & appendFormat(const char * format, ...) __attribute__((format (printf, 2, 3)));
  85. StringBuilder & appendFormatList(const char * format, va_list arg);
  86. StringBuilder & appendSpace(uint n);
  87. StringBuilder & number( int i, int base = 10 );
  88. StringBuilder & number( uint i, int base = 10 );
  89. StringBuilder & reserve(uint size_hint);
  90. StringBuilder & copy(const char * str);
  91. StringBuilder & copy(const char * str, uint len);
  92. StringBuilder & copy(const StringBuilder & str);
  93. StringBuilder & toLower();
  94. StringBuilder & toUpper();
  95. bool endsWith(const char * str) const;
  96. bool beginsWith(const char * str) const;
  97. char * reverseFind(char c);
  98. void reset();
  99. bool isNull() const { return m_size == 0; }
  100. // const char * accessors
  101. //operator const char * () const { return m_str; }
  102. //operator char * () { return m_str; }
  103. const char * str() const { return m_str; }
  104. char * str() { return m_str; }
  105. char * release(); // Release ownership of string.
  106. void acquire(char *); // Take ownership of string.
  107. /// Implement value semantics.
  108. StringBuilder & operator=( const StringBuilder & s ) {
  109. return copy(s);
  110. }
  111. /// Implement value semantics.
  112. StringBuilder & operator=( const char * s ) {
  113. return copy(s);
  114. }
  115. /// Equal operator.
  116. bool operator==( const StringBuilder & s ) const {
  117. return strMatch(s.m_str, m_str);
  118. }
  119. /// Return the exact length.
  120. uint length() const { return isNull() ? 0 : strLen(m_str); }
  121. /// Return the size of the string container.
  122. uint capacity() const { return m_size; }
  123. /// Return the hash of the string.
  124. uint hash() const { return isNull() ? 0 : strHash(m_str); }
  125. // Swap strings.
  126. friend void swap(StringBuilder & a, StringBuilder & b);
  127. protected:
  128. /// Size of the string container.
  129. uint m_size;
  130. /// String.
  131. char * m_str;
  132. };
  133. /// Path string. @@ This should be called PathBuilder.
  134. class NVCORE_CLASS Path : public StringBuilder
  135. {
  136. public:
  137. Path() : StringBuilder() {}
  138. explicit Path(int size_hint) : StringBuilder(size_hint) {}
  139. Path(const char * str) : StringBuilder(str) {}
  140. Path(const Path & path) : StringBuilder(path) {}
  141. const char * fileName() const;
  142. const char * extension() const;
  143. void translatePath(char pathSeparator = NV_PATH_SEPARATOR);
  144. void appendSeparator(char pathSeparator = NV_PATH_SEPARATOR);
  145. void stripFileName();
  146. void stripExtension();
  147. // statics
  148. NVCORE_API static char separator();
  149. NVCORE_API static const char * fileName(const char *);
  150. NVCORE_API static const char * extension(const char *);
  151. NVCORE_API static void translatePath(char * path, char pathSeparator = NV_PATH_SEPARATOR);
  152. };
  153. /// String class.
  154. class NVCORE_CLASS String
  155. {
  156. public:
  157. /// Constructs a null string. @sa isNull()
  158. String()
  159. {
  160. data = NULL;
  161. }
  162. /// Constructs a shared copy of str.
  163. String(const String & str)
  164. {
  165. data = str.data;
  166. if (data != NULL) addRef();
  167. }
  168. /// Constructs a shared string from a standard string.
  169. String(const char * str)
  170. {
  171. setString(str);
  172. }
  173. /// Constructs a shared string from a standard string.
  174. String(const char * str, int length)
  175. {
  176. setString(str, length);
  177. }
  178. /// Constructs a shared string from a StringBuilder.
  179. String(const StringBuilder & str)
  180. {
  181. setString(str);
  182. }
  183. /// Dtor.
  184. ~String()
  185. {
  186. release();
  187. }
  188. String clone() const;
  189. /// Release the current string and allocate a new one.
  190. const String & operator=( const char * str )
  191. {
  192. release();
  193. setString( str );
  194. return *this;
  195. }
  196. /// Release the current string and allocate a new one.
  197. const String & operator=( const StringBuilder & str )
  198. {
  199. release();
  200. setString( str );
  201. return *this;
  202. }
  203. /// Implement value semantics.
  204. String & operator=( const String & str )
  205. {
  206. if (str.data != data)
  207. {
  208. release();
  209. data = str.data;
  210. addRef();
  211. }
  212. return *this;
  213. }
  214. /// Equal operator.
  215. bool operator==( const String & str ) const
  216. {
  217. return strMatch(str.data, data);
  218. }
  219. /// Equal operator.
  220. bool operator==( const char * str ) const
  221. {
  222. return strMatch(str, data);
  223. }
  224. /// Not equal operator.
  225. bool operator!=( const String & str ) const
  226. {
  227. return !strMatch(str.data, data);
  228. }
  229. /// Not equal operator.
  230. bool operator!=( const char * str ) const
  231. {
  232. return !strMatch(str, data);
  233. }
  234. /// Returns true if this string is the null string.
  235. bool isNull() const { return data == NULL; }
  236. /// Return the exact length.
  237. uint length() const { nvDebugCheck(data != NULL); return strLen(data); }
  238. /// Return the hash of the string.
  239. uint hash() const { nvDebugCheck(data != NULL); return strHash(data); }
  240. /// const char * cast operator.
  241. operator const char * () const { return data; }
  242. /// Get string pointer.
  243. const char * str() const { return data; }
  244. private:
  245. // Add reference count.
  246. void addRef();
  247. // Decrease reference count.
  248. void release();
  249. uint16 getRefCount() const
  250. {
  251. nvDebugCheck(data != NULL);
  252. return *reinterpret_cast<const uint16 *>(data - 2);
  253. }
  254. void setRefCount(uint16 count) {
  255. nvDebugCheck(data != NULL);
  256. nvCheck(count < 0xFFFF);
  257. *reinterpret_cast<uint16 *>(const_cast<char *>(data - 2)) = uint16(count);
  258. }
  259. void setData(const char * str) {
  260. data = str + 2;
  261. }
  262. void allocString(const char * str)
  263. {
  264. allocString(str, strLen(str));
  265. }
  266. void allocString(const char * str, uint length);
  267. void setString(const char * str);
  268. void setString(const char * str, uint length);
  269. void setString(const StringBuilder & str);
  270. // Swap strings.
  271. friend void swap(String & a, String & b);
  272. private:
  273. const char * data;
  274. };
  275. template <> struct Hash<String> {
  276. uint operator()(const String & str) const { return str.hash(); }
  277. };
  278. // Like AutoPtr, but for const char strings.
  279. class AutoString
  280. {
  281. NV_FORBID_COPY(AutoString);
  282. NV_FORBID_HEAPALLOC();
  283. public:
  284. // Ctor.
  285. AutoString(const char * p = NULL) : m_ptr(p) { }
  286. #if NV_CC_CPP11
  287. // Move ctor.
  288. AutoString(AutoString && ap) : m_ptr(ap.m_ptr) { ap.m_ptr = NULL; }
  289. #endif
  290. // Dtor. Deletes owned pointer.
  291. ~AutoString() {
  292. delete [] m_ptr;
  293. m_ptr = NULL;
  294. }
  295. // Delete owned pointer and assign new one.
  296. void operator=(const char * p) {
  297. if (p != m_ptr)
  298. {
  299. delete [] m_ptr;
  300. m_ptr = p;
  301. }
  302. }
  303. // Get pointer.
  304. const char * ptr() const { return m_ptr; }
  305. operator const char *() const { return m_ptr; }
  306. // Relinquish ownership of the underlying pointer and returns that pointer.
  307. const char * release() {
  308. const char * tmp = m_ptr;
  309. m_ptr = NULL;
  310. return tmp;
  311. }
  312. // comparison operators.
  313. friend bool operator == (const AutoString & ap, const char * const p) {
  314. return (ap.ptr() == p);
  315. }
  316. friend bool operator != (const AutoString & ap, const char * const p) {
  317. return (ap.ptr() != p);
  318. }
  319. friend bool operator == (const char * const p, const AutoString & ap) {
  320. return (ap.ptr() == p);
  321. }
  322. friend bool operator != (const char * const p, const AutoString & ap) {
  323. return (ap.ptr() != p);
  324. }
  325. private:
  326. const char * m_ptr;
  327. };
  328. } // nv namespace
  329. #endif // NV_CORE_STRING_H