|
|
|
|
|
|
#include "global.h" |
#include "bignum.h" |
#include "object.h" |
#include "interpret.h" |
|
#include "fdlib.h" |
#include "fd_control.h" |
|
#include <sys/stat.h> |
|
#include "shuffler.h" |
|
|
|
|
|
static struct program *callback_program; |
|
struct pf_source |
{ |
struct source s; |
|
struct object *obj; |
struct object *cb_obj; |
struct pike_string *str; |
|
void (*when_data_cb)( void *a ); |
void *when_data_cb_arg; |
size_t len, skip; |
}; |
|
|
struct callback_prog |
{ |
struct pf_source *s; |
}; |
|
static void setup_callbacks( struct source *src ) |
{ |
struct pf_source *s = (struct pf_source *)src; |
if( !s->str ) |
{ |
ref_push_object( s->cb_obj ); |
apply( s->obj, "set_read_callback", 1 ); |
pop_stack(); |
ref_push_object( s->cb_obj ); |
apply( s->obj, "set_close_callback", 1 ); |
pop_stack(); |
} |
} |
|
static void remove_callbacks( struct source *src ) |
{ |
struct pf_source *s = (struct pf_source *)src; |
push_int(0); |
apply( s->obj, "set_read_callback", 1 ); |
pop_stack(); |
push_int(0); |
apply( s->obj, "set_close_callback", 1 ); |
pop_stack(); |
} |
|
|
static struct data get_data( struct source *src, off_t len ) |
{ |
struct pf_source *s = (struct pf_source *)src; |
struct data res = { 0, 0, 0, NULL }; |
char *buffer = NULL; |
|
if( s->str ) |
{ |
len = s->str->len; |
if( s->skip ) |
{ |
if( s->skip >= (size_t)s->str->len ) |
{ |
s->skip -= (size_t)s->str->len; |
res.len = -2; |
return res; |
} |
len -= s->skip; |
buffer = malloc( len ); |
memcpy( buffer, s->str->str+s->skip, len); |
} |
else |
{ |
if( s->len > 0 ) |
{ |
if( s->len < (size_t)len ) |
len = s->len; |
s->len -= len; |
if( !s->len ) |
s->s.eof = 1; |
} |
buffer = malloc( len ); |
memcpy( buffer, s->str->str, len ); |
} |
res.data = buffer; |
res.len = len; |
res.do_free = 1; |
free_string( s->str ); |
s->str = 0; |
setup_callbacks( src ); |
} |
else if( !s->len ) |
s->s.eof = 1; |
else |
|
|
|
|
res.len = -2; |
|
return res; |
} |
|
static void free_source( struct source *src ) |
{ |
remove_callbacks( src ); |
free_object(((struct pf_source *)src)->cb_obj); |
free_object(((struct pf_source *)src)->obj); |
} |
|
static void f_got_data( INT32 args ) |
{ |
struct pf_source *s = |
((struct callback_prog *)Pike_fp->current_object->storage)->s; |
|
remove_callbacks( (struct source *)s ); |
|
if( s->str || |
TYPEOF(Pike_sp[-1]) != PIKE_T_STRING || |
Pike_sp[-1].u.string->size_shift || |
Pike_sp[-1].u.string->len == 0) |
{ |
s->s.eof = 1; |
pop_n_elems(args); |
push_int(0); |
return; |
} |
s->str = Pike_sp[-1].u.string; |
Pike_sp--; |
pop_n_elems(args-1); |
push_int(0); |
|
if( s->when_data_cb ) |
s->when_data_cb( s->when_data_cb_arg ); |
} |
|
static void set_callback( struct source *src, void (*cb)( void *a ), void *a ) |
{ |
struct pf_source *s = (struct pf_source *)src; |
s->when_data_cb = cb; |
s->when_data_cb_arg = a; |
} |
|
struct source *source_pikestream_make( struct svalue *s, |
INT64 start, INT64 len ) |
{ |
struct pf_source *res; |
|
if( (TYPEOF(*s) != PIKE_T_OBJECT) || |
(find_identifier("set_read_callback",s->u.object->prog)==-1) ) |
return 0; |
|
res = calloc( 1, sizeof( struct pf_source ) ); |
if( !res ) return NULL; |
|
res->len = len; |
res->skip = start; |
|
res->s.get_data = get_data; |
res->s.free_source = free_source; |
res->s.set_callback = set_callback; |
res->s.setup_callbacks = setup_callbacks; |
res->s.remove_callbacks = remove_callbacks; |
res->obj = s->u.object; |
add_ref(res->obj); |
|
res->cb_obj = clone_object( callback_program, 0 ); |
((struct callback_prog *)res->cb_obj->storage)->s = res; |
|
return (struct source *)res; |
} |
|
void source_pikestream_exit( ) |
{ |
free_program( callback_program ); |
} |
|
void source_pikestream_init( ) |
{ |
start_new_program(); |
ADD_STORAGE( struct callback_prog ); |
add_function("`()", f_got_data, "function(int,string:void)",0); |
callback_program = end_program(); |
} |
|
|