Index: third_party/grpc/src/core/support/slice.c |
diff --git a/third_party/grpc/src/core/support/slice.c b/third_party/grpc/src/core/support/slice.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b9a7c77bda6e649eca6635e0dcd84b19462dd95b |
--- /dev/null |
+++ b/third_party/grpc/src/core/support/slice.c |
@@ -0,0 +1,343 @@ |
+/* |
+ * |
+ * Copyright 2015, Google Inc. |
+ * All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#include <grpc/support/alloc.h> |
+#include <grpc/support/log.h> |
+#include <grpc/support/slice.h> |
+ |
+#include <string.h> |
+ |
+gpr_slice gpr_empty_slice(void) { |
+ gpr_slice out; |
+ out.refcount = 0; |
+ out.data.inlined.length = 0; |
+ return out; |
+} |
+ |
+gpr_slice gpr_slice_ref(gpr_slice slice) { |
+ if (slice.refcount) { |
+ slice.refcount->ref(slice.refcount); |
+ } |
+ return slice; |
+} |
+ |
+void gpr_slice_unref(gpr_slice slice) { |
+ if (slice.refcount) { |
+ slice.refcount->unref(slice.refcount); |
+ } |
+} |
+ |
+/* gpr_slice_from_static_string support structure - a refcount that does |
+ nothing */ |
+static void noop_ref_or_unref(void *unused) {} |
+ |
+static gpr_slice_refcount noop_refcount = {noop_ref_or_unref, |
+ noop_ref_or_unref}; |
+ |
+gpr_slice gpr_slice_from_static_string(const char *s) { |
+ gpr_slice slice; |
+ slice.refcount = &noop_refcount; |
+ slice.data.refcounted.bytes = (uint8_t *)s; |
+ slice.data.refcounted.length = strlen(s); |
+ return slice; |
+} |
+ |
+/* gpr_slice_new support structures - we create a refcount object extended |
+ with the user provided data pointer & destroy function */ |
+typedef struct new_slice_refcount { |
+ gpr_slice_refcount rc; |
+ gpr_refcount refs; |
+ void (*user_destroy)(void *); |
+ void *user_data; |
+} new_slice_refcount; |
+ |
+static void new_slice_ref(void *p) { |
+ new_slice_refcount *r = p; |
+ gpr_ref(&r->refs); |
+} |
+ |
+static void new_slice_unref(void *p) { |
+ new_slice_refcount *r = p; |
+ if (gpr_unref(&r->refs)) { |
+ r->user_destroy(r->user_data); |
+ gpr_free(r); |
+ } |
+} |
+ |
+gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) { |
+ gpr_slice slice; |
+ new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount)); |
+ gpr_ref_init(&rc->refs, 1); |
+ rc->rc.ref = new_slice_ref; |
+ rc->rc.unref = new_slice_unref; |
+ rc->user_destroy = destroy; |
+ rc->user_data = p; |
+ |
+ slice.refcount = &rc->rc; |
+ slice.data.refcounted.bytes = p; |
+ slice.data.refcounted.length = len; |
+ return slice; |
+} |
+ |
+/* gpr_slice_new_with_len support structures - we create a refcount object |
+ extended with the user provided data pointer & destroy function */ |
+typedef struct new_with_len_slice_refcount { |
+ gpr_slice_refcount rc; |
+ gpr_refcount refs; |
+ void *user_data; |
+ size_t user_length; |
+ void (*user_destroy)(void *, size_t); |
+} new_with_len_slice_refcount; |
+ |
+static void new_with_len_ref(void *p) { |
+ new_with_len_slice_refcount *r = p; |
+ gpr_ref(&r->refs); |
+} |
+ |
+static void new_with_len_unref(void *p) { |
+ new_with_len_slice_refcount *r = p; |
+ if (gpr_unref(&r->refs)) { |
+ r->user_destroy(r->user_data, r->user_length); |
+ gpr_free(r); |
+ } |
+} |
+ |
+gpr_slice gpr_slice_new_with_len(void *p, size_t len, |
+ void (*destroy)(void *, size_t)) { |
+ gpr_slice slice; |
+ new_with_len_slice_refcount *rc = |
+ gpr_malloc(sizeof(new_with_len_slice_refcount)); |
+ gpr_ref_init(&rc->refs, 1); |
+ rc->rc.ref = new_with_len_ref; |
+ rc->rc.unref = new_with_len_unref; |
+ rc->user_destroy = destroy; |
+ rc->user_data = p; |
+ rc->user_length = len; |
+ |
+ slice.refcount = &rc->rc; |
+ slice.data.refcounted.bytes = p; |
+ slice.data.refcounted.length = len; |
+ return slice; |
+} |
+ |
+gpr_slice gpr_slice_from_copied_buffer(const char *source, size_t length) { |
+ gpr_slice slice = gpr_slice_malloc(length); |
+ memcpy(GPR_SLICE_START_PTR(slice), source, length); |
+ return slice; |
+} |
+ |
+gpr_slice gpr_slice_from_copied_string(const char *source) { |
+ return gpr_slice_from_copied_buffer(source, strlen(source)); |
+} |
+ |
+typedef struct { |
+ gpr_slice_refcount base; |
+ gpr_refcount refs; |
+} malloc_refcount; |
+ |
+static void malloc_ref(void *p) { |
+ malloc_refcount *r = p; |
+ gpr_ref(&r->refs); |
+} |
+ |
+static void malloc_unref(void *p) { |
+ malloc_refcount *r = p; |
+ if (gpr_unref(&r->refs)) { |
+ gpr_free(r); |
+ } |
+} |
+ |
+gpr_slice gpr_slice_malloc(size_t length) { |
+ gpr_slice slice; |
+ |
+ if (length > sizeof(slice.data.inlined.bytes)) { |
+ /* Memory layout used by the slice created here: |
+ |
+ +-----------+----------------------------------------------------------+ |
+ | refcount | bytes | |
+ +-----------+----------------------------------------------------------+ |
+ |
+ refcount is a malloc_refcount |
+ bytes is an array of bytes of the requested length |
+ Both parts are placed in the same allocation returned from gpr_malloc */ |
+ malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length); |
+ |
+ /* Initial refcount on rc is 1 - and it's up to the caller to release |
+ this reference. */ |
+ gpr_ref_init(&rc->refs, 1); |
+ |
+ rc->base.ref = malloc_ref; |
+ rc->base.unref = malloc_unref; |
+ |
+ /* Build up the slice to be returned. */ |
+ /* The slices refcount points back to the allocated block. */ |
+ slice.refcount = &rc->base; |
+ /* The data bytes are placed immediately after the refcount struct */ |
+ slice.data.refcounted.bytes = (uint8_t *)(rc + 1); |
+ /* And the length of the block is set to the requested length */ |
+ slice.data.refcounted.length = length; |
+ } else { |
+ /* small slice: just inline the data */ |
+ slice.refcount = NULL; |
+ slice.data.inlined.length = (uint8_t)length; |
+ } |
+ return slice; |
+} |
+ |
+gpr_slice gpr_slice_sub_no_ref(gpr_slice source, size_t begin, size_t end) { |
+ gpr_slice subset; |
+ |
+ GPR_ASSERT(end >= begin); |
+ |
+ if (source.refcount) { |
+ /* Enforce preconditions */ |
+ GPR_ASSERT(source.data.refcounted.length >= end); |
+ |
+ /* Build the result */ |
+ subset.refcount = source.refcount; |
+ /* Point into the source array */ |
+ subset.data.refcounted.bytes = source.data.refcounted.bytes + begin; |
+ subset.data.refcounted.length = end - begin; |
+ } else { |
+ /* Enforce preconditions */ |
+ GPR_ASSERT(source.data.inlined.length >= end); |
+ subset.refcount = NULL; |
+ subset.data.inlined.length = (uint8_t)(end - begin); |
+ memcpy(subset.data.inlined.bytes, source.data.inlined.bytes + begin, |
+ end - begin); |
+ } |
+ return subset; |
+} |
+ |
+gpr_slice gpr_slice_sub(gpr_slice source, size_t begin, size_t end) { |
+ gpr_slice subset; |
+ |
+ if (end - begin <= sizeof(subset.data.inlined.bytes)) { |
+ subset.refcount = NULL; |
+ subset.data.inlined.length = (uint8_t)(end - begin); |
+ memcpy(subset.data.inlined.bytes, GPR_SLICE_START_PTR(source) + begin, |
+ end - begin); |
+ } else { |
+ subset = gpr_slice_sub_no_ref(source, begin, end); |
+ /* Bump the refcount */ |
+ subset.refcount->ref(subset.refcount); |
+ } |
+ return subset; |
+} |
+ |
+gpr_slice gpr_slice_split_tail(gpr_slice *source, size_t split) { |
+ gpr_slice tail; |
+ |
+ if (source->refcount == NULL) { |
+ /* inlined data, copy it out */ |
+ GPR_ASSERT(source->data.inlined.length >= split); |
+ tail.refcount = NULL; |
+ tail.data.inlined.length = (uint8_t)(source->data.inlined.length - split); |
+ memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split, |
+ tail.data.inlined.length); |
+ source->data.inlined.length = (uint8_t)split; |
+ } else { |
+ size_t tail_length = source->data.refcounted.length - split; |
+ GPR_ASSERT(source->data.refcounted.length >= split); |
+ if (tail_length < sizeof(tail.data.inlined.bytes)) { |
+ /* Copy out the bytes - it'll be cheaper than refcounting */ |
+ tail.refcount = NULL; |
+ tail.data.inlined.length = (uint8_t)tail_length; |
+ memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split, |
+ tail_length); |
+ } else { |
+ /* Build the result */ |
+ tail.refcount = source->refcount; |
+ /* Bump the refcount */ |
+ tail.refcount->ref(tail.refcount); |
+ /* Point into the source array */ |
+ tail.data.refcounted.bytes = source->data.refcounted.bytes + split; |
+ tail.data.refcounted.length = tail_length; |
+ } |
+ source->data.refcounted.length = split; |
+ } |
+ |
+ return tail; |
+} |
+ |
+gpr_slice gpr_slice_split_head(gpr_slice *source, size_t split) { |
+ gpr_slice head; |
+ |
+ if (source->refcount == NULL) { |
+ GPR_ASSERT(source->data.inlined.length >= split); |
+ |
+ head.refcount = NULL; |
+ head.data.inlined.length = (uint8_t)split; |
+ memcpy(head.data.inlined.bytes, source->data.inlined.bytes, split); |
+ source->data.inlined.length = |
+ (uint8_t)(source->data.inlined.length - split); |
+ memmove(source->data.inlined.bytes, source->data.inlined.bytes + split, |
+ source->data.inlined.length); |
+ } else if (split < sizeof(head.data.inlined.bytes)) { |
+ GPR_ASSERT(source->data.refcounted.length >= split); |
+ |
+ head.refcount = NULL; |
+ head.data.inlined.length = (uint8_t)split; |
+ memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split); |
+ source->data.refcounted.bytes += split; |
+ source->data.refcounted.length -= split; |
+ } else { |
+ GPR_ASSERT(source->data.refcounted.length >= split); |
+ |
+ /* Build the result */ |
+ head.refcount = source->refcount; |
+ /* Bump the refcount */ |
+ head.refcount->ref(head.refcount); |
+ /* Point into the source array */ |
+ head.data.refcounted.bytes = source->data.refcounted.bytes; |
+ head.data.refcounted.length = split; |
+ source->data.refcounted.bytes += split; |
+ source->data.refcounted.length -= split; |
+ } |
+ |
+ return head; |
+} |
+ |
+int gpr_slice_cmp(gpr_slice a, gpr_slice b) { |
+ int d = (int)(GPR_SLICE_LENGTH(a) - GPR_SLICE_LENGTH(b)); |
+ if (d != 0) return d; |
+ return memcmp(GPR_SLICE_START_PTR(a), GPR_SLICE_START_PTR(b), |
+ GPR_SLICE_LENGTH(a)); |
+} |
+ |
+int gpr_slice_str_cmp(gpr_slice a, const char *b) { |
+ size_t b_length = strlen(b); |
+ int d = (int)(GPR_SLICE_LENGTH(a) - b_length); |
+ if (d != 0) return d; |
+ return memcmp(GPR_SLICE_START_PTR(a), b, b_length); |
+} |