Make move_first linear
diff --git a/include/grpc/slice_buffer.h b/include/grpc/slice_buffer.h
index f1de653..ebd0db7 100644
--- a/include/grpc/slice_buffer.h
+++ b/include/grpc/slice_buffer.h
@@ -77,8 +77,14 @@
/* move the first n bytes of src into dst */
GPRAPI void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
grpc_slice_buffer *dst);
+/* move the first n bytes of src into dst (copying them) */
+GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_slice_buffer *src,
+ size_t n, void *dst);
/* take the first slice in the slice buffer */
GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer *src);
+/* undo the above with (a possibly different) \a slice */
+GPRAPI void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *src,
+ grpc_slice slice);
#ifdef __cplusplus
}
diff --git a/src/core/lib/slice/slice_buffer.c b/src/core/lib/slice/slice_buffer.c
index a76b86f..84fa896 100644
--- a/src/core/lib/slice/slice_buffer.c
+++ b/src/core/lib/slice/slice_buffer.c
@@ -254,7 +254,6 @@
void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
grpc_slice_buffer *dst) {
- size_t src_idx;
size_t output_len = dst->length + n;
size_t new_input_len = src->length - n;
GPR_ASSERT(src->length >= n);
@@ -263,34 +262,53 @@
return;
}
- src_idx = 0;
- while (src_idx < src->count) {
- grpc_slice slice = src->slices[src_idx];
+ 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;
- src_idx++;
} else if (n == slice_len) {
grpc_slice_buffer_add(dst, slice);
- src_idx++;
break;
} else { /* n < slice_len */
- src->slices[src_idx] = grpc_slice_split_tail(&slice, n);
+ grpc_slice_buffer_undo_take_first(src, grpc_slice_split_tail(&slice, n));
GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
- GPR_ASSERT(GRPC_SLICE_LENGTH(src->slices[src_idx]) == slice_len - n);
grpc_slice_buffer_add(dst, slice);
break;
}
}
GPR_ASSERT(dst->length == output_len);
- memmove(src->slices, src->slices + src_idx,
- sizeof(grpc_slice) * (src->count - src_idx));
- src->count -= src_idx;
- src->length = new_input_len;
+ GPR_ASSERT(src->length == new_input_len);
GPR_ASSERT(src->count > 0);
}
+void grpc_slice_buffer_move_first_into_buffer(grpc_slice_buffer *src, size_t n,
+ void *dst) {
+ char *dstp = dst;
+ GPR_ASSERT(src->length >= n);
+
+ while (n > 0) {
+ grpc_slice slice = grpc_slice_buffer_take_first(src);
+ size_t slice_len = GRPC_SLICE_LENGTH(slice);
+ if (slice_len > n) {
+ memcpy(dstp, GRPC_SLICE_START_PTR(slice), n);
+ grpc_slice_buffer_undo_take_first(
+ src, grpc_slice_sub_no_ref(slice, n, slice_len));
+ n = 0;
+ } else if (slice_len == n) {
+ memcpy(dstp, GRPC_SLICE_START_PTR(slice), n);
+ grpc_slice_unref(slice);
+ n = 0;
+ } else {
+ memcpy(dstp, GRPC_SLICE_START_PTR(slice), slice_len);
+ dstp += slice_len;
+ n -= slice_len;
+ grpc_slice_unref(slice);
+ }
+ }
+}
+
void grpc_slice_buffer_trim_end(grpc_slice_buffer *sb, size_t n,
grpc_slice_buffer *garbage) {
GPR_ASSERT(n <= sb->length);
@@ -325,3 +343,11 @@
return slice;
}
+
+void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *sb,
+ grpc_slice slice) {
+ sb->slices--;
+ sb->slices[0] = slice;
+ sb->count++;
+ sb->length += GRPC_SLICE_LENGTH(slice);
+}