1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017 Jason King.
14 * Copyright 2017 Joyent, Inc.
15 */
16 #include <sys/debug.h>
17 #include <string.h>
18 #include <umem.h>
19 #include "buf.h"
20
21 static inline boolean_t
22 eof_check(buf_t *buf, size_t len)
23 {
24 if (buf_eof(buf))
25 return (B_TRUE);
26 if (buf->b_ptr + len > buf->b_buf + buf->b_len) {
27 buf->b_flags |= BUF_EOF;
28 return (B_TRUE);
29 }
30 return (B_FALSE);
31 }
32
33 size_t
34 buf_cat(buf_t *restrict dest, const buf_t *restrict src, size_t n)
35 {
36 size_t total = 0;
37
38 BUF_IS_WRITE(dest);
39
40 for (size_t i = 0; i < n; i++, src++) {
41 size_t amt = buf_left(src);
42
43 BUF_IS_READ(src);
44 if (eof_check(dest, amt))
45 return (total);
46
47 (void) memcpy(dest->b_ptr, src->b_ptr, amt);
48 dest->b_ptr += amt;
49 total += amt;
50 }
51
52 return (total);
53 }
54
55 size_t
56 buf_copy(buf_t *restrict dest, const buf_t *restrict src, size_t n)
57 {
58 uchar_t *p = dest->b_buf;
59 size_t total = 0;
60
61 BUF_IS_WRITE(dest);
62
63 dest->b_ptr = dest->b_buf;
64 return (buf_cat(dest, src, n));
65 for (size_t i = 0; i < n; i++) {
66 size_t amt = src[i].b_len;
67
68 if (total + amt > dest->b_len)
69 amt = dest->b_len - total;
70 if (amt == 0)
71 break;
72
73 (void) memcpy(p, src[i].b_buf, amt);
74 total += amt;
75 p += amt;
76 }
77
78
79 /* XXX: what to do about b_ptr? */
80 return (total);
81 }
82
83 void
84 buf_clear(buf_t *buf)
85 {
86 if (buf == NULL || buf->b_buf == NULL || buf->b_len == 0)
87 return;
88
89 (void) memset(buf->b_buf, 0, buf->b_len);
90 buf->b_ptr = buf->b_buf;
91 buf->b_flags &= ~(BUF_EOF);
92 }
93
94 void
95 buf_range(buf_t *restrict dest, buf_t *restrict src, size_t off, size_t len)
96 {
97 ASSERT(off + len <= src->len);
98 dest->b_ptr = dest->b_buf = src->b_ptr + off;
99 dest->b_len = src->b_len - off;
100 dest->b_flags = src->b_flags & ~(BUF_ALLOCED);
101 }
102
103 boolean_t
104 buf_alloc(buf_t *buf, size_t len)
105 {
106 if ((buf->b_buf = umem_zalloc(len, UMEM_DEFAULT)) == NULL)
107 return (B_FALSE);
108 buf->b_ptr = buf->b_buf;
109 buf->b_len = len;
110 buf->b_flags = BUF_ALLOCED;
111 return (B_TRUE);
112 }
113
114 void
115 buf_free(buf_t *buf)
116 {
117 if (buf == NULL)
118 return;
119
120 VERIFY(buf->b_flags & BUF_ALLOCED);
121 buf_clear(buf);
122 umem_free(buf->b_buf, buf->b_len);
123 }
124
125 int
126 buf_cmp(const buf_t *restrict l, const buf_t *restrict r)
127 {
128 size_t minlen;
129 int cmp;
130
131 /* !NULL > NULL, NULL == NULL */
132 if (r == NULL || r->b_len == 0 || r->b_ptr == NULL) {
133 if (l != NULL && l->b_len > 0 && l->b_ptr != NULL)
134 return (1);
135 else
136 return (0);
137 }
138
139 /* NULL < !NULL */
140 if (l == NULL || l->b_len == 0 || l->b_ptr == NULL)
141 return (1);
142
143 minlen = l->b_len;
144 if (r->b_len < minlen)
145 minlen = r->b_len;
146
147 cmp = memcmp(l->b_buf, r->b_buf, minlen);
148 if (cmp != 0)
149 return ((cmp > 0) ? 1 : - 1);
150
151 if (l->b_len > r->b_len)
152 return (1);
153 if (l->b_len < r->b_len)
154 return (-1);
155 return (0);
156 }
157
158 void
159 buf_put8(buf_t *buf, uint8_t val)
160 {
161 BUF_IS_WRITE(buf);
162 if (eof_check(buf, sizeof (uint8_t)))
163 return;
164
165 *(buf->b_ptr++) = val;
166 }
167
168 void
169 buf_put64(buf_t *buf, uint64_t val)
170 {
171 BUF_IS_WRITE(buf);
172 if (eof_check(buf, sizeof (uint64_t)))
173 return;
174
175 *(buf->b_ptr++) = (uchar_t)((val >> 56) & 0xffLL);
176 *(buf->b_ptr++) = (uchar_t)((val >> 48) & 0xffLL);
177 *(buf->b_ptr++) = (uchar_t)((val >> 40) & 0xffLL);
178 *(buf->b_ptr++) = (uchar_t)((val >> 32) & 0xffLL);
179 *(buf->b_ptr++) = (uchar_t)((val >> 24) & 0xffLL);
180 *(buf->b_ptr++) = (uchar_t)((val >> 16) & 0xffLL);
181 *(buf->b_ptr++) = (uchar_t)((val >> 8) & 0xffLL);
182 *(buf->b_ptr++) = (uchar_t)(val & 0xffLL);
183 }
184
185 void
186 buf_put32(buf_t *buf, uint32_t val)
187 {
188 BUF_IS_WRITE(buf);
189 if (eof_check(buf, sizeof (uint32_t)))
190 return;
191
192 *(buf->b_ptr++) = (uchar_t)((val >> 24) & (uint32_t)0xff);
193 *(buf->b_ptr++) = (uchar_t)((val >> 16) & (uint32_t)0xff);
194 *(buf->b_ptr++) = (uchar_t)((val >> 8) & (uint32_t)0xff);
195 *(buf->b_ptr++) = (uchar_t)(val & (uint32_t)0xffLL);
196 }
197
198 extern boolean_t buf_eof(const buf_t *);
199 extern size_t buf_left(const buf_t *);
200 extern void buf_reset(buf_t *);
201 extern void buf_skip(buf_t *, size_t);
202 extern void buf_set_read(buf_t *);
203 extern void buf_set_write(buf_t *);