diff options
| author | Mike Buland <eichlan@xagasoft.com> | 2007-10-03 09:13:28 +0000 |
|---|---|---|
| committer | Mike Buland <eichlan@xagasoft.com> | 2007-10-03 09:13:28 +0000 |
| commit | b3eef5b0b82c20a9f11868ba376f6bb2d94faae4 (patch) | |
| tree | 7c5f4243d3a528f86daad826ed886dea6b816871 /src/doxy/streams.dox | |
| parent | 850ebb96df909a4113fdf9c5bf82cf0f598901ca (diff) | |
| download | libbu++-b3eef5b0b82c20a9f11868ba376f6bb2d94faae4.tar.gz libbu++-b3eef5b0b82c20a9f11868ba376f6bb2d94faae4.tar.bz2 libbu++-b3eef5b0b82c20a9f11868ba376f6bb2d94faae4.tar.xz libbu++-b3eef5b0b82c20a9f11868ba376f6bb2d94faae4.zip | |
Nothing about function. I added a bunch of docs and re-arranged a bunch of
the existing docs. Taking advantage of some of the cooler extra features of
doxygen I've started writing extra how-to pages covering working with sections
of the library. Also, I started grouping the classes by function so they show
up on the Modules page together, very cute.
Diffstat (limited to 'src/doxy/streams.dox')
| -rw-r--r-- | src/doxy/streams.dox | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/doxy/streams.dox b/src/doxy/streams.dox new file mode 100644 index 0000000..65f01d7 --- /dev/null +++ b/src/doxy/streams.dox | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /** | ||
| 2 | *@page howto_streams Working With Streams | ||
| 3 | * | ||
| 4 | * Working with libbu++ streams is simple and very straight-forward, but there | ||
| 5 | * are a few things to understand when you pick them up for the first time. | ||
| 6 | * | ||
| 7 | *@section whatis What is a stream? | ||
| 8 | * A stream is a mechanism that allows data to be transported from one place to | ||
| 9 | * another without interruption and in order. Examples of this include data | ||
| 10 | * being written to a file or being read from a file, data being written to a | ||
| 11 | * network socket or read from a network socket, and so on. | ||
| 12 | * Every type of stream will support a different number of options, for example | ||
| 13 | * file streams are usually seekable, that is, you can select where in the file | ||
| 14 | * you are reading and writing, however network sockets are not seekable. All | ||
| 15 | * of these properties can be determined at runtime through the Stream class. | ||
| 16 | * | ||
| 17 | *@section filters Using filters with streams | ||
| 18 | * Libbu++ supports a special type of Stream that is known as a Filter. Filters | ||
| 19 | * are actually streams, except instead of reading or writing to or from a | ||
| 20 | * file they read or write to or from another stream. This provides a handy | ||
| 21 | * way of chaining any number of filters together along with end-point streams | ||
| 22 | * such as files. One example of this would be applying a BZip2 compression | ||
| 23 | * filter to a file stream to compress all data being written to it. | ||
| 24 | * Once a filter is applied the transformations that it applies to the data will | ||
| 25 | * happen automatically as you use the stream. | ||
| 26 | * | ||
| 27 | * One important thing to remember about streams is that they will commonly | ||
| 28 | * change the options that you have when it comes to interacting with the | ||
| 29 | * stream. This is not a bad thing, it is necesarry, but it is easy to tell | ||
| 30 | * when this is happening. To continue with the above example, you can seek in | ||
| 31 | * a File stream, but not in a BZip2 filtered File stream. This has to do with | ||
| 32 | * the way the compression algorithms work and restrict the operations that can | ||
| 33 | * be easily performed on the data. | ||
| 34 | * | ||
| 35 | * Not all changes that filters apply will be restrictive, filters such as the | ||
| 36 | * Buffer filter will add the ability to seek (to an extent) within the buffered | ||
| 37 | * data. | ||
| 38 | * | ||
| 39 | *@section difference How are libbu++ streams different form stl streams? | ||
| 40 | * While not globally true, many stl streams are designed for formatting the | ||
| 41 | * data that flows through the stream, that means that when you attempt to | ||
| 42 | * write a uint32_t into a standard stream it can be difficult to predict what | ||
| 43 | * the result will be, will it be the binary representation or a textual | ||
| 44 | * conversion? | ||
| 45 | * | ||
| 46 | * Libbu++ streams are very direct about how the data is handled. All end-point | ||
| 47 | * streams will always handle the data that you provide or request without any | ||
| 48 | * modification or formatting, very much like the way libc style file access | ||
| 49 | * works. | ||
| 50 | * | ||
| 51 | * The design of Libbu++ streams was, from the begining, to try to make it as | ||
| 52 | * easy as possible to write general code that was as easy as possible to | ||
| 53 | * extend, and as clear as possible. We have accomplished this by making | ||
| 54 | * streams simple, yet flexible, with a clear API and a flexible filter system | ||
| 55 | * that something geared towards more general formatting, conversion, and | ||
| 56 | * operator-only access can't touch. | ||
| 57 | * | ||
| 58 | *@section usage Using streams directly | ||
| 59 | * To create a stream depends on the type of stream that you're interested in, | ||
| 60 | * each type has it's own constructors designed to create the stream and get | ||
| 61 | * it ready for use. We'll use the Bu::File stream as an example here. | ||
| 62 | * | ||
| 63 | *@code | ||
| 64 | // The constructor and each function call to access the stream could throw | ||
| 65 | // an exception, it's important to catch these and handle them | ||
| 66 | // appropriately. | ||
| 67 | try | ||
| 68 | { | ||
| 69 | // sFileName is a Bu::FString object containing the name of the file to | ||
| 70 | // open, possibly with path elements. The second parameter works like | ||
| 71 | // the fopen mode parameter, and can be "w" for write, "r" for read, or | ||
| 72 | // "a" for append. This will likely be replaced with a bitfield later. | ||
| 73 | Bu::File f( sFileName, "w"); | ||
| 74 | |||
| 75 | // At this point we know our file is open, lets write some data to it | ||
| 76 | // The first parameter is a pointer to the data to write, the second is | ||
| 77 | // how many bytes to write. | ||
| 78 | f.write( "Test data, boring old test data.\n", 33 ); | ||
| 79 | |||
| 80 | // We don't actually need to close the file explicitly, the | ||
| 81 | // deconstructor will take care of that for us, we could if we wanted | ||
| 82 | // to, simply by calling the f.close() function, but it isn't necesarry. | ||
| 83 | } | ||
| 84 | catch( Bu::FileException &e ) | ||
| 85 | { | ||
| 86 | // Here we can report the error to the system, whatever it happened to | ||
| 87 | // be. | ||
| 88 | printf("Error: %s\n", e.what() ); | ||
| 89 | } | ||
| 90 | @endcode | ||
| 91 | * This is a most basic example, but it covers all the basics. You don't need | ||
| 92 | * much more than this to write just about any file i/o program, just use the | ||
| 93 | * Bu::Stream::read() and Bu::Stream::write() functions. | ||
| 94 | * | ||
| 95 | * Now lets look at how to add a stream to the mix, we'll BZip2 compress the | ||
| 96 | * above example. | ||
| 97 | *@code | ||
| 98 | // Again, we want to catch exceptions in the entire file handling block. | ||
| 99 | try | ||
| 100 | { | ||
| 101 | // We create the file just like before, nothing different about this. | ||
| 102 | Bu::File f( sFileName, "w"); | ||
| 103 | |||
| 104 | // Here, however, we create our Bu::BZip2 object, and pass it a | ||
| 105 | // reference to the file. Now our data will go through Bu::BZip2, then | ||
| 106 | // into Bu::File and onto disk. Notice that you don't have to specify | ||
| 107 | // wether you want to read or write explicitly, the filter can usually | ||
| 108 | // determine this for itself by examining the underlying stream. | ||
| 109 | Bu::BZip2 bz2( f ); | ||
| 110 | |||
| 111 | // This is done exactly as before, but this time we write into bz2, not | ||
| 112 | // f. We already know how to do this, because both BZip2 and File | ||
| 113 | // inherit from Bu::Stream, so they both have very similar (if not | ||
| 114 | // identicle) API. | ||
| 115 | bz2.write( "Test data, boring old test data.\n", 33 ); | ||
| 116 | |||
| 117 | // Just like last time, we don't have to close either stream explicitly, | ||
| 118 | // they will be destroyed appropriately by the system, and in the | ||
| 119 | // correct order (bz2 first, then f). | ||
| 120 | } | ||
| 121 | catch( Bu::FileException &e ) | ||
| 122 | { | ||
| 123 | // Here we can report the error to the system, whatever it happened to | ||
| 124 | // be. | ||
| 125 | printf("Error: %s\n", e.what() ); | ||
| 126 | } | ||
| 127 | @endcode | ||
| 128 | * | ||
| 129 | * As you can tell in this example, using streams and filters is very easy to | ||
| 130 | * do, and even makes formerly very complex procedures take almost no time at | ||
| 131 | * all. | ||
| 132 | * | ||
| 133 | *@section usingmore Accepting strings in other classes and functions | ||
| 134 | * | ||
| 135 | * When writing a class or function that uses an already opened stream to read | ||
| 136 | * or write data from or to it's important to plan ahead, and probably accept | ||
| 137 | * an object reference of type Bu::Stream. This makes your code immediately | ||
| 138 | * much more portable, useful, and flexible. You don't have to change anything | ||
| 139 | * about the way you write your class or function, use the standard Bu::Stream | ||
| 140 | * functions like read and write just like before. | ||
| 141 | * | ||
| 142 | * For example, lets say you're creating a new image format, and need to be able | ||
| 143 | * to store images on disk and read them off again, so you write the approprate | ||
| 144 | * file fromat handlers. By using Bu::Stream instead of Bu::File you allow | ||
| 145 | * anyone using your image format to send that data anywhere they would like, | ||
| 146 | * including files, sockets, memory buffers, composite archives, and even | ||
| 147 | * through types of streams that don't exist yet. Not only that, but since | ||
| 148 | * every filter is a stream, anyone is now free to pass you a BZip2 filter or | ||
| 149 | * an encryption filter, or any other chain, so that your data can be | ||
| 150 | * compressed, and possibly encrypted, and sent over the network without any | ||
| 151 | * changes to your original code. | ||
| 152 | * | ||
| 153 | * Understandably you probably want to be sure of a few basics before you go | ||
| 154 | * writing image data to any old stream, such as ensuring the stream supports | ||
| 155 | * writing to begin with. This can be easily handled by taking advantage of | ||
| 156 | * the capability accessors in Bu::Stream, these begin with "can" and "is," see | ||
| 157 | * the documentation for more information. | ||
| 158 | */ | ||
