Reduce duplication
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 4dce6da..fe6379c 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -124,8 +124,11 @@
Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
-/* The same as grpc_slice_split_tail, but without altering refcounts */
-GPRAPI grpc_slice grpc_slice_split_tail_no_ref(grpc_slice *s, size_t split);
+/* The same as grpc_slice_split_tail, but with an option to skip altering
+ * refcounts (grpc_slice_split_tail_maybe_ref(..., true) is equivalent to
+ * grpc_slice_split_tail(...)) */
+GPRAPI grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *s, size_t split,
+ bool inc_refs);
/* Splits s into two: modifies s to be s[split:s.length], and returns a new
slice, sharing a refcount with s, that contains s[0:split].
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 8896f1d..2852188 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -312,7 +312,8 @@
return subset;
}
-grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
+grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *source, size_t split,
+ bool incref) {
grpc_slice tail;
if (source->refcount == NULL) {
@@ -334,9 +335,13 @@
tail_length);
} else {
/* Build the result */
- tail.refcount = source->refcount->sub_refcount;
- /* Bump the refcount */
- tail.refcount->vtable->ref(tail.refcount);
+ if (incref) {
+ tail.refcount = source->refcount->sub_refcount;
+ /* Bump the refcount */
+ tail.refcount->vtable->ref(tail.refcount);
+ } else {
+ tail.refcount = &noop_refcount;
+ }
/* Point into the source array */
tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
tail.data.refcounted.length = tail_length;
@@ -348,38 +353,8 @@
return tail;
}
-grpc_slice grpc_slice_split_tail_no_ref(grpc_slice *source, size_t split) {
- grpc_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 = &noop_refcount;
- /* Point into the source array */
- tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
- tail.data.refcounted.length = tail_length;
- }
- source->refcount = source->refcount->sub_refcount;
- source->data.refcounted.length = split;
- }
-
- return tail;
+grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
+ return grpc_slice_split_tail_maybe_ref(source, split, true);
}
grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
diff --git a/src/core/lib/slice/slice_buffer.c b/src/core/lib/slice/slice_buffer.c
index a13941e..5a4b434 100644
--- a/src/core/lib/slice/slice_buffer.c
+++ b/src/core/lib/slice/slice_buffer.c
@@ -253,40 +253,9 @@
src->length = 0;
}
-void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
- grpc_slice_buffer *dst) {
- GPR_ASSERT(src->length >= n);
- if (src->length == n) {
- grpc_slice_buffer_move_into(src, dst);
- return;
- }
-
- size_t output_len = dst->length + n;
- size_t new_input_len = src->length - n;
-
- while (src->count > 0) {
- grpc_slice slice = grpc_slice_buffer_take_first(src);
- size_t slice_len = GRPC_SLICE_LENGTH(slice);
- if (n > slice_len) {
- grpc_slice_buffer_add(dst, slice);
- n -= slice_len;
- } else if (n == slice_len) {
- grpc_slice_buffer_add(dst, slice);
- break;
- } else { /* n < slice_len */
- grpc_slice_buffer_undo_take_first(src, grpc_slice_split_tail(&slice, n));
- GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
- grpc_slice_buffer_add(dst, slice);
- break;
- }
- }
- GPR_ASSERT(dst->length == output_len);
- GPR_ASSERT(src->length == new_input_len);
- GPR_ASSERT(src->count > 0);
-}
-
-void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer *src, size_t n,
- grpc_slice_buffer *dst) {
+static void slice_buffer_move_first_maybe_ref(grpc_slice_buffer *src, size_t n,
+ grpc_slice_buffer *dst,
+ bool incref) {
GPR_ASSERT(src->length >= n);
if (src->length == n) {
grpc_slice_buffer_move_into(src, dst);
@@ -307,7 +276,7 @@
break;
} else { /* n < slice_len */
grpc_slice_buffer_undo_take_first(
- src, grpc_slice_split_tail_no_ref(&slice, n));
+ src, grpc_slice_split_tail_maybe_ref(&slice, n, incref));
GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
grpc_slice_buffer_add(dst, slice);
break;
@@ -318,6 +287,16 @@
GPR_ASSERT(src->count > 0);
}
+void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
+ grpc_slice_buffer *dst) {
+ slice_buffer_move_first_maybe_ref(src, n, dst, true);
+}
+
+void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer *src, size_t n,
+ grpc_slice_buffer *dst) {
+ slice_buffer_move_first_maybe_ref(src, n, dst, false);
+}
+
void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer *src, size_t n,
void *dst) {