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 | */ | ||