da_string.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * Copyright [2021] JD.com, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "da_string.h"
  17. #include <stdlib.h>
  18. #include <string.h>
  19. /*
  20. * String (struct string) is a sequence of unsigned char objects terminated
  21. * by the null character '\0'. The length of the string is pre-computed and
  22. * made available explicitly as an additional field. This means that we don't
  23. * have to walk the entire character sequence until the null terminating
  24. * character everytime that the length of the String is requested
  25. *
  26. * The only way to create a String is to initialize it using, string_init()
  27. * and duplicate an existing String - string_duplicate() or copy an existing
  28. * raw sequence of character bytes - string_copy(). Such String's must be
  29. * freed using string_deinit()
  30. *
  31. * We can also create String as reference to raw string - string_set_raw()
  32. * or to text string - string_set_text() or string(). Such String don't have
  33. * to be freed.
  34. */
  35. void string_init(struct string *str)
  36. {
  37. str->len = 0;
  38. str->data = NULL;
  39. }
  40. void string_deinit(struct string *str)
  41. {
  42. ASSERT((str->len == 0 && str->data == NULL) ||
  43. (str->len != 0 && str->data != NULL));
  44. if (str->data != NULL) {
  45. free(str->data);
  46. string_init(str);
  47. }
  48. }
  49. bool string_empty(const struct string *str)
  50. {
  51. ASSERT((str->len == 0 && str->data == NULL) ||
  52. (str->len != 0 && str->data != NULL));
  53. return str->len == 0 ? true : false;
  54. }
  55. int string_duplicate(struct string *dst, const struct string *src)
  56. {
  57. ASSERT(dst->len == 0 && dst->data == NULL);
  58. ASSERT(src->len != 0 && src->data != NULL);
  59. dst->data = da_strndup(src->data, src->len + 1);
  60. if (dst->data == NULL) {
  61. return -1;
  62. }
  63. dst->len = src->len;
  64. dst->data[dst->len] = '\0';
  65. return 0;
  66. }
  67. bool string_lower(struct string *str)
  68. {
  69. int i = 0;
  70. if (string_empty(str))
  71. return false;
  72. for (i = 0; i < str->len; i++) {
  73. str->data[i] = lower(str->data[i]);
  74. }
  75. return true;
  76. }
  77. bool string_upper(struct string *str)
  78. {
  79. int i = 0;
  80. if (string_empty(str))
  81. return false;
  82. for (i = 0; i < str->len; i++) {
  83. str->data[i] = upper(str->data[i]);
  84. }
  85. return true;
  86. }
  87. int string_copy(struct string *dst, const uint8_t *src, uint32_t srclen)
  88. {
  89. ASSERT(dst->len == 0 && dst->data == NULL);
  90. ASSERT(src != NULL && srclen != 0);
  91. dst->data = da_strndup(src, srclen + 1);
  92. if (dst->data == NULL) {
  93. return -1;
  94. }
  95. dst->len = srclen;
  96. dst->data[dst->len] = '\0';
  97. return 0;
  98. }
  99. int string_compare(const struct string *s1, const struct string *s2)
  100. {
  101. if (s1->len != s2->len) {
  102. return s1->len > s2->len ? 1 : -1;
  103. }
  104. return da_strncmp(s1->data, s2->data, s1->len);
  105. }
  106. int string_compare_nonsentive(const struct string *s1, const struct string *s2)
  107. {
  108. struct string tmp1, tmp2;
  109. if (s1->len != s2->len) {
  110. return s1->len > s2->len ? 1 : -1;
  111. }
  112. string_copy(&tmp1, s1, s1->len);
  113. string_copy(&tmp2, s2, s2->len);
  114. string_upper(&tmp1);
  115. string_upper(&tmp2);
  116. return da_strncmp(&tmp1.data, &tmp2.data, &tmp1.len);
  117. }
  118. static const char *_safe_check_longlong(const char *fmt, int32_t *have_longlong)
  119. {
  120. *have_longlong = false;
  121. if (*fmt == 'l') {
  122. fmt++;
  123. if (*fmt != 'l') {
  124. *have_longlong = (sizeof(long) == sizeof(int64_t));
  125. } else {
  126. fmt++;
  127. *have_longlong = true;
  128. }
  129. }
  130. return fmt;
  131. }
  132. static char *_safe_utoa(int _base, uint64_t val, char *buf)
  133. {
  134. char hex[] = "0123456789abcdef";
  135. uint32_t base = (uint32_t)_base;
  136. *buf-- = 0;
  137. do {
  138. *buf-- = hex[val % base];
  139. } while ((val /= base) != 0);
  140. return buf + 1;
  141. }
  142. static char *_safe_itoa(int base, int64_t val, char *buf)
  143. {
  144. char hex[] = "0123456789abcdef";
  145. char *orig_buf = buf;
  146. const int32_t is_neg = (val < 0);
  147. *buf-- = 0;
  148. if (is_neg) {
  149. val = -val;
  150. }
  151. if (is_neg && base == 16) {
  152. int ix;
  153. val -= 1;
  154. for (ix = 0; ix < 16; ++ix)
  155. buf[-ix] = '0';
  156. }
  157. do {
  158. *buf-- = hex[val % base];
  159. } while ((val /= base) != 0);
  160. if (is_neg && base == 10) {
  161. *buf-- = '-';
  162. }
  163. if (is_neg && base == 16) {
  164. int ix;
  165. buf = orig_buf - 1;
  166. for (ix = 0; ix < 16; ++ix, --buf) {
  167. /* *INDENT-OFF* */
  168. switch (*buf) {
  169. case '0':
  170. *buf = 'f';
  171. break;
  172. case '1':
  173. *buf = 'e';
  174. break;
  175. case '2':
  176. *buf = 'd';
  177. break;
  178. case '3':
  179. *buf = 'c';
  180. break;
  181. case '4':
  182. *buf = 'b';
  183. break;
  184. case '5':
  185. *buf = 'a';
  186. break;
  187. case '6':
  188. *buf = '9';
  189. break;
  190. case '7':
  191. *buf = '8';
  192. break;
  193. case '8':
  194. *buf = '7';
  195. break;
  196. case '9':
  197. *buf = '6';
  198. break;
  199. case 'a':
  200. *buf = '5';
  201. break;
  202. case 'b':
  203. *buf = '4';
  204. break;
  205. case 'c':
  206. *buf = '3';
  207. break;
  208. case 'd':
  209. *buf = '2';
  210. break;
  211. case 'e':
  212. *buf = '1';
  213. break;
  214. case 'f':
  215. *buf = '0';
  216. break;
  217. }
  218. /* *INDENT-ON* */
  219. }
  220. }
  221. return buf + 1;
  222. }
  223. int _safe_vsnprintf(char *to, size_t size, const char *format, va_list ap)
  224. {
  225. char *start = to;
  226. char *end = start + size - 1;
  227. for (; *format; ++format) {
  228. int32_t have_longlong = false;
  229. if (*format != '%') {
  230. if (to == end) { /* end of buffer */
  231. break;
  232. }
  233. *to++ = *format; /* copy ordinary char */
  234. continue;
  235. }
  236. ++format; /* skip '%' */
  237. format = _safe_check_longlong(format, &have_longlong);
  238. switch (*format) {
  239. case 'd':
  240. case 'i':
  241. case 'u':
  242. case 'x':
  243. case 'p': {
  244. int64_t ival = 0;
  245. uint64_t uval = 0;
  246. if (*format == 'p')
  247. have_longlong =
  248. (sizeof(void *) == sizeof(uint64_t));
  249. if (have_longlong) {
  250. if (*format == 'u') {
  251. uval = va_arg(ap, uint64_t);
  252. } else {
  253. ival = va_arg(ap, int64_t);
  254. }
  255. } else {
  256. if (*format == 'u') {
  257. uval = va_arg(ap, uint32_t);
  258. } else {
  259. ival = va_arg(ap, int32_t);
  260. }
  261. }
  262. {
  263. char buff[22];
  264. const int base =
  265. (*format == 'x' || *format == 'p') ?
  266. 16 :
  267. 10;
  268. /* *INDENT-OFF* */
  269. char *val_as_str =
  270. (*format == 'u') ?
  271. _safe_utoa(base, uval,
  272. &buff[sizeof(buff) -
  273. 1]) :
  274. _safe_itoa(
  275. base, ival,
  276. &buff[sizeof(buff) - 1]);
  277. /* *INDENT-ON* */
  278. /* Strip off "ffffffff" if we have 'x' format without 'll' */
  279. if (*format == 'x' && !have_longlong &&
  280. ival < 0) {
  281. val_as_str += 8;
  282. }
  283. while (*val_as_str && to < end) {
  284. *to++ = *val_as_str++;
  285. }
  286. continue;
  287. }
  288. }
  289. case 's': {
  290. const char *val = va_arg(ap, char *);
  291. if (!val) {
  292. val = "(null)";
  293. }
  294. while (*val && to < end) {
  295. *to++ = *val++;
  296. }
  297. continue;
  298. }
  299. }
  300. }
  301. *to = 0;
  302. return (int)(to - start);
  303. }
  304. int _safe_snprintf(char *to, size_t n, const char *fmt, ...)
  305. {
  306. int result;
  307. va_list args;
  308. va_start(args, fmt);
  309. result = _safe_vsnprintf(to, n, fmt, args);
  310. va_end(args);
  311. return result;
  312. }