/* $OpenBSD: bytebuf.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /**@file * bytebuffer provides 'byte buffer' helper methods. * * Example:
* bytebuffer *buf = bytebuffer_create(BUFSIZ); * int sz = read(STDIN_FILENO, bytebuffer_pointer(buf), * bytebuffer_remaining(buf)); * if (sz > 0) { * bytebuffer_put(buf, BYTEBUFFER_PUT_DIRECT, sz); * bytebuffer_flip(buf); * * sz = write(STDOUT_FILENO, bytebuffer_pointer(buf), * bytebuffer_remaining(buf)); * bytebuffer_compact(buf); * }* * @author Yasuoka Masahiko * $Id: bytebuf.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */ #include
NULL
and
* errno
is ENOBUFS
*
* @param _this the bytebuffer object.
* @param src source data. To specify the data that has been
* written already by direct access, use
* {@link ::BYTEBUFFER_PUT_DIRECT} for putting the data.
* NULL is the same {@link ::BYTEBUFFER_PUT_DIRECT}
* at least on this version, but using NULL is deprecated.
* @param srclen length of the source data.
* @see ::BYTEBUFFER_PUT_DIRECT
*/
void *
bytebuffer_put(bytebuffer *_this, const void *src, size_t srclen)
{
void *rval;
BYTEBUF_ASSERT(_this != NULL);
BYTEBUF_ASSERT(srclen > 0);
if (srclen > bytebuffer_remaining(_this)) {
errno = ENOBUFS;
return NULL;
}
rval = (char *)_this->data + _this->position;
if (src != NULL && src != BYTEBUFFER_PUT_DIRECT)
memcpy(rval, src, srclen);
_this->position += srclen;
return rval;
}
/*
* Transfer data from this buffer to the given destination memory.
* If the given buffer is too small, this function returns NULL
* and errno
is ENOBUFS
*
* @param dst pointer of the destination memory. Specify NULL
* to skip transfering the data.
* @param dstlne memory size of the destination.
*/
void *
bytebuffer_get(bytebuffer *_this, void *dst, size_t dstlen)
{
BYTEBUF_ASSERT(_this != NULL);
BYTEBUF_ASSERT(dstlen > 0);
if (dstlen > bytebuffer_remaining(_this)) {
errno = ENOBUFS;
return NULL;
}
if (dst != NULL && dst != BYTEBUFFER_GET_DIRECT)
memcpy(dst, (char *)_this->data + _this->position, dstlen);
_this->position += dstlen;
return dst;
}
/** Returns this buffer's position */
int
bytebuffer_position(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
return _this->position;
}
/** Returns this buffer's limit */
int
bytebuffer_limit(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
return _this->limit;
}
/** Returns this buffer's capacity */
int
bytebuffer_capacity(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
return _this->capacity;
}
/** Returns a pointer to current position */
void *
bytebuffer_pointer(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
return (char *)_this->data + _this->position;
}
/** Returns the number of byte between current position and the limit*/
size_t
bytebuffer_remaining(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
BYTEBUF_ASSERT(_this->limit >= _this->position);
return _this->limit - _this->position;
}
/** Returns whether there are data between current position and the limit */
int
bytebuffer_has_remaining(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
return bytebuffer_remaining(_this) > 0;
}
/**
* Flip this buffer.
* The limit is set to the position and the position is set zero.
*/
void
bytebuffer_flip(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
_this->limit = _this->position;
_this->position = 0;
_this->mark = -1;
}
/**
* Rewind this buffer.
* The position is set to zero.
*/
void
bytebuffer_rewind(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
_this->position = 0;
_this->mark = -1;
}
/**
* Clear this buffer.
* The position is set to zero.
*/
void
bytebuffer_clear(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
_this->limit = _this->capacity;
_this->position = 0;
_this->mark = -1;
}
/** mark the current position. */
void
bytebuffer_mark(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
_this->mark = _this->position;
}
/** reset the position to the mark. */
void
bytebuffer_reset(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
BYTEBUF_ASSERT(_this->mark >= 0);
if (_this->mark >= 0)
_this->position = _this->mark;
}
/**
* Destroy bytebuffer object.
*/
void
bytebuffer_destroy(bytebuffer *_this)
{
BYTEBUF_ASSERT(_this != NULL);
if (_this != NULL) {
if (_this->data != NULL)
free(_this->data);
free(_this);
}
}