GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/../common/bytebuf.c Lines: 0 77 0.0 %
Date: 2017-11-07 Branches: 0 34 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: bytebuf.c,v 1.8 2015/12/05 18:43:36 mmcc Exp $ */
2
/*-
3
 * Copyright (c) 2009 Internet Initiative Japan 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
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 */
27
/**@file
28
 * bytebuffer provides 'byte buffer' helper methods.
29
 *
30
 * Example:<pre>
31
 *	bytebuffer *buf = bytebuffer_create(BUFSIZ);
32
 *	int sz = read(STDIN_FILENO, bytebuffer_pointer(buf),
33
 *	    bytebuffer_remaining(buf));
34
 *	if (sz > 0) {
35
 *	    bytebuffer_put(buf, BYTEBUFFER_PUT_DIRECT, sz);
36
 *	    bytebuffer_flip(buf);
37
 *
38
 *	    sz = write(STDOUT_FILENO, bytebuffer_pointer(buf),
39
 *		bytebuffer_remaining(buf));
40
 *	    bytebuffer_compact(buf);
41
 *	}</pre>
42
 *
43
 * @author Yasuoka Masahiko
44
 * $Id: bytebuf.c,v 1.8 2015/12/05 18:43:36 mmcc Exp $
45
 */
46
#include <stdlib.h>
47
#include <string.h>
48
#include <errno.h>
49
50
#ifdef	BYTEBUF_DEBUG
51
#include <stdio.h>
52
#endif
53
54
#ifndef	BYTEBUF_ASSERT
55
#ifdef	BYTEBUF_DEBUG
56
#define	BYTEBUF_ASSERT(cond)						\
57
	if (!(cond)) {						\
58
	    fprintf(stderr,					\
59
		"\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\
60
		, __func__, __FILE__, __LINE__);		\
61
	    abort(); 						\
62
	}
63
#else
64
#define	BYTEBUF_ASSERT(cond)
65
#endif
66
#endif
67
68
#include "bytebuf.h"
69
70
struct _bytebuffer {
71
	/** current position */
72
	int 	position;
73
	/** current limit */
74
	int	limit;
75
	/** position mark*/
76
	int 	mark;
77
	/** capacity of buffer */
78
	size_t 	capacity;
79
	/** allocated memory area */
80
	void	*data;
81
};
82
83
/**
84
 * Create a bytebuffer and allocate memory area.
85
 *
86
 * @param	capacity	Capacity of allocating memory.  If zero or
87
 *		    negative value is specified, this function don't allocate
88
 *		    memory.
89
 */
90
bytebuffer *
91
bytebuffer_create(size_t capacity)
92
{
93
	bytebuffer *_this = NULL;
94
95
	if ((_this = calloc(1, sizeof(bytebuffer))) == NULL)
96
		return NULL;
97
98
	if (capacity > 0) {
99
		if ((_this->data = calloc(1, capacity)) == NULL)
100
			goto fail;
101
		_this->capacity = capacity;
102
	} else
103
		_this->capacity = 0;
104
105
	_this->limit = _this->capacity;
106
	_this->mark = -1;
107
	return _this;
108
fail:
109
	free(_this);
110
	return NULL;
111
}
112
113
/**
114
 * Create a bytebuffer using existing memory area.  This memory area will
115
 * be freed by bytebuffer's destructor.
116
 *
117
 * @data		the pointer to existing memory area
118
 * @param capacity	capacity of 'data'.
119
 */
120
bytebuffer *
121
bytebuffer_wrap(void *data, size_t capacity)
122
{
123
	bytebuffer *_this;
124
125
	if ((_this = bytebuffer_create(0)) == NULL)
126
		return NULL;
127
128
	_this->data = data;
129
	_this->capacity = capacity;
130
	_this->mark = -1;
131
132
	return _this;
133
}
134
135
/**
136
 * Unwrap memory from bytebuffer.
137
 *
138
 * @param _this		the bytebuffer object.
139
 */
140
void *
141
bytebuffer_unwrap(bytebuffer *_this)
142
{
143
	void *rval;
144
145
	rval = _this->data;
146
	_this->data = NULL;
147
	_this->capacity = 0;
148
	_this->position = 0;
149
	_this->limit = 0;
150
	_this->mark = -1;
151
152
	return rval;
153
}
154
155
/**
156
 * Change capacity of this buffer.
157
 *
158
 * @param _this		the bytebuffer object.
159
 * @param capacity	new capacity.
160
 */
161
int
162
bytebuffer_realloc(bytebuffer *_this, size_t capacity)
163
{
164
	void *new_data;
165
166
	BYTEBUF_ASSERT(_this->limit <= capacity);
167
168
	if (_this->limit > capacity) {
169
		errno = EINVAL;
170
		return -1;
171
	}
172
173
	if ((new_data = realloc(_this->data, capacity)) == NULL)
174
		return -1;
175
176
	_this->data = new_data;
177
	if (_this->limit == _this->capacity)
178
		_this->limit = capacity;
179
	_this->capacity = capacity;
180
181
	return 0;
182
}
183
184
/**
185
 * Compact this buffer.  the bytes between position and limit are copied
186
 * to the beginning of the buffer.
187
 *
188
 * @param _this		the bytebuffer object.
189
 */
190
void
191
bytebuffer_compact(bytebuffer *_this)
192
{
193
	int len;
194
195
	len = bytebuffer_remaining(_this);
196
197
	if (len <= 0)
198
		len = 0;
199
	else if (_this->position != 0)
200
		memmove(_this->data,
201
		    (const char *)_this->data + _this->position, (size_t)len);
202
203
	_this->position = len;
204
	_this->limit = _this->capacity;
205
	_this->mark = -1;
206
}
207
208
static int bytebuffer_direct0;
209
/**
210
 * BYTEBUFFER_PUT_DIRECT specifies the data that has been written already by
211
 * direct access.
212
 */
213
const void * BYTEBUFFER_PUT_DIRECT = &bytebuffer_direct0;
214
215
/**
216
 * BYTEBUFFER_GET_DIRECT specifies the data that has been read already by
217
 * direct access.
218
 */
219
void * BYTEBUFFER_GET_DIRECT = &bytebuffer_direct0;
220
221
/**
222
 * Write the given data to the buffer.
223
 * If buffer is too small, this function returns <code>NULL</code> and
224
 * <code>errno</code> is <code>ENOBUFS</code>
225
 *
226
 * @param _this		the bytebuffer object.
227
 * @param src		source data.  To specify the data that has been
228
 *			written already by direct access, use
229
 *			{@link ::BYTEBUFFER_PUT_DIRECT} for putting the data.
230
 *			NULL is the same {@link ::BYTEBUFFER_PUT_DIRECT}
231
 *			at least on this version, but using NULL is deprecated.
232
 * @param srclen	length of the source data.
233
 * @see ::BYTEBUFFER_PUT_DIRECT
234
 */
235
void *
236
bytebuffer_put(bytebuffer *_this, const void *src, size_t srclen)
237
{
238
	void *rval;
239
240
	BYTEBUF_ASSERT(_this != NULL);
241
	BYTEBUF_ASSERT(srclen > 0);
242
243
	if (srclen > bytebuffer_remaining(_this)) {
244
		errno = ENOBUFS;
245
		return NULL;
246
	}
247
	rval = (char *)_this->data + _this->position;
248
249
	if (src != NULL && src != BYTEBUFFER_PUT_DIRECT)
250
		memcpy(rval, src, srclen);
251
252
	_this->position += srclen;
253
254
	return rval;
255
}
256
257
/*
258
 * Transfer data from this buffer to the given destination memory.
259
 * If the given buffer is too small, this function returns <code>NULL</code>
260
 * and <code>errno</code> is <code>ENOBUFS</code>
261
 *
262
 * @param	dst	pointer of the destination memory.  Specify NULL
263
 *			to skip transferring the data.
264
 * @param	dstlne	memory size of the destination.
265
 */
266
void *
267
bytebuffer_get(bytebuffer *_this, void *dst, size_t dstlen)
268
{
269
	BYTEBUF_ASSERT(_this != NULL);
270
	BYTEBUF_ASSERT(dstlen > 0);
271
272
	if (dstlen > bytebuffer_remaining(_this)) {
273
		errno = ENOBUFS;
274
		return NULL;
275
	}
276
	if (dst != NULL && dst != BYTEBUFFER_GET_DIRECT)
277
		memcpy(dst, (char *)_this->data + _this->position, dstlen);
278
279
	_this->position += dstlen;
280
281
	return dst;
282
}
283
284
/** Returns this buffer's position */
285
int
286
bytebuffer_position(bytebuffer *_this)
287
{
288
	BYTEBUF_ASSERT(_this != NULL);
289
290
	return _this->position;
291
}
292
293
/** Returns this buffer's limit */
294
int
295
bytebuffer_limit(bytebuffer *_this)
296
{
297
	BYTEBUF_ASSERT(_this != NULL);
298
299
	return _this->limit;
300
}
301
302
/** Returns this buffer's capacity */
303
int
304
bytebuffer_capacity(bytebuffer *_this)
305
{
306
	BYTEBUF_ASSERT(_this != NULL);
307
308
	return _this->capacity;
309
}
310
311
/** Returns a pointer to current position */
312
void *
313
bytebuffer_pointer(bytebuffer *_this)
314
{
315
	BYTEBUF_ASSERT(_this != NULL);
316
317
	return (char *)_this->data + _this->position;
318
}
319
320
/** Returns the number of byte between current position and the limit*/
321
size_t
322
bytebuffer_remaining(bytebuffer *_this)
323
{
324
	BYTEBUF_ASSERT(_this != NULL);
325
	BYTEBUF_ASSERT(_this->limit >= _this->position);
326
327
	return _this->limit - _this->position;
328
}
329
330
/** Returns whether there are data between current position and the limit */
331
int
332
bytebuffer_has_remaining(bytebuffer *_this)
333
{
334
	BYTEBUF_ASSERT(_this != NULL);
335
336
	return bytebuffer_remaining(_this) > 0;
337
}
338
339
/**
340
 * Flip this buffer.
341
 * The limit is set to the position and the position is set zero.
342
 */
343
void
344
bytebuffer_flip(bytebuffer *_this)
345
{
346
	BYTEBUF_ASSERT(_this != NULL);
347
348
	_this->limit = _this->position;
349
	_this->position = 0;
350
	_this->mark = -1;
351
}
352
353
/**
354
 * Rewind this buffer.
355
 * The position is set to zero.
356
 */
357
void
358
bytebuffer_rewind(bytebuffer *_this)
359
{
360
	BYTEBUF_ASSERT(_this != NULL);
361
362
	_this->position = 0;
363
	_this->mark = -1;
364
}
365
366
/**
367
 * Clear this buffer.
368
 * The position is set to zero.
369
 */
370
void
371
bytebuffer_clear(bytebuffer *_this)
372
{
373
	BYTEBUF_ASSERT(_this != NULL);
374
375
	_this->limit = _this->capacity;
376
	_this->position = 0;
377
	_this->mark = -1;
378
}
379
380
/** mark the current position.  */
381
void
382
bytebuffer_mark(bytebuffer *_this)
383
{
384
	BYTEBUF_ASSERT(_this != NULL);
385
386
	_this->mark = _this->position;
387
}
388
389
/** reset the position to the mark.  */
390
void
391
bytebuffer_reset(bytebuffer *_this)
392
{
393
	BYTEBUF_ASSERT(_this != NULL);
394
	BYTEBUF_ASSERT(_this->mark >= 0);
395
396
	if (_this->mark >= 0)
397
		_this->position = _this->mark;
398
}
399
400
/**
401
 * Destroy bytebuffer object.
402
 */
403
void
404
bytebuffer_destroy(bytebuffer *_this)
405
{
406
	BYTEBUF_ASSERT(_this != NULL);
407
408
	if (_this != NULL) {
409
		free(_this->data);
410
		free(_this);
411
	}
412
}