databuffer.monkey2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. Namespace std.memory
  2. Using std.stream
  3. #rem monkeydoc DataBuffer class.
  4. #end
  5. Class DataBuffer
  6. #rem monkeydoc Creates a new databuffer.
  7. The new databuffer initally uses little endian byte order. You can change this via the ByteOrder property.
  8. @example
  9. \#Import "<std>"
  10. Using std.memory
  11. Function Main()
  12. Local buf:=New DataBuffer( 10 )
  13. Print buf.Length
  14. For Local i:=0 Until 10
  15. buf.PokeByte( i,i*2 )
  16. Next
  17. For Local i:=0 Until 10
  18. Print buf.PeekByte( i )
  19. Next
  20. End
  21. @end
  22. @param length The length of the databuffer to create, in bytes.
  23. #end
  24. Method New( length:Int )
  25. _length=length
  26. _data=Cast<UByte Ptr>( libc.malloc( length ) )
  27. _byteOrder=ByteOrder.LittleEndian
  28. _swapEndian=False
  29. End
  30. #rem monkeydoc Frees the databuffer's internal memory.
  31. Once discarded, a databuffer's length is set to 0.
  32. #end
  33. Method Discard()
  34. libc.free( _data )
  35. _data=Null
  36. _length=0
  37. End
  38. #rem monkeydoc A raw pointer to the databuffer's internal memory.
  39. Note: This pointer will change if the databuffer is resized using Resize.
  40. #end
  41. Property Data:UByte Ptr()
  42. Return _data
  43. End
  44. #rem monkeydoc The length of the databuffer in bytes.
  45. #end
  46. Property Length:Int()
  47. Return _length
  48. End
  49. #rem monkeydoc The byte order of the databuffer.
  50. #end
  51. Property ByteOrder:ByteOrder()
  52. Return _byteOrder
  53. Setter( byteOrder:ByteOrder )
  54. _byteOrder=byteOrder
  55. _swapEndian=(_byteOrder=ByteOrder.BigEndian)
  56. End
  57. #rem monkeydoc Resizes the databuffer.
  58. Note: This method reallocates the internal memory buffer and will cause the Data property to change.
  59. @param length The new length of the databuffer.
  60. #end
  61. Method Resize( length:Int )
  62. Local data:=Cast<UByte Ptr>( libc.malloc( length ) )
  63. libc.memcpy( data,_data,Min( length,_length ) )
  64. libc.free( _data )
  65. _data=data
  66. End
  67. #rem monkeydoc Reads a byte from the databuffer.
  68. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  69. #param offset The offset to read.
  70. #return The byte read from `offset`.
  71. #end
  72. Method PeekByte:Byte( offset:Int )
  73. DebugAssert( offset>=0 And offset<_length )
  74. Return Cast<Byte Ptr>( _data+offset )[0]
  75. End
  76. #rem monkeydoc Reads a ubyte from the databuffer.
  77. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  78. #param offset The offset to read.
  79. #return The ubyte read from `offset`.
  80. #end
  81. Method PeekUByte:UByte( offset:Int )
  82. DebugAssert( offset>=0 And offset<_length )
  83. Return Cast<UByte Ptr>( _data+offset )[0]
  84. End
  85. #rem monkeydoc Reads a 16 bit short from the databuffer.
  86. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  87. #param offset The offset to read.
  88. #return The short read from `offset`.
  89. #end
  90. Method PeekShort:Short( offset:Int )
  91. DebugAssert( offset>=0 And offset<_length-1 )
  92. Local t:=Cast<Short Ptr>( _data+offset )[0]
  93. If _swapEndian Swap2( Varptr t )
  94. Return t
  95. End
  96. #rem monkeydoc Reads a 16 bit ushort from the databuffer.
  97. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  98. #param offset The offset to read.
  99. #return The ushort read from `offset`.
  100. #end
  101. Method PeekUShort:UShort( offset:Int )
  102. DebugAssert( offset>=0 And offset<_length-1 )
  103. Local t:=Cast<UShort Ptr>( _data+offset )[0]
  104. If _swapEndian Swap2( Varptr t )
  105. Return t
  106. End
  107. #rem monkeydoc Reads a 32 bit int from the databuffer.
  108. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  109. #param offset The offset to read.
  110. #return The int read from `offset`.
  111. #end
  112. Method PeekInt:Int( offset:Int )
  113. DebugAssert( offset>=0 And offset<_length-3 )
  114. Local t:=Cast<Int Ptr>( _data+offset )[0]
  115. If _swapEndian Swap4( Varptr t )
  116. Return t
  117. End
  118. #rem monkeydoc Reads a 32 bit uint from the databuffer.
  119. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  120. #param offset The offset to read.
  121. #return The uint read from `offset`.
  122. #end
  123. Method PeekUInt:UInt( offset:Int )
  124. DebugAssert( offset>=0 And offset<_length-3 )
  125. Local t:=Cast<UInt Ptr>( _data+offset )[0]
  126. If _swapEndian Swap4( Varptr t )
  127. Return t
  128. End
  129. #rem monkeydoc Reads a 64 bit long from the databuffer.
  130. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  131. #param offset The offset to read.
  132. #return The long read from `offset`.
  133. #end
  134. Method PeekLong:Long( offset:Int )
  135. DebugAssert( offset>=0 And offset<_length-7 )
  136. Local t:=Cast<Long Ptr>( _data+offset )[0]
  137. If _swapEndian Swap8( Varptr t )
  138. Return t
  139. End
  140. #rem monkeydoc Reads a 64 bit ulong from the databuffer.
  141. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  142. #param offset The offset to read.
  143. #return The ulong read from `offset`.
  144. #end
  145. Method PeekULong:ULong( offset:Int )
  146. DebugAssert( offset>=0 And offset<_length-7 )
  147. Local t:=Cast<ULong Ptr>( _data+offset )[0]
  148. If _swapEndian Swap8( Varptr t )
  149. Return t
  150. End
  151. #rem monkeydoc Reads a 32 bit float from the databuffer.
  152. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  153. #param offset The offset to read.
  154. #return The float read from `offset`.
  155. #end
  156. Method PeekFloat:Float( offset:Int )
  157. DebugAssert( offset>=0 And offset<_length-3 )
  158. Local t:=Cast<Float Ptr>( _data+offset )[0]
  159. If _swapEndian Swap4( Varptr t )
  160. Return t
  161. End
  162. #rem monkeydoc Reads a 64 bit double from the databuffer.
  163. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  164. #param offset The offset to read.
  165. #return The double read from `offset`.
  166. #end
  167. Method PeekDouble:Double( offset:Int )
  168. DebugAssert( offset>=0 And offset<_length-7 )
  169. Local t:=Cast<Double Ptr>( _data+offset )[0]
  170. If _swapEndian Swap8( Varptr t )
  171. Return t
  172. End
  173. #rem monkeydoc Writes a byte to the databuffer
  174. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  175. #param offset The offset to write.
  176. #end
  177. Method PokeByte( offset:Int,value:Byte )
  178. DebugAssert( offset>=0 And offset<_length )
  179. Cast<Byte Ptr>( _data+offset )[0]=value
  180. End
  181. #rem monkeydoc Writes an unsigned byte to the databuffer.
  182. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  183. #param offset The offset to write.
  184. #end
  185. Method PokeUByte( offset:Int,value:UByte )
  186. DebugAssert( offset>=0 And offset<_length )
  187. Cast<UByte Ptr>( _data+offset )[0]=value
  188. End
  189. #rem monkeydoc Writes a 16 bit short to the databuffer
  190. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  191. #param offset The offset to write.
  192. #end
  193. Method PokeShort( offset:Int,value:Short )
  194. DebugAssert( offset>=0 And offset<_length-1 )
  195. If _swapEndian Swap2( Varptr value )
  196. Cast<Short Ptr>( _data+offset )[0]=value
  197. End
  198. #rem monkeydoc Writes a 16 bit unsigned short to the databuffer
  199. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  200. #param offset The offset to write.
  201. #end
  202. Method PokeUShort( offset:Int,value:UShort )
  203. DebugAssert( offset>=0 And offset<_length-1 )
  204. If _swapEndian Swap2( Varptr value )
  205. Cast<UShort Ptr>( _data+offset )[0]=value
  206. End
  207. #rem monkeydoc Writes a 32 bit int to the databuffer
  208. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  209. #param offset The offset to write.
  210. #end
  211. Method PokeInt( offset:Int,value:Int )
  212. DebugAssert( offset>=0 And offset<_length-3 )
  213. If _swapEndian Swap4( Varptr value )
  214. Cast<Int Ptr>( _data+offset )[0]=value
  215. End
  216. #rem monkeydoc Writes a 32 bit unsigned int to the databuffer
  217. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  218. #param offset The offset to write.
  219. #end
  220. Method PokeUInt( offset:Int,value:UInt )
  221. DebugAssert( offset>=0 And offset<_length-3 )
  222. If _swapEndian Swap4( Varptr value )
  223. Cast<UInt Ptr>( _data+offset )[0]=value
  224. End
  225. #rem monkeydoc Writes a 64 bit long to the databuffer
  226. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  227. #param offset The offset to write.
  228. #end
  229. Method PokeLong( offset:Int,value:Long )
  230. DebugAssert( offset>=0 And offset<_length-7 )
  231. If _swapEndian Swap8( Varptr value )
  232. Cast<Long Ptr>( _data+offset )[0]=value
  233. End
  234. #rem monkeydoc Writes a 64 bit unsigned long to the databuffer
  235. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  236. #param offset The offset to write.
  237. #end
  238. Method PokeULong( offset:Int,value:ULong )
  239. DebugAssert( offset>=0 And offset<_length-7 )
  240. If _swapEndian Swap8( Varptr value )
  241. Cast<ULong Ptr>( _data+offset )[0]=value
  242. End
  243. #rem monkeydoc Writes a 32 bit float to the databuffer
  244. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  245. #param offset The offset to write.
  246. #end
  247. Method PokeFloat( offset:Int,value:Float )
  248. DebugAssert( offset>=0 And offset<_length-3 )
  249. If _swapEndian Swap4( Varptr value )
  250. Cast<Float Ptr>( _data+offset )[0]=value
  251. End
  252. #rem monkeydoc Writes a 64 bit double to the databuffer
  253. In debug builds, a runtime error will occur if `offset` is outside the range of the databuffer.
  254. #param offset The offset to write.
  255. #end
  256. Method PokeDouble( offset:Int,value:Double )
  257. DebugAssert( offset>=0 And offset<_length-7 )
  258. If _swapEndian Swap8( Varptr value )
  259. Cast<Double Ptr>( _data+offset )[0]=value
  260. End
  261. #rem monkeydoc Copies databuffer data.
  262. In debug builds, a runtime error while occur if an attempt it made to copy data outside the range of either databuffer.
  263. @param dst The destination databuffer.
  264. @param srcOffset The starting byte offset in this databuffer to copy from.
  265. @param dstOffset The starting byte offest in the destination databuffer to copy to.
  266. @param count The number of bytes to copy.
  267. #end
  268. Method CopyTo( dst:DataBuffer,srcOffset:Int,dstOffset:Int,count:Int )
  269. DebugAssert( srcOffset>=0 And srcOffset+count<=_length And dstOffset>=0 And dstOffset+count<=dst._length )
  270. libc.memmove( dst._data+dstOffset,_data+srcOffset,count )
  271. End
  272. #rem monkeydoc Saves the contents of the databuffer to a file.
  273. @param path The file path.
  274. @return True if successful, false if `path` could not be opened or not all data could be written.
  275. #end
  276. Method Save:Bool( path:String )
  277. Local stream:=Stream.Open( path,"w" )
  278. If Not stream Return False
  279. Local n:=stream.Write( _data,_length )
  280. stream.Close()
  281. Return n=_length
  282. End
  283. #rem monkeydoc Creates a databuffer with the contents of a file.
  284. @param path The file path.
  285. @return A new databuffer containing the contents of `path`, or null if `path` could not be opened.
  286. #end
  287. Function Load:DataBuffer( path:String )
  288. Local stream:=Stream.Open( path,"r" )
  289. If Not stream Return Null
  290. Local length:=stream.Length
  291. Local buf:=New DataBuffer( length )
  292. stream.Read( buf.Data,length )
  293. stream.Close()
  294. Return buf
  295. End
  296. Private
  297. Field _data:UByte Ptr
  298. Field _length:Int
  299. Field _byteOrder:ByteOrder
  300. Field _swapEndian:Bool
  301. Function Swap2( v:Void Ptr )
  302. Local t:=Cast<UShort Ptr>( v )[0]
  303. Cast<UShort Ptr>( v )[0]=(t Shr 8 & $ff) | (t & $ff) Shl 8
  304. End
  305. Function Swap4( v:Void Ptr )
  306. Local t:=Cast<UInt Ptr>( v )[0]
  307. Cast<UInt Ptr>( v )[0]=(t Shr 24 & $ff) | (t & $ff) Shl 24 | (t Shr 8 & $ff00) | (t & $ff00) Shl 8
  308. End
  309. Function Swap8( v:Void Ptr )
  310. Local t:=Cast<ULong Ptr>( v )[0]
  311. Cast<ULong Ptr>( v )[0]=(t Shr 56 & $ff) | (t & $ff) Shl 56 | (t Shr 40 & $ff00) | (t & $ff00) Shl 40 | (t Shr 24 & $ff0000) | (t & $ff0000) Shl 24 | (t Shr 8 & $ff000000) | (t & $ff000000) Shl 8
  312. End
  313. End