e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
1b10db2002-10-08Martin Nilsson 
22363a2002-05-30Per Hedbor #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"
67c6c42002-11-07Martin Nilsson /* Source: Pike-Stream
22363a2002-05-30Per Hedbor  * Argument: Stdio.File lookalike with read * callback support (set_read_callback) */ static struct program *callback_program; struct pf_source { struct source s; struct object *obj; struct object *cb_obj; struct pike_string *str;
a42f7c2019-06-21Stephen R. van den Berg  char *data; size_t available; int eof;
22363a2002-05-30Per Hedbor  void (*when_data_cb)( void *a ); void *when_data_cb_arg; size_t len, skip; }; struct callback_prog { struct pf_source *s; };
feb6822009-08-13Henrik Grubbström (Grubba) static void setup_callbacks( struct source *src )
22363a2002-05-30Per Hedbor {
feb6822009-08-13Henrik Grubbström (Grubba)  struct pf_source *s = (struct pf_source *)src;
a42f7c2019-06-21Stephen R. van den Berg  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();
22363a2002-05-30Per Hedbor }
feb6822009-08-13Henrik Grubbström (Grubba) static void remove_callbacks( struct source *src )
22363a2002-05-30Per Hedbor {
feb6822009-08-13Henrik Grubbström (Grubba)  struct pf_source *s = (struct pf_source *)src;
a42f7c2019-06-21Stephen R. van den Berg  if (s->obj->prog) { push_int(0); apply( s->obj, "set_read_callback", 1 ); pop_stack(); push_int(0); apply( s->obj, "set_close_callback", 1 ); pop_stack(); }
22363a2002-05-30Per Hedbor }
eb94452019-06-11Stephen R. van den Berg static void frees(struct pf_source*s) { if (s->str) { free_string(s->str); s->str = 0; } }
22363a2002-05-30Per Hedbor 
feb6822009-08-13Henrik Grubbström (Grubba) static struct data get_data( struct source *src, off_t len )
22363a2002-05-30Per Hedbor {
feb6822009-08-13Henrik Grubbström (Grubba)  struct pf_source *s = (struct pf_source *)src;
eb94452019-06-11Stephen R. van den Berg  struct data res;
b2986f2002-07-05Per Hedbor 
a42f7c2019-06-21Stephen R. van den Berg  res.len = s->available; if (s->eof) s->s.eof = 1;
eb94452019-06-11Stephen R. van den Berg  if (s->available) {
a42f7c2019-06-21Stephen R. van den Berg  res.data = s->data;
eb94452019-06-11Stephen R. van den Berg  s->available = 0; } else {
22363a2002-05-30Per Hedbor  /* No data available, but there should be in the future (no EOF, nor * out of the range of data to send as specified by the arguments to * source_stream_make) */ res.len = -2;
ba96832019-06-14Stephen R. van den Berg  setup_callbacks(src);
eb94452019-06-11Stephen R. van den Berg  }
22363a2002-05-30Per Hedbor  return res; }
feb6822009-08-13Henrik Grubbström (Grubba) static void free_source( struct source *src )
22363a2002-05-30Per Hedbor {
eb94452019-06-11Stephen R. van den Berg  struct pf_source *s = (struct pf_source *)src;
feb6822009-08-13Henrik Grubbström (Grubba)  remove_callbacks( src );
eb94452019-06-11Stephen R. van den Berg  frees(s); free_object(s->cb_obj); free_object(s->obj);
22363a2002-05-30Per Hedbor } 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 );
a42f7c2019-06-21Stephen R. van den Berg  if (args < 2 || TYPEOF(Pike_sp[-1]) != PIKE_T_STRING) { s->eof = 1; /* signal EOF */ pop_n_elems(args); if (!s->available) goto cb;
8de3272019-06-21Stephen R. van den Berg  } else {
a42f7c2019-06-21Stephen R. van den Berg  size_t slen;
8de3272019-06-21Stephen R. van den Berg  frees(s); s->str = Pike_sp[-1].u.string;
a42f7c2019-06-21Stephen R. van den Berg  slen = s->str->len; if (!slen) Pike_error("Shuffler: Read callback passing a zero size string\n"); if (s->str->size_shift) Pike_error("Shuffler: Wide strings are not supported\n"); if (slen > s->skip) { s->available = slen -= s->skip; s->data = s->str->str + s->skip; s->skip = 0; Pike_sp--; args--; } else { s->skip -= slen; s->str = 0; } pop_n_elems(args); cb: if( s->when_data_cb ) s->when_data_cb( s->when_data_cb_arg );
22363a2002-05-30Per Hedbor  }
8de3272019-06-21Stephen R. van den Berg  push_int(0);
22363a2002-05-30Per Hedbor }
feb6822009-08-13Henrik Grubbström (Grubba) static void set_callback( struct source *src, void (*cb)( void *a ), void *a )
22363a2002-05-30Per Hedbor {
feb6822009-08-13Henrik Grubbström (Grubba)  struct pf_source *s = (struct pf_source *)src;
22363a2002-05-30Per Hedbor  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;
017b572011-10-28Henrik Grubbström (Grubba)  if( (TYPEOF(*s) != PIKE_T_OBJECT) ||
22363a2002-05-30Per Hedbor  (find_identifier("set_read_callback",s->u.object->prog)==-1) ) return 0;
13670c2015-05-25Martin Nilsson 
97611f2019-06-17Stephen R. van den Berg  if (!(res = calloc( 1, sizeof( struct pf_source)))) return 0;
22363a2002-05-30Per Hedbor  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;
50ea682003-03-14Henrik Grubbström (Grubba)  add_ref(res->obj);
22363a2002-05-30Per Hedbor  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 );
362e4e2016-01-29Martin Nilsson  ADD_FUNCTION("`()", f_got_data, tFunc(tInt tStr,tVoid),0);
22363a2002-05-30Per Hedbor  callback_program = end_program(); }