/*! @class IOBuffer
*!
*! A buffer to use as input or buffering when doing I/O. It is
*! similar to @[String.Buffer], but can only contain 8bit data and is
*! designed for protocol parsing. It is optimized for reading from
*! the beginning and adding to the end, and will try to minimize the
*! amount of data copying that is done.
*!

*! The class maintains two separate offsets, one for reading and one
*! for writing. The functions that add data all do so at the write
*! offset (the end of the buffer), and reading is done from the read
*! offset (the start of the buffer).
*!
*! 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 IOBuffer will never shrink
*! unless you call the @[trim] function.
*!

/*! @decl protected bool range_error( int howmuch )
*!
*! This function is called when an attempt is made to read out of bounds.
*! The default implementation simply returnns 0.
*!
*! Override this function to change the behaviour
*!
*! The argument @[howmuch] indicates how much data is needed:
*!
*! @dl

*! Tried to @[unread] X bytes. There is usually no way to satisfy
*! the requested range.
*!
*! The only supported way is to extract the data from the buffer,
*! add the requested amount of "go backbuffer", add the data
*! back, and forward -@[howmuch] bytes.

*!
*! @returns
*!
*! @[true] if the operation should be retried, @[false] otherwise.
*!
*! Do not return true unless you have added data to the buffer,
*! doing so could result in an infinite loop (since no data is
*! added, the range_error will be called again immediately).
*/
PIKEFUN int(0..1) range_error( int howmuch )
flags ID_PROTECTED;

*!
*! Returns the amount of data that was read
*!
*! @note
*! Please note that this funcition will read all data from the
*! filedescriptor unless it's set to be non-blocking.
*!
*! It is designed to only be used in non-blocking IO mode.

}
else
push_undefined();
}
/*! @decl string(8bit) read_hstring( int(0..) n )
*!
*! 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).
*/

{
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);
}
/*! @decl IOBuffer read_hbuffer( int n )
*! @decl IOBuffer read_hbuffer( int n, bool copy )
*!
*! Same as @[read_hstring], but returns the result as an IOBuffer.
*!
*! No data is copied unless @[copy] is specified and true, the new
*! buffer points into the old one.
*!
*! @note
*! 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.
*/

*! If @[require_whitespace_separator] is true there must be a whitespace
*! after each json value (as an example, newline or space).
*!
*! The JSON is assumed to be utf-8 encoded.
*!
*! @returns
*! UNDEFINED if no data is available to read.
*! The read value otherwise.
*!
*! @note
*! Unless whitespaces are required this function only really work correctly
*! with objects, arrays and strings.
*!
*! There is really no way to see where one value starts and the other ends
*! for most other cases
*/
PIKEFUN mixed read_json(int|void require_whitespace)
{
int stop, whites = 0;
static ptrdiff_t(*parse_json_pcharp)(PCHARP,size_t,int,char**);
char *err = NULL;
if( require_whitespace )
whites = require_whitespace->u.integer;
if( !parse_json_pcharp )
parse_json_pcharp = PIKE_MODULE_IMPORT(Standards.JSON, parse_json_pcharp );

/*! @decl mixed match(string(8bit) format)
*!
*! Reads data from the beginning of the buffer to match the
*! specifed format, then return the match.
*!
*! The non-matching data will be left in the buffer.
*!
*! 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
*/

}
/*! @decl string(8bit) read( )
*!
*! Read all data from the buffer.
*!
*! If there is not enough data available this returns 0.
*!
*! This is basically equivalent to (string)buffer, but it also
*! removes the data from the buffer.
*/
PIKEFUN string(0..255) read()
{
struct pike_string * s = io_read_string(THIS, io_len(THIS));

*!
*! 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.
*/

*! In the @[String.Buffer] case the data has to be copied unless
*! there is only one reference to the String.Buffer object, since
*! modifications of the String.Buffer would cause the IOBuffer to
*! point into invalid memory.
*!
*! In all other cases this will not copy the string data, instead
*! data will be read from the source until it needs to be modified,
*! so the buffer creation is fast regardless of the length of the

*!
*! However, as an example, if the buffer is created with a 100Gb
*! @[System.Memory] mmap:ed file as the @[contents] and you later on
*! try to modify the buffer using one of the @[add] functions (or
*! @[sprintf] and similar) the old contents @b{will@} be copied.
*!
*! You can use @[read_only()] to avoid accidents.