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

version» Context lines:

pike.git/src/modules/_Stdio/buffer.cmod:68:    *! The class can also be used to directly read from and write to    *! filedescriptors if so desired. This eliminates at least one memory    *! copy.    *!    *! @note    *! The "avoid copy" part means that a Buffer will never shrink    *! unless you call the @[trim] function.    *!    */   PIKECLASS Buffer -  /* This is needed to get consisten behavior in case this +  /* This is needed to get consistent behaviour in case this    * buffer is a sub-buffer, in which case the source    * buffer needs to be unlocked as soon as possible.    */    program_flags PROGRAM_DESTRUCT_IMMEDIATE;   {   #if PRECOMPILE_API_VERSION > 5   #ifdef PIKE_DEBUG    PIKEVAR int b.num_malloc;    PIKEVAR int b.num_move;   #endif
pike.git/src/modules/_Stdio/buffer.cmod:91:    CVAR Buffer b;       EXTRA    {    /* The __output variable is merely for the benefit of the GC so that    it can detect cycles */    PIKE_MAP_VARIABLE("__output", OFFSETOF(Buffer_struct, b.output),    tMix, PIKE_T_MIXED, ID_PRIVATE|ID_HIDDEN|ID_PROTECTED);    }    + #undef THIS + #define THIS (&(((struct Buffer_struct *)Pike_fp->current_storage)->b)) + #define THIS_OBJECT (Pike_fp->current_object)       static void io_set_error_mode( Buffer *io, struct program *m )    {    if( m ) add_ref(m);    if( io->error_mode ) free_program( io->error_mode );    io->error_mode = m;    }       PMOD_EXPORT Buffer *io_buffer_from_object(struct object *o) {    return get_storage(o, Buffer_program);
pike.git/src/modules/_Stdio/buffer.cmod:144:    }    return 0;    }       static void io_discard_bufstart( Buffer *io )    {    if ( LIKELY(!io->locked_move) )    {    memmove( io->buffer, io_read_pointer(io), io_len(io) );    io->len -= io->offset; +  io->offset = 0;   #ifdef PIKE_DEBUG    io->num_move++;   #endif -  io->offset = 0; +     }    }       PMOD_EXPORT void io_trim( Buffer *io )    {    if( io->allocated && (io->offset > 64 || io->len > 64) && !io->locked)    {    if( io->offset > 64 && io->offset > io_len(io) )    io_discard_bufstart(io);   
pike.git/src/modules/_Stdio/buffer.cmod:198:    io->sourcetype = 0;    }       PMOD_EXPORT void io_ensure_malloced( Buffer *io, size_t headroom )    {    if( UNLIKELY(!io->allocated) )    {    /* convert to malloced buffer from a shared one. */    unsigned char *old = io_read_pointer(io);    -  headroom += io->len - io->offset; +  headroom += io_len(io);    -  if (headroom < io->len - io->offset) +  if (headroom < io_len(io))    Pike_error(msg_out_of_mem_2, headroom);       io->buffer = xalloc( headroom );    io->allocated = headroom;    io->len -= io->offset;    io->offset = 0;   #ifdef PIKE_DEBUG    io->num_malloc++;   #endif -  memcpy( io->buffer, old, io->len ); +  memcpy( io->buffer, old, io_len(io) );    io_unlink_external_storage(io);    }    }       static struct object *    io_read_buffer( Buffer *io, size_t len, int do_copy, size_t headroom )    ATTRIBUTE((noclone,noinline));       PMOD_EXPORT unsigned char *io_add_space_do_something( Buffer *io, size_t bytes, int force )    ATTRIBUTE((noclone,noinline));
pike.git/src/modules/_Stdio/buffer.cmod:516:    apply_current( f_Buffer_range_error_fun_num, 1 );    res = Pike_sp[-1].u.integer;    pop_n_elems( Pike_sp-osp );    if( !res ) io_range_error_throw( io, howmuch );       return res;    }       static int io_avail( Buffer *io, ptrdiff_t len )    { -  if( len < 0 || len + io->offset > io->len ) +  if (UNLIKELY(len < 0 || len > io_len(io)))    { -  if( len < 0 ) +  if (UNLIKELY(len < 0))    io_range_error_throw( io, 0 ); -  else if( io_range_error( io, len+io->len-io->offset ) ) +  else if( io_range_error( io, len + io_len(io) ) )    return io_avail(io,len);    return 0;    }    return 1;    }       static int io_avail_mul( Buffer *io, ptrdiff_t len, ptrdiff_t each )    {    /* safely check if len*each is available. */    size_t total = io_len(io);    if( len < 0 || each <= 0 )    {    io_range_error_throw( io, 0 );    return 0;    }       if( (total/(size_t)each) < (size_t)len )    { -  if( io_range_error( io, len+io->len-io->offset ) ) +  if( io_range_error( io, len + io_len(io) ) )    return io_avail_mul(io,len,each);    return 0;    }    return 1;    }       static void io_append( Buffer *io, const void *p, size_t bytes )    {    memcpy( io_add_space( io, bytes, 0 ), p, bytes );    io->len += bytes;
pike.git/src/modules/_Stdio/buffer.cmod:590:    static struct object *    io_read_buffer( Buffer *io, size_t len, int do_copy, size_t headroom )    {    struct object *b;    Buffer *to;       if (UNLIKELY(!io_avail(io, len)))    return NULL;       b = fast_clone_object( Buffer_program ); -  to = get_storage(b, Buffer_program); +  to = io_buffer_from_object(b);       to->buffer = io_read_pointer(io);    to->len = len;       io_consume( io, len );       if (UNLIKELY(do_copy))    io_ensure_malloced( to, headroom );    else {    Buffer *parent = io;
pike.git/src/modules/_Stdio/buffer.cmod:936:    }    break;    case PIKE_T_INT:    {    unsigned char a = p->u.integer;    io_append( io, &a, 1 );    }    }    }    - #undef THIS - #define THIS (&(((struct Buffer_struct *)Pike_fp->current_storage)->b)) -  -  +     /* pike functions */       /*! @decl int(-1..) input_from( Stdio.Stream f, int|void nbytes )    *!    *! Read data from @[f] into this buffer. If @[nbytes] is not    *! specified, read until there is no more data to read (currently).    *!    *! Returns the amount of data that was read, or @expr{-1@} on    *! read error.    *!
pike.git/src/modules/_Stdio/buffer.cmod:1290:    /*! @decl Buffer add_int8( int(8bit) )    *! Adds a single byte to the buffer.    */    PIKEFUN Buffer add_int8( int i )    {    Buffer *io = THIS;    *io_add_space(io,1,0)=i;    io->len++;    Pike_sp--;    io_trigger_output( io ); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_int8( Gmp.mpz )    *! Adds a single byte to the buffer.    */    PIKEFUN Buffer add_int8( object mpz )    {    INT64 i = 0;    Buffer *io = THIS;    unsigned char *p = io_add_space(io,1,0);    if (!low_int64_from_bignum(&i, mpz)) {    SIMPLE_ARG_TYPE_ERROR("add_int8", 1, "int|Gmp.mpz");    }    *p = i;    io->len++; -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_int16( int(16bit) )    *!    *! Add a 16-bit network byte order value to the buffer    */    PIKEFUN Buffer add_int16( int i )    {    Buffer *io = THIS;    unsigned char *p = io_add_space(io,2,0);    p[0] = i>>8;    p[1] = i;    io->len += 2;    io_trigger_output( io ); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_int16( Gmp.mpz )    *!    *! Add a 16-bit network byte order value to the buffer    */    PIKEFUN Buffer add_int16( object mpz )    {    INT64 i = 0;    Buffer *io = THIS;    unsigned char *p = io_add_space(io,2,0);    if (!low_int64_from_bignum(&i, mpz)) {    SIMPLE_ARG_TYPE_ERROR("add_int16", 1, "int|Gmp.mpz");    }    p[0] = i>>8;    p[1] = i;    io->len += 2; -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_int32( int i )    *! Adds a 32 bit network byte order value to the buffer    */    PIKEFUN Buffer add_int32( int i )    {    Buffer *io = THIS;    unsigned char *p = io_add_space(io,4,0);    p[0] = i>>24;    p[1] = i>>16;    p[2] = i>>8;    p[3] = i;    io->len += 4;    io_trigger_output( io ); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_int32( Gmp.mpz i )    *! Adds a 32 bit network byte order value to the buffer    */    PIKEFUN Buffer add_int32( object mpz )    {    INT64 i = 0;    Buffer *io = THIS;    unsigned char *p = io_add_space(io,4,0);    if (!low_int64_from_bignum(&i, mpz)) {    SIMPLE_ARG_TYPE_ERROR("add_int32", 1, "int|Gmp.mpz");    }    p[0] = i>>24;    p[1] = i>>16;    p[2] = i>>8;    p[3] = i;    io->len += 4;    io_trigger_output( io ); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_hstring( string(8bit) data, int size_size )    *! @decl Buffer add_hstring( Stdio.Buffer data, int size_size )    *! @decl Buffer add_hstring( System.Memory data, int size_size )    *! @decl Buffer add_hstring( String.Buffer data, int size_size )    *! @decl Buffer add_hstring( int(8bit) data, int size_size )    *! @decl Buffer add_hstring( array data, int size_size )    *! @decl Buffer add_hstring( int|string(8bit)|Stdio.Buffer|System.Memory|array data, int size_size, int offset )    *!
pike.git/src/modules/_Stdio/buffer.cmod:1466:    {    io_add_int( THIS, i->u.integer, width );    Pike_sp--;    }    else    {    convert_stack_top_to_bignum();    io_add_bignum( THIS, i->u.object, width );    pop_stack(); /* o. */    } -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_hint( int i, int(0..) size_width )    *!    *! First add the size of the integer when encoded to base 256 as a    *! @[size_width] integer, then add the integer to the buffer, both    *! in network byte order.    *!    *! @[size_width] must be less than Int.NATIVE_MAX.    *!
pike.git/src/modules/_Stdio/buffer.cmod:1505:    Pike_sp--;    }    else    {    convert_stack_top_to_bignum();    width = (mpz_sizeinbase( (void*)i->u.object->storage, 2)+7)/8;    io_add_int( THIS, width, len_width );    io_add_bignum( THIS, i->u.object, width );    pop_stack(); /* o. */    } -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl Buffer add_ints( array(int) integers, int(8bit) len )    *!    *! Add the integers in the specified array, @[len] bytes per int.    *! Equivalent to calling @[add_int] for each integer, but faster,    *! and if an error occurs the buffer will contain no new    *! data. Either all or none of the integers will be added.    *!    *! Errors can occur if one of the elements in @[integers] is not
pike.git/src/modules/_Stdio/buffer.cmod:1723:    *! @endcode    */    PIKEFUN Buffer set_error_mode( int|program 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(); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl object lock()    *!    *! Makes this buffer read only until the returned object is released.    *!    *! @note    *! This currently simply returns a 0-length subbuffer.    */    PIKEFUN Buffer lock()
pike.git/src/modules/_Stdio/buffer.cmod:1749:    flags ID_PROTECTED;    {    size_t bytes;    pop_n_elems(args-1);    Pike_sp--;    switch( o )    {    case 'O':    {    push_static_text("%O(%d bytes, read=[..%d] data=[%d..%d] free=[%d..%d] %s%s)"); -  ref_push_program(Pike_fp->current_object->prog); +  ref_push_program(THIS_OBJECT->prog);    /* io_len [..offset] [offset..len] [..allocated] */    push_int(io_len(THIS));    push_int(THIS->offset-1);    push_int(THIS->offset);       push_int(THIS->len-1);    push_int(THIS->len);    push_int(THIS->allocated);    switch (THIS->sourcetype) {    case PIKE_T_STRING:
pike.git/src/modules/_Stdio/buffer.cmod:2181:    ONERROR _e;    struct string_builder tmp;    init_string_builder(&tmp,0);    SET_ONERROR(_e, free_string_builder, &tmp);    low_f_sprintf(args, &tmp);    if( tmp.s->size_shift )    Pike_error("Buffer only handles 8bit data.\n");    io_append( THIS, tmp.s->str, tmp.s->len );    pop_n_elems(args);    CALL_AND_UNSET_ONERROR(_e); -  ref_push_object(Pike_fp->current_object); +  ref_push_object(THIS_OBJECT);    }       /*! @decl array sscanf(string(8bit) format)    *!    *! Reads data from the beginning of the buffer to match the    *! specifed format, then return an array with the matches.    *!    *! The non-matching data will be left in the buffer.    *!    *! See @[array_sscanf] for more information.
pike.git/src/modules/_Stdio/buffer.cmod:2380:    *! Note that calling this function excessively will slow things    *! down, since the data often has to be copied.    *!    *! @note    *! This function could possibly throw an out-of-memory error    *! if the realloc fails to find a new (smaller) memory area.    */    PIKEFUN void trim( )    {    Buffer *io = THIS; -  +     io_add_space( io, 0, 1 );    io_trim(io);    }       /*! @decl void allocate( int(0..) n )    *!    *! Make sure that at least @[n] bytes of space are available in this buffer.    */    PIKEFUN void allocate( int n )    {
pike.git/src/modules/_Stdio/buffer.cmod:2408:       /*! @decl int(0..)|int(-1..-1) consume( int(0..) n )    *!    *! Discard the first @[n] bytes from the buffer    *!    *! Returns -1 on error and the amount of space still left otherwise.    */    PIKEFUN int(-1..) consume( int n )    {    Pike_sp--; -  if( !io_avail( THIS, n ) ) -  push_int(-1); -  else +  if (LIKELY(io_avail(THIS, n)))    push_int64( io_consume( THIS, n ) ); -  +  else +  push_int(-1);    }       /*! @decl int(0..)|int(-1..-1) truncate( int(0..) n )    *!    *! Truncates the buffer to a length of @[n] bytes.    *!    *! Returns -1 on error and the number of bytes removed otherwise.    */    PIKEFUN int(-1..) truncate( int(0..) n )    {    Buffer *io = THIS;    ptrdiff_t diff = io_len(io) - n;    Pike_sp--;    -  if( diff < 0 || io_len(io) < (size_t)diff ) +  if (UNLIKELY(diff < 0 || io_len(io) < (size_t)diff))    push_int(-1);    else {    io->len -= diff;    push_int64( diff );    }    }       /*! @decl int(0..)|int(-1..-1) unread( int(0..) n )    *!    *! Rewind the buffer @[n] bytes.
pike.git/src/modules/_Stdio/buffer.cmod:2469:    *!    *! If there is not enough data available this returns 0.    *!    *! @seealso    *! @[try_read()]    */    PIKEFUN string(8bit) read( int bytes )    {    struct pike_string *s;    Pike_sp--; -  s = io_read_string(THIS, bytes ); -  if( s ) -  push_string( s ); +  s = io_read_string(THIS, bytes); +  if (LIKELY(s)) +  push_string(s);    else    push_undefined();    }       /*! @decl string(8bit) read( )    *!    *! Read all data from the buffer.    *!    *! If there is not enough data available this returns 0.    *!
pike.git/src/modules/_Stdio/buffer.cmod:2891:    else    {    io_append_svalue( THIS, x );    pop_stack();    }    }       INIT {    Buffer *this = THIS;    this->max_waste = 0.615; -  this->this = Pike_fp->current_object; +  this->this = THIS_OBJECT;    }       EXIT {    Buffer *this = THIS;    io_unlink_external_storage( this );    if( this->error_mode )    free_program( this->error_mode );    if( this->allocated )    free( this->buffer );    }
pike.git/src/modules/_Stdio/buffer.cmod:2931:    CVAR size_t rewind_to;    CVAR int auto_mode;       /*! @decl void release()    *! Do not rewind if the object is released.    *! @note    *! This is equivalent to calling destruct() on the object    */    PIKEFUN void release()    { -  destruct_object(Pike_fp->current_object, DESTRUCT_EXPLICIT); +  destruct_object(THIS_OBJECT, DESTRUCT_EXPLICIT);    }       /*! @decl void update()    *!    *! Update the location the buffer will be rewound to to the current    *! position of the buffer.    */    PIKEFUN void update()    {    if( THIS->obj->prog && THIS->io )
pike.git/src/modules/_Stdio/buffer.cmod:2968:    }    }       /*! @decl void rewind()    *! Rewinds the buffer explicitly.    *! @note    *! Destructs this @[RewindKey]    */    PIKEFUN void rewind() {    THIS->auto_mode = 1; -  destruct_object(Pike_fp->current_object, DESTRUCT_GC); +  destruct_object(THIS_OBJECT, DESTRUCT_GC);    }       PIKEFUN void create()    flags ID_PROTECTED;    {    /* FIXME: The following zeroing isn't safe! */    THIS->obj = 0;    THIS->io = 0;    Pike_error("Not supported\n");    }