package KinoSearch::Util::ByteBuf;
use strict;
use warnings;
use KinoSearch::Util::ToolSet;
use base qw( KinoSearch::Util::CClass );
1;
__END__
__H__
#ifndef H_KINOSEARCH_UTIL_BYTEBUF
#define H_KINOSEARCH_UTIL_BYTEBUF 1
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "KinoSearchUtilCarp.h"
#include "KinoSearchUtilMemManager.h"
typedef struct bytebuf {
char *ptr;
I32 size; /* number of valid chars */
I32 cap; /* allocated bytes, including any null termination */
U32 flags;
} ByteBuf;
ByteBuf* Kino_BB_new(I32);
ByteBuf* Kino_BB_new_string(char*, I32);
ByteBuf* Kino_BB_new_view(char*, I32);
ByteBuf* Kino_BB_clone(ByteBuf*);
void Kino_BB_assign_view(ByteBuf*, char*, I32);
void Kino_BB_assign_string(ByteBuf*, char*, I32);
void Kino_BB_cat_string(ByteBuf*, char*, I32);
void Kino_BB_grow(ByteBuf*, I32);
I32 Kino_BB_compare(ByteBuf*, ByteBuf*);
void Kino_BB_destroy(ByteBuf*);
#endif /* include guard */
__C__
#include "KinoSearchUtilByteBuf.h"
#define KINO_BB_VIEW 0x1
/* Return a pointer to a new ByteBuf capable of holding a string of [size]
* bytes. Though the ByteBuf's size member is set, none of the allocated
* memory is initialized.
*/
ByteBuf*
Kino_BB_new(I32 size) {
ByteBuf *bb;
/* allocate */
Kino_New(0, bb, 1, ByteBuf);
Kino_New(0, bb->ptr, size + 1, char);
/* assign */
bb->size = size;
bb->cap = size + 1;
bb->flags = 0;
return bb;
}
/* Return a pointer to a new ByteBuf which holds a copy of the passed in
* string.
*/
ByteBuf*
Kino_BB_new_string(char *ptr, I32 size) {
ByteBuf *bb;
/* allocate */
Kino_New(0, bb, 1, ByteBuf);
Kino_New(0, bb->ptr, size + 1, char);
/* copy */
Copy(ptr, bb->ptr, size, char);
/* assign */
bb->size = size;
bb->cap = size + 1;
bb->ptr[size] = '\0'; /* null terminate */
bb->flags = 0;
return bb;
}
/* Return a pointer to a new "view" ByteBuf, offing a persective on the passed
* in string.
*/
ByteBuf*
Kino_BB_new_view(char *ptr, I32 size) {
ByteBuf *bb;
/* allocate */
Kino_New(0, bb, 1, ByteBuf);
/* assign */
bb->ptr = ptr;
bb->size = size;
bb->cap = 0;
bb->flags = 0 | KINO_BB_VIEW;
return bb;
}
/* Return a "real" copy of the ByteBuf (regardless of whether it was a "view"
* ByteBuf before).
*/
ByteBuf*
Kino_BB_clone(ByteBuf *bb) {
if (bb == NULL)
return NULL;
else
return Kino_BB_new_string(bb->ptr, bb->size);
}
/* Assign the ptr and size members to the passed in values. Downgrade the
* ByteBuf to a "view" ByteBuf and free any existing assigned memory if
* necessary.
*/
void
Kino_BB_assign_view(ByteBuf *bb, char*ptr, I32 size) {
/* downgrade the ByteBuf to a view */
if (!bb->flags & KINO_BB_VIEW) {
Kino_Safefree(bb->ptr);
bb->flags |= KINO_BB_VIEW;
}
/* assign */
bb->ptr = ptr;
bb->size = size;
}
/* Copy the passed-in string into the ByteBuf. Allocate more memory if
* necessary.
*/
void
Kino_BB_assign_string(ByteBuf *bb, char* ptr, I32 size) {
Kino_BB_grow(bb, size);
Copy(ptr, bb->ptr, size, char);
bb->size = size;
}
/* Concatenate the passed-in string onto the end of the ByteBuf. Allocate more
* memory as needed.
*/
void
Kino_BB_cat_string(ByteBuf *bb, char* ptr, I32 size) {
I32 new_size;
new_size = bb->size + size;
Kino_BB_grow(bb, new_size);
Copy(ptr, (bb->ptr + bb->size), size, char);
bb->size = new_size;
}
/* Assign more memory to the ByteBuf, if it doesn't already have enough room
* to hold a string of [size] bytes. Cannot shrink the allocation.
*/
void
Kino_BB_grow(ByteBuf *bb, I32 new_size) {
if (bb->flags & KINO_BB_VIEW)
Kino_confess("grow called on 'view' ByteBuf");
/* bail out if the buffer's already at least as big as required */
if (bb->cap > new_size)
return;
Kino_Renew(bb->ptr, (new_size + 1), char);
bb->cap = new_size;
}
void
Kino_BB_destroy(ByteBuf *bb) {
if (bb == NULL)
return;
if (!(bb->flags & KINO_BB_VIEW))
Kino_Safefree(bb->ptr);
Kino_Safefree(bb);
}
/* Lexically compare two ByteBufs.
*/
I32
Kino_BB_compare(ByteBuf *a, ByteBuf *b) {
I32 size;
I32 comparison;
size = a->size < b->size ? a->size : b->size;
comparison = memcmp(a->ptr, b->ptr, size);
if (comparison == 0 && a->size != b->size)
comparison = a->size < b->size ? -1 : 1;
return comparison;
}
__POD__
=begin devdocs
=head1 NAME
KinoSearch::Util::ByteBuf - stripped down scalar
=head1 DESCRIPTION
The ByteBuf is a C struct that's essentially a growable string of char. It's
like a stripped down scalar that can only deal with strings. It knows its own
size and capacity, so it can contain arbitrary binary data.
"View" ByteBufs don't own their own strings.
=head1 COPYRIGHT
Copyright 2005-2006 Marvin Humphrey
=head1 LICENSE, DISCLAIMER, BUGS, etc.
See L<KinoSearch|KinoSearch> version 0.13.
=end devdocs
=cut