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
19 #include "test/core/test_util/slice_splitter.h"
20
21 #include <grpc/slice_buffer.h>
22 #include <grpc/support/alloc.h>
23 #include <stdint.h>
24 #include <string.h>
25
26 #include <algorithm>
27
grpc_slice_split_mode_name(grpc_slice_split_mode mode)28 const char* grpc_slice_split_mode_name(grpc_slice_split_mode mode) {
29 switch (mode) {
30 case GRPC_SLICE_SPLIT_IDENTITY:
31 return "identity";
32 case GRPC_SLICE_SPLIT_MERGE_ALL:
33 return "merge_all";
34 case GRPC_SLICE_SPLIT_ONE_BYTE:
35 return "one_byte";
36 }
37 return "error";
38 }
39
grpc_split_slices(grpc_slice_split_mode mode,grpc_slice * src_slices,size_t src_slice_count,grpc_slice ** dst_slices,size_t * dst_slice_count)40 void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice* src_slices,
41 size_t src_slice_count, grpc_slice** dst_slices,
42 size_t* dst_slice_count) {
43 size_t i, j;
44 size_t length;
45
46 switch (mode) {
47 case GRPC_SLICE_SPLIT_IDENTITY:
48 *dst_slice_count = src_slice_count;
49 *dst_slices = static_cast<grpc_slice*>(
50 gpr_malloc(sizeof(grpc_slice) * src_slice_count));
51 for (i = 0; i < src_slice_count; i++) {
52 (*dst_slices)[i] = src_slices[i];
53 grpc_slice_ref((*dst_slices)[i]);
54 }
55 break;
56 case GRPC_SLICE_SPLIT_MERGE_ALL:
57 *dst_slice_count = 1;
58 length = 0;
59 for (i = 0; i < src_slice_count; i++) {
60 length += GRPC_SLICE_LENGTH(src_slices[i]);
61 }
62 *dst_slices = static_cast<grpc_slice*>(gpr_malloc(sizeof(grpc_slice)));
63 **dst_slices = grpc_slice_malloc(length);
64 length = 0;
65 for (i = 0; i < src_slice_count; i++) {
66 memcpy(GRPC_SLICE_START_PTR(**dst_slices) + length,
67 GRPC_SLICE_START_PTR(src_slices[i]),
68 GRPC_SLICE_LENGTH(src_slices[i]));
69 length += GRPC_SLICE_LENGTH(src_slices[i]);
70 }
71 break;
72 case GRPC_SLICE_SPLIT_ONE_BYTE:
73 length = 0;
74 for (i = 0; i < src_slice_count; i++) {
75 length += GRPC_SLICE_LENGTH(src_slices[i]);
76 }
77 *dst_slice_count = length;
78 *dst_slices =
79 static_cast<grpc_slice*>(gpr_malloc(sizeof(grpc_slice) * length));
80 length = 0;
81 for (i = 0; i < src_slice_count; i++) {
82 for (j = 0; j < GRPC_SLICE_LENGTH(src_slices[i]); j++) {
83 (*dst_slices)[length] = grpc_slice_sub(src_slices[i], j, j + 1);
84 length++;
85 }
86 }
87 break;
88 }
89 }
90
grpc_split_slices_to_buffer(grpc_slice_split_mode mode,grpc_slice * src_slices,size_t src_slice_count,grpc_slice_buffer * dst)91 void grpc_split_slices_to_buffer(grpc_slice_split_mode mode,
92 grpc_slice* src_slices, size_t src_slice_count,
93 grpc_slice_buffer* dst) {
94 grpc_slice* slices;
95 size_t nslices;
96 size_t i;
97 grpc_split_slices(mode, src_slices, src_slice_count, &slices, &nslices);
98 for (i = 0; i < nslices; i++) {
99 // add indexed to avoid re-merging split slices
100 grpc_slice_buffer_add_indexed(dst, slices[i]);
101 }
102 gpr_free(slices);
103 }
104
grpc_split_slice_buffer(grpc_slice_split_mode mode,grpc_slice_buffer * src,grpc_slice_buffer * dst)105 void grpc_split_slice_buffer(grpc_slice_split_mode mode, grpc_slice_buffer* src,
106 grpc_slice_buffer* dst) {
107 grpc_split_slices_to_buffer(mode, src->slices, src->count, dst);
108 }
109
grpc_slice_merge(grpc_slice * slices,size_t nslices)110 grpc_slice grpc_slice_merge(grpc_slice* slices, size_t nslices) {
111 uint8_t* out = nullptr;
112 size_t length = 0;
113 size_t capacity = 0;
114 size_t i;
115
116 for (i = 0; i < nslices; i++) {
117 if (GRPC_SLICE_LENGTH(slices[i]) + length > capacity) {
118 capacity = std::max(capacity * 2, GRPC_SLICE_LENGTH(slices[i]) + length);
119 out = static_cast<uint8_t*>(gpr_realloc(out, capacity));
120 }
121 memcpy(out + length, GRPC_SLICE_START_PTR(slices[i]),
122 GRPC_SLICE_LENGTH(slices[i]));
123 length += GRPC_SLICE_LENGTH(slices[i]);
124 }
125
126 return grpc_slice_new(out, length, gpr_free);
127 }
128