Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <grpc/support/alloc.h>
35 : #include <grpc/support/log.h>
36 : #include <grpc/support/slice.h>
37 :
38 : #include <string.h>
39 :
40 4419 : gpr_slice gpr_empty_slice(void) {
41 : gpr_slice out;
42 4419 : out.refcount = 0;
43 4419 : out.data.inlined.length = 0;
44 4419 : return out;
45 : }
46 :
47 14254182 : gpr_slice gpr_slice_ref(gpr_slice slice) {
48 14254182 : if (slice.refcount) {
49 312666 : slice.refcount->ref(slice.refcount);
50 : }
51 14263736 : return slice;
52 : }
53 :
54 41035752 : void gpr_slice_unref(gpr_slice slice) {
55 41035752 : if (slice.refcount) {
56 1977637 : slice.refcount->unref(slice.refcount);
57 : }
58 41035992 : }
59 :
60 : /* gpr_slice_new support structures - we create a refcount object extended
61 : with the user provided data pointer & destroy function */
62 : typedef struct new_slice_refcount {
63 : gpr_slice_refcount rc;
64 : gpr_refcount refs;
65 : void (*user_destroy)(void *);
66 : void *user_data;
67 : } new_slice_refcount;
68 :
69 3264 : static void new_slice_ref(void *p) {
70 3264 : new_slice_refcount *r = p;
71 3264 : gpr_ref(&r->refs);
72 3264 : }
73 :
74 117313 : static void new_slice_unref(void *p) {
75 117313 : new_slice_refcount *r = p;
76 117313 : if (gpr_unref(&r->refs)) {
77 114049 : r->user_destroy(r->user_data);
78 114049 : gpr_free(r);
79 : }
80 117313 : }
81 :
82 114138 : gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
83 : gpr_slice slice;
84 114138 : new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
85 114138 : gpr_ref_init(&rc->refs, 1);
86 114138 : rc->rc.ref = new_slice_ref;
87 114138 : rc->rc.unref = new_slice_unref;
88 114138 : rc->user_destroy = destroy;
89 114138 : rc->user_data = p;
90 :
91 114138 : slice.refcount = &rc->rc;
92 114138 : slice.data.refcounted.bytes = p;
93 114138 : slice.data.refcounted.length = len;
94 114138 : return slice;
95 : }
96 :
97 : /* gpr_slice_new_with_len support structures - we create a refcount object
98 : extended with the user provided data pointer & destroy function */
99 : typedef struct new_with_len_slice_refcount {
100 : gpr_slice_refcount rc;
101 : gpr_refcount refs;
102 : void *user_data;
103 : size_t user_length;
104 : void (*user_destroy)(void *, size_t);
105 : } new_with_len_slice_refcount;
106 :
107 0 : static void new_with_len_ref(void *p) {
108 0 : new_with_len_slice_refcount *r = p;
109 0 : gpr_ref(&r->refs);
110 0 : }
111 :
112 1 : static void new_with_len_unref(void *p) {
113 1 : new_with_len_slice_refcount *r = p;
114 1 : if (gpr_unref(&r->refs)) {
115 1 : r->user_destroy(r->user_data, r->user_length);
116 1 : gpr_free(r);
117 : }
118 1 : }
119 :
120 1 : gpr_slice gpr_slice_new_with_len(void *p, size_t len,
121 : void (*destroy)(void *, size_t)) {
122 : gpr_slice slice;
123 1 : new_with_len_slice_refcount *rc =
124 : gpr_malloc(sizeof(new_with_len_slice_refcount));
125 1 : gpr_ref_init(&rc->refs, 1);
126 1 : rc->rc.ref = new_with_len_ref;
127 1 : rc->rc.unref = new_with_len_unref;
128 1 : rc->user_destroy = destroy;
129 1 : rc->user_data = p;
130 1 : rc->user_length = len;
131 :
132 1 : slice.refcount = &rc->rc;
133 1 : slice.data.refcounted.bytes = p;
134 1 : slice.data.refcounted.length = len;
135 1 : return slice;
136 : }
137 :
138 10953 : gpr_slice gpr_slice_from_copied_buffer(const char *source, size_t length) {
139 10953 : gpr_slice slice = gpr_slice_malloc(length);
140 10953 : memcpy(GPR_SLICE_START_PTR(slice), source, length);
141 10953 : return slice;
142 : }
143 :
144 9005 : gpr_slice gpr_slice_from_copied_string(const char *source) {
145 9005 : return gpr_slice_from_copied_buffer(source, strlen(source));
146 : }
147 :
148 : typedef struct {
149 : gpr_slice_refcount base;
150 : gpr_refcount refs;
151 : } malloc_refcount;
152 :
153 1579383 : static void malloc_ref(void *p) {
154 1579383 : malloc_refcount *r = p;
155 1579383 : gpr_ref(&r->refs);
156 1579522 : }
157 :
158 1778824 : static void malloc_unref(void *p) {
159 1778824 : malloc_refcount *r = p;
160 1778824 : if (gpr_unref(&r->refs)) {
161 199397 : gpr_free(r);
162 : }
163 1779117 : }
164 :
165 23473926 : gpr_slice gpr_slice_malloc(size_t length) {
166 : gpr_slice slice;
167 :
168 23473926 : if (length > sizeof(slice.data.inlined.bytes)) {
169 : /* Memory layout used by the slice created here:
170 :
171 : +-----------+----------------------------------------------------------+
172 : | refcount | bytes |
173 : +-----------+----------------------------------------------------------+
174 :
175 : refcount is a malloc_refcount
176 : bytes is an array of bytes of the requested length
177 : Both parts are placed in the same allocation returned from gpr_malloc */
178 199389 : malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length);
179 :
180 : /* Initial refcount on rc is 1 - and it's up to the caller to release
181 : this reference. */
182 199396 : gpr_ref_init(&rc->refs, 1);
183 :
184 241734 : rc->base.ref = malloc_ref;
185 241734 : rc->base.unref = malloc_unref;
186 :
187 : /* Build up the slice to be returned. */
188 : /* The slices refcount points back to the allocated block. */
189 241734 : slice.refcount = &rc->base;
190 : /* The data bytes are placed immediately after the refcount struct */
191 241734 : slice.data.refcounted.bytes = (gpr_uint8 *)(rc + 1);
192 : /* And the length of the block is set to the requested length */
193 241734 : slice.data.refcounted.length = length;
194 : } else {
195 : /* small slice: just inline the data */
196 23274537 : slice.refcount = NULL;
197 23274537 : slice.data.inlined.length = (gpr_uint8)length;
198 : }
199 23516271 : return slice;
200 : }
201 :
202 13495070 : gpr_slice gpr_slice_sub_no_ref(gpr_slice source, size_t begin, size_t end) {
203 : gpr_slice subset;
204 :
205 13495070 : GPR_ASSERT(end >= begin);
206 :
207 13495070 : if (source.refcount) {
208 : /* Enforce preconditions */
209 8895351 : GPR_ASSERT(source.data.refcounted.length >= end);
210 :
211 : /* Build the result */
212 8895351 : subset.refcount = source.refcount;
213 : /* Point into the source array */
214 8895351 : subset.data.refcounted.bytes = source.data.refcounted.bytes + begin;
215 8895351 : subset.data.refcounted.length = end - begin;
216 : } else {
217 : /* Enforce preconditions */
218 4599719 : GPR_ASSERT(source.data.inlined.length >= end);
219 4599719 : subset.refcount = NULL;
220 4599719 : subset.data.inlined.length = (gpr_uint8)(end - begin);
221 4599719 : memcpy(subset.data.inlined.bytes, source.data.inlined.bytes + begin,
222 : end - begin);
223 : }
224 13495070 : return subset;
225 : }
226 :
227 14890094 : gpr_slice gpr_slice_sub(gpr_slice source, size_t begin, size_t end) {
228 : gpr_slice subset;
229 :
230 14890094 : if (end - begin <= sizeof(subset.data.inlined.bytes)) {
231 14587576 : subset.refcount = NULL;
232 14587576 : subset.data.inlined.length = (gpr_uint8)(end - begin);
233 14587576 : memcpy(subset.data.inlined.bytes, GPR_SLICE_START_PTR(source) + begin,
234 : end - begin);
235 : } else {
236 302518 : subset = gpr_slice_sub_no_ref(source, begin, end);
237 : /* Bump the refcount */
238 302518 : subset.refcount->ref(subset.refcount);
239 : }
240 14900073 : return subset;
241 : }
242 :
243 8217 : gpr_slice gpr_slice_split_tail(gpr_slice *source, size_t split) {
244 : gpr_slice tail;
245 :
246 8217 : if (source->refcount == NULL) {
247 : /* inlined data, copy it out */
248 120 : GPR_ASSERT(source->data.inlined.length >= split);
249 120 : tail.refcount = NULL;
250 120 : tail.data.inlined.length = (gpr_uint8)(source->data.inlined.length - split);
251 120 : memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split,
252 120 : tail.data.inlined.length);
253 120 : source->data.inlined.length = (gpr_uint8)split;
254 : } else {
255 8097 : size_t tail_length = source->data.refcounted.length - split;
256 8097 : GPR_ASSERT(source->data.refcounted.length >= split);
257 8097 : if (tail_length < sizeof(tail.data.inlined.bytes)) {
258 : /* Copy out the bytes - it'll be cheaper than refcounting */
259 1568 : tail.refcount = NULL;
260 1568 : tail.data.inlined.length = (gpr_uint8)tail_length;
261 1568 : memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split,
262 : tail_length);
263 : } else {
264 : /* Build the result */
265 6529 : tail.refcount = source->refcount;
266 : /* Bump the refcount */
267 6529 : tail.refcount->ref(tail.refcount);
268 : /* Point into the source array */
269 6529 : tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
270 6529 : tail.data.refcounted.length = tail_length;
271 : }
272 8097 : source->data.refcounted.length = split;
273 : }
274 :
275 8217 : return tail;
276 : }
277 :
278 1655201 : gpr_slice gpr_slice_split_head(gpr_slice *source, size_t split) {
279 : gpr_slice head;
280 :
281 1655201 : if (source->refcount == NULL) {
282 235 : GPR_ASSERT(source->data.inlined.length >= split);
283 :
284 235 : head.refcount = NULL;
285 235 : head.data.inlined.length = (gpr_uint8)split;
286 235 : memcpy(head.data.inlined.bytes, source->data.inlined.bytes, split);
287 235 : source->data.inlined.length =
288 235 : (gpr_uint8)(source->data.inlined.length - split);
289 235 : memmove(source->data.inlined.bytes, source->data.inlined.bytes + split,
290 235 : source->data.inlined.length);
291 1654966 : } else if (split < sizeof(head.data.inlined.bytes)) {
292 612351 : GPR_ASSERT(source->data.refcounted.length >= split);
293 :
294 612351 : head.refcount = NULL;
295 612351 : head.data.inlined.length = (gpr_uint8)split;
296 612351 : memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split);
297 612351 : source->data.refcounted.bytes += split;
298 612351 : source->data.refcounted.length -= split;
299 : } else {
300 1042615 : GPR_ASSERT(source->data.refcounted.length >= split);
301 :
302 : /* Build the result */
303 1042615 : head.refcount = source->refcount;
304 : /* Bump the refcount */
305 1042615 : head.refcount->ref(head.refcount);
306 : /* Point into the source array */
307 1042663 : head.data.refcounted.bytes = source->data.refcounted.bytes;
308 1042663 : head.data.refcounted.length = split;
309 1042663 : source->data.refcounted.bytes += split;
310 1042663 : source->data.refcounted.length -= split;
311 : }
312 :
313 1655249 : return head;
314 : }
315 :
316 568 : int gpr_slice_cmp(gpr_slice a, gpr_slice b) {
317 568 : int d = (int)(GPR_SLICE_LENGTH(a) - GPR_SLICE_LENGTH(b));
318 568 : if (d != 0) return d;
319 612 : return memcmp(GPR_SLICE_START_PTR(a), GPR_SLICE_START_PTR(b),
320 612 : GPR_SLICE_LENGTH(a));
321 : }
322 :
323 4222432 : int gpr_slice_str_cmp(gpr_slice a, const char *b) {
324 4222432 : size_t b_length = strlen(b);
325 4222432 : int d = (int)(GPR_SLICE_LENGTH(a) - b_length);
326 4222432 : if (d != 0) return d;
327 4222428 : return memcmp(GPR_SLICE_START_PTR(a), b, b_length);
328 : }
329 :
330 0 : char *gpr_slice_to_cstring(gpr_slice slice) {
331 0 : char *result = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1);
332 0 : memcpy(result, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
333 0 : result[GPR_SLICE_LENGTH(slice)] = '\0';
334 0 : return result;
335 : }
|