X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/dd3c57bc8cac59e0d657ee665ce462988d27d714..18c831dcd0ae4d660c70ccac69d27ed2a97851be:/struct/buf.3 diff --git a/struct/buf.3 b/struct/buf.3 new file mode 100644 index 0000000..76c7dcb --- /dev/null +++ b/struct/buf.3 @@ -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 " + +.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,