buffer.c 8.55 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
2
 * Copyright (C) 1998, 1999  Internet Software Consortium.
Bob Halley's avatar
Bob Halley committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
Bob Halley's avatar
Bob Halley committed
17

Bob Halley's avatar
Bob Halley committed
18
19
#include <config.h>

Bob Halley's avatar
Bob Halley committed
20
21
22
23
24
25
#include <string.h>

#include <isc/assertions.h>
#include <isc/buffer.h>

void
Bob Halley's avatar
lint    
Bob Halley committed
26
isc_buffer_init(isc_buffer_t *b, void *base, unsigned int length,
27
28
		unsigned int type)
{
Bob Halley's avatar
Bob Halley committed
29
30
31
32
	/*
	 * Make 'b' refer to the 'length'-byte region starting at base.
	 */

33
	REQUIRE(b != NULL);
Bob Halley's avatar
Bob Halley committed
34

35
	b->magic = ISC_BUFFER_MAGIC;
36
	b->type = type;
Bob Halley's avatar
Bob Halley committed
37
38
39
	b->base = base;
	b->length = length;
	b->used = 0;
40
	b->current = 0;
41
	b->active = 0;
42
43
	b->mctx = NULL;
	ISC_LINK_INIT(b, link);
44
45
46
47
48
49
50
51
}

void
isc_buffer_invalidate(isc_buffer_t *b) {
	/*
	 * Make 'b' an invalid buffer.
	 */

52
	REQUIRE(ISC_BUFFER_VALID(b));
53
54
	REQUIRE(!ISC_LINK_LINKED(b, link));
	REQUIRE(b->mctx == NULL);
55
56
57
58
59
60
61
	
	b->magic = 0;
	b->type = 0;
	b->base = NULL;
	b->length = 0;
	b->used = 0;
	b->current = 0;
62
	b->active = 0;
63
64
65
66
67
68
69
70
}

unsigned int
isc_buffer_type(isc_buffer_t *b) {
	/*
	 * The type of 'b'.
	 */

71
	REQUIRE(ISC_BUFFER_VALID(b));
72
73

	return (b->type);
Bob Halley's avatar
Bob Halley committed
74
75
76
}

void
Bob Halley's avatar
Bob Halley committed
77
isc_buffer_region(isc_buffer_t *b, isc_region_t *r) {
Bob Halley's avatar
Bob Halley committed
78
79
80
81
	/*
	 * Make 'r' refer to the region of 'b'.
	 */

82
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
83
84
85
86
87
88
89
	REQUIRE(r != NULL);

	r->base = b->base;
	r->length = b->length;
}

void
Bob Halley's avatar
Bob Halley committed
90
isc_buffer_used(isc_buffer_t *b, isc_region_t *r) {
Bob Halley's avatar
Bob Halley committed
91
92
93
94
	/*
	 * Make 'r' refer to the used region of 'b'.
	 */

95
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
96
97
98
99
100
101
102
	REQUIRE(r != NULL);

	r->base = b->base;
	r->length = b->used;
}

void
Bob Halley's avatar
Bob Halley committed
103
isc_buffer_available(isc_buffer_t *b, isc_region_t *r) {
Bob Halley's avatar
Bob Halley committed
104
105
106
107
	/*
	 * Make 'r' refer to the available region of 'b'.
	 */

108
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
109
110
	REQUIRE(r != NULL);

Bob Halley's avatar
lint    
Bob Halley committed
111
	r->base = (unsigned char *)b->base + b->used;
Bob Halley's avatar
Bob Halley committed
112
113
114
115
	r->length = b->length - b->used;
}

void
Bob Halley's avatar
Bob Halley committed
116
isc_buffer_add(isc_buffer_t *b, unsigned int n) {
Bob Halley's avatar
Bob Halley committed
117
118
119
120
	/*
	 * Increase the 'used' region of 'b' by 'n' bytes.
	 */

121
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
122
123
124
125
126
127
	REQUIRE(b->used + n <= b->length);

	b->used += n;
}

void
Bob Halley's avatar
Bob Halley committed
128
isc_buffer_subtract(isc_buffer_t *b, unsigned int n) {
Bob Halley's avatar
Bob Halley committed
129
130
131
132
	/*
	 * Decrease the 'used' region of 'b' by 'n' bytes.
	 */

133
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
134
135
136
	REQUIRE(b->used >= n);

	b->used -= n;
137
138
139
140
	if (b->current > b->used)
		b->current = b->used;
	if (b->active > b->used)
		b->active = b->used;
Bob Halley's avatar
Bob Halley committed
141
142
143
}

void
Bob Halley's avatar
Bob Halley committed
144
isc_buffer_clear(isc_buffer_t *b) {
Bob Halley's avatar
Bob Halley committed
145
146
147
148
	/*
	 * Make the used region empty.
	 */

149
	REQUIRE(ISC_BUFFER_VALID(b));
150

Bob Halley's avatar
Bob Halley committed
151
	b->used = 0;
152
153
	b->current = 0;
	b->active = 0;
Bob Halley's avatar
Bob Halley committed
154
155
156
}

void
Bob Halley's avatar
Bob Halley committed
157
isc_buffer_consumed(isc_buffer_t *b, isc_region_t *r) {
Bob Halley's avatar
Bob Halley committed
158
159
160
161
	/*
	 * Make 'r' refer to the consumed region of 'b'.
	 */

162
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
163
164
165
	REQUIRE(r != NULL);

	r->base = b->base;
166
	r->length = b->current;
Bob Halley's avatar
Bob Halley committed
167
168
169
}

void
Bob Halley's avatar
Bob Halley committed
170
isc_buffer_remaining(isc_buffer_t *b, isc_region_t *r) {
Bob Halley's avatar
Bob Halley committed
171
172
173
174
	/*
	 * Make 'r' refer to the remaining region of 'b'.
	 */

175
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
176
177
	REQUIRE(r != NULL);

178
179
	r->base = (unsigned char *)b->base + b->current;
	r->length = b->used - b->current;
Bob Halley's avatar
Bob Halley committed
180
181
}

182
183
184
185
186
187
void
isc_buffer_active(isc_buffer_t *b, isc_region_t *r) {
	/*
	 * Make 'r' refer to the active region of 'b'.
	 */

188
	REQUIRE(ISC_BUFFER_VALID(b));
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
	REQUIRE(r != NULL);

	if (b->current < b->active) {
		r->base = (unsigned char *)b->base + b->current;
		r->length = b->active - b->current;
	} else {
		r->base = NULL;
		r->length = 0;
	}
}

void
isc_buffer_setactive(isc_buffer_t *b, unsigned int n) {
	unsigned int active;

	/*
	 * Sets the end of the active region 'n' bytes after current.
	 */

208
	REQUIRE(ISC_BUFFER_VALID(b));
209
210
211
212
213
214
	active = b->current + n;
	REQUIRE(active <= b->used);

	b->active = active;
}

Bob Halley's avatar
Bob Halley committed
215
void
Bob Halley's avatar
Bob Halley committed
216
isc_buffer_first(isc_buffer_t *b) {
Bob Halley's avatar
Bob Halley committed
217
218
219
220
	/*
	 * Make the consumed region empty.
	 */

221
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
222

223
	b->current = 0;
Bob Halley's avatar
Bob Halley committed
224
225
226
}

void
Bob Halley's avatar
Bob Halley committed
227
isc_buffer_forward(isc_buffer_t *b, unsigned int n) {
Bob Halley's avatar
Bob Halley committed
228
	/*
229
	 * Increase the 'consumed' region of 'b' by 'n' bytes.
Bob Halley's avatar
Bob Halley committed
230
231
	 */

232
	REQUIRE(ISC_BUFFER_VALID(b));
233
	REQUIRE(b->current + n <= b->used);
Bob Halley's avatar
Bob Halley committed
234
235
236
237
238

	b->current += n;
}

void
Bob Halley's avatar
Bob Halley committed
239
isc_buffer_back(isc_buffer_t *b, unsigned int n) {
Bob Halley's avatar
Bob Halley committed
240
241
242
243
	/*
	 * Decrease the 'consumed' region of 'b' by 'n' bytes.
	 */

244
	REQUIRE(ISC_BUFFER_VALID(b));
245
	REQUIRE(n <= b->current);
Bob Halley's avatar
Bob Halley committed
246
247
248
249
250

	b->current -= n;
}

void
Bob Halley's avatar
Bob Halley committed
251
isc_buffer_compact(isc_buffer_t *b) {
Bob Halley's avatar
Bob Halley committed
252
	unsigned int length;
253
	void *src;
Bob Halley's avatar
Bob Halley committed
254
255
256
257
258
259
260

	/*
	 * Compact the used region by moving the remaining region so it occurs
	 * at the start of the buffer.  The used region is shrunk by the size
	 * of the consumed region, and the consumed region is then made empty.
	 */

261
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
262

263
264
265
	src = (unsigned char *)b->base + b->current;
	length = b->used - b->current;
	(void)memmove(b->base, src, (size_t)length);
Bob Halley's avatar
Bob Halley committed
266

267
268
269
270
	if (b->active > b->current)
		b->active -= b->current;
	else
		b->active = 0;
271
	b->current = 0;
Bob Halley's avatar
Bob Halley committed
272
273
	b->used = length;
}
Bob Halley's avatar
Bob Halley committed
274

275
276
277
278
279
280
281
282
283
isc_uint8_t
isc_buffer_getuint8(isc_buffer_t *b) {
	unsigned char *cp;
	isc_uint8_t result;

	/*
	 * Read an unsigned 8-bit integer from 'b' and return it.
	 */

284
	REQUIRE(ISC_BUFFER_VALID(b));
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	REQUIRE(b->used - b->current >= 1);

	cp = b->base;
	cp += b->current;
	b->current += 1;
	result = ((unsigned int)(cp[0]));

	return (result);
}

void
isc_buffer_putuint8(isc_buffer_t *b, isc_uint8_t val)
{
	unsigned char *cp;

300
	REQUIRE(ISC_BUFFER_VALID(b));
301
302
303
304
305
306
307
308
	REQUIRE(b->used + 1 <= b->length);

	cp = b->base;
	cp += b->used;
	b->used += 1;
	cp[0] = (val & 0x00ff);
}

Bob Halley's avatar
Bob Halley committed
309
310
311
312
313
314
315
316
317
318
isc_uint16_t
isc_buffer_getuint16(isc_buffer_t *b) {
	unsigned char *cp;
	isc_uint16_t result;

	/*
	 * Read an unsigned 16-bit integer in network byte order from 'b',
	 * convert it to host byte order, and return it.
	 */

319
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
320
321
322
323
324
325
326
327
328
329
330
	REQUIRE(b->used - b->current >= 2);

	cp = b->base;
	cp += b->current;
	b->current += 2;
	result = ((unsigned int)(cp[0])) << 8;
	result |= ((unsigned int)(cp[1]));

	return (result);
}

331
332
333
334
335
void
isc_buffer_putuint16(isc_buffer_t *b, isc_uint16_t val)
{
	unsigned char *cp;

336
	REQUIRE(ISC_BUFFER_VALID(b));
337
338
339
340
341
342
343
344
345
	REQUIRE(b->used + 2 <= b->length);

	cp = b->base;
	cp += b->used;
	b->used += 2;
	cp[0] = (val & 0xff00) >> 8;
	cp[1] = (val & 0x00ff);
}

Bob Halley's avatar
Bob Halley committed
346
347
348
349
350
351
352
353
354
355
isc_uint32_t
isc_buffer_getuint32(isc_buffer_t *b) {
	unsigned char *cp;
	isc_uint32_t result;

	/*
	 * Read an unsigned 32-bit integer in network byte order from 'b',
	 * convert it to host byte order, and return it.
	 */

356
	REQUIRE(ISC_BUFFER_VALID(b));
Bob Halley's avatar
Bob Halley committed
357
358
359
360
361
362
363
364
365
366
367
368
	REQUIRE(b->used - b->current >= 4);

	cp = b->base;
	cp += b->current;
	b->current += 4;
	result = ((unsigned int)(cp[0])) << 24;
	result |= ((unsigned int)(cp[1])) << 16;
	result |= ((unsigned int)(cp[2])) << 8;
	result |= ((unsigned int)(cp[3]));

	return (result);
}
369
370
371
372
373
374

void
isc_buffer_putuint32(isc_buffer_t *b, isc_uint32_t val)
{
	unsigned char *cp;

375
	REQUIRE(ISC_BUFFER_VALID(b));
376
377
378
379
380
381
382
383
384
385
	REQUIRE(b->used + 4 <= b->length);

	cp = b->base;
	cp += b->used;
	b->used += 4;
	cp[0] = (val & 0xff000000) >> 24;
	cp[1] = (val & 0x00ff0000) >> 16;
	cp[2] = (val & 0x0000ff00) >> 8;
	cp[3] = (val & 0x000000ff);
}
386

Bob Halley's avatar
Bob Halley committed
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
isc_result_t
isc_buffer_copyregion(isc_buffer_t *b, isc_region_t *r) {
	unsigned char *base;
	unsigned int available;

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(r != NULL);

	base = (unsigned char *)b->base + b->used;
	available = b->length - b->used;
        if (r->length > available)
		return (ISC_R_NOSPACE);
	memcpy(base, r->base, r->length);
	b->used += r->length;

	return (ISC_R_SUCCESS);
}

405
isc_result_t
406
407
isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
		    unsigned int length, unsigned int type)
408
{
409
	isc_buffer_t *dbuf;
410
411
412
413

	REQUIRE(dynbuffer != NULL);
	REQUIRE(*dynbuffer == NULL);

414
	dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
415
416
417
	if (dbuf == NULL)
		return (ISC_R_NOMEMORY);

418
	isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
419
			length, type);
420
	dbuf->mctx = mctx;
421
422
423
424
425
426

	*dynbuffer = dbuf;

	return (ISC_R_SUCCESS);
}

427
void
428
isc_buffer_free(isc_buffer_t **dynbuffer)
429
430
{
	unsigned int real_length;
431
432
	isc_buffer_t *dbuf;
	isc_mem_t *mctx;
433
434

	REQUIRE(dynbuffer != NULL);
435
	REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
436
	REQUIRE((*dynbuffer)->mctx != NULL);
437
438
439
440

	dbuf = *dynbuffer;
	*dynbuffer = NULL;	/* destroy external reference */

441
442
443
444
	real_length = dbuf->length + sizeof(isc_buffer_t);
	mctx = dbuf->mctx;
	dbuf->mctx = NULL;
	isc_buffer_invalidate(dbuf);
445
446
447

	isc_mem_put(mctx, dbuf, real_length);
}