strlib.h 12 KB

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