blob: 03c59e72a0f54ae0b9c6cab496a682f74c7b1260 [file] [log] [blame]
David Garcia Quintas2425bbb2016-01-25 17:32:48 -08001/*
2 *
David Garcia Quintas3452ae22016-01-25 17:34:49 -08003 * Copyright 2015-2016, Google Inc.
David Garcia Quintas2425bbb2016-01-25 17:32:48 -08004 * 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#ifndef GRPC_IMPL_CODEGEN_SLICE_H
35#define GRPC_IMPL_CODEGEN_SLICE_H
36
37#include <grpc/impl/codegen/sync.h>
38
39#include <stddef.h>
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45/* Slice API
46
47 A slice represents a contiguous reference counted array of bytes.
48 It is cheap to take references to a slice, and it is cheap to create a
49 slice pointing to a subset of another slice.
50
51 The data-structure for slices is exposed here to allow non-gpr code to
52 build slices from whatever data they have available.
53
54 When defining interfaces that handle slices, care should be taken to define
55 reference ownership semantics (who should call unref?) and mutability
56 constraints (is the callee allowed to modify the slice?) */
57
58/* Reference count container for gpr_slice. Contains function pointers to
59 increment and decrement reference counts. Implementations should cleanup
60 when the reference count drops to zero.
61 Typically client code should not touch this, and use gpr_slice_malloc,
62 gpr_slice_new, or gpr_slice_new_with_len instead. */
63typedef struct gpr_slice_refcount {
64 void (*ref)(void *);
65 void (*unref)(void *);
66} gpr_slice_refcount;
67
68#define GPR_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
69
70/* A gpr_slice s, if initialized, represents the byte range
71 s.bytes[0..s.length-1].
72
73 It can have an associated ref count which has a destruction routine to be run
74 when the ref count reaches zero (see gpr_slice_new() and grp_slice_unref()).
75 Multiple gpr_slice values may share a ref count.
76
77 If the slice does not have a refcount, it represents an inlined small piece
78 of data that is copied by value. */
79typedef struct gpr_slice {
80 struct gpr_slice_refcount *refcount;
81 union {
82 struct {
83 uint8_t *bytes;
84 size_t length;
85 } refcounted;
86 struct {
87 uint8_t length;
88 uint8_t bytes[GPR_SLICE_INLINED_SIZE];
89 } inlined;
90 } data;
91} gpr_slice;
92
93#define GPR_SLICE_START_PTR(slice) \
94 ((slice).refcount ? (slice).data.refcounted.bytes \
95 : (slice).data.inlined.bytes)
96#define GPR_SLICE_LENGTH(slice) \
97 ((slice).refcount ? (slice).data.refcounted.length \
98 : (slice).data.inlined.length)
99#define GPR_SLICE_SET_LENGTH(slice, newlen) \
100 ((slice).refcount ? ((slice).data.refcounted.length = (size_t)(newlen)) \
101 : ((slice).data.inlined.length = (uint8_t)(newlen)))
102#define GPR_SLICE_END_PTR(slice) \
103 GPR_SLICE_START_PTR(slice) + GPR_SLICE_LENGTH(slice)
104#define GPR_SLICE_IS_EMPTY(slice) (GPR_SLICE_LENGTH(slice) == 0)
105
106/* Increment the refcount of s. Requires slice is initialized.
107 Returns s. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100108GPRAPI gpr_slice gpr_slice_ref(gpr_slice s);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800109
110/* Decrement the ref count of s. If the ref count of s reaches zero, all
111 slices sharing the ref count are destroyed, and considered no longer
112 initialized. If s is ultimately derived from a call to gpr_slice_new(start,
113 len, dest) where dest!=NULL , then (*dest)(start) is called, else if s is
114 ultimately derived from a call to gpr_slice_new_with_len(start, len, dest)
115 where dest!=NULL , then (*dest)(start, len). Requires s initialized. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100116GPRAPI void gpr_slice_unref(gpr_slice s);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800117
118/* Create a slice pointing at some data. Calls malloc to allocate a refcount
119 for the object, and arranges that destroy will be called with the pointer
120 passed in at destruction. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100121GPRAPI gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *));
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800122
123/* Equivalent to gpr_slice_new, but with a two argument destroy function that
124 also takes the slice length. */
Craig Tillerf40df232016-03-25 13:38:14 -0700125GPRAPI gpr_slice gpr_slice_new_with_len(void *p, size_t len,
126 void (*destroy)(void *, size_t));
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800127
128/* Equivalent to gpr_slice_new(malloc(len), len, free), but saves one malloc()
129 call.
130 Aborts if malloc() fails. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100131GPRAPI gpr_slice gpr_slice_malloc(size_t length);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800132
133/* Create a slice by copying a string.
134 Does not preserve null terminators.
135 Equivalent to:
136 size_t len = strlen(source);
137 gpr_slice slice = gpr_slice_malloc(len);
138 memcpy(slice->data, source, len); */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100139GPRAPI gpr_slice gpr_slice_from_copied_string(const char *source);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800140
141/* Create a slice by copying a buffer.
142 Equivalent to:
143 gpr_slice slice = gpr_slice_malloc(len);
144 memcpy(slice->data, source, len); */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100145GPRAPI gpr_slice gpr_slice_from_copied_buffer(const char *source, size_t len);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800146
147/* Create a slice pointing to constant memory */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100148GPRAPI gpr_slice gpr_slice_from_static_string(const char *source);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800149
150/* Return a result slice derived from s, which shares a ref count with s, where
151 result.data==s.data+begin, and result.length==end-begin.
152 The ref count of s is increased by one.
153 Requires s initialized, begin <= end, begin <= s.length, and
154 end <= source->length. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100155GPRAPI gpr_slice gpr_slice_sub(gpr_slice s, size_t begin, size_t end);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800156
157/* The same as gpr_slice_sub, but without altering the ref count */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100158GPRAPI gpr_slice gpr_slice_sub_no_ref(gpr_slice s, size_t begin, size_t end);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800159
160/* Splits s into two: modifies s to be s[0:split], and returns a new slice,
161 sharing a refcount with s, that contains s[split:s.length].
162 Requires s intialized, split <= s.length */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100163GPRAPI gpr_slice gpr_slice_split_tail(gpr_slice *s, size_t split);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800164
165/* Splits s into two: modifies s to be s[split:s.length], and returns a new
166 slice, sharing a refcount with s, that contains s[0:split].
167 Requires s intialized, split <= s.length */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100168GPRAPI gpr_slice gpr_slice_split_head(gpr_slice *s, size_t split);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800169
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100170GPRAPI gpr_slice gpr_empty_slice(void);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800171
172/* Returns <0 if a < b, ==0 if a == b, >0 if a > b
173 The order is arbitrary, and is not guaranteed to be stable across different
174 versions of the API. */
Nicolas "Pixel" Noblecd41a0b2016-02-08 22:53:14 +0100175GPRAPI int gpr_slice_cmp(gpr_slice a, gpr_slice b);
176GPRAPI int gpr_slice_str_cmp(gpr_slice a, const char *b);
David Garcia Quintas2425bbb2016-01-25 17:32:48 -0800177
178#ifdef __cplusplus
179}
180#endif
181
182#endif /* GRPC_IMPL_CODEGEN_SLICE_H */