Overview

The RoseOutputStream class is a utility class used to generalize the destination for file format writing code within the ROSE library. It maintains a data buffer and calls the virtual flush() function to write the block when full.

The RoseOutputFile subclass wraps FILE* and is most common, but other subtypes exist to write to a memory string, a Gzip compressed source, or a member of a Zip archive.

You can create one of the specific subtypes and then pass around a pointer or reference cast as this supertype. Strings are written with the put() function. A put_sprintf() function is also available, which allocates an intermediate buffer, does sprintf(), and then put().

RoseOutputStream * stream;
unsigned some_number

// add something to the stream, do not know if the stream
// is a file, string, or something else.
stream->put("Hello World\n");
stream->put_sprintf("My favorite number is %u\n", some_number);

as_file()

virtual FILE * as_file();

The as_file() function is a convenience function for transitioning legacy code that can only work on a FILE*. By default this returns null, but will return the underlying file pointer if the stream is a RoseOutputFile.

buffer()

unsigned char * buffer()

The buffer() function returns the start of the I/O memory buffer used to accumulate many put() calls and write data in a single block. The io_size() function gives the size of this buffer.

curpos()

size_t curpos();
void curpos (size_t v);

The curpos() function returns or sets the offset within the I/O memory buffer of the next character to write. So an empty buffer is curpos() zero.

error_state()

int error_state();

The error_state() function returns a non-zero value if there has been some sort of I/O error, usually when flushing the buffer. All further pushes will be ignored if the stream is in an error state. In the file context, this is the value returned by ferror().

flush()

virtual int flush();	// return ferror()

The flush() function writes the contents of the I/O memory buffer to the destination of the stream and returns the error_state(). This is called automatically by put() when the buffer is full. You must also call it manually when you are done to write the last partial buffer of data out to the destination.

This is a virtual function that is overridden by each stream subtype.

io_size()

size_t io_size();
void io_size(size_t sz);

The io_size() function gets and set the size used for the I/O memory buffer. Changing the size of the buffer in the middle of writing will lose any data not yet flushed.

name()

void name (const char * s);
const char * name();

The name() function gets and sets a description for the stream. This could be filename or any other appropriate value.

put()

int put (int c);
int put (const char * str);

The put() function writes an individual character or a null-terminated character string to the stream. The function returns the number of characters written, or negtive on error.

put_sprintf()

int put_sprintf (const char* fmat, ...);

The put_sprintf() function takes a printf-style format string and variable arguements. It allocates an intermediate buffer, does sprintf() to build a string, and then calls put() to write the resulting string.

When efficiency is important, call sprintf() yourself and put() the result. You can then reuse your string buffer and make wise choices for the initial size. The put_sprintf() must allocate a new string every time and does not know the best size, so it may call sprintf() more than once and reallocate memory if the result is larger than expected.

unsigned i;

// works just fine.
stream.put_sprintf("My favorite number is %u\n", i);


// In a tight loop, the following is less clear but more efficient
// because we know the string will not exceed a certain size and can
// use stack memory.   This is classic "C programmers disease" so use
// sparingly.

char numbuf[256];
snprintf(str, 256, "My favorite number is %u\n", i);

stream.put(numbuf);