stream.monkey2 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. Namespace std.stream
  2. Using libc
  3. Using std.memory
  4. Using std.collections
  5. #rem monkeydoc Stream class.
  6. #end
  7. Class Stream
  8. #rem monkeydoc True if no more data can be read from the stream.
  9. #end
  10. Property Eof:Bool() Abstract
  11. #rem monkeydoc Current stream position.
  12. In the case of non-seekable streams, `Position` will always be -1.
  13. #end
  14. Property Position:Int() Abstract
  15. #rem monkeydoc Current stream length.
  16. In the case of non-seekable streams, `Length` is the number of bytes that can be read from the stream without 'blocking'.
  17. #end
  18. Property Length:Int() Abstract
  19. #rem monkeydoc Closes the stream.
  20. #end
  21. Method Close:Void()
  22. OnClose()
  23. _tmpbuf.Discard()
  24. End
  25. #rem monkeydoc Seeks to a position in the stream.
  26. In debug builds, a runtime error will occur if the stream is not seekable or `position` is out of range.
  27. @param position The position to seek to.
  28. #end
  29. Method Seek( position:Int ) Abstract
  30. #rem monkeydoc Reads data from the stream into memory.
  31. Reads `count` bytes of data from the stream into either a raw memory pointer or a databuffer.
  32. Returns the number of bytes actually read.
  33. @param buf A pointer to the memory to read the data into.
  34. @param data The databuffer to read the data into.
  35. @param count The number of bytes to read from the stream.
  36. @return The number of bytes actually read.
  37. #end
  38. Method Read:Int( buf:Void Ptr,count:Int ) Abstract
  39. Method Read:Int( data:DataBuffer,offset:Int,count:Int )
  40. DebugAssert( offset>=0 And count>=0 And offset+count<=data.Length )
  41. Return Read( data.Data+offset,count )
  42. End
  43. #rem monkeydoc Writes data to the stream from memory.
  44. Writes `count` bytes of data to the stream from either a raw memory pointer or a databuffer.
  45. Returns the number of bytes actually written
  46. @param buf A pointer to the memory to write the data from.
  47. @param data The databuffer to write the data from.
  48. @param count The number of bytes to write to the stream.
  49. @return The number of bytes actually written.
  50. #end
  51. Method Write:Int( buf:Void Ptr,count:Int ) Abstract
  52. Method Write:Int( data:DataBuffer,offset:Int,count:Int )
  53. DebugAssert( offset>=0 And count>=0 And offset+count<=data.Length )
  54. Return Write( data.Data+offset,count )
  55. End
  56. #rem monkeydoc The byte order of the stream.
  57. The default byte order is ByteOrder.BigEndian.
  58. #end
  59. Property ByteOrder:ByteOrder()
  60. Return _tmpbuf.ByteOrder
  61. Setter( byteOrder:ByteOrder )
  62. _tmpbuf.ByteOrder=byteOrder
  63. End
  64. #rem monkeydoc Reads as many bytes as possible from a stream into memory.
  65. Continously reads data from a stream until either `count` bytes are read or the end of stream is reached.
  66. Returns the number of bytes read or the data read.
  67. @param buf memory to read bytes into.
  68. @param data data buffer to read bytes into.
  69. @param count number of bytes to read.
  70. #end
  71. Method ReadAll:Int( buf:Void Ptr,count:Int )
  72. Local pos:=0
  73. While pos<count
  74. Local n:=Read( Cast<Byte Ptr>( buf )+pos,count-pos )
  75. If n<=0 Exit
  76. pos+=n
  77. Wend
  78. Return pos
  79. End
  80. Method ReadAll:Int( data:DataBuffer,offset:Int,count:Int )
  81. Return ReadAll( data.Data+offset,count )
  82. End
  83. Method ReadAll:DataBuffer( count:Int )
  84. Local data:=New DataBuffer( count )
  85. Local n:=ReadAll( data,0,count )
  86. If n>=count Return data
  87. Local tmp:=data.Slice( 0,n )
  88. data.Discard()
  89. Return tmp
  90. End
  91. Method ReadAll:DataBuffer()
  92. If Length>=0 Return ReadAll( Length-Position )
  93. Local bufs:=New Stack<DataBuffer>
  94. Local buf:=New DataBuffer( 4096 ),pos:=0
  95. Repeat
  96. pos=ReadAll( buf,0,4096 )
  97. If pos<4096 Exit
  98. bufs.Push( buf )
  99. buf=New DataBuffer( 4096 )
  100. Forever
  101. Local len:=bufs.Length * 4096 + pos
  102. Local data:=New DataBuffer( len )
  103. pos=0
  104. For Local buf:=Eachin bufs
  105. buf.CopyTo( data,0,pos,4096 )
  106. buf.Discard()
  107. pos+=4096
  108. Next
  109. buf.CopyTo( data,0,pos,len-pos )
  110. buf.Discard()
  111. Return data
  112. End
  113. #rem monkeydoc Reads data from the stream and throws it away.
  114. @param count The number of bytes to skip.
  115. @return The number of bytes actually skipped.
  116. #end
  117. Method Skip:Int( count:Int )
  118. If count<=0 Return 0
  119. Local tmp:=libc.malloc( 4096 ),n:=0
  120. While n<count
  121. Local t:=Read( tmp,Min( count-n,4096 ) )
  122. If t<=0 Exit
  123. n+=t
  124. Wend
  125. libc.free( tmp )
  126. Return n
  127. End
  128. #rem monkeydoc Reads a byte from the stream.
  129. @return The byte read.
  130. #end
  131. Method ReadByte:Byte()
  132. If Read( _tmpbuf.Data,1 )=1 Return _tmpbuf.PeekByte( 0 )
  133. Return 0
  134. End
  135. #rem monkeydoc Reads an unsigned byte from the stream.
  136. @return The ubyte read.
  137. #end
  138. Method ReadUByte:UByte()
  139. If Read( _tmpbuf.Data,1 )=1 Return _tmpbuf.PeekUByte( 0 )
  140. Return 0
  141. End
  142. #rem monkeydoc Reads a 16 bit short from the stream.
  143. @return The short read.
  144. #end
  145. Method ReadShort:Short()
  146. If ReadAll( _tmpbuf.Data,2 )=2 Return _tmpbuf.PeekShort( 0 )
  147. Return 0
  148. End
  149. #rem monkeydoc Reads a 16 bit unsigned short from the stream.
  150. @return The ushort read.
  151. #end
  152. Method ReadUShort:UShort()
  153. If ReadAll( _tmpbuf.Data,2 )=2 Return _tmpbuf.PeekUShort( 0 )
  154. Return 0
  155. End
  156. #rem monkeydoc Reads a 32 bit int from the stream.
  157. @return The int read.
  158. #end
  159. Method ReadInt:Int()
  160. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekInt( 0 )
  161. Return 0
  162. End
  163. #rem monkeydoc Reads a 32 bit unsigned int from the stream.
  164. @return The uint read.
  165. #end
  166. Method ReadUInt:UInt()
  167. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekUInt( 0 )
  168. Return 0
  169. End
  170. #rem monkeydoc Reads a 32 bit long from the stream.
  171. @return The long read.
  172. #end
  173. Method ReadLong:Long()
  174. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekLong( 0 )
  175. Return 0
  176. End
  177. #rem monkeydoc Reads a 32 bit unsigned long from the stream.
  178. @return The ulong read.
  179. #end
  180. Method ReadULong:ULong()
  181. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekULong( 0 )
  182. Return 0
  183. End
  184. #rem monkeydoc Reads a 32 bit float from the stream.
  185. @return The float read.
  186. #end
  187. Method ReadFloat:Float()
  188. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekFloat( 0 )
  189. Return 0
  190. End
  191. #rem monkeydoc Reads a 64 bit double from the stream.
  192. @return The double read.
  193. #end
  194. Method ReadDouble:Double()
  195. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekDouble( 0 )
  196. Return 0
  197. End
  198. #rem monkeydoc Reads the entire stream into a string.
  199. #end
  200. Method ReadString:String()
  201. Local data:=ReadAll()
  202. Local str:=data.PeekString( 0 )
  203. data.Discard()
  204. Return str
  205. End
  206. #rem monkeydoc Reads a size prefixed string from the stream.
  207. Reads an int from the stream, then a string from that many bytes.
  208. @return the string read.
  209. #end
  210. Method ReadSizedString:String()
  211. Local n:=ReadInt()
  212. Local data:=ReadAll( n )
  213. Local str:=data.PeekString( 0 )
  214. data.Discard()
  215. Return str
  216. End
  217. #rem monkeydoc Reads a null terminated cstring from the stream.
  218. @return the string read.
  219. #end
  220. Method ReadCString:String()
  221. Local buf:=New Stack<Byte>
  222. While Not Eof
  223. Local chr:=ReadByte()
  224. If Not chr Exit
  225. buf.Push( chr )
  226. Wend
  227. Return String.FromCString( buf.Data.Data,buf.Length )
  228. End
  229. #rem monkeydoc Reads a line of text from the stream.
  230. Bytes are read from the stream until a newline character (ascii code 10) or null character (ascii code 0) is read, or end of file is detected.
  231. The bytes read are returned in the form of a string, excluding any terminating newline or null character.
  232. Carriage return characters (ascii code 13) are silently ignored.
  233. #end
  234. Method ReadLine:String()
  235. Local buf:=New Stack<Byte>
  236. While Not Eof
  237. Local chr:=ReadByte()
  238. If Not chr Or chr=10 exit
  239. If chr=13 Continue
  240. buf.Push( chr )
  241. Wend
  242. Return String.FromCString( buf.Data.Data,buf.Length )
  243. End
  244. #rem monkeydoc Writes a byte to the stream.
  245. @param data The byte to write.
  246. #end
  247. Method WriteByte( data:Byte )
  248. _tmpbuf.PokeByte( 0,data )
  249. Write( _tmpbuf.Data,1 )
  250. End
  251. #rem monkeydoc Write an unsigned byte to the stream.
  252. @param data The ubyte to write.
  253. #end
  254. Method WriteUByte( data:UByte )
  255. _tmpbuf.PokeUByte( 0,data )
  256. Write( _tmpbuf.Data,1 )
  257. End
  258. #rem monkeydoc Writes a 16 bit short to the stream.
  259. @param data The short to write.
  260. #end
  261. Method WriteShort( data:Short )
  262. _tmpbuf.PokeShort( 0,data )
  263. Write( _tmpbuf.Data,2 )
  264. End
  265. #rem monkeydoc Writes a 16 bit unsigned short to the stream.
  266. @param data The ushort to write.
  267. #end
  268. Method WriteUShort( data:UShort )
  269. _tmpbuf.PokeUShort( 0,data )
  270. Write( _tmpbuf.Data,2 )
  271. End
  272. #rem monkeydoc Writes a 32 bit int to the stream.
  273. @param data The int to write.
  274. #end
  275. Method WriteInt( data:Int )
  276. _tmpbuf.PokeInt( 0,data )
  277. Write( _tmpbuf.Data,4 )
  278. End
  279. #rem monkeydoc Writes a 32 bit unsigned int to the stream.
  280. @param data The uint to write.
  281. #end
  282. Method WriteUInt( data:UInt )
  283. _tmpbuf.PokeUInt( 0,data )
  284. Write( _tmpbuf.Data,4 )
  285. End
  286. #rem monkeydoc Writes a 64 bit long to the stream.
  287. @param data The long to write.
  288. #end
  289. Method WriteLong( data:Long )
  290. _tmpbuf.PokeLong( 0,data )
  291. Write( _tmpbuf.Data,8 )
  292. End
  293. #rem monkeydoc Writes a 64 bit unsigned long to the stream.
  294. @param data The ulong to write.
  295. #end
  296. Method WriteULong( data:ULong )
  297. _tmpbuf.PokeULong( 0,data )
  298. Write( _tmpbuf.Data,8 )
  299. End
  300. #rem monkeydoc Writes a 32 bit float to the stream,
  301. @param data The float to write.
  302. #end
  303. Method WriteFloat:Void( data:Float )
  304. _tmpbuf.PokeFloat( 0,data )
  305. Write( _tmpbuf.Data,4 )
  306. End
  307. #rem monkeydoc Writes a 64 bit double to the stream.
  308. @param data The double to write.
  309. #end
  310. Method WriteDouble( data:Double )
  311. _tmpbuf.PokeDouble( 0,data )
  312. Write( _tmpbuf.Data,8 )
  313. End
  314. #rem monkeydoc Writes a string to the stream (NOT null terminated).
  315. @param str The string to write.
  316. #end
  317. Method WriteString( str:String )
  318. Local buf:=New DataBuffer( str.CStringLength )
  319. buf.PokeString( 0,str )
  320. Write( buf,0,buf.Length )
  321. buf.Discard()
  322. End
  323. #rem monkeydoc Writes a size prefixed string to the stream.
  324. Writes an int containing the size of the string to the stream, followed the string itself.
  325. #end
  326. Method WriteSizedString( str:String )
  327. WriteInt( str.CStringLength )
  328. WriteString( str )
  329. End
  330. #rem monkeydoc Writes a null terminated cstring to the stream.
  331. @param str The string to write.
  332. #end
  333. Method WriteCString( str:String )
  334. WriteString( str )
  335. WriteByte( 0 )
  336. End
  337. #rem monkeydoc Writes a line of text to the stream.
  338. Writes the characters in `str` followed by the line terminating sequence "~r~n".
  339. #end
  340. Method WriteLine( str:String )
  341. WriteString( str )
  342. WriteString( "~r~n" )
  343. End
  344. #rem monkeydoc Opens a stream
  345. `mode` should be "r" for read, "w" for write or "rw" for read/write.
  346. @param mode The mode to open the stream in: "r", "w" or "rw"
  347. #end
  348. Function Open:Stream( path:String,mode:String )
  349. Local i:=path.Find( "::" )
  350. If i=-1 Return FileStream.Open( path,mode )
  351. Local proto:=path.Slice( 0,i )
  352. Local ipath:=path.Slice( i+2 )
  353. Return OpenFuncs[proto]( proto,ipath,mode )
  354. End
  355. #rem monkeydoc @hidden
  356. #end
  357. Alias OpenFunc:Stream( proto:String,path:String,mode:String )
  358. #rem monkeydoc @hidden
  359. #end
  360. Const OpenFuncs:=New StringMap<OpenFunc>
  361. Protected
  362. Method New()
  363. _tmpbuf=New DataBuffer( 8,ByteOrder.LittleEndian )
  364. End
  365. Method OnClose() Abstract
  366. Private
  367. Field _tmpbuf:DataBuffer
  368. End