jstring.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef __JSTRING__
  14. #define __JSTRING__
  15. #include "jiface.hpp"
  16. #include "jio.hpp"
  17. #include "jstream.hpp"
  18. #include "jbuff.hpp"
  19. // A Java compatible String and StringBuffer class - useful for dynamic strings.
  20. class String;
  21. interface IAtom;
  22. interface IFile;
  23. class jlib_decl StringBuffer
  24. {
  25. enum { InternalBufferSize = 16 };
  26. public:
  27. StringBuffer();
  28. StringBuffer(String & value);
  29. StringBuffer(const char *value);
  30. StringBuffer(StringBuffer && value);
  31. StringBuffer(unsigned len, const char *value);
  32. StringBuffer(const StringBuffer & value);
  33. StringBuffer(bool useInternal);
  34. StringBuffer(char value);
  35. ~StringBuffer();
  36. inline size32_t length() const { return curLen; }
  37. inline bool isEmpty() const { return (curLen == 0); }
  38. void setLength(unsigned len);
  39. inline void ensureCapacity(unsigned max) { if (maxLen <= curLen + max) _realloc(curLen + max); }
  40. size32_t lengthUtf8() const;
  41. StringBuffer & append(char value);
  42. StringBuffer & append(unsigned char value);
  43. StringBuffer & append(const char * value);
  44. StringBuffer & append(const unsigned char * value);
  45. StringBuffer & append(const IAtom * value);
  46. StringBuffer & append(size_t len, const char * value);
  47. StringBuffer & append(const char * value, int offset, int len);
  48. StringBuffer & append(double value);
  49. StringBuffer & append(float value);
  50. StringBuffer & append(int value);
  51. StringBuffer & append(unsigned value);
  52. StringBuffer & append(__int64 value);
  53. StringBuffer & append(unsigned __int64 value);
  54. StringBuffer & append(const String & value);
  55. StringBuffer & append(const IStringVal & value);
  56. StringBuffer & append(const IStringVal * value);
  57. StringBuffer & appendN(size32_t count, char fill);
  58. StringBuffer & appendf(const char *format, ...) __attribute__((format(printf, 2, 3)));
  59. StringBuffer & appendLower(unsigned len, const char * value);
  60. StringBuffer & setf(const char* format, ...) __attribute__((format(printf,2,3)));
  61. StringBuffer & limited_valist_appendf(unsigned szLimit, const char *format, va_list args) __attribute__((format(printf,3,0)));
  62. inline StringBuffer &valist_appendf(const char *format, va_list args) __attribute__((format(printf,2,0))) { return limited_valist_appendf(0, format, args); }
  63. StringBuffer & appendhex(unsigned char value, char lower);
  64. inline char charAt(size32_t pos) { return buffer[pos]; }
  65. inline StringBuffer & clear() { curLen = 0; return *this; }
  66. void kill();
  67. void getChars(int srcBegin, int srcEnd, char * target) const;
  68. StringBuffer & insert(int offset, char value);
  69. StringBuffer & insert(int offset, unsigned char value);
  70. StringBuffer & insert(int offset, const char * value);
  71. StringBuffer & insert(int offset, const unsigned char * value);
  72. StringBuffer & insert(int offset, double value);
  73. StringBuffer & insert(int offset, float value);
  74. StringBuffer & insert(int offset, int value);
  75. StringBuffer & insert(int offset, unsigned value);
  76. StringBuffer & insert(int offset, __int64 value);
  77. StringBuffer & insert(int offset, const String & value);
  78. StringBuffer & insert(int offset, const StringBuffer & value);
  79. StringBuffer & insert(int offset, const IStringVal & value);
  80. StringBuffer & insert(int offset, const IStringVal * value);
  81. StringBuffer & reverse();
  82. void setCharAt(unsigned offset, char value);
  83. //Non-standard functions:
  84. MemoryBuffer & deserialize(MemoryBuffer & in);
  85. MemoryBuffer & serialize(MemoryBuffer & out) const;
  86. StringBuffer & loadFile(const char *fname, bool binaryMode=false);
  87. StringBuffer & loadFile(IFile* f);
  88. StringBuffer & append(const StringBuffer & value);
  89. StringBuffer & newline();
  90. StringBuffer & pad(unsigned count);
  91. StringBuffer & padTo(unsigned count);
  92. char * detach();
  93. StringBuffer & clip();
  94. StringBuffer & trim();
  95. StringBuffer & trimLeft();
  96. inline StringBuffer & trimRight() { return clip(); }
  97. StringBuffer & remove(unsigned start, unsigned len);
  98. const char * str() const;
  99. StringBuffer & toLowerCase();
  100. StringBuffer & toUpperCase();
  101. StringBuffer & replace(char oldChar, char newChar);
  102. StringBuffer & replaceString(const char* oldStr, const char* newStr);
  103. char * reserve(size32_t size);
  104. char * reserveTruncate(size32_t size);
  105. void setown(StringBuffer &other);
  106. StringBuffer & stripChar(char oldChar);
  107. void swapWith(StringBuffer &other);
  108. void setBuffer(size32_t buffLen, char * newBuff, size32_t strLen);
  109. inline StringBuffer& set(const char* value) { return clear().append(value); }
  110. inline operator const char* () const { return str(); }
  111. inline StringBuffer& operator=(const char* value)
  112. {
  113. return clear().append(value);
  114. }
  115. inline StringBuffer& operator=(const StringBuffer& value)
  116. {
  117. return clear().append(value.str());
  118. }
  119. StringBuffer& operator=(StringBuffer&& value);
  120. StringBuffer & appendlong(long value);
  121. StringBuffer & appendulong(unsigned long value);
  122. private: // long depreciated
  123. StringBuffer & append(long value);
  124. StringBuffer & append(unsigned long value);
  125. StringBuffer & insert(int offset, long value);
  126. protected:
  127. inline bool useInternal() const { return buffer == internalBuffer; }
  128. void init()
  129. {
  130. buffer = internalBuffer;
  131. curLen = 0;
  132. maxLen = InternalBufferSize;
  133. }
  134. void initNoInternal()
  135. {
  136. buffer = NULL;
  137. curLen = 0;
  138. maxLen = 0;
  139. }
  140. void freeBuffer();
  141. void _insert(unsigned offset, size32_t insertLen);
  142. void _realloc(size32_t newLen);
  143. private:
  144. char internalBuffer[InternalBufferSize];
  145. char * buffer;
  146. size32_t curLen;
  147. size32_t maxLen;
  148. };
  149. // add a variable-parameter constructor to StringBuffer.
  150. class jlib_decl VStringBuffer : public StringBuffer
  151. {
  152. public:
  153. VStringBuffer(const char* format, ...) __attribute__((format(printf, 2, 3)));
  154. };
  155. class SCMStringBuffer : public CInterface, implements IStringVal
  156. {
  157. public:
  158. IMPLEMENT_IINTERFACE;
  159. StringBuffer s;
  160. virtual const char * str() const { return s.str(); };
  161. virtual void set(const char *val) { s.clear().append(val); };
  162. virtual void set(StringBuffer &&str) { s.swapWith(str); }
  163. virtual void clear() { s.clear(); };
  164. virtual void setLen(const char *val, unsigned length) { s.clear().append(length, val); };
  165. virtual unsigned length() const { return s.length(); };
  166. };
  167. class jlib_decl String : public CInterface, implements IInterface
  168. {
  169. public:
  170. IMPLEMENT_IINTERFACE;
  171. String();
  172. // String(byte[]);
  173. // String(byte[], int);
  174. // String(byte[], int, int);
  175. // String(byte[], int, int, int);
  176. // String(byte[], int, int, String);
  177. // String(byte[], String);
  178. String(const char * value);
  179. String(const char * value, int offset, int count);
  180. String(String & value);
  181. String(StringBuffer & value);
  182. ~String();
  183. char charAt(size32_t index) const;
  184. int compareTo(const String & value) const;
  185. int compareTo(const char* value) const;
  186. String * concat(const String & value) const;
  187. bool endsWith(const String & value) const;
  188. bool endsWith(const char* value) const;
  189. bool equals(String & value) const;
  190. bool equalsIgnoreCase(const String & value) const;
  191. void getBytes(int srcBegin, int srcEnd, void * dest, int dstBegin) const;
  192. void getChars(int srcBegin, int srcEnd, void * dest, int dstBegin) const;
  193. int hashCode() const;
  194. int indexOf(int ch) const;
  195. int indexOf(int ch, int from) const;
  196. int indexOf(const String & search) const;
  197. int indexOf(const String & search, int from) const;
  198. int lastIndexOf(int ch) const;
  199. int lastIndexOf(int ch, int from) const;
  200. int lastIndexOf(const String & search) const;
  201. int lastIndexOf(const String & serach, int from) const;
  202. size32_t length() const;
  203. bool startsWith(String & value) const;
  204. bool startsWith(String & value, int offset) const;
  205. bool startsWith(const char* value) const;
  206. String * substring(int beginIndex) const;
  207. String * substring(int beginIndex, int endIndex) const;
  208. const char *str() const;
  209. String * toLowerCase() const;
  210. String * toString(); // Links this
  211. String * toUpperCase() const;
  212. String * trim() const;
  213. protected:
  214. char * text;
  215. };
  216. //This simple class is useful for storing string member variables
  217. class jlib_decl StringAttr
  218. {
  219. public:
  220. inline StringAttr(void) { text = NULL; }
  221. StringAttr(const char * _text, size_t _len);
  222. StringAttr(const char * _text);
  223. StringAttr(const StringAttr & src);
  224. StringAttr(StringAttr && src);
  225. StringAttr& operator = (StringAttr && from);
  226. StringAttr& operator = (const StringAttr & from);
  227. inline ~StringAttr(void) { free(text); }
  228. inline operator const char * () const { return text; }
  229. inline void clear() { setown(NULL); }
  230. inline char * detach() { char * ret = text; text = NULL; return ret; }
  231. inline const char * get() const { return text; }
  232. inline size_t length() const { return text ? strlen(text) : 0; }
  233. inline bool isEmpty() const { return !text||!*text; } // faster than (length==0)
  234. inline const char * str() const { return text ? text : ""; } // safe form (doesn't return NULL)
  235. void set(const char * _text);
  236. void setown(const char * _text);
  237. void set(const char * _text, size_t _len);
  238. void set(const StringBuffer & source);
  239. void setown(StringBuffer & source);
  240. void toLowerCase();
  241. void toUpperCase();
  242. private:
  243. char * text;
  244. };
  245. class jlib_decl StringAttrBuilder : public StringBuffer
  246. {
  247. public:
  248. StringAttrBuilder(StringAttr & _target);
  249. ~StringAttrBuilder();
  250. protected:
  251. StringAttr & target;
  252. };
  253. class jlib_decl StringAttrAdaptor : implements IStringVal
  254. {
  255. public:
  256. StringAttrAdaptor(StringAttr & _attr) : attr(_attr) {}
  257. virtual const char * str() const { return attr.get(); };
  258. virtual void set(const char *val) { attr.set(val); };
  259. virtual void clear() { attr.clear(); };
  260. virtual void setLen(const char *val, unsigned length) { attr.set(val, length); };
  261. virtual unsigned length() const { return (unsigned)attr.length(); };
  262. private:
  263. StringAttr & attr;
  264. };
  265. class jlib_decl StringBufferAdaptor : implements IStringVal
  266. {
  267. public:
  268. StringBufferAdaptor(StringBuffer & _buffer) : buffer(_buffer) { initsize=buffer.length(); }
  269. virtual const char * str() const { return buffer.str(); };
  270. virtual void set(const char *val) { clear(); buffer.append(val); };
  271. virtual void clear() { buffer.setLength(initsize); }
  272. virtual void setLen(const char *val, unsigned length) { clear(); buffer.append(length, val); };
  273. virtual unsigned length() const { return buffer.length(); };
  274. private:
  275. size32_t initsize;
  276. StringBuffer & buffer;
  277. };
  278. #ifdef __GNUC__
  279. class jlib_decl GccStringAttrAdaptor
  280. {
  281. public:
  282. GccStringAttrAdaptor(StringAttr & _attr) : adaptor(_attr) {}
  283. inline operator IStringVal & () { return adaptor; }
  284. private:
  285. StringAttrAdaptor adaptor;
  286. };
  287. class jlib_decl GccStringBufferAdaptor
  288. {
  289. public:
  290. GccStringBufferAdaptor(StringBuffer & _buffer) : adaptor(_buffer) {}
  291. inline operator IStringVal & () { return adaptor; }
  292. private:
  293. StringBufferAdaptor adaptor;
  294. };
  295. #define StringAttrAdaptor GccStringAttrAdaptor
  296. #define StringBufferAdaptor GccStringBufferAdaptor
  297. #endif
  298. class jlib_decl StringBufferItem : public CInterface, public StringBuffer
  299. {
  300. public:
  301. StringBufferItem() : StringBuffer() {}
  302. StringBufferItem(const char *value) : StringBuffer(value) {}
  303. StringBufferItem(unsigned len, const char *value) : StringBuffer(len, value) {}
  304. StringBufferItem(const StringBuffer & value) : StringBuffer(value) {}
  305. };
  306. class jlib_decl StringAttrItem : public CInterface
  307. {
  308. public:
  309. StringAttrItem(void) {}
  310. StringAttrItem(const char * _text) : text(_text) {}
  311. StringAttrItem(const char * _text, unsigned _len);
  312. public:
  313. StringAttr text;
  314. };
  315. // --$appendURL-----------------------------------------------------------------
  316. // appends the URL encoded version of src to dest
  317. // if len is unspecified, then src is assumed to be an NTS
  318. // if lower is TRUE a-f is used for hex numbers, otherwise A-F is used
  319. // -----------------------------------------------------------------------------
  320. #define ENCODE_SPACES 1
  321. #define ENCODE_NEWLINES 2
  322. #define ENCODE_WHITESPACE 3
  323. #define ENCODE_NONE 4
  324. interface IEntityHelper
  325. {
  326. virtual bool find(const char *entity, StringBuffer &value) = 0;
  327. };
  328. void jlib_decl appendURL(StringBuffer *dest, const char *src, size32_t len = -1, char lower=FALSE);
  329. extern jlib_decl StringBuffer &appendDecodedURL(StringBuffer &out, const char *url);
  330. extern jlib_decl StringBuffer & appendStringAsCPP(StringBuffer &out, unsigned len, const char * src, bool addBreak);
  331. extern jlib_decl StringBuffer & appendStringAsQuotedCPP(StringBuffer &out, unsigned len, const char * src, bool addBreak);
  332. extern jlib_decl StringBuffer & appendDataAsHex(StringBuffer &out, unsigned len, const void * data);
  333. extern jlib_decl StringBuffer & appendStringAsSQL(StringBuffer & out, unsigned len, const char * src);
  334. extern jlib_decl StringBuffer & appendStringAsECL(StringBuffer & out, unsigned len, const char * src);
  335. extern jlib_decl StringBuffer & appendStringAsQuotedECL(StringBuffer &out, unsigned len, const char * src);
  336. extern jlib_decl StringBuffer & appendUtf8AsECL(StringBuffer &out, unsigned len, const char * src);
  337. extern jlib_decl const char *decodeJSON(const char *x, StringBuffer &ret, unsigned len=(unsigned)-1, const char **errMark=NULL);
  338. extern jlib_decl void extractItem(StringBuffer & res, const char * src, const char * sep, int whichItem, bool caps);
  339. extern jlib_decl const char *encodeXML(const char *x, StringBuffer &ret, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=false);
  340. extern jlib_decl const char *decodeXML(const char *x, StringBuffer &ret, const char **errMark=NULL, IEntityHelper *entityHelper=NULL, bool strict = true);
  341. extern jlib_decl const char *encodeXML(const char *x, IIOStream &out, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=false);
  342. extern jlib_decl void decodeXML(ISimpleReadStream &in, StringBuffer &out, unsigned len=(unsigned)-1);
  343. extern jlib_decl int utf8CharLen(unsigned char ch);
  344. extern jlib_decl int utf8CharLen(const unsigned char *ch, unsigned maxsize = (unsigned)-1);
  345. extern jlib_decl StringBuffer &replaceString(StringBuffer & result, size32_t lenSource, const char *source, size32_t lenOldStr, const char* oldStr, size32_t lenNewStr, const char* newStr);
  346. inline const char *encodeUtf8XML(const char *x, StringBuffer &ret, unsigned flags=false, unsigned len=(unsigned)-1)
  347. {
  348. return encodeXML(x, ret, flags, len, true);
  349. }
  350. inline StringBuffer &appendXMLTagName(StringBuffer &xml, const char *tag, const char *prefix=NULL)
  351. {
  352. if (prefix && *prefix)
  353. xml.append(prefix).append(':');
  354. xml.append(tag);
  355. return xml;
  356. }
  357. extern jlib_decl StringBuffer & appendXMLOpenTag(StringBuffer &xml, const char *tag, const char *prefix=NULL, bool complete=true, bool close=false, const char *uri=NULL);
  358. inline StringBuffer &appendXMLAttr(StringBuffer &xml, const char *name, const char *value, const char *prefix=NULL)
  359. {
  360. if (!name || !*name || !value)
  361. return xml;
  362. xml.append(' ');
  363. appendXMLTagName(xml, name, prefix);
  364. encodeXML(value, xml.append("='"));
  365. xml.append("'");
  366. return xml;
  367. }
  368. inline StringBuffer & appendXMLCloseTag(StringBuffer &xml, const char *tag, const char *prefix=NULL)
  369. {
  370. if (!tag || !*tag)
  371. return xml;
  372. xml.append("</");
  373. return appendXMLTagName(xml, tag, prefix).append('>');
  374. }
  375. inline StringBuffer &appendXMLTag(StringBuffer &xml, const char *tag, const char *value, const char *prefix=NULL, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=true)
  376. {
  377. appendXMLOpenTag(xml, tag, prefix);
  378. if (value && *value)
  379. {
  380. if (flags != ENCODE_NONE)
  381. encodeXML(value, xml, flags, len, utf8);
  382. else
  383. xml.append(value);
  384. }
  385. return appendXMLCloseTag(xml, tag, prefix);
  386. }
  387. inline StringBuffer &delimitJSON(StringBuffer &s, bool addNewline=false, bool escapeNewline=false)
  388. {
  389. if (s.length() && !strchr("{ [:,n\n", s.charAt(s.length()-1))) //'n' or '\n' indicates already formatted with optionally escaped newline
  390. {
  391. s.append(",");
  392. if (addNewline)
  393. s.append(escapeNewline ? "\\n" : "\n");
  394. else
  395. s.append(' ');
  396. }
  397. return s;
  398. }
  399. jlib_decl StringBuffer &encodeJSON(StringBuffer &s, const char *value);
  400. jlib_decl StringBuffer &encodeJSON(StringBuffer &s, unsigned len, const char *value);
  401. jlib_decl StringBuffer &appendJSONName(StringBuffer &s, const char *name);
  402. jlib_decl StringBuffer &appendfJSONName(StringBuffer &s, const char *format, ...) __attribute__((format(printf, 2, 3)));
  403. jlib_decl StringBuffer &appendJSONDataValue(StringBuffer& s, const char *name, unsigned len, const void *_value);
  404. jlib_decl StringBuffer &appendJSONRealValue(StringBuffer& s, const char *name, double value);
  405. inline StringBuffer &appendJSONNameOrDelimit(StringBuffer &s, const char *name)
  406. {
  407. if (name && *name)
  408. return appendJSONName(s, name);
  409. return delimitJSON(s);
  410. }
  411. inline StringBuffer &appendJSONStringValue(StringBuffer& s, const char *name, unsigned len, const char *value, bool encode, bool quoted=true)
  412. {
  413. appendJSONNameOrDelimit(s, name);
  414. if (!value)
  415. return s.append("null");
  416. if (quoted)
  417. s.append('"');
  418. if (encode)
  419. encodeJSON(s, len, value);
  420. else
  421. s.append(len, value);
  422. if (quoted)
  423. s.append('"');
  424. return s;
  425. }
  426. inline StringBuffer &appendJSONStringValue(StringBuffer& s, const char *name, const char *value, bool encode, bool quoted=true)
  427. {
  428. return appendJSONStringValue(s, name, (size32_t)(value ? strlen(value) : 0), value, encode, quoted);
  429. }
  430. template <typename type>
  431. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, type value)
  432. {
  433. appendJSONNameOrDelimit(s, name);
  434. return s.append(value);
  435. }
  436. //specialization
  437. template <>
  438. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, bool value)
  439. {
  440. appendJSONNameOrDelimit(s, name);
  441. return s.append((value) ? "true" : "false");
  442. }
  443. template <>
  444. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, const char *value)
  445. {
  446. return appendJSONStringValue(s, name, value, true);
  447. }
  448. template <>
  449. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, long value)
  450. {
  451. appendJSONNameOrDelimit(s, name);
  452. return s.appendlong(value);
  453. }
  454. template <>
  455. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, double value)
  456. {
  457. return ::appendJSONRealValue(s, name, value);
  458. }
  459. template <>
  460. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, float value)
  461. {
  462. return ::appendJSONRealValue(s, name, value);
  463. }
  464. template <>
  465. inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, unsigned long value)
  466. {
  467. appendJSONNameOrDelimit(s, name);
  468. return s.appendulong(value);
  469. }
  470. template <typename TValue>
  471. inline StringBuffer& operator << (StringBuffer& s, const TValue& value)
  472. {
  473. return s.append(value);
  474. }
  475. extern jlib_decl void decodeCppEscapeSequence(StringBuffer & out, const char * in, bool errorIfInvalid);
  476. extern jlib_decl bool strToBool(const char * text);
  477. inline const char *boolToStr(bool b) { return b ? "true" : "false"; }
  478. extern jlib_decl bool strToBool(size_t len, const char * text);
  479. extern jlib_decl bool clipStrToBool(size_t len, const char * text);
  480. extern jlib_decl bool clipStrToBool(const char * text);
  481. extern jlib_decl StringBuffer & ncnameEscape(char const * in, StringBuffer & out);
  482. extern jlib_decl StringBuffer & ncnameUnescape(char const * in, StringBuffer & out);
  483. extern jlib_decl StringBuffer & elideString(StringBuffer & s, unsigned maxLength);
  484. extern jlib_decl bool startsWith(const char* src, const char* dst);
  485. extern jlib_decl bool endsWith(const char* src, const char* dst);
  486. extern jlib_decl bool startsWithIgnoreCase(const char* src, const char* dst);
  487. extern jlib_decl bool endsWithIgnoreCase(const char* src, const char* dst);
  488. inline bool strieq(const char* s, const char* t) { return stricmp(s,t)==0; }
  489. inline bool streq(const char* s, const char* t) { return strcmp(s,t)==0; }
  490. inline bool strsame(const char* s, const char* t) { return (s == t) || (s && t && strcmp(s,t)==0); } // also allow nulls
  491. inline bool isEmptyString(const char *text) { return !text||!*text; }
  492. inline bool hasPrefix(const char * text, const char * prefix, bool caseSensitive)
  493. {
  494. if (caseSensitive)
  495. return strncmp(text, prefix, strlen(prefix)) == 0;
  496. else
  497. return strnicmp(text, prefix, strlen(prefix)) == 0;
  498. }
  499. // Search for a string in a null terminated array of const char * strings
  500. extern jlib_decl unsigned matchString(const char * search, const char * const * strings);
  501. extern jlib_decl char *j_strtok_r(char *str, const char *delim, char **saveptr);
  502. extern jlib_decl int j_memicmp (const void *s1, const void *s2, size32_t len);
  503. extern jlib_decl size32_t memcount(size32_t len, const char * str, char search);
  504. extern jlib_decl const char * nullText(const char * text);
  505. #endif