.. default-domain:: chpl

.. module:: Buffers
   :synopsis: Support for buffers - regions of memory without a particular interpretation.

Buffers
=======
Support for buffers - regions of memory without a particular interpretation.

This module provides :record:`bytes` and :record:`buffer` types which
can be used to manage memory regions.

A :record:`bytes` is a contiguous memory region - really a data structure
containing a pointer, length, and also the information necessary to free the
memory region when it is no longer used.

A :record:`buffer` consists of a sequence views into :record:`bytes`
objects. A :record:`bytes` object might be shared by several
:record:`buffer` objects.

These types should be safe to use in a multi-locale context. These types
should free their memory after the last user of that memory goes out of
scope. They are currently reference counted but that may not always be the
case.



.. record:: bytes

   This type represents a contiguous sequence of bytes.
   This sequence of bytes is represented with a C pointer and length and is
   currently reference counted.  Note that this record contains private
   fields in addition to the home field. 
   
   


   .. attribute:: var home: locale

      The home locale storing the data 

.. method:: proc bytes.bytes()

   Construct an empty bytes object 

.. method:: proc bytes.bytes(len: int(64), out error: syserr)

   Construct a bytes object by allocating zero-filled memory.
   
   :arg len: the number of bytes to allocate
   :arg error: (optional) capture an error that was encountered instead of
               halting on error
   

.. method:: proc bytes.len: int(64)

   :returns: the number of bytes stored in a :record:`bytes` object 

.. record:: buffer_iterator

   This type represents a particular location with a buffer.
   Use buffer methods like :proc:`buffer.start` and :proc:`buffer.advance` to
   create and manipulate :record:`buffer_iterator` s.  Note that this record
   contains private fields in addition to the home field. 
   
   


   .. attribute:: var home: locale

      The home locale storing the data 

.. record:: buffer_range

   A region within a buffer (indicated by two :record:`buffer_iterator` s ) 


   .. attribute:: var start: buffer_iterator

   .. attribute:: var end: buffer_iterator

.. method:: proc buffer_range.len: int(64)

   :returns: the number of bytes stored in a :record:`buffer_range` 

.. record:: buffer

   A buffer which can contain multiple memory regions
   (that is, multiple regions of :record:`bytes` objects).  Note that this
   record contains private fields in addition to the home field. 
   
   


   .. attribute:: var home: locale

      The home locale storing the data 

.. method:: proc buffer.buffer(out error: syserr)

   Create an empty buffer.
   
   :arg error: (optional) capture an error that was encountered instead of
                halting on error
   

.. method:: proc buffer.flatten(range: buffer_range, out error: syserr)

   Flatten a buffer. Create a new :record:`bytes` object and copy
   the buffer into it. This function should work even if buffer is
   remote.
   
   :arg range: the region of the buffer to copy, for example buffer.all()
   :arg error: (optional) capture an error that was encountered instead of
               halting on error
   :returns: a newly constructed bytes object on the current locale
   

.. method:: proc buffer.len

   :returns: the number of bytes stored in a :record:`buffer` object 

.. method:: proc buffer.append(b: bytes, skip_bytes: int(64) = 0, len_bytes: int(64) = b.len, out error: syserr)

   Append a :record:`bytes` object to a :record:`buffer`.
   This function might store the passed bytes object by reference instead of
   copying it. The current implementation will always do so and will always
   increase the reference count of the bytes object.  The version of this
   function called without the error argument will halt if an error is
   encountered.
   
   :arg b: the :record:`bytes` object to append
   :arg skip_bytes: how many bytes at the front of b to skip
   :arg len_bytes: how many bytes to append to the buffer
   :arg error: (optional) capture an error that was encountered instead of
         halting on error
   

.. method:: proc buffer.append(buf: buffer, part: buffer_range = AppendExpr.Call08, out error: syserr)

   Append a :record:`buffer` object to a :record:`buffer`.
   This function might store a pointers to the bytes objects contained in
   `buf` instead of copying them. If that happens, the current implementation
   will increase their reference counts.  The version of this function called
   without the error argument will halt if an error is encountered.
   
   :arg buf: the :record:`buffer` object to append
   :arg part: a :record:`buffer_range` indicating which section of the
              buffer to copy. Defaults to all of the buffer.
   :arg error: (optional) capture an error that was encountered instead of
               halting on error
   

.. method:: proc buffer.prepend(b: bytes, skip_bytes: int(64) = 0, len_bytes: int(64) = b.len, out error: syserr)

   Prepend a :record:`bytes` object to a :record:`buffer`.
   This function might store the passed bytes object by reference instead of
   copying it. The current implementation will always do so and will always
   increase the reference count of the bytes object.  The version of this
   function called without the error argument will halt if an error is
   encountered.
   
   :arg b: the :record:`bytes` object to prepend
   :arg skip_bytes: how many bytes at the front of b to skip
   :arg len_bytes: how many bytes to append to the buffer
   :arg error: (optional) capture an error that was encountered instead of
         halting on error
   

.. method:: proc buffer.start(): buffer_iterator

   :return: a :record:`buffer_iterator` to the start of a buffer 

.. method:: proc buffer.end(): buffer_iterator

   :return: a :record:`buffer_iterator` to the end of a buffer 

.. method:: proc buffer.all(): buffer_range

   :return: a :record:`buffer_range` for the entirety of a buffer 

.. method:: proc buffer.next_part(ref it: buffer_iterator)

   Advance a :record:`buffer_iterator` to the next contigous
   memory region stored therein
   
   :arg it: the buffer iterator to advance
   

.. method:: proc buffer.prev_part(ref it: buffer_iterator)

   Advance a :record:`buffer_iterator` to the previous contigous
   memory region stored therein
   
   :arg it: the buffer iterator to advance
   

.. method:: proc buffer.advance(ref it: buffer_iterator, amount: int(64))

   Advance a :record:`buffer_iterator` by a particular number
   of bytes.
   
   :arg it: the buffer iterator to advance
   :arg amount: the number of bytes to advance
   

.. method:: proc buffer.copyout(it: buffer_iterator, out value, out error: syserr): buffer_iterator

   Read a basic type from a buffer. This method reads the value
   by copying from memory - so it reads a binary value in native endianness.
   
   :arg it: a :record:`buffer_iterator` where reading will start
   :arg value: a basic type (integral or floating point value)
   :arg error: (optional) capture an error that was encountered instead of
               halting on error
   :returns: a buffer iterator storing the position immediately after
             the read value.
   

.. method:: proc buffer.copyin(it: buffer_iterator, value, out error: syserr): buffer_iterator

   Write a basic type to a buffer. This method writes the value
   by copying to memory - so it reads a binary value in native endianness.
   
   :arg it: a :record:`buffer_iterator` where reading will start
   :arg value: a basic type (integral or floating point value)
   :arg error: (optional) capture an error that was encountered instead of
               halting on error
   :returns: a buffer iterator storing the position immediately after
             the written value.
   

