aboutsummaryrefslogtreecommitdiff
path: root/src/doxy/streams.dox
diff options
context:
space:
mode:
Diffstat (limited to 'src/doxy/streams.dox')
-rw-r--r--src/doxy/streams.dox158
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 */