
1 // 2 // Copyright (c) 2006, Brian Frank and Andy Frank 3 // Licensed under the Academic Free License version 3.0 4 // 5 // History: 6 // 16 Mar 06 Brian Frank Creation 7 // 8 9 ** 10 ** InStream is used to read binary and text stream based input. 11 ** 12 class InStream 13 { 14 15 ////////////////////////////////////////////////////////////////////////// 16 // Construction 17 ////////////////////////////////////////////////////////////////////////// 18 19 ** 20 ** Make an input stream designed to read characters from the specified 21 ** string. If binary reads are made from the string, then each character 22 ** is read as a one byte ASCII char. 23 ** 24 static InStream makeForStr(Str str) 25 26 ** 27 ** Constructor for an InStream which wraps another stream. 28 ** All reads from this stream will be routed to the specified 29 ** inner stream. 30 ** 31 ** If in is null, then it is the subclass responsibility to 32 ** handle reads by overriding the following methods: `read`, 33 ** `readBuf`, and `unread`. 34 ** 35 protected new make(InStream out) 36 37 ////////////////////////////////////////////////////////////////////////// 38 // Virtuals 39 ////////////////////////////////////////////////////////////////////////// 40 41 ** 42 ** Read the next unsigned byte from the input stream. 43 ** Return null if at end of stream. Throw IOErr on error. 44 ** 45 virtual Int read() 46 47 ** 48 ** Attempt to read the next n bytes into the Buf at it's current 49 ** position. The buffer will be grown as needed. Return the number 50 ** of bytes read and increment buf's size and position accordingly. 51 ** Return null and leave buf's state untouched if end of stream. 52 ** Note this method may not read the full number of n bytes, use 53 ** readBufFully() if you must block until all n bytes read. 54 ** Throw IOErr on error. 55 ** 56 virtual Int readBuf(Buf buf, Int n) 57 58 ** 59 ** Pushback a byte so that it is the next byte to be read. There 60 ** is a finite limit to the number of bytes which may be pushed 61 ** back. Return this. 62 ** 63 virtual InStream unread(Int b) 64 65 ** 66 ** Close the input stream. This method is guaranteed to never 67 ** throw an IOErr. Return true if the stream was closed successfully 68 ** or false if the stream was closed abnormally. Default implementation 69 ** does nothing and returns true. 70 ** 71 virtual Bool close() 72 73 ** 74 ** Attempt to skip 'n' number of bytes. Return the number of bytes 75 ** actually skipped which may be equal to or lesser than n. 76 ** 77 virtual Int skip(Int n) 78 79 ////////////////////////////////////////////////////////////////////////// 80 // Buf Support 81 ////////////////////////////////////////////////////////////////////////// 82 83 ** 84 ** Read the entire contents of the stream into a memory Buf. 85 ** The resulting buffer is automatically positioned at the beginning. 86 ** This InStream is guaranteed to be closed. 87 ** 88 Buf readAllBuf() 89 90 ** 91 ** Read the next n bytes from the stream into the Buf at it's 92 ** current position. The buffer will be grown as needed. If the 93 ** buf parameter is null, then a buffer is automatically created 94 ** with a capacity of n. Block until exactly n bytes have been 95 ** read or throw IOErr if end of stream is reached first. Return 96 ** the Buf passed in or the one created automatically if buf is null. 97 ** The buffer is automatically positioned at the beginning. 98 ** 99 Buf readBufFully(Buf buf, Int n) 100 101 ////////////////////////////////////////////////////////////////////////// 102 // Binary Data 103 ////////////////////////////////////////////////////////////////////////// 104 105 ** 106 ** Peek at the next byte to be read without actually consuming 107 ** it. Peek has the same semantics as a read/unread. Return 108 ** null if at end of stream. 109 ** 110 Int peek() 111 112 ** 113 ** Read the next byte as an unsigned 8-bit number in network 114 ** byte order. This method may be paired with OutStream.write. 115 ** Throw IOErr on error or if the end of stream is reached before 116 ** one byte can be read. This method differs from read() in that 117 ** it will throw IOErr on end of stream rather than return null. 118 ** 119 Int readU1() 120 121 ** 122 ** Read the next byte as a signed 8-bit number. This method may be 123 ** paired with `OutStream.write`. Throw IOErr on error or if the end 124 ** of stream is reached before one byte can be read. 125 ** 126 Int readS1() 127 128 ** 129 ** Read the next two bytes as an unsigned 16-bit number in network 130 ** byte order. This method may be paired with `OutStream.writeI2`. 131 ** Throw IOErr on error or if the end of stream is reached before 132 ** two bytes can be read. 133 ** 134 Int readU2() 135 136 ** 137 ** Read the next two bytes as a signed 16-bit number in network 138 ** byte order. This method may be paired with `OutStream.writeI2`. 139 ** Throw IOErr on error or if the end of stream is reached before 140 ** two bytes can be read. 141 ** 142 Int readS2() 143 144 ** 145 ** Read the next four bytes as an unsigned 32-bit number in network 146 ** byte order. This method may be paired with `OutStream.writeI4`. 147 ** Throw IOErr on error or if the end of stream is reached before 148 ** four bytes can be read. 149 ** 150 Int readU4() 151 152 ** 153 ** Read the next four bytes as a signed 32-bit number in network 154 ** byte order. This method may be paired with `OutStream.writeI4`. 155 ** Throw IOErr on error or if the end of stream is reached before 156 ** four bytes can be read. 157 ** 158 Int readS4() 159 160 ** 161 ** Read the next eight bytes as a signed 64-bit number in network 162 ** byte order. This method may be paired with `OutStream.writeI8`. 163 ** Throw IOErr on error or if the end of stream is reached before 164 ** eight bytes can be read. Note there is no readU8 (because Java 165 ** doesn't support unsigned longs). 166 ** 167 Int readS8() 168 169 ** 170 ** Read the next four bytes as a 32-bit floating point number in 171 ** network byte order according to `Float.bits32`. This method may be 172 ** paired with `OutStream.writeF4`. Throw IOErr on error or if the 173 ** end of stream is reached before four bytes can be read. 174 ** 175 Float readF4() 176 177 ** 178 ** Read the next eight bytes as a 64-bit floating point number in 179 ** network byte order according to `Float.bits`. This method may be 180 ** paired with `OutStream.writeF8`. Throw IOErr on error or if the 181 ** end of stream is reached before four bytes can be read. 182 ** 183 Float readF8() 184 185 ** 186 ** Read the next byte and return true if nonzero. This method may 187 ** be paired with `OutStream.writeBool`. Throw IOErr on error or if 188 ** the end of stream is reached before one byte can be read. 189 ** 190 Bool readBool() 191 192 ** 193 ** Read a Str in modified UTF-8 format according the java.io.DataInput 194 ** specification. This method may be paired with `OutStream.writeUtf`. 195 ** Throw IOErr on error, invalid UTF encoding, or if the end of stream 196 ** is reached before the string is fully read. 197 ** 198 Str readUtf() 199 200 ////////////////////////////////////////////////////////////////////////// 201 // Text Data 202 ////////////////////////////////////////////////////////////////////////// 203 204 ** 205 ** The current charset used to decode bytes into Unicode 206 ** characters. The default charset should always be UTF-8. 207 ** 208 virtual Charset charset 209 210 ** 211 ** Read a single Unicode character from the stream using the 212 ** current charset encoding. Return null if at end of stream. 213 ** Throw IOErr if there is a problem reading the stream, or 214 ** an invalid character encoding is encountered. 215 ** 216 Int readChar() 217 218 ** 219 ** Pushback a char so that it is the next char to be read. This 220 ** method pushes back one or more bytes depending on the current 221 ** character encoding. Return this. 222 ** 223 InStream unreadChar(Int b) 224 225 ** 226 ** Peek at the next char to be read without actually consuming 227 ** it. Peek has the same semantics as a readChar/unreadChar. 228 ** Return null if at end of stream. 229 ** 230 Int peekChar() 231 232 ** 233 ** Read the next line from the input stream as a Str based on the 234 ** configured charset. A line is terminated by \n, \r\n, \r, or 235 ** EOF. The Str returned never contains the trailing newline. 236 ** 237 ** The max parameter specifies the maximum number of Unicode 238 ** chacters (not bytes) to read before truncating the line and 239 ** returning. If max is null, then no boundary is enforced except 240 ** of course the end of the stream. Max defaults to 4kb. 241 ** 242 ** Return null if the end of stream has been reached. Throw IOErr 243 ** if there is a problem reading the stream or an invalid character 244 ** encoding is encountered. 245 ** 246 Str readLine(Int max := 4096) 247 248 ** 249 ** Read a Str token from the input stream which is terminated 250 ** when the specified function 'c' returns false. The terminating 251 ** char is unread and will be the next char read once this 252 ** method returns. Characters are read based on the currently 253 ** configured charset. 254 ** 255 ** If 'c' is null then the default implementation tokenizes up 256 ** until the next character which returns true for `Int.isSpace`. 257 ** 258 ** The max parameter specifies the maximum number of Unicode 259 ** chacters (not bytes) to read before truncating the line and 260 ** returning. If max is null, then no boundary is enforced except 261 ** of course the end of the stream. Max defaults to 4kb. 262 ** 263 ** Return null if the end of stream has been reached. Throw IOErr 264 ** if there is a problem reading the stream or an invalid character 265 ** encoding is encountered. 266 ** 267 Str readStrToken(Int max := 4096, |Int ch->Bool| c := null) 268 269 ** 270 ** Read the entire stream into a list of Str lines based on the 271 ** configured charset encoding. Each Str in the list maps 272 ** to a line terminated by \n, \r\n, \r, or EOF. The Str lines 273 ** themselves do not contain a trailing newline. Empty lines 274 ** are returned as the empty Str "". Return an empty list if 275 ** currently at end of stream (not null). Throw IOErr if there 276 ** is a problem reading the stream or an invalid character encoding 277 ** is encountered. This InStream is guaranteed to be closed upon 278 ** return. 279 ** 280 Str[] readAllLines() 281 282 ** 283 ** Read the entire stream into Str lines based on the current 284 ** encoding. Call the specified function for each line read. 285 ** Each line is terminated by \n, \r\n, \r, or EOF. The Str 286 ** lines themselves do not contain a trailing newline. Empty 287 ** lines are returned as the empty Str "". This InStream is 288 ** guaranteed to be closed upon return. 289 ** 290 Void eachLine(|Str line| f) 291 292 ** 293 ** Read the entire stream into a Str based on the configured 294 ** charset encoding. If the normalizeNewlines flag is true, 295 ** then all occurances of \r\n or \r newlines are normalized 296 ** into \n. Return "" if the stream is empty. Throw IOErr if 297 ** there is a problem reading the stream or an invalid character 298 ** encoding is encountered. This InStream is guaranteed to 299 ** be closed. 300 ** 301 Str readAllStr(Bool normalizeNewlines := true) 302 303 ** 304 ** Read a serialized object from the stream according to 305 ** the Fan [serialization format]`docLang::Serialization`. 306 ** Throw IOErr or ParseErr on error. This method may consume 307 ** bytes/chars past the end of the serialized object (we may 308 ** want to add a "full stop" token at some point to support 309 ** compound object streams). 310 ** 311 ** The options may be used to specify additional decoding 312 ** logic: 313 ** - "makeArgs": Obj[] arguments to pass to the root 314 ** object's make constructor via 'Type.make' 315 ** 316 Obj readObj(Str:Obj options := null) 317 318 ////////////////////////////////////////////////////////////////////////// 319 // Utils 320 ////////////////////////////////////////////////////////////////////////// 321 322 ** 323 ** Read the entire stream into a Str:Str of name value pairs using the 324 ** Fan props file format. This format is similiar but different than 325 ** the Java properties file format: 326 ** - Input must be UTF-8 encoded (current charset is ignored) 327 ** - Name/value pairs formatted as logical line: <name>"="<value> 328 ** - Any Unicode character allowed in name or value 329 ** - Leading and trailing whitespace trimmed from both name and value 330 ** - Duplicate name keys within one file is an error condition 331 ** - Comment to end of line is '//' if start of line or preceeded 332 ** by whitespace 333 ** - Block comment is '/* */' (may be nested) 334 ** - Use trailing \ to continue logical line to another actual line, 335 ** any leading whitespace (space or tab char) is trimmed from beginning 336 ** of continued line 337 ** - Fan Str literal escape sequences supported: \n \r \t or \uxxxx 338 ** - The $ character is treated as a normal character and should not be 339 ** escaped, but convention is to indicate a variable in a format string 340 ** - Convention is that name is lower camel case with dot separators 341 ** 342 ** Throw IOErr if there is a problem reading the stream or an invalid 343 ** props format is encountered. This InStream is guaranteed to be closed. 344 ** 345 Str:Str readProps() 346 347 ** 348 ** Pipe bytes from this input stream to the specified output stream. 349 ** If n is specified, then block until exactly n bytes have been 350 ** read or throw IOErr if end of stream is reached first. If n is 351 ** null then the entire contents of this input stream are piped. If 352 ** close is true, then this input stream is guaranteed to be closed 353 ** upon return (the OutStream is never closed). Return the number 354 ** of bytes piped to the output stream. 355 ** 356 Int pipe(OutStream out, Int n := null, Bool close := true) 357 358 } 359 360 ************************************************************************** 361 ** SysInStream 362 ************************************************************************** 363 364 internal class SysInStream : InStream 365 { 366 override Int read() 367 override Int readBuf(Buf buf, Int n) 368 override InStream unread(Int n) 369 override Bool close() 370 }