slice.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "src/core/lib/slice/slice_internal.h"
  19. #include <grpc/slice.h>
  20. #include <grpc/support/alloc.h>
  21. #include <grpc/support/log.h>
  22. #include <string.h>
  23. #include "src/core/lib/iomgr/exec_ctx.h"
  24. char *grpc_slice_to_c_string(grpc_slice slice) {
  25. char *out = gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1);
  26. memcpy(out, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));
  27. out[GRPC_SLICE_LENGTH(slice)] = 0;
  28. return out;
  29. }
  30. grpc_slice grpc_empty_slice(void) {
  31. grpc_slice out;
  32. out.refcount = NULL;
  33. out.data.inlined.length = 0;
  34. return out;
  35. }
  36. grpc_slice grpc_slice_copy(grpc_slice s) {
  37. grpc_slice out = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(s));
  38. memcpy(GRPC_SLICE_START_PTR(out), GRPC_SLICE_START_PTR(s),
  39. GRPC_SLICE_LENGTH(s));
  40. return out;
  41. }
  42. grpc_slice grpc_slice_ref_internal(grpc_slice slice) {
  43. if (slice.refcount) {
  44. slice.refcount->vtable->ref(slice.refcount);
  45. }
  46. return slice;
  47. }
  48. void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
  49. if (slice.refcount) {
  50. slice.refcount->vtable->unref(exec_ctx, slice.refcount);
  51. }
  52. }
  53. /* Public API */
  54. grpc_slice grpc_slice_ref(grpc_slice slice) {
  55. return grpc_slice_ref_internal(slice);
  56. }
  57. /* Public API */
  58. void grpc_slice_unref(grpc_slice slice) {
  59. grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  60. grpc_slice_unref_internal(&exec_ctx, slice);
  61. grpc_exec_ctx_finish(&exec_ctx);
  62. }
  63. /* grpc_slice_from_static_string support structure - a refcount that does
  64. nothing */
  65. static void noop_ref(void *unused) {}
  66. static void noop_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
  67. static const grpc_slice_refcount_vtable noop_refcount_vtable = {
  68. noop_ref, noop_unref, grpc_slice_default_eq_impl,
  69. grpc_slice_default_hash_impl};
  70. static grpc_slice_refcount noop_refcount = {&noop_refcount_vtable,
  71. &noop_refcount};
  72. grpc_slice grpc_slice_from_static_buffer(const void *s, size_t len) {
  73. grpc_slice slice;
  74. slice.refcount = &noop_refcount;
  75. slice.data.refcounted.bytes = (uint8_t *)s;
  76. slice.data.refcounted.length = len;
  77. return slice;
  78. }
  79. grpc_slice grpc_slice_from_static_string(const char *s) {
  80. return grpc_slice_from_static_buffer(s, strlen(s));
  81. }
  82. /* grpc_slice_new support structures - we create a refcount object extended
  83. with the user provided data pointer & destroy function */
  84. typedef struct new_slice_refcount {
  85. grpc_slice_refcount rc;
  86. gpr_refcount refs;
  87. void (*user_destroy)(void *);
  88. void *user_data;
  89. } new_slice_refcount;
  90. static void new_slice_ref(void *p) {
  91. new_slice_refcount *r = p;
  92. gpr_ref(&r->refs);
  93. }
  94. static void new_slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
  95. new_slice_refcount *r = p;
  96. if (gpr_unref(&r->refs)) {
  97. r->user_destroy(r->user_data);
  98. gpr_free(r);
  99. }
  100. }
  101. static const grpc_slice_refcount_vtable new_slice_vtable = {
  102. new_slice_ref, new_slice_unref, grpc_slice_default_eq_impl,
  103. grpc_slice_default_hash_impl};
  104. grpc_slice grpc_slice_new_with_user_data(void *p, size_t len,
  105. void (*destroy)(void *),
  106. void *user_data) {
  107. grpc_slice slice;
  108. new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
  109. gpr_ref_init(&rc->refs, 1);
  110. rc->rc.vtable = &new_slice_vtable;
  111. rc->rc.sub_refcount = &rc->rc;
  112. rc->user_destroy = destroy;
  113. rc->user_data = user_data;
  114. slice.refcount = &rc->rc;
  115. slice.data.refcounted.bytes = p;
  116. slice.data.refcounted.length = len;
  117. return slice;
  118. }
  119. grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *)) {
  120. /* Pass "p" to *destroy when the slice is no longer needed. */
  121. return grpc_slice_new_with_user_data(p, len, destroy, p);
  122. }
  123. /* grpc_slice_new_with_len support structures - we create a refcount object
  124. extended with the user provided data pointer & destroy function */
  125. typedef struct new_with_len_slice_refcount {
  126. grpc_slice_refcount rc;
  127. gpr_refcount refs;
  128. void *user_data;
  129. size_t user_length;
  130. void (*user_destroy)(void *, size_t);
  131. } new_with_len_slice_refcount;
  132. static void new_with_len_ref(void *p) {
  133. new_with_len_slice_refcount *r = p;
  134. gpr_ref(&r->refs);
  135. }
  136. static void new_with_len_unref(grpc_exec_ctx *exec_ctx, void *p) {
  137. new_with_len_slice_refcount *r = p;
  138. if (gpr_unref(&r->refs)) {
  139. r->user_destroy(r->user_data, r->user_length);
  140. gpr_free(r);
  141. }
  142. }
  143. static const grpc_slice_refcount_vtable new_with_len_vtable = {
  144. new_with_len_ref, new_with_len_unref, grpc_slice_default_eq_impl,
  145. grpc_slice_default_hash_impl};
  146. grpc_slice grpc_slice_new_with_len(void *p, size_t len,
  147. void (*destroy)(void *, size_t)) {
  148. grpc_slice slice;
  149. new_with_len_slice_refcount *rc =
  150. gpr_malloc(sizeof(new_with_len_slice_refcount));
  151. gpr_ref_init(&rc->refs, 1);
  152. rc->rc.vtable = &new_with_len_vtable;
  153. rc->rc.sub_refcount = &rc->rc;
  154. rc->user_destroy = destroy;
  155. rc->user_data = p;
  156. rc->user_length = len;
  157. slice.refcount = &rc->rc;
  158. slice.data.refcounted.bytes = p;
  159. slice.data.refcounted.length = len;
  160. return slice;
  161. }
  162. grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t length) {
  163. if (length == 0) return grpc_empty_slice();
  164. grpc_slice slice = GRPC_SLICE_MALLOC(length);
  165. memcpy(GRPC_SLICE_START_PTR(slice), source, length);
  166. return slice;
  167. }
  168. grpc_slice grpc_slice_from_copied_string(const char *source) {
  169. return grpc_slice_from_copied_buffer(source, strlen(source));
  170. }
  171. typedef struct {
  172. grpc_slice_refcount base;
  173. gpr_refcount refs;
  174. } malloc_refcount;
  175. static void malloc_ref(void *p) {
  176. malloc_refcount *r = p;
  177. gpr_ref(&r->refs);
  178. }
  179. static void malloc_unref(grpc_exec_ctx *exec_ctx, void *p) {
  180. malloc_refcount *r = p;
  181. if (gpr_unref(&r->refs)) {
  182. gpr_free(r);
  183. }
  184. }
  185. static const grpc_slice_refcount_vtable malloc_vtable = {
  186. malloc_ref, malloc_unref, grpc_slice_default_eq_impl,
  187. grpc_slice_default_hash_impl};
  188. grpc_slice grpc_slice_malloc_large(size_t length) {
  189. grpc_slice slice;
  190. /* Memory layout used by the slice created here:
  191. +-----------+----------------------------------------------------------+
  192. | refcount | bytes |
  193. +-----------+----------------------------------------------------------+
  194. refcount is a malloc_refcount
  195. bytes is an array of bytes of the requested length
  196. Both parts are placed in the same allocation returned from gpr_malloc */
  197. malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length);
  198. /* Initial refcount on rc is 1 - and it's up to the caller to release
  199. this reference. */
  200. gpr_ref_init(&rc->refs, 1);
  201. rc->base.vtable = &malloc_vtable;
  202. rc->base.sub_refcount = &rc->base;
  203. /* Build up the slice to be returned. */
  204. /* The slices refcount points back to the allocated block. */
  205. slice.refcount = &rc->base;
  206. /* The data bytes are placed immediately after the refcount struct */
  207. slice.data.refcounted.bytes = (uint8_t *)(rc + 1);
  208. /* And the length of the block is set to the requested length */
  209. slice.data.refcounted.length = length;
  210. return slice;
  211. }
  212. grpc_slice grpc_slice_malloc(size_t length) {
  213. grpc_slice slice;
  214. if (length > sizeof(slice.data.inlined.bytes)) {
  215. return grpc_slice_malloc_large(length);
  216. } else {
  217. /* small slice: just inline the data */
  218. slice.refcount = NULL;
  219. slice.data.inlined.length = (uint8_t)length;
  220. }
  221. return slice;
  222. }
  223. grpc_slice grpc_slice_sub_no_ref(grpc_slice source, size_t begin, size_t end) {
  224. grpc_slice subset;
  225. GPR_ASSERT(end >= begin);
  226. if (source.refcount) {
  227. /* Enforce preconditions */
  228. GPR_ASSERT(source.data.refcounted.length >= end);
  229. /* Build the result */
  230. subset.refcount = source.refcount->sub_refcount;
  231. /* Point into the source array */
  232. subset.data.refcounted.bytes = source.data.refcounted.bytes + begin;
  233. subset.data.refcounted.length = end - begin;
  234. } else {
  235. /* Enforce preconditions */
  236. GPR_ASSERT(source.data.inlined.length >= end);
  237. subset.refcount = NULL;
  238. subset.data.inlined.length = (uint8_t)(end - begin);
  239. memcpy(subset.data.inlined.bytes, source.data.inlined.bytes + begin,
  240. end - begin);
  241. }
  242. return subset;
  243. }
  244. grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) {
  245. grpc_slice subset;
  246. if (end - begin <= sizeof(subset.data.inlined.bytes)) {
  247. subset.refcount = NULL;
  248. subset.data.inlined.length = (uint8_t)(end - begin);
  249. memcpy(subset.data.inlined.bytes, GRPC_SLICE_START_PTR(source) + begin,
  250. end - begin);
  251. } else {
  252. subset = grpc_slice_sub_no_ref(source, begin, end);
  253. /* Bump the refcount */
  254. subset.refcount->vtable->ref(subset.refcount);
  255. }
  256. return subset;
  257. }
  258. grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *source, size_t split,
  259. grpc_slice_ref_whom ref_whom) {
  260. grpc_slice tail;
  261. if (source->refcount == NULL) {
  262. /* inlined data, copy it out */
  263. GPR_ASSERT(source->data.inlined.length >= split);
  264. tail.refcount = NULL;
  265. tail.data.inlined.length = (uint8_t)(source->data.inlined.length - split);
  266. memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split,
  267. tail.data.inlined.length);
  268. source->data.inlined.length = (uint8_t)split;
  269. } else {
  270. size_t tail_length = source->data.refcounted.length - split;
  271. GPR_ASSERT(source->data.refcounted.length >= split);
  272. if (tail_length < sizeof(tail.data.inlined.bytes) &&
  273. ref_whom != GRPC_SLICE_REF_TAIL) {
  274. /* Copy out the bytes - it'll be cheaper than refcounting */
  275. tail.refcount = NULL;
  276. tail.data.inlined.length = (uint8_t)tail_length;
  277. memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split,
  278. tail_length);
  279. source->refcount = source->refcount->sub_refcount;
  280. } else {
  281. /* Build the result */
  282. switch (ref_whom) {
  283. case GRPC_SLICE_REF_TAIL:
  284. tail.refcount = source->refcount->sub_refcount;
  285. source->refcount = &noop_refcount;
  286. break;
  287. case GRPC_SLICE_REF_HEAD:
  288. tail.refcount = &noop_refcount;
  289. source->refcount = source->refcount->sub_refcount;
  290. break;
  291. case GRPC_SLICE_REF_BOTH:
  292. tail.refcount = source->refcount->sub_refcount;
  293. source->refcount = source->refcount->sub_refcount;
  294. /* Bump the refcount */
  295. tail.refcount->vtable->ref(tail.refcount);
  296. break;
  297. }
  298. /* Point into the source array */
  299. tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
  300. tail.data.refcounted.length = tail_length;
  301. }
  302. source->data.refcounted.length = split;
  303. }
  304. return tail;
  305. }
  306. grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
  307. return grpc_slice_split_tail_maybe_ref(source, split, GRPC_SLICE_REF_BOTH);
  308. }
  309. grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
  310. grpc_slice head;
  311. if (source->refcount == NULL) {
  312. GPR_ASSERT(source->data.inlined.length >= split);
  313. head.refcount = NULL;
  314. head.data.inlined.length = (uint8_t)split;
  315. memcpy(head.data.inlined.bytes, source->data.inlined.bytes, split);
  316. source->data.inlined.length =
  317. (uint8_t)(source->data.inlined.length - split);
  318. memmove(source->data.inlined.bytes, source->data.inlined.bytes + split,
  319. source->data.inlined.length);
  320. } else if (split < sizeof(head.data.inlined.bytes)) {
  321. GPR_ASSERT(source->data.refcounted.length >= split);
  322. head.refcount = NULL;
  323. head.data.inlined.length = (uint8_t)split;
  324. memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split);
  325. source->refcount = source->refcount->sub_refcount;
  326. source->data.refcounted.bytes += split;
  327. source->data.refcounted.length -= split;
  328. } else {
  329. GPR_ASSERT(source->data.refcounted.length >= split);
  330. /* Build the result */
  331. head.refcount = source->refcount->sub_refcount;
  332. /* Bump the refcount */
  333. head.refcount->vtable->ref(head.refcount);
  334. /* Point into the source array */
  335. head.data.refcounted.bytes = source->data.refcounted.bytes;
  336. head.data.refcounted.length = split;
  337. source->refcount = source->refcount->sub_refcount;
  338. source->data.refcounted.bytes += split;
  339. source->data.refcounted.length -= split;
  340. }
  341. return head;
  342. }
  343. int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b) {
  344. if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false;
  345. if (GRPC_SLICE_LENGTH(a) == 0) return true;
  346. return 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
  347. GRPC_SLICE_LENGTH(a));
  348. }
  349. int grpc_slice_eq(grpc_slice a, grpc_slice b) {
  350. if (a.refcount && b.refcount && a.refcount->vtable == b.refcount->vtable) {
  351. return a.refcount->vtable->eq(a, b);
  352. }
  353. return grpc_slice_default_eq_impl(a, b);
  354. }
  355. int grpc_slice_cmp(grpc_slice a, grpc_slice b) {
  356. int d = (int)(GRPC_SLICE_LENGTH(a) - GRPC_SLICE_LENGTH(b));
  357. if (d != 0) return d;
  358. return memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
  359. GRPC_SLICE_LENGTH(a));
  360. }
  361. int grpc_slice_str_cmp(grpc_slice a, const char *b) {
  362. size_t b_length = strlen(b);
  363. int d = (int)(GRPC_SLICE_LENGTH(a) - b_length);
  364. if (d != 0) return d;
  365. return memcmp(GRPC_SLICE_START_PTR(a), b, b_length);
  366. }
  367. int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b) {
  368. if (a.refcount == NULL || b.refcount == NULL) {
  369. return grpc_slice_eq(a, b);
  370. }
  371. return a.data.refcounted.length == b.data.refcounted.length &&
  372. a.data.refcounted.bytes == b.data.refcounted.bytes;
  373. }
  374. int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t len) {
  375. if (GRPC_SLICE_LENGTH(a) < len) return 0;
  376. return 0 == memcmp(GRPC_SLICE_START_PTR(a), b, len);
  377. }
  378. int grpc_slice_rchr(grpc_slice s, char c) {
  379. const char *b = (const char *)GRPC_SLICE_START_PTR(s);
  380. int i;
  381. for (i = (int)GRPC_SLICE_LENGTH(s) - 1; i != -1 && b[i] != c; i--)
  382. ;
  383. return i;
  384. }
  385. int grpc_slice_chr(grpc_slice s, char c) {
  386. const char *b = (const char *)GRPC_SLICE_START_PTR(s);
  387. const char *p = memchr(b, c, GRPC_SLICE_LENGTH(s));
  388. return p == NULL ? -1 : (int)(p - b);
  389. }
  390. int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) {
  391. size_t haystack_len = GRPC_SLICE_LENGTH(haystack);
  392. const uint8_t *haystack_bytes = GRPC_SLICE_START_PTR(haystack);
  393. size_t needle_len = GRPC_SLICE_LENGTH(needle);
  394. const uint8_t *needle_bytes = GRPC_SLICE_START_PTR(needle);
  395. if (haystack_len == 0 || needle_len == 0) return -1;
  396. if (haystack_len < needle_len) return -1;
  397. if (haystack_len == needle_len)
  398. return grpc_slice_eq(haystack, needle) ? 0 : -1;
  399. if (needle_len == 1) return grpc_slice_chr(haystack, (char)*needle_bytes);
  400. const uint8_t *last = haystack_bytes + haystack_len - needle_len;
  401. for (const uint8_t *cur = haystack_bytes; cur != last; ++cur) {
  402. if (0 == memcmp(cur, needle_bytes, needle_len)) {
  403. return (int)(cur - haystack_bytes);
  404. }
  405. }
  406. return -1;
  407. }
  408. grpc_slice grpc_slice_dup(grpc_slice a) {
  409. grpc_slice copy = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(a));
  410. memcpy(GRPC_SLICE_START_PTR(copy), GRPC_SLICE_START_PTR(a),
  411. GRPC_SLICE_LENGTH(a));
  412. return copy;
  413. }