stream.monkey2 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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() Abstract
  22. #rem monkeydoc Seeks to a position in the stream.
  23. In debug builds, a runtime error will occur if the stream is not seekable or `position` is out of range.
  24. @param position The position to seek to.
  25. #end
  26. Method Seek( position:Int ) Abstract
  27. #rem monkeydoc Reads data from the stream into memory.
  28. Reads `count` bytes of data from the stream into either a raw memory pointer or a databuffer.
  29. Returns the number of bytes actually read.
  30. @param buf A pointer to the memory to read the data into.
  31. @param data The databuffer to read the data into.
  32. @param count The number of bytes to read from the stream.
  33. @return The number of bytes actually read.
  34. #end
  35. Method Read:Int( buf:Void Ptr,count:Int ) Abstract
  36. Method Read:Int( data:DataBuffer,offset:Int,count:Int )
  37. DebugAssert( offset>=0 And count>=0 And offset+count<=data.Length )
  38. Return Read( data.Data+offset,count )
  39. End
  40. #rem monkeydoc Writes data to the stream from memory.
  41. Writes `count` bytes of data to the stream from either a raw memory pointer or a databuffer.
  42. Returns the number of bytes actually written
  43. @param buf A pointer to the memory to write the data from.
  44. @param data The databuffer to write the data from.
  45. @param count The number of bytes to write to the stream.
  46. @return The number of bytes actually written.
  47. #end
  48. Method Write:Int( buf:Void Ptr,count:Int ) Abstract
  49. Method Write:Int( data:DataBuffer,offset:Int,count:Int )
  50. DebugAssert( offset>=0 And count>=0 And offset+count<=data.Length )
  51. Return Write( data.Data+offset,count )
  52. End
  53. #rem monkeydoc The byte order of the stream.
  54. The default byte order is ByteOrder.BigEndian.
  55. #end
  56. Property ByteOrder:ByteOrder()
  57. Return _tmpbuf.ByteOrder
  58. Setter( byteOrder:ByteOrder )
  59. _tmpbuf.ByteOrder=byteOrder
  60. End
  61. #rem monkeydoc Reads as many bytes as possible from a stream into memory.
  62. Continously reads data from a stream until either `count` bytes are read or the end of stream is reached.
  63. Returns the number of bytes read or the data read.
  64. @param buf memory to read bytes into.
  65. @param data data buffer to read bytes into.
  66. @param count number of bytes to read.
  67. #end
  68. Method ReadAll:Int( buf:Void Ptr,count:Int )
  69. Local pos:=0
  70. While pos<count
  71. Local n:=Read( Cast<Byte Ptr>( buf )+pos,count-pos )
  72. If n<=0 Exit
  73. pos+=n
  74. Wend
  75. Return pos
  76. End
  77. Method ReadAll:Int( data:DataBuffer,offset:Int,count:Int )
  78. Return ReadAll( data.Data+offset,count )
  79. End
  80. Method ReadAll:DataBuffer( count:Int )
  81. Local data:=New DataBuffer( count )
  82. Local n:=ReadAll( data,0,count )
  83. If n<count Return data.Slice( 0,n )
  84. Return data
  85. End
  86. Method ReadAll:DataBuffer()
  87. If Length>=0 Return ReadAll( Length-Position )
  88. Local bufs:=New Stack<DataBuffer>
  89. Local buf:=New DataBuffer( 4096 ),pos:=0
  90. Repeat
  91. pos=ReadAll( buf,0,4096 )
  92. If pos<4096 Exit
  93. bufs.Push( buf )
  94. buf=New DataBuffer( 4096 )
  95. Forever
  96. Local len:=bufs.Length * 4096 + pos
  97. Local data:=New DataBuffer( len )
  98. pos=0
  99. For Local buf:=Eachin bufs
  100. buf.CopyTo( data,0,pos,4096 )
  101. buf.Discard()
  102. pos+=4096
  103. Next
  104. buf.CopyTo( data,0,pos,len-pos )
  105. buf.Discard()
  106. Return data
  107. End
  108. #rem monkeydoc Reads data from the filestream and throws it away.
  109. @param count The number of bytes to skip.
  110. @return The number of bytes actually skipped.
  111. #end
  112. Method Skip:Int( count:Int )
  113. Local tmp:=libc.malloc( count )
  114. Local n:=Read( tmp,count )
  115. libc.free( tmp )
  116. Return n
  117. End
  118. #rem monkeydoc Reads a byte from the stream.
  119. @return The byte read.
  120. #end
  121. Method ReadByte:Byte()
  122. If Read( _tmpbuf.Data,1 )=1 Return _tmpbuf.PeekByte( 0 )
  123. Return 0
  124. End
  125. #rem monkeydoc Reads an unsigned byte from the stream.
  126. @return The ubyte read.
  127. #end
  128. Method ReadUByte:UByte()
  129. If Read( _tmpbuf.Data,1 )=1 Return _tmpbuf.PeekUByte( 0 )
  130. Return 0
  131. End
  132. #rem monkeydoc Reads a 16 bit short from the stream.
  133. @return The short read.
  134. #end
  135. Method ReadShort:Short()
  136. If ReadAll( _tmpbuf.Data,2 )=2 Return _tmpbuf.PeekShort( 0 )
  137. Return 0
  138. End
  139. #rem monkeydoc Reads a 16 bit unsigned short from the stream.
  140. @return The ushort read.
  141. #end
  142. Method ReadUShort:UShort()
  143. If ReadAll( _tmpbuf.Data,2 )=2 Return _tmpbuf.PeekUShort( 0 )
  144. Return 0
  145. End
  146. #rem monkeydoc Reads a 32 bit int from the stream.
  147. @return The int read.
  148. #end
  149. Method ReadInt:Int()
  150. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekInt( 0 )
  151. Return 0
  152. End
  153. #rem monkeydoc Reads a 32 bit unsigned int from the stream.
  154. @return The uint read.
  155. #end
  156. Method ReadUInt:UInt()
  157. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekUInt( 0 )
  158. Return 0
  159. End
  160. #rem monkeydoc Reads a 32 bit long from the stream.
  161. @return The long read.
  162. #end
  163. Method ReadLong:Long()
  164. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekLong( 0 )
  165. Return 0
  166. End
  167. #rem monkeydoc Reads a 32 bit unsigned long from the stream.
  168. @return The ulong read.
  169. #end
  170. Method ReadULong:ULong()
  171. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekULong( 0 )
  172. Return 0
  173. End
  174. #rem monkeydoc Reads a 32 bit float from the stream.
  175. @return The float read.
  176. #end
  177. Method ReadFloat:Float()
  178. If ReadAll( _tmpbuf.Data,4 )=4 Return _tmpbuf.PeekFloat( 0 )
  179. Return 0
  180. End
  181. #rem monkeydoc Reads a 64 bit double from the stream.
  182. @return The double read.
  183. #end
  184. Method ReadDouble:Double()
  185. If ReadAll( _tmpbuf.Data,8 )=8 Return _tmpbuf.PeekDouble( 0 )
  186. Return 0
  187. End
  188. #rem monkeydoc Reads the entire stream into a string.
  189. #end
  190. Method ReadString:String( encoding:String="utf8" )
  191. Local data:=ReadAll()
  192. Local str:=data.PeekString( 0,encoding )
  193. data.Discard()
  194. Return str
  195. End
  196. #rem monkeydoc Reads a null terminated string from the stream.
  197. @return the string read.
  198. #end
  199. Method ReadCString:String( encoding:String="utf8" )
  200. Local buf:=New Stack<Byte>
  201. While Not Eof
  202. Local chr:=ReadByte()
  203. If Not chr Exit
  204. buf.Push( chr )
  205. Wend
  206. If encoding="utf8" Return String.FromUtf8Data( buf.Data.Data,buf.Length )
  207. Return String.FromAsciiData( buf.Data.Data,buf.Length )
  208. End
  209. #rem monkeydoc Writes a byte to the stream.
  210. @param data The byte to write.
  211. #end
  212. Method WriteByte( data:Byte )
  213. _tmpbuf.PokeByte( 0,data )
  214. Write( _tmpbuf.Data,1 )
  215. End
  216. #rem monkeydoc Write an unsigned byte to the stream.
  217. @param data The ubyte to write.
  218. #end
  219. Method WriteUByte( data:UByte )
  220. _tmpbuf.PokeUByte( 0,data )
  221. Write( _tmpbuf.Data,1 )
  222. End
  223. #rem monkeydoc Writes a 16 bit short to the stream.
  224. @param data The short to write.
  225. #end
  226. Method WriteShort( data:Short )
  227. _tmpbuf.PokeShort( 0,data )
  228. Write( _tmpbuf.Data,2 )
  229. End
  230. #rem monkeydoc Writes a 16 bit unsigned short to the stream.
  231. @param data The ushort to write.
  232. #end
  233. Method WriteUShort( data:UShort )
  234. _tmpbuf.PokeUShort( 0,data )
  235. Write( _tmpbuf.Data,2 )
  236. End
  237. #rem monkeydoc Writes a 32 bit int to the stream.
  238. @param data The int to write.
  239. #end
  240. Method WriteInt( data:Int )
  241. _tmpbuf.PokeInt( 0,data )
  242. Write( _tmpbuf.Data,4 )
  243. End
  244. #rem monkeydoc Writes a 32 bit unsigned int to the stream.
  245. @param data The uint to write.
  246. #end
  247. Method WriteUInt( data:UInt )
  248. _tmpbuf.PokeUInt( 0,data )
  249. Write( _tmpbuf.Data,4 )
  250. End
  251. #rem monkeydoc Writes a 64 bit long to the stream.
  252. @param data The long to write.
  253. #end
  254. Method WriteLong( data:Long )
  255. _tmpbuf.PokeLong( 0,data )
  256. Write( _tmpbuf.Data,8 )
  257. End
  258. #rem monkeydoc Writes a 64 bit unsigned long to the stream.
  259. @param data The ulong to write.
  260. #end
  261. Method WriteULong( data:ULong )
  262. _tmpbuf.PokeULong( 0,data )
  263. Write( _tmpbuf.Data,8 )
  264. End
  265. #rem monkeydoc Writes a 32 bit float to the stream,
  266. @param data The float to write.
  267. #end
  268. Method WriteFloat:Void( data:Float )
  269. _tmpbuf.PokeFloat( 0,data )
  270. Write( _tmpbuf.Data,4 )
  271. End
  272. #rem monkeydoc Writes a 64 bit double to the stream.
  273. @param data The double to write.
  274. #end
  275. Method WriteDouble( data:Double )
  276. _tmpbuf.PokeDouble( 0,data )
  277. Write( _tmpbuf.Data,8 )
  278. End
  279. #rem monkeydoc Writes a string to the stream (NOT null terminated).
  280. @param str The string to write.
  281. #end
  282. Method WriteString( str:String,encoding:String="utf8" )
  283. Local size:=(encoding="utf8" ? str.Utf8Length Else str.Length)
  284. Local buf:=New DataBuffer( size )
  285. buf.PokeString( 0,str,encoding )
  286. Write( buf,0,size )
  287. End
  288. #rem monkeydoc Writes a null terminated string to the stream.
  289. @param str The string to write.
  290. #end
  291. Method WriteCString( str:String,encoding:String="utf8" )
  292. Local size:=(encoding="utf8" ? str.Utf8Length Else str.Length)+1
  293. Local buf:=New DataBuffer( size )
  294. buf.PokeString( 0,str,encoding )
  295. buf.PokeByte( size-1,0 )
  296. Write( buf,0,size )
  297. End
  298. #rem monkeydoc Opens a stream
  299. `mode` should be "r" for read, "w" for write or "rw" for read/write.
  300. @param mode The mode to open the stream in: "r", "w" or "rw"
  301. #end
  302. Function Open:Stream( path:String,mode:String )
  303. Local i:=path.Find( "::" )
  304. If i=-1 Return FileStream.Open( path,mode )
  305. Local proto:=path.Slice( 0,i )
  306. Local ipath:=path.Slice( i+2 )
  307. Return OpenFuncs[proto]( proto,ipath,mode )
  308. End
  309. #rem monkeydoc @hidden
  310. #end
  311. Alias OpenFunc:Stream( proto:String,path:String,mode:String )
  312. #rem monkeydoc @hidden
  313. #end
  314. Const OpenFuncs:=New StringMap<OpenFunc>
  315. Protected
  316. Method New()
  317. _tmpbuf=New DataBuffer( 8,ByteOrder.LittleEndian )
  318. End
  319. Private
  320. Field _tmpbuf:DataBuffer
  321. End