chiark / gitweb /
Infrastructure: Split the files into subdirectories.
[mLib] / struct / buf.3
diff --git a/struct/buf.3 b/struct/buf.3
new file mode 100644 (file)
index 0000000..76c7dcb
--- /dev/null
@@ -0,0 +1,406 @@
+.\" -*-nroff-*-
+.de VS
+.sp 1
+.RS
+.nf
+.ft B
+..
+.de VE
+.ft R
+.fi
+.RE
+.sp 1
+..
+.de hP
+.IP
+.ft B
+\h'-\w'\\$1\ 'u'\\$1\ \c
+.ft P
+..
+.ie t .ds o \(bu
+.el .ds o o
+.TH buf 3 "23 September 2005" "Straylight/Edgeware" "mLib utilities library"
+.SH NAME
+buf \- reading and writing stuff in buffers
+.\" @BBASE
+.\" @BLIM
+.\" @BCUR
+.\" @BSZ
+.\" @BLEN
+.\" @BLEFT
+.\" @BSTEP
+.\" @BBAD
+.\" @BOK
+.\" @BENSURE
+.
+.\" @buf_init
+.\" @buf_break
+.\" @buf_flip
+.\" @buf_ensure
+.\" @buf_get
+.\" @buf_put
+.
+.\" @buf_getbyte
+.\" @buf_putbyte
+.
+.\" @buf_getu8
+.\" @buf_getu16
+.\" @buf_getu16b
+.\" @buf_getu16l
+.\" @buf_getu24
+.\" @buf_getu24b
+.\" @buf_getu24l
+.\" @buf_getu32
+.\" @buf_getu32b
+.\" @buf_getu32l
+.
+.\" @buf_putu8
+.\" @buf_putu16
+.\" @buf_putu16b
+.\" @buf_putu16l
+.\" @buf_putu24
+.\" @buf_putu24b
+.\" @buf_putu24l
+.\" @buf_putu32
+.\" @buf_putu32b
+.\" @buf_putu32l
+.
+.\" @buf_getbuf8
+.\" @buf_getbuf16
+.\" @buf_getbuf16b
+.\" @buf_getbuf16l
+.\" @buf_getbuf24
+.\" @buf_getbuf24b
+.\" @buf_getbuf24l
+.\" @buf_getbuf32
+.\" @buf_getbuf32b
+.\" @buf_getbuf32l
+.\" @buf_getbufz
+.
+.\" @buf_putbuf8
+.\" @buf_putbuf16
+.\" @buf_putbuf16b
+.\" @buf_putbuf16l
+.\" @buf_putbuf24
+.\" @buf_putbuf24b
+.\" @buf_putbuf24l
+.\" @buf_putbuf32
+.\" @buf_putbuf32b
+.\" @buf_putbuf32l
+.\" @buf_putbufz
+.
+.\" @buf_getmem16
+.\" @buf_getmem16b
+.\" @buf_getmem16l
+.\" @buf_getmem24
+.\" @buf_getmem24b
+.\" @buf_getmem24l
+.\" @buf_getmem32
+.\" @buf_getmem32b
+.\" @buf_getmem32l
+.\" @buf_getmem8
+.\" @buf_getmemz
+.
+.\" @buf_putmem8
+.\" @buf_putmem16
+.\" @buf_putmem16b
+.\" @buf_putmem16l
+.\" @buf_putmem24
+.\" @buf_putmem24b
+.\" @buf_putmem24l
+.\" @buf_putmem32
+.\" @buf_putmem32b
+.\" @buf_putmem32l
+.\" @buf_putmemz
+.
+.\" @buf_putstr8
+.\" @buf_putstr16
+.\" @buf_putstr16b
+.\" @buf_putstr16l
+.\" @buf_putstr24
+.\" @buf_putstr24b
+.\" @buf_putstr24l
+.\" @buf_putstr32
+.\" @buf_putstr32b
+.\" @buf_putstr32l
+.\" @buf_putstrz
+.
+.\" @buf_getdstr8
+.\" @buf_getdstr16
+.\" @buf_getdstr16b
+.\" @buf_getdstr16l
+.\" @buf_getdstr24
+.\" @buf_getdstr24b
+.\" @buf_getdstr24l
+.\" @buf_getdstr32
+.\" @buf_getdstr32b
+.\" @buf_getdstr32l
+.\" @buf_getdstrz
+.
+.\" @buf_putdstr8
+.\" @buf_putdstr16
+.\" @buf_putdstr16b
+.\" @buf_putdstr16l
+.\" @buf_putdstr24
+.\" @buf_putdstr24b
+.\" @buf_putdstr24l
+.\" @buf_putdstr32
+.\" @buf_putdstr32b
+.\" @buf_putdstr32l
+.\" @buf_putdstrz
+.SH SYNOPSIS
+.nf
+.B "#include <mLib/dstr.h>"
+
+.BI "void buf_init(buf *" b ", void *" p ", size_t " sz );
+.BI "void buf_flip(buf *" b );
+.BI "octet *BBASE(buf *" b );
+.BI "octet *BLIM(buf *" b );
+.BI "octet *BCUR(buf *" b );
+.BI "ptrdiff_t BSZ(buf *" b );
+.BI "ptrdiff_t BLEN(buf *" b );
+.BI "ptrdiff_t BLEFT(buf *" b );
+
+.BI "int buf_break(buf *" b );
+.BI "int BBAD(buf *" b );
+.BI "int BOK(buf *" b );
+
+.BI "int buf_ensure(buf *" b ", size_t " sz );
+.BI "int BENSURE(buf *" b ", size_t " sz );
+.BI "octet *BSTEP(buf *" b );
+
+.BI "void *buf_get(buf *" b ", size_t " sz );
+.BI "void *buf_put(buf *" b ", const void *" p ", size_t " sz );
+
+.BI "int buf_getbyte(buf *" b );
+.BI "int buf_putbyte(buf *" b ", int ch" );
+.BI "int buf_getu" suff "(buf *" b ", uint" suff " *" w );
+.BI "int buf_putu" suff "(buf *" b ", uint" suff " " w );
+.BI "void *buf_getmem" suff "(buf *" b ", size_t *" sz );
+.BI "int buf_putmem" suff "(buf *" b ", const void *" p ", size_t " sz );
+.BI "int buf_getbuf" suff "(buf *" b ", buf *" bb );
+.BI "int buf_putbuf" suff "(buf *" b ", buf *" bb );
+.BI "int buf_getdstr" suff "(buf *" b ", dstr *" d );
+.BI "int buf_putdstr" suff "(buf *" b ", dstr *" d );
+.BI "int buf_putstr" suff "(buf *" b ", const char *" p );
+.fi
+.SH DESCRIPTION
+The
+.B buf
+interface allows relatively convenient reading and writing of structured
+binary data from and to fixed-size memory buffers.  It's useful for
+formatting and parsing down network data packets, for example.
+.SS "Buffer basics"
+A buffer has three important pointers associated with it:
+.TP
+.I base
+The base address of the buffer.
+.TP
+.I limit
+Just past the last usable byte in the buffer
+.TP
+.I current
+The position in the buffer at which the next read or write will occur.
+.PP
+A buffer is created using the
+.B buf_init
+function.  You must pass it the buffer base address and size, and a
+pointer to a
+.B buf
+structure to fill in.  It doesn't allocate any memory, so you don't need
+to dispose of the
+.B buf
+structure in any way before forgetting about it.
+.PP
+A collection of macros is provided for finding the positions of the
+various interesting pointers known about a buffer, and the sizes of the
+regions of memory they imply.
+.TP
+.B BBASE
+The buffer's
+.I base
+pointer.
+.TP
+.B BLIM
+The buffer's
+.I limit
+pointer.
+.TP
+.B BCUR
+The buffer's
+.I current
+pointer.
+.TP
+.B BSZ
+The size of the buffer; i.e.,
+.I limit
+\-
+.IR base .
+.TP
+.B BLEN
+The length of data in the buffer (if writing) or the amount of data
+read (if reading); i.e.,
+.I current
+\-
+.IR base .
+.TP
+.B BLEFT
+The amount of space left in the buffer (if writing) or the amount of
+data yet to read (if reading); i.e.,
+.I limit
+\-
+.IR current .
+.PP
+The function
+.B buf_flip
+takes a buffer which has been used for writing, and makes it suitable
+for reading.  This turns out to be useful when building packets in
+multi-layered networking software.  Its precise behaviour is to preserve
+.IR base ,
+to set
+.I limit
+to
+.IR current ,
+and to set
+.I current
+to
+.IR base .
+.PP
+A buffer can be
+.IR broken ,
+to indicate that it has overflowed or that its contents are otherwise
+invalid.  The various buffer access functions described below all fail
+on a broken buffer, and any errors they encounter cause the buffer to
+become broken.  Most simple programs which only use the supplied buffer
+access functions can avoid the tedium of error-checking every function
+call and just check the brokenness state at the end of their run.
+.PP
+The function
+.B buf_break
+will break a buffer.  The macro
+.B BBAD
+reports true (nonzero) if its buffer argument is broken, or false (zero)
+otherwise; its counterpart
+.B BOK
+reports true if the buffer is OK, and false if it is broken.
+.SS "Low-level buffer access"
+Access to the data in the buffer is usually sequential.  The
+.B BENSURE
+macro (or the equivalent
+.B buf_ensure
+function) checks that the buffer is OK and that there is enough space
+remaining in the buffer for
+.I sz
+bytes: if so, it returns zero; otherwise it breaks the buffer and
+returns \-1.
+.PP
+The
+.B BSTEP
+macro advances the buffer's
+.I current
+pointer by
+.I sz
+bytes.  It does no bounds checking.  Together with
+.BR BENSURE ,
+this provides sequential access to the buffer's contents.
+.PP
+The
+.B buf_get
+function is the basis of most buffer access functions, whether for
+reading or writing.  If the buffer is OK, and there are
+.I sz
+or more bytes remaining, it steps the buffer's
+.I current
+pointer by
+.I sz
+and returns the
+.I original
+(pre-stepping)
+.I current
+pointer; otherwise it breaks the buffer if necessary, and returns a null
+pointer.
+.PP
+The
+.B buf_put
+function writes
+.I sz
+bytes of data starting at
+.I p
+to the buffer.  If it succeeded, it returns 0; otherwise it returns \-1.
+.SS "Formatted buffer access"
+The function
+.B buf_getbyte
+returns the next byte from a buffer as a nonnegative integer, or \-1 on
+error.  The function
+.B buf_putbyte
+writes its argument to a buffer, and returns 0 on succes; it returns \-1
+if it failed.
+.PP
+Many of the remaining functions deal with integer formatting and buffer
+lengths.  The functions support 8-, 16-, 24- and 32-bit integers, in
+big- or little-endian order; on platforms with 64-bit integers, these
+are supported too.  The functions' names carry a suffix which is the
+width in bits of the integers they deal with and an optional
+.RB ` l '
+for little- or
+.RB ` b '
+for big-endian byte order.  (The variant with no letter uses big-endian
+order.  Use of these variants tends to mean `I don't really care, but be
+consistent,' and is not recommended if you have an externally-defined
+spec you're meant to be compatible with.)
+.PP
+The function
+.BI buf_getu suff
+reads an integer.  On success, it stores the integer it read at the
+address
+.I w
+given, and returns zero; on failure, it returns \-1.  The function
+.BI buf_putu suff
+write an integer.  It returns zero on success or \-1 on failure.
+.PP
+Functions which deal with block lengths assume the length is prefixed to
+the data, and don't include themselves.  They also have an additional
+.RB ` z '
+variant, which deals with zero-terminated data.  No checks are done on
+writing that the data written contains no zero bytes.
+.PP
+The function
+.BI buf_getmem suff
+fetches a block of data.  On success, it returns its base address and
+stores its length at the given address; on failure, it returns null.
+The function
+.BI buf_putmem suff
+writes a block of data; it return zero on success or \-1 on failure.
+.PP
+The functon
+.BI buf_getbuf suff
+fetches a block of data and makes a second buffer point to it, i.e.,
+setting its
+.I base
+and
+.I current
+pointers to the start of the block and its
+.I limit
+pointer to just past the end.  No copying of bulk data is performed.
+The function
+.BI buf_putbuf suff
+writes the contents of a buffer (i.e., between its
+.I base
+and
+.I current
+pointers).  The function
+.BI buf_getdstr suff
+fetches a block of data and append it to a dynamic string (see
+.BR dstr (3)).
+The function
+.BI buf_putdstr suff
+writes the contents of a dynamic string to a buffer.  Finally, the
+function
+.BI buf_putstr suff
+writes a standard C null-terminated string to a buffer.  All these
+functions return zero on success or \-1 on failure.
+.SH "SEE ALSO"
+.BR dstr (3),
+.BR mLib (3).
+.SH AUTHOR
+Mark Wooding, <mdw@distorted.org.uk>