pike.git
/
src
/
modules
/
_Roxen
/
roxen.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/modules/_Roxen/roxen.c:47:
#define THB ((struct buffer_str *)Pike_fp->current_object->storage) struct buffer_str { unsigned int len, size, initial; unsigned char *data; int shift; }; #define INITIAL_BUF_LEN 4096
+
/*! @class Buffer A buffer, used for building strings. It's
+
*! conceptually similar to a string, but you can only @[add]
+
*! strings to it, and you can only @[get] the value from it once.
+
*!
+
*! There is a reason for those seemingly rather odd limitations,
+
*! it makes it possible to do some optimizations that really speed
+
*! things up.
+
*!
+
*! You do not need to use this class unless you add very many
+
*! strings together, or very large strings.
+
*!
+
*! For the fastest possible operation, write your code like this:
+
*!
+
*! @example{
+
*! String.Buffer b = String.Buffer( );
+
*!
+
*! function add = b->add;
+
*!
+
*! .. call add several times in code ...
+
*!
+
*! string result = b->get(); // also clears the buffer
+
*! @}
+
*/
+
static void f_buf_create( INT32 args )
-
+
/*! @method void create(int|void initial_size) Initializes a new
+
*! buffer. If no @[initial_size] is specified, 4096 is used. If you
+
*! know aproximately how big the buffer will be, you can optimize
+
*! the operation of add (slightly) by passing the size to this
+
*! function.
+
*/
{ struct buffer_str *str = THB; if( args && Pike_sp[-1].type == PIKE_T_INT ) str->initial = Pike_sp[-1].u.integer; else str->initial = INITIAL_BUF_LEN; } static void f_buf_add( INT32 args )
-
+
/*! @method void add(string data)
+
*! Adds @[data] to the buffer
+
*/
{ struct buffer_str *str = THB; struct pike_string *a; unsigned int l;
-
+
if( args != 1 || Pike_sp[-args].type != PIKE_T_STRING ) Pike_error("Illegal argument\n"); a = Pike_sp[-args].u.string; if(!(l = (unsigned)a->len) ) return;
-
if( str->
len && str->shift != a->
size
_shift
)
+
+
if(
!
str->size )
{
-
/* do something here.... */
+
str->shift = a->size_shift;
-
+
str->size = str->initial + sizeof( struct pike_string );
+
str->data = xalloc( str->size );
+
str->len = sizeof( struct pike_string );
}
-
-
l<<=
str->shift
;
-
-
if( !str
->size )
+
else if(
str->shift
<
a
->size
_shift
)
{
-
str->size
=
str->initial + sizeof
(
struct
pike_string
);
-
str->data
=
xalloc
(
str->size
);
-
str->len
=
sizeof(
struct
pike
_
string
);
+
static
void
f_buf_get
(
INT32
args
);
+
/*
This
will not win the "most optimal code of the year"
+
award, but it works. */
+
f_buf_get
(
0
);
+
f_add(
2
);
+
f
_
buf_add(
1
);
+
return;
}
-
+
l<<=str->shift;
+
while( str->size < ((unsigned)l+str->len) ) { str->size *= 2; str->data = realloc( str->data, str->size ); if(!str->data ) { int sz = str->size; str->len = 0; str->size = 0; Pike_error( "Malloc %d failed!\n", sz ); } }
-
+
#ifdef DEBUG
+
if( str->shift < a->size_shift )
+
fatal("Impossible!\n");
+
#endif
+
/* str->shift is always greater than or equal to a->size_shift here. */
-
MEMCPY( str->data+str->len, a->str, l );
+
if( a->size_shift == str->shift )
+
MEMCPY(
(
str->data+str->len
)
, a->str, l );
+
else
+
if( a->size_shift )
+
convert_1_to_2((p_wchar2 *)(str->data+str->len),
+
(p_wchar1 *)a->str, a->len);
+
else
+
if( str->shift & 1 )
+
convert_0_to_1((p_wchar1 *)(str->data+str->len),
+
(p_wchar0 *)a->str, a->len);
+
else
+
convert_0_to_2((p_wchar2 *)(str->data+str->len),
+
(p_wchar0 *)a->str, a->len);
str->len += l; pop_stack(); push_int( str->len ); } static void f_buf_get( INT32 args )
-
+
/*! @method string get( )
+
*! Get the data from the buffer.
+
*! @note This will clear the data in the buffer
+
*/
{ struct buffer_str *str = THB; int len = str->len-sizeof(struct pike_string); if( len <= 0 ) { push_text(""); return; } if( str->len < 64 )