00001 /******************************************************************************* 00002 00003 @file IBuffer.d 00004 00005 Copyright (C) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 00027 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00028 00029 00030 @version Initial version, March 2004 00031 @author Kris 00032 00033 00034 *******************************************************************************/ 00035 00036 module mango.io.model.IBuffer; 00037 00038 private import mango.io.model.IConduit; 00039 00040 00041 /******************************************************************************* 00042 00043 The basic premise behind this IO package is as follows: 00044 00045 1) the central concept is that of a buffer. The buffer acts 00046 as a queue (line) where items are removed from the front 00047 and new items are added to the back. Buffers are modeled 00048 by this interface, and mango.io.Buffer exposes a concrete 00049 implementation. 00050 00051 2) buffers can be written to directly, but a Reader and/or 00052 Writer are typically used to read & write formatted data. 00053 These readers & writers are bound to a specific buffer; 00054 often the same buffer. It's also perfectly legitimate to 00055 bind multiple writers to the same buffer; they will all 00056 behave serially as one would expect. The same applies to 00057 multiple readers on the same buffer. Readers and writers 00058 support two styles of IO: put/get, and the C++ style << 00059 and >> operators. All such operations can be chained. 00060 00061 3) Any class can be made compatable with the reader/writer 00062 framework by implementing the IReadable and/or IWritable 00063 interfaces. Each of these specify just a single method. 00064 00065 4) Buffers may also be tokenized. This is handy when one is 00066 dealing with text input, and/or the content suits a more 00067 fluid format than most typical readers & writers support. 00068 Tokens are mapped directly onto buffer content, so there 00069 is only minor overhead in using them. Tokens can be read 00070 and written by reader/writers also, using a more relaxed 00071 set of rules than those applied to integral IO. 00072 00073 5) buffers are sometimes memory-only, in which case there 00074 is nothing left to do when a reader (or tokenizer) hits 00075 end of buffer conditions. Other buffers are themselves 00076 bound to a Conduit. When this is the case, a reader will 00077 eventually cause the buffer to reload via its associated 00078 conduit. Previous buffer content will thus be lost. The 00079 same concept is applied to writers, whereby they flush 00080 the content of a full buffer to a bound conduit before 00081 continuing. 00082 00083 6) conduits provide virtualized access to external content, 00084 and represent things like files or Internet connections. 00085 They are just a different kind of stream. Conduits are 00086 modelled by mango.io.model.IConduit, and implemented via 00087 classes FileConduit and SocketConduit. Additional kinds 00088 of conduit are easy to construct: one either subclasses 00089 mango.io.Conduit, or implements mango.io.model.IConduit. A 00090 conduit reads and writes from/to a buffer in big chunks 00091 (typically the entire buffer). 00092 00093 *******************************************************************************/ 00094 00095 interface IBuffer 00096 { 00097 /*********************************************************************** 00098 00099 Create an instance of an IBuffer. Use this when you 00100 don't know anything about the concrete implementation, 00101 and have only the IBuffer interface available 00102 00103 ***********************************************************************/ 00104 00105 IBuffer create (); 00106 00107 /*********************************************************************** 00108 00109 Return the backing array 00110 00111 ***********************************************************************/ 00112 00113 void[] getContent (); 00114 00115 /*********************************************************************** 00116 00117 Return a char[] slice of the buffer up to the limit of 00118 valid content. 00119 00120 ***********************************************************************/ 00121 00122 char[] toString (); 00123 00124 /*********************************************************************** 00125 00126 Set the backing array with all content readable. Writing 00127 to this will either flush it to an associated conduit, or 00128 raise an Eof condition. Use IBuffer.clear() to reset the 00129 content (make it all writable). 00130 00131 ***********************************************************************/ 00132 00133 IBuffer setValidContent (void[] data); 00134 00135 /*********************************************************************** 00136 00137 Set the backing array with some content readable. Writing 00138 to this will either flush it to an associated conduit, or 00139 raise an Eof condition. Use IBuffer.clear() to reset the 00140 content (make it all writable). 00141 00142 ***********************************************************************/ 00143 00144 IBuffer setContent (void[] data, uint readable); 00145 00146 /*********************************************************************** 00147 00148 Write an array of data into this buffer, and flush to the 00149 conduit as necessary. Returns a chaining reference if all 00150 data was written; throws an IOException indicating eof or 00151 eob if not. 00152 00153 This is often used in lieu of a Writer. 00154 00155 ***********************************************************************/ 00156 00157 IBuffer append (void[] content); 00158 00159 /*********************************************************************** 00160 00161 Read a chunk of data from the buffer, loading from the 00162 conduit as necessary. The requested number of bytes are 00163 loaded into the buffer, and marked as having been read 00164 when the 'eat' parameter is set true. When 'eat' is set 00165 false, the read position is not adjusted. 00166 00167 Returns the corresponding buffer slice when successful, 00168 or null if there's not enough data available (Eof; Eob). 00169 00170 ***********************************************************************/ 00171 00172 void[] get (uint size, bool eat = true); 00173 00174 /*********************************************************************** 00175 00176 Write a chunk of data into this buffer, and flush to the 00177 conduit as necessary. Returns true if all data was written, 00178 false otherwise (indicating eof, or eob). 00179 00180 This is typically used for streaming formatted data. Note 00181 that this should ideally have package visibility only, as 00182 it should be restricted to Writers etc. 00183 00184 ***********************************************************************/ 00185 00186 void* put (void *src, uint size); 00187 00188 /*********************************************************************** 00189 00190 Exposes the raw data buffer at the current write position, 00191 The delegate is provided with a void[] representing space 00192 available within the buffer at the current write position. 00193 00194 The delegate should return the approriate number of bytes 00195 if it writes valid content, or IConduit.Eof on error. 00196 00197 Returns whatever the delegate returns. 00198 00199 ***********************************************************************/ 00200 00201 int write (int delegate(void[]) writer); 00202 00203 /*********************************************************************** 00204 00205 Exposes the raw data buffer at the current read position. The 00206 delegate is provided with a void[] representing the available 00207 data, and should return zero to leave the current read position 00208 intact. 00209 00210 If the delegate consumes data, it should return the number of 00211 bytes consumed; or IConduit.Eof to indicate an error. 00212 00213 Returns whatever the delegate returns. 00214 00215 ***********************************************************************/ 00216 00217 int read (int delegate(void[]) reader); 00218 00219 /*********************************************************************** 00220 00221 If we have some data left after an export, move it to 00222 front-of-buffer and set position to be just after the 00223 remains. This is for supporting certain conduits which 00224 choose to write just the initial portion of a request. 00225 00226 Limit is set to the amount of data remaining. Position 00227 is always reset to zero. 00228 00229 ***********************************************************************/ 00230 00231 IBuffer compress (); 00232 00233 /*********************************************************************** 00234 00235 Skip ahead by the specified number of bytes, streaming from 00236 the associated conduit as necessary. 00237 00238 Can also reverse the read position by 'size' bytes. This may 00239 be used to support lookahead-type operations. 00240 00241 Returns true if successful, false otherwise. 00242 00243 ***********************************************************************/ 00244 00245 bool skip (int size); 00246 00247 /*********************************************************************** 00248 00249 flush the contents of this buffer to the related conduit. 00250 Throws an IOException on premature eof. 00251 00252 ***********************************************************************/ 00253 00254 void flush (); 00255 00256 /*********************************************************************** 00257 00258 Reset position and limit to zero. 00259 00260 ***********************************************************************/ 00261 00262 IBuffer clear (); 00263 00264 /*********************************************************************** 00265 00266 return count of readable bytes remaining in buffer. This is 00267 calculated simply as limit() - position() 00268 00269 ***********************************************************************/ 00270 00271 uint readable (); 00272 00273 /*********************************************************************** 00274 00275 Return count of writable bytes available in buffer. This is 00276 calculated simply as capacity() - limit() 00277 00278 ***********************************************************************/ 00279 00280 uint writable (); 00281 00282 /*********************************************************************** 00283 00284 returns the limit of readable content within this buffer 00285 00286 ***********************************************************************/ 00287 00288 uint getLimit (); 00289 00290 /*********************************************************************** 00291 00292 returns the total capacity of this buffer 00293 00294 ***********************************************************************/ 00295 00296 uint getCapacity (); 00297 00298 /*********************************************************************** 00299 00300 returns the current position within this buffer 00301 00302 ***********************************************************************/ 00303 00304 uint getPosition (); 00305 00306 /*********************************************************************** 00307 00308 Overridable method to grow the buffer size when it becomes 00309 full. Default is to not grow at all. 00310 00311 ***********************************************************************/ 00312 00313 bool grow (uint size); 00314 00315 /*********************************************************************** 00316 00317 Returns the conduit associated with this buffer. Returns 00318 null if the buffer is purely memory based; that is, it's 00319 not backed by some external conduit. 00320 00321 Buffers do not require a conduit to operate, but it can 00322 be convenient to associate one. For example, the IReader 00323 and IWriter classes use this to import/export content as 00324 necessary. 00325 00326 ***********************************************************************/ 00327 00328 IConduit getConduit (); 00329 00330 /*********************************************************************** 00331 00332 Sets the external conduit associated with this buffer. 00333 00334 Buffers do not require an external conduit to operate, but 00335 it can be convenient to associate one. For example, methods 00336 read and write use it to import/export content as necessary. 00337 00338 ***********************************************************************/ 00339 00340 void setConduit (IConduit conduit); 00341 } 00342 00343 00344 /******************************************************************************* 00345 00346 *******************************************************************************/ 00347 00348 typedef void delegate(void* dst, uint count) BufferConverter; 00349