MBuf Class


The MBuf class is a malloc'ed, multi-chunk-supporting, memory-buffer. You can extend the buffer by either appending data to the object (which may reallocate the last chunk of data to fit the new characters) and/or you can add more pre-allocated chunks of data to the object (which can be either appended or prepended to the list of buffer chunks).

The MBuf_new() function is used to create a new MBuf object. You pass it two parameters to indicate how the memory management for this buffer will happen. The first number indicates the incremental steps that the buffer will be grown by. The second number indicates how big each chunk of data can grow to be before we stop reallocating the current chunk and move on to a new chunk of data that will be appended to the MBuf object. As a special case, if you specify "0" for the second number, the buffer will never stop reallocating the final chunk (which will remain the only chunk of data unless you manually add other data chunks into the MBuf object).

The MBuf_delete() function destroys an MBuf object and all the data chunks that it contains.

The MBuf_vwrite() function is the workhorse that gets used the most. It takes one or more strings or memory segments and transfers the bytes into the last chunk of malloc'ed memory, extending the buffer in the process. If the chunk-size limit is reached, a new chunk will be allocated, appended to the tail of the chunk list, and the data will continue to be written into the new chunk. Arguments are specified in pairs: the buffer pointer and the length of the data at that location (use a length of -1 to tell the vwrite function to count the length of a null-terminated string for itself). The list of arguments is terminated with a single NULL ptr.

The MBuf_write() function is a shorthand for writing out a single length-terminated buffer. It is just like calling MBuf_vwrite(mbuf,buf,len,NULL).

The MBuf_puts() function is a shorthand for writing out a single null-terminated string. It is just like calling MBuf_vwrite(mbuf,str,-1,NULL).

The MBuf_putc() function is a more optimal way to write a single character onto the end of the last chunk of data than it would be to call the vwrite function with a character pointer and a length of 1.

The MBuf_overwrite() function allows you to write data to a specific position in the buffer (wrapping around all chunk boundaries, as required). The function will not extend the size of the MBuf, however.

The MBuf_getLength() call returns the total size of all the associated data. The currently allocated size may be slightly larger.

The MBuf_memcpy() function works just like memcpy(), except that you specify the destination and source positions as offsets rather than using pointers. The data copying correctly handles the crossing of any and all chunk boundaries.

The MBuf_truncate() call trims a buffer back to the indicated length. If the length is short enough that one or more chunks of data are no longer needed, they will be freed.

The MBuf_setReadPos() function sets the point where the next read will occur. By default, all buffers start out with a read position of 0.

The MBuf_getReadPos() function returns the offset of the current read position within the list of all buffer chunks.

The MBuf_read() function reads data from the current read position into your buffer, up to the indicated length. The only reason you won't get the full length number of bytes would be if you had reached the end of the last chunk of data. The read position is bumped forward to point past the last byte that was returned.

The MBuf_gets() function reads a single line of data from the current read position, up to the maximum line size specified. The read position is bumped forward to the start of the next line (or the next unreturned character if the current line didn't entirely fit). The trailing newline is included in the buffer, and non-standard line-endings (such as CR+LF or just CR) are translated into the unix standard (NL).

The MBuf_getc() function is a more optimal way to read a single character at a time from the read position than it would be to use MBuf_read() directly. EOF is returned if there are no more characters, otherwise the read position is bumped forward to the next available character.

The MBuf_dataPtr() is a slightly more efficient means of reading the data back out of the buffer since it does not copy any bytes from the MBuf chunks into a separate buffer. The returned data pointer points to the current read position within the buffer. You also specify the maximum size that you want to deal with in a single piece, and the function will update this value downward as needed to fit within the current data chunk. You can therefore use this just like you would a read function with the only caveat being that you might get as few as 1 character at a time, depending on how big the chunks are and how much data is left in the current chunk. (Of course, if you ask for the same sized chunks of data that you put into the buffer, you don't have to worry about this.)

The MBuf_dataPtrAt() works much the same as MBuf_dataPtr() does except that you specify the offset for the pointer's position, and the read position is not affected at all. The length value (if specified) may be adjusted downward to indicate how many bytes are actually available at the indicated position. Feel free to specify a NULL pointer for the length if you either don't need more than a single byte or if you know how many bytes are already available at the requested position.

The MBuf_appendMBuf() function takes all the chunks of data from another MBuf and appends them to the tail of our buffer-chunk list. The MBuf that gives up its chunks is destroyed in the process.

The MBuf_appendBuffer() function takes a chunk of malloc'ed memory (as indicated by its pointer, used length, and allocated length) and puts it onto the tail of the list of buffer chunks. You can specify 0 for the allocated length if the buffer does not have any extra space allocated.

The MBuf_prependBuffer() function takes a chunk of malloc'ed memory (as indicated by its pointer and length) and puts it onto the head of the list of buffer chunks. The read position and size are updated appropriately.

The MBuf_toBuffer() function turns an MBuf into a simple malloced buffer. If the MBuf had multiple chunks, they are collapsed into a single buffer. If there was only one chunk and you passed in an int pointer for the allocated size to be returned to you (as opposed to a NULL), the single buffer is left with its extra space intact -- otherwise any unused space it returned to the malloc pool.