pike.git / src / modules / _Stdio / buffer.cmod

version» Context lines:

pike.git/src/modules/_Stdio/buffer.cmod:83:    *!    *! @note    *! The "avoid copy" part means that a IOBuffer will never shrink    *! unless you call the @[trim] function.    *!    */   PIKECLASS IOBuffer   {    CVAR IOBuffer b;    -  static void io_set_error_mode( IOBuffer *io, int m ) +  static void io_set_error_mode( IOBuffer *io, struct program *m )    { -  +  if( m ) m->refs++; +  if( io->error_mode ) free_program( io->error_mode );    io->error_mode = m;    }       static size_t io_len( IOBuffer *io )    {    return io->len-io->offset;    }       static void io_unlock( IOBuffer *io )    {
pike.git/src/modules/_Stdio/buffer.cmod:181:    }       static void io_range_error( IOBuffer *io, int howmuch )    {    /* throw error if so desired. */    if( io->error_mode )    {    push_text("Trying to read %d outside allowed range\n");    push_int(howmuch);    f_sprintf(2); -  push_object(clone_object(buffer_error_program, 1)); +  push_object(clone_object(io->error_mode, 1));    f_throw(1);    }    }       static int io_avail( IOBuffer *io, int len )    {    if( len < 0 || len + io->offset > io->len )    {    io_range_error( io, len );    return 0;
pike.git/src/modules/_Stdio/buffer.cmod:341:       /* pike functions */      #undef THIS   #define THIS (&(((struct IOBuffer_struct *)Pike_fp->current_storage)->b))       /*! @decl int input_from( Stdio.Stream f )    *!    *! Read data from @[f] into this buffer.    */ -  PIKEFUN int input_from( object f ) +  PIKEFUN int(0..) input_from( object f )    {    IOBuffer *io = THIS;    size_t sz = io_len( io );    size_t bread = 0;    struct my_file *fd;       if( (fd = get_storage( f, file_program )) )    {    while( 1 )    {
pike.git/src/modules/_Stdio/buffer.cmod:401:    }    RETURN bread;    }       /*! @decl int output_to( Stdio.Strem f )    *!    *! Write data from the buffer to the indicated file.    *!    *! Will return the number of bytes that were successfully written.    */ -  PIKEFUN int output_to( object f ) +  PIKEFUN int(0..) output_to( object f )    {    IOBuffer *io = THIS;    size_t sz = io_len( io );    size_t written = 0;    struct my_file *fd;    INT_TYPE *wr = &Pike_sp->u.integer;       if( (fd = get_storage( f, file_program )) )    {    /* lock this object. */
pike.git/src/modules/_Stdio/buffer.cmod:459:    if( *wr < 4096 ) {    io_rewind(io, rd-*wr );    break;    }    pop_stack();    }    }    RETURN written;    }    -  PIKEFUN int _size_object( ) +  PIKEFUN int(0..) _size_object( )    {    RETURN THIS->malloced ? THIS->allocated : 0;    }       /*! @decl void add( System.Memory|Stdio.IOBuffer|String.Buffer|string(8bit)|int(8bit) ... data )    *!    *! Add the items in data to the end of the buffer.    *! Integers are assumed to be 8bit numbers (characters)    *!    *! @see also    *! @[sprintf], @[add_int8], @[add_int16], @[add_int32], @[add_int]    *! and    *! @[add_hstring]    */ -  PIKEFUN int add( object|string|int ... argp) +  PIKEFUN int(0..) add( object|string|int ... argp)    {    int i;    IOBuffer *io = THIS;    for(i=0; i<args; i++ )    {    if( TYPEOF(argp[i]) == PIKE_T_STRING )    {    struct pike_string *s = argp[i].u.string;    if( s->size_shift ) Pike_error("IOBuffer only handles 8bit data\n");    io_append( io, s->str, s->len );
pike.git/src/modules/_Stdio/buffer.cmod:524:    io_append( io, &a, 1 );    }    }    RETURN io_len(io);    }       /*! @decl int add_byte( int(0..255) )    *! @decl int add_int8( int(0..255) )    *! Adds a single byte to the buffer.    */ -  PIKEFUN int add_byte( int(0..255) i ) +  PIKEFUN int(0..) add_byte( int i )    {    unsigned char a = i&255;    RETURN io_append( THIS, &a, 1 );    }    -  PIKEFUN int add_int8( int(0..255) i ) +  PIKEFUN int(0..) add_int8( int i )    {    unsigned char a = i&255;    RETURN io_append( THIS, &a, 1 );    }       /*! @decl int add_int16( int(0..65535) )    *! @decl int add_short( int(0..65535) )    *!    *! Add a 16-bit network byte order value to the buffer    */ -  PIKEFUN int add_int16( int(0..65535) i ) +  PIKEFUN int(0..) add_int16( int i )    {    unsigned short a = htons((i&65535));    push_int(io_append( THIS, &a, 2 ));    }    -  PIKEFUN int add_short( int(0..65535) i ) +  PIKEFUN int(0..) add_short( int i )    {    unsigned short a = htons((i&65535));    RETURN io_append( THIS, &a, 2 );    }       /*! @decl int add_int32( int i )    *! Adds a 32 bit network byte order value to the buffer    */ -  PIKEFUN int add_int32( int i ) +  PIKEFUN int(0..) add_int32( int i )    {    INT32 a = htonl(i);    push_int(io_append( THIS, &a, 4 ));    }       /*! @decl void add_hstring( string(0..255) data, int size_size )    *!    *! Adds length/data for @[data] to the buffer.    *!    *! This is identical to @[sprintf("%"+size_size+"H",data)] but    *! significantly faster.    *!    *! @[size_size] must be less than Int.NATIVE_MAX.    */ -  PIKEFUN int add_hstring( string str, int size_size ) +  PIKEFUN int(0..) add_hstring( string str, int size_size )    {    if( str->size_shift )    Pike_error("Only 8bit is supported\n");       /* We know this is safe for len>=4, since pike strings are at    * most 0x7ffffff bytes long.    */    if( size_size < 4 &&    str->len > (1<<(8*(size_size<0?-size_size:size_size)))-1 )    Pike_error("Too long string\n");
pike.git/src/modules/_Stdio/buffer.cmod:595:    }       /*! @decl int add_int( int i, int(0..) width )    *!    *! Adds a generic integer to the buffer as an (width*8)bit    *! network byteorder number.    *!    *! @[width] must be less than Int.NATIVE_MAX.    *!    */ -  PIKEFUN int add_int( int i, int width ) +  PIKEFUN int(0..) add_int( int i, int width )    {    RETURN io_add_int( THIS, i, width );    }    -  PIKEFUN int add_int( object o, int width ) +  PIKEFUN int(0..) add_int( object o, int width )    {    char *p;    int extra, len;    pop_stack();    convert_stack_top_to_bignum();    /* we now know for sure it's a bignum. */    push_int(256);    apply( Pike_sp[-2].u.object, "digits", 1 );    p = Pike_sp[-1].u.string->str;    len = Pike_sp[-1].u.string->len;
pike.git/src/modules/_Stdio/buffer.cmod:633:    width-=a;    }    }    RETURN io_append( THIS, p, width );    }       /*! @decl protected int `[](int off)    *!    *! Return the character at the specified offset.    */ -  PIKEFUN int `[]( int off ) +  PIKEFUN int(0..255) `[]( int off )    flags ID_PROTECTED;    {    IOBuffer *io = THIS;    pop_stack();    if( off < 0 )    off = io_len(io)-off;       if( io_avail( io, off ) )    push_int( io_read_pointer(io)[off] );    else    push_int(-1);    }       /*! @decl protected int `[]=(int off, int char)    *!    *! Set the character at the specified offset to @[char].    */ -  PIKEFUN int `[]=( int off, int val ) +  PIKEFUN int(0..255) `[]=( int off, int val )    flags ID_PROTECTED;    {    IOBuffer *io = THIS;    io_add_space( io, 0, 0 );       if( off < 0 ) off = io_len(io)-off;       if( io_avail( io, off ) )    {    io_read_pointer(io)[off]=(val&0xff);
pike.git/src/modules/_Stdio/buffer.cmod:676:    push_int(-1);    }    }          /*! @decl int _sizeof()    *!    *! Returns the buffer size, in bytes.    *! This is how much you can read from the buffer until it runs out of data.    */ -  PIKEFUN int _sizeof() +  PIKEFUN int(0..) _sizeof()    flags ID_PROTECTED;    {    push_int64(io_len(THIS));    }       /*! @decl string cast(string type)    *!    *! Convert the buffer to a string.    *!    *!@note    *! This only works for buffers whose length is less than 0x7fffffff.    */ -  PIKEFUN string cast(string to) +  PIKEFUN string(0..255) cast(string to)    {    if( to != literal_string_string )    {    push_undefined();    return;    }    if( io_len(THIS) > 0x7fffffff )    Pike_error("This buffer is too large to convert to a string.\n");    push_string(make_shared_binary_string((void*)io_read_pointer(THIS),    (INT32)io_len(THIS)));    }          /*! @decl void set_error_mode(int m) -  +  *! @decl void set_error_mode(program m)    *!    *! Set the error mode of this buffer to @[m].    *! -  *! If true operations that would normally return 0 (like trying to read too much) -  *! will instead thrown an error. +  *! If true operations that would normally return 0 (like trying to +  *! read too much) will instead throw an error. If @[m] is a program +  *! a clone of it will be thrown on error.    *!    *! This is useful when parsing received data, you do not have to    *! verify that each and every read operation suceeds.    *!    *! However, the non-error mode is more useful when checking to see    *! if a packet/segment/whatever has arrived.    *!    *! The thrown error object will have the constant buffer_error set    *! to a non-false value.    *!
pike.git/src/modules/_Stdio/buffer.cmod:751:    *! ...    *! case HEADER_FRAME:    *! int num_headers = pack->read_int32();    *! for( int i = 0; i<num_headers; i++ )    *! headers[pack->read_hstring(2)] = pack->read_hstring(2);    *! ...    *! }    *! }    *! @endcode    */ -  PIKEFUN void set_error_mode( int m ) +  PIKEFUN void set_error_mode( int|program m )    { -  io_set_error_mode( THIS, m ); +  if( TYPEOF(*m) == PIKE_T_INT ) +  io_set_error_mode( THIS, m->u.integer ? buffer_error_program : 0 ); +  else +  { +  io_set_error_mode( THIS, program_from_svalue(m)); +  }    pop_stack();    }       /*! @decl object lock()    *!    *! Makes this buffer read only until the returned object is released.    *!    *! @note    *! This currently simply returns a 0-length subbuffer.    */    PIKEFUN IOBuffer lock()    {    push_object( io_read_buffer( THIS, 0, 0 ) );    }    -  PIKEFUN string _sprintf(int o, mapping ignore) +  PIKEFUN string(0..255) _sprintf(int o, mapping ignore)    flags ID_PROTECTED;    {    pop_n_elems(args);    if( o == 'O' )    {    push_text("IOBuffer(%d bytes, read=[..%d] data=[%d..%d] free=[%d..%d] %s%s)");    /* io_len [..offset] [offset..len] [..allocated] */    push_int(io_len(THIS));    push_int(THIS->offset-1);    push_int(THIS->offset);
pike.git/src/modules/_Stdio/buffer.cmod:806:    *! Identical in functionality to @[read](@[read_number](@[n])) but    *! faster.    *!    *! Read a network byte order number of size n*8 bits, then return the    *! indicated number of bytes as a string.    *!    *! If there is not enough data available return 0.    *!    *! Note that pike string can not be longer than 0x7fffffff bytes (~2Gb).    */ -  PIKEFUN string(0..255) read_hstring( int(0..) bytes ) +  PIKEFUN string(0..255) read_hstring( int bytes )    {    LONGEST len;    struct pike_string *s;       len = io_read_number( THIS, bytes );    s = io_read_string( THIS, len );    if( s )    push_string(s);    else    push_int(0);
pike.git/src/modules/_Stdio/buffer.cmod:838:    *! As long as the subbuffer exists no data can be added to the    *! main buffer.    *!    *! Usually this is OK, since it often represents something that    *! should be parsed before the next whatever is extracted from    *! the buffer, but do take care.    *!    *! If you need to unlink the new buffer after it has been    *! created, call @[trim] in it.    */ -  PIKEFUN IOBuffer read_hbuffer( int(0..) bytes, int|void copy ) +  PIKEFUN IOBuffer read_hbuffer( int bytes, int|void copy )    {    LONGEST len = io_read_number( THIS, bytes );    int do_copy = 0;    struct object *o;    if( copy ) do_copy = copy->u.integer;    pop_n_elems(args);       if( (o = io_read_buffer( THIS, len, do_copy )) )    push_object(o);    else
pike.git/src/modules/_Stdio/buffer.cmod:887:    push_int(0);    }       /*! @decl int sprintf(strict_sprintf_format format, sprintf_args ... args)    *!    *! Appends the output from @[sprintf] at the end of the buffer.    *!    *! This is somewhat faster than add(sprintf(...)) since no    *! intermediate string is created.    */ -  PIKEFUN int sprintf(mixed ... ignored) +  PIKEFUN int(0..) sprintf(mixed ... ignored)    rawtype tFuncV(tAttr("strict_sprintf_format", tOr(tStr, tObj)),    tAttr("sprintf_args", tMix), tStr);    {    ONERROR _e;    struct string_builder tmp;    INT_TYPE sz;    init_string_builder(&tmp,0);    SET_ONERROR(_e, free_string_builder, &tmp);    low_f_sprintf(args, 0, &tmp );    if( tmp.s->size_shift )
pike.git/src/modules/_Stdio/buffer.cmod:1030:    *! This function is very similar to @[sscanf], but the    *! result is the sum of the matches. Most useful to match    *! a single value.    *!    *! @example    *! @code    *! // get the next whitespace separated word from the buffer.    *! buffer->match("%*[ \t\r\n]%*[^ \t\r\n]");    *! @endcode    */ -  PIKEFUN string|int|float|array match( string format ) +  PIKEFUN string(0..255)|int|float|array match( string format )    {    INT32 i;    ptrdiff_t num_used;    struct svalue *start = Pike_sp;       i = low_sscanf_pcharp(    MKPCHARP(io_read_pointer(THIS), 0), io_len(THIS),    MKPCHARP(format->str,format->size_shift), format->len,    &num_used,    0);
pike.git/src/modules/_Stdio/buffer.cmod:1121:    *! This function returns how many more bytes of buffer is    *! available to rewind, or -1 on error.    *!    *! @note    *!    *! Unless you add new data to the buffer using any of the add    *! functions you can always rewind.    *!    *! You can call @[undread(0)] to see how much.    */ -  PIKEFUN int(-1..) unread( int(0..) bytes ) +  PIKEFUN int(-1..) unread( int bytes )    {    push_int64( io_rewind( THIS, bytes ) );    }       /*! @decl string(8bit) read( int n )    *!    *! Read @[bytes] bytes of data from the buffer.    *!    *! If there is not enough data available this returns 0.    */ -  PIKEFUN string(0..255) read( int(0..) bytes ) +  PIKEFUN string(0..255) read( int bytes )    {    struct pike_string * s = io_read_string(THIS, bytes );    pop_stack();    if( s )    push_string(s);    else    push_int(0);    }       /*! @decl string(8bit) read( )
pike.git/src/modules/_Stdio/buffer.cmod:1169:       /*! @decl int read_int( int n )    *!    *! Read a network (if n is positive) or little endian (if n is    *! negative) byte order unsigned number of size n*8 bits, then    *! return it.    *!    *! Will return -1 if there is not enough buffer space available    *! unless error mode is set to throw errors.    */ -  PIKEFUN int read_int( int len ) +  PIKEFUN int(0..) read_int( int len )    {    IOBuffer *io = THIS;    struct object *o;       pop_stack();       if( len < SIZEOF_INT_TYPE-1 ) /* will for sure fit. */    {    push_int( io_read_number( io, len ) );    return;
pike.git/src/modules/_Stdio/buffer.cmod:1335:    IOBuffer *this = THIS;    if( this->sub )    {    free_object( this->sub );    io_unlock( get_storage(this->sub,IOBuffer_program ) );    }    if( this->source )    free_object( this->source );    if( this->str )    free_string( this->str ); +  if( this->error_mode ) +  free_program( this->error_mode );    if( this->malloced )    free( this->buffer );    }   }      void init_stdio_buffer(void)   {    INIT    start_new_program();    low_inherit(generic_error_program,0,0,0,0,0);