kstring.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* The MIT License
  2. Copyright (c) by Attractive Chaos <attractor@live.co.uk>
  3. Permission is hereby granted, free of charge, to any person obtaining
  4. a copy of this software and associated documentation files (the
  5. "Software"), to deal in the Software without restriction, including
  6. without limitation the rights to use, copy, modify, merge, publish,
  7. distribute, sublicense, and/or sell copies of the Software, and to
  8. permit persons to whom the Software is furnished to do so, subject to
  9. the following conditions:
  10. The above copyright notice and this permission notice shall be
  11. included in all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  16. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  17. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  18. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. SOFTWARE.
  20. */
  21. #ifndef KSTRING_H
  22. #define KSTRING_H
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include <stdint.h>
  27. #include <stdio.h>
  28. #ifndef kroundup32
  29. #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
  30. #endif
  31. #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
  32. #define KS_ATTR_PRINTF(fmt, arg) __attribute__((__format__ (__printf__, fmt, arg)))
  33. #else
  34. #define KS_ATTR_PRINTF(fmt, arg)
  35. #endif
  36. /* kstring_t is a simple non-opaque type whose fields are likely to be
  37. * used directly by user code (but see also ks_str() and ks_len() below).
  38. * A kstring_t object is initialised by either of
  39. * kstring_t str = { 0, 0, NULL };
  40. * kstring_t str; ...; str.l = str.m = 0; str.s = NULL;
  41. * and either ownership of the underlying buffer should be given away before
  42. * the object disappears (i.e., the str.s pointer copied and something else
  43. * responsible for freeing it), or the kstring_t should be destroyed with
  44. * free(str.s); */
  45. #ifndef KSTRING_T
  46. #define KSTRING_T kstring_t
  47. typedef struct __kstring_t {
  48. size_t l, m;
  49. char *s;
  50. } kstring_t;
  51. #endif
  52. typedef struct {
  53. uint64_t tab[4];
  54. int sep, finished;
  55. const char *p; // end of the current token
  56. } ks_tokaux_t;
  57. #ifdef __cplusplus
  58. extern "C" {
  59. #endif
  60. int kvsprintf(kstring_t *s, const char *fmt, va_list ap) KS_ATTR_PRINTF(2,0);
  61. int ksprintf(kstring_t *s, const char *fmt, ...) KS_ATTR_PRINTF(2,3);
  62. int ksplit_core(char *s, int delimiter, int *_max, int **_offsets);
  63. char *kstrstr(const char *str, const char *pat, int **_prep);
  64. char *kstrnstr(const char *str, const char *pat, int n, int **_prep);
  65. void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep);
  66. /* kstrtok() is similar to strtok_r() except that str is not
  67. * modified and both str and sep can be NULL. For efficiency, it is
  68. * actually recommended to set both to NULL in the subsequent calls
  69. * if sep is not changed. */
  70. char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux);
  71. #ifdef __cplusplus
  72. }
  73. #endif
  74. static inline int ks_resize(kstring_t *s, size_t size)
  75. {
  76. if (s->m < size) {
  77. char *tmp;
  78. s->m = size;
  79. kroundup32(s->m);
  80. if ((tmp = (char*)realloc(s->s, s->m)))
  81. s->s = tmp;
  82. else
  83. return -1;
  84. }
  85. return 0;
  86. }
  87. static inline char *ks_str(kstring_t *s)
  88. {
  89. return s->s;
  90. }
  91. static inline size_t ks_len(kstring_t *s)
  92. {
  93. return s->l;
  94. }
  95. static inline int kputsn(const char *p, int l, kstring_t *s)
  96. {
  97. if (s->l + l + 1 >= s->m) {
  98. char *tmp;
  99. s->m = s->l + l + 2;
  100. kroundup32(s->m);
  101. if ((tmp = (char*)realloc(s->s, s->m)))
  102. s->s = tmp;
  103. else
  104. return EOF;
  105. }
  106. memcpy(s->s + s->l, p, l);
  107. s->l += l;
  108. s->s[s->l] = 0;
  109. return l;
  110. }
  111. static inline int kputs(const char *p, kstring_t *s)
  112. {
  113. return kputsn(p, strlen(p), s);
  114. }
  115. static inline int kputc(int c, kstring_t *s)
  116. {
  117. if (s->l + 1 >= s->m) {
  118. char *tmp;
  119. s->m = s->l + 2;
  120. kroundup32(s->m);
  121. if ((tmp = (char*)realloc(s->s, s->m)))
  122. s->s = tmp;
  123. else
  124. return EOF;
  125. }
  126. s->s[s->l++] = c;
  127. s->s[s->l] = 0;
  128. return c;
  129. }
  130. static inline int kputc_(int c, kstring_t *s)
  131. {
  132. if (s->l + 1 > s->m) {
  133. char *tmp;
  134. s->m = s->l + 1;
  135. kroundup32(s->m);
  136. if ((tmp = (char*)realloc(s->s, s->m)))
  137. s->s = tmp;
  138. else
  139. return EOF;
  140. }
  141. s->s[s->l++] = c;
  142. return 1;
  143. }
  144. static inline int kputsn_(const void *p, int l, kstring_t *s)
  145. {
  146. if (s->l + l > s->m) {
  147. char *tmp;
  148. s->m = s->l + l;
  149. kroundup32(s->m);
  150. if ((tmp = (char*)realloc(s->s, s->m)))
  151. s->s = tmp;
  152. else
  153. return EOF;
  154. }
  155. memcpy(s->s + s->l, p, l);
  156. s->l += l;
  157. return l;
  158. }
  159. static inline int kputw(int c, kstring_t *s)
  160. {
  161. char buf[16];
  162. int i, l = 0;
  163. unsigned int x = c;
  164. if (c < 0) x = -x;
  165. do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0);
  166. if (c < 0) buf[l++] = '-';
  167. if (s->l + l + 1 >= s->m) {
  168. char *tmp;
  169. s->m = s->l + l + 2;
  170. kroundup32(s->m);
  171. if ((tmp = (char*)realloc(s->s, s->m)))
  172. s->s = tmp;
  173. else
  174. return EOF;
  175. }
  176. for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
  177. s->s[s->l] = 0;
  178. return 0;
  179. }
  180. static inline int kputuw(unsigned c, kstring_t *s)
  181. {
  182. char buf[16];
  183. int l, i;
  184. unsigned x;
  185. if (c == 0) return kputc('0', s);
  186. for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0';
  187. if (s->l + l + 1 >= s->m) {
  188. char *tmp;
  189. s->m = s->l + l + 2;
  190. kroundup32(s->m);
  191. if ((tmp = (char*)realloc(s->s, s->m)))
  192. s->s = tmp;
  193. else
  194. return EOF;
  195. }
  196. for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
  197. s->s[s->l] = 0;
  198. return 0;
  199. }
  200. static inline int kputl(long c, kstring_t *s)
  201. {
  202. char buf[32];
  203. int i, l = 0;
  204. unsigned long x = c;
  205. if (c < 0) x = -x;
  206. do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0);
  207. if (c < 0) buf[l++] = '-';
  208. if (s->l + l + 1 >= s->m) {
  209. char *tmp;
  210. s->m = s->l + l + 2;
  211. kroundup32(s->m);
  212. if ((tmp = (char*)realloc(s->s, s->m)))
  213. s->s = tmp;
  214. else
  215. return EOF;
  216. }
  217. for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
  218. s->s[s->l] = 0;
  219. return 0;
  220. }
  221. /*
  222. * Returns 's' split by delimiter, with *n being the number of components;
  223. * NULL on failue.
  224. */
  225. static inline int *ksplit(kstring_t *s, int delimiter, int *n)
  226. {
  227. int max = 0, *offsets = 0;
  228. *n = ksplit_core(s->s, delimiter, &max, &offsets);
  229. return offsets;
  230. }
  231. #endif