bytebuffer.bmx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. ' Copyright (c) 2020 Bruce A Henderson
  2. '
  3. ' This software is provided 'as-is', without any express or implied
  4. ' warranty. In no event will the authors be held liable for any damages
  5. ' arising from the use of this software.
  6. '
  7. ' Permission is granted to anyone to use this software for any purpose,
  8. ' including commercial applications, and to alter it and redistribute it
  9. ' freely, subject to the following restrictions:
  10. '
  11. ' 1. The origin of this software must not be misrepresented; you must not
  12. ' claim that you wrote the original software. If you use this software
  13. ' in a product, an acknowledgment in the product documentation would be
  14. ' appreciated but is not required.
  15. ' 2. Altered source versions must be plainly marked as such, and must not be
  16. ' misrepresented as being the original software.
  17. ' 3. This notice may not be removed or altered from any source distribution.
  18. '
  19. SuperStrict
  20. Rem
  21. bbdoc: Byte Buffer
  22. End Rem
  23. Module BRL.ByteBuffer
  24. ModuleInfo "Version: 1.01"
  25. ModuleInfo "License: zlib/libpng"
  26. ModuleInfo "Copyright: 2020 Bruce A Henderson"
  27. ModuleInfo "History: 1.01"
  28. ModuleInfo "History: Added GetBytes() and PutBytes()"
  29. ModuleInfo "History: 1.00 Initial Release"
  30. Import "glue.c"
  31. Rem
  32. bbdoc: The byte order.
  33. End Rem
  34. Enum EByteOrder
  35. BigEndian
  36. LittleEndian
  37. End Enum
  38. Rem
  39. bbdoc: A buffer is a list of elements of a specific type.
  40. End Rem
  41. Type TBuffer Abstract
  42. Protected
  43. Field ReadOnly _size:Int
  44. Field _limit:Int
  45. Field _mark:Int = -1
  46. Field _position:Int
  47. Method New(size:Int)
  48. _size = size
  49. _limit = size
  50. End Method
  51. Public
  52. Rem
  53. bbdoc: Clears the buffer.
  54. about: Does not change the the content of the buffer, other than to set the position to zero, the mark is cleared, and the limit is set to buffer size.
  55. End Rem
  56. Method Clear:TBuffer()
  57. _position = 0
  58. _limit = _size
  59. _mark = -1
  60. Return Self
  61. End Method
  62. Rem
  63. bbdoc: Flips the buffer.
  64. about: The limit is set to the current position, position set to zero, and the mark is cleared.
  65. End Rem
  66. Method Flip:TBuffer()
  67. _limit = _position
  68. _position = 0
  69. _mark = -1
  70. Return Self
  71. End Method
  72. Rem
  73. bbdoc: Return the buffer limit.
  74. End Rem
  75. Method Limit:Int()
  76. Return _limit
  77. End Method
  78. Rem
  79. bbdoc: Sets the buffer limit.
  80. End Rem
  81. Method Limit:TBuffer(newLimit:Int)
  82. If newLimit < 0 Or newLimit > _size Then
  83. Throw "Bad limit"
  84. End If
  85. _limit = newLimit
  86. If _position > newLimit Then
  87. _position = newLimit
  88. End If
  89. If _mark <> -1 And _mark > newLimit Then
  90. _mark = -1
  91. End If
  92. Return Self
  93. End Method
  94. Rem
  95. bbdoc: Marks the current position that can be returned to later with a call to #Reset.
  96. End Rem
  97. Method Mark:TBuffer()
  98. _mark = _position
  99. Return Self
  100. End Method
  101. Rem
  102. bbdoc: Returns the current position of the buffer.
  103. End Rem
  104. Method Position:Int()
  105. Return _position
  106. End Method
  107. Rem
  108. bbdoc: Sets the position of the buffer.
  109. End Rem
  110. Method Position:TBuffer(newPos:Int)
  111. DoSetPosition(newPos)
  112. Return Self
  113. End Method
  114. Protected
  115. Method DoSetPosition(newPos:Int)
  116. If newPos < 0 Or newPos > _limit Then
  117. Throw "Bad position"
  118. End If
  119. _position = newPos
  120. If _mark <> -1 And _mark > _position Then
  121. _mark = -1
  122. End If
  123. End Method
  124. Public
  125. Rem
  126. bbdoc: Returns whether there are any bytes remaining in the buffer.
  127. End Rem
  128. Method HasRemaining:Int()
  129. Return _position < _limit
  130. End Method
  131. Rem
  132. bbdoc: Returns the number of bytes remaining in the buffer.
  133. End Rem
  134. Method Remaining:Int()
  135. Return _limit - _position
  136. End Method
  137. Rem
  138. bbdoc: Resets the current position to that of the last mark.
  139. about: If mark is not set, this method will throw.
  140. End Rem
  141. Method Reset:TBuffer()
  142. If _mark = -1 Then
  143. Throw "Mark not set"
  144. End If
  145. _position = _mark
  146. Return Self
  147. End Method
  148. Rem
  149. bbdoc: Rewinds the the position back to the start of the buffer.
  150. End Rem
  151. Method Rewind:TBuffer()
  152. _position = 0
  153. _mark = -1
  154. Return Self
  155. End Method
  156. End Type
  157. Rem
  158. bbdoc: A #TBuffer for bytes.
  159. End Rem
  160. Type TByteBuffer Extends TBuffer
  161. Field _order:EByteOrder = EByteOrder.BigEndian
  162. Rem
  163. bbdoc: Allocates a new #TByteBuffer of the specific @size number of bytes.
  164. End Rem
  165. Function Allocate:TByteBuffer(size:Int)
  166. Assert size >= 0 Else "Size < 0 : " + size
  167. Return New TByteArrayBuffer(New Byte[size])
  168. End Function
  169. Rem
  170. bbdoc: Creates a new #TByteBuffer by wrapping the provided #Byte array.
  171. End Rem
  172. Function Wrap:TByteBuffer(data:Byte[])
  173. Return New TByteArrayBuffer(data)
  174. End Function
  175. Rem
  176. bbdoc: Creates a new #TByteBuffer by wrapping the provided Byte Ptr.
  177. about: Note that the Byte Ptr is expected to remain valid throughout the use of the #TByteBuffer.
  178. Freeing the associated memory early may result in undefined behaviour.
  179. End Rem
  180. Function Wrap:TByteBuffer(data:Byte Ptr, size:Int)
  181. Return New TBytePtrBuffer(data, size)
  182. End Function
  183. Rem
  184. bbdoc: Gets the byte order used by the #TByteBuffer when doing #Byte conversions.
  185. End Rem
  186. Method Order:EByteOrder()
  187. Return _order
  188. End Method
  189. Rem
  190. bbdoc: Sets the byte order to use by the #TByteBuffer when doing #Byte conversions.
  191. End Rem
  192. Method Order:TByteBuffer(byteOrder:EByteOrder)
  193. _order = byteOrder
  194. Return Self
  195. End Method
  196. Rem
  197. bbdoc: Returns the #Byte at the current position, and increments the position by 1.
  198. End Rem
  199. Method Get:Byte() Abstract
  200. Rem
  201. bbdoc: Returns the #Short at the current position, and increments the position by 2.
  202. End Rem
  203. Method GetShort:Short() Abstract
  204. Rem
  205. bbdoc: Returns the #Int at the current position, and increments the position by 4.
  206. End Rem
  207. Method GetInt:Int() Abstract
  208. Rem
  209. bbdoc: Returns the #UInt at the current position, and increments the position by 4.
  210. End Rem
  211. Method GetUInt:UInt() Abstract
  212. Rem
  213. bbdoc: Returns the #Long at the current position, and increments the position by 8.
  214. End Rem
  215. Method GetLong:Long() Abstract
  216. Rem
  217. bbdoc: Returns the #ULong at the current position, and increments the position by 8.
  218. End Rem
  219. Method GetULong:ULong() Abstract
  220. Rem
  221. bbdoc: Returns the #Size_T at the current position, and increments the position by 8 (64-bit) or 4 (32-bit).
  222. End Rem
  223. Method GetSizeT:Size_T() Abstract
  224. Rem
  225. bbdoc: Returns the #Float at the current position, and increments the position by 4.
  226. End Rem
  227. Method GetFloat:Float() Abstract
  228. Rem
  229. bbdoc: Returns the #Double at the current position, and increments the position by 8.
  230. End Rem
  231. Method GetDouble:Double() Abstract
  232. Rem
  233. bbdoc: Copies @length bytes into @dst at the curent position, and increments the position by @length.
  234. End Rem
  235. Method GetBytes(dst:Byte Ptr, length:UInt) Abstract
  236. Rem
  237. bbdoc: Writes the specified #Byte to the current position and increments the position by 1.
  238. End Rem
  239. Method Put:TByteBuffer(value:Byte) Abstract
  240. Rem
  241. bbdoc: Writes the specified #Short to the current position and increments the position by 2.
  242. End Rem
  243. Method PutShort:TByteBuffer(value:Short) Abstract
  244. Rem
  245. bbdoc: Writes the specified #Int to the current position and increments the position by 4.
  246. End Rem
  247. Method PutInt:TByteBuffer(value:Int) Abstract
  248. Rem
  249. bbdoc: Writes the specified #UInt to the current position and increments the position by 4.
  250. End Rem
  251. Method PutUInt:TByteBuffer(value:UInt) Abstract
  252. Rem
  253. bbdoc: Writes the specified #Long to the current position and increments the position by 8.
  254. End Rem
  255. Method PutLong:TByteBuffer(value:Long) Abstract
  256. Rem
  257. bbdoc: Writes the specified #ULong to the current position and increments the position by 8.
  258. End Rem
  259. Method PutULong:TByteBuffer(value:ULong) Abstract
  260. Rem
  261. bbdoc: Writes the specified #Size_T to the current position and increments the position by 8 (64-bit) or 4 (32-bit).
  262. End Rem
  263. Method PutSizeT:TByteBuffer(value:Size_T) Abstract
  264. Rem
  265. bbdoc: Writes the specified #Float to the current position and increments the position by 4.
  266. End Rem
  267. Method PutFloat:TByteBuffer(value:Float) Abstract
  268. Rem
  269. bbdoc: Writes the specified #Double to the current position and increments the position by 8.
  270. End Rem
  271. Method PutDouble:TByteBuffer(value:Double) Abstract
  272. Rem
  273. bbdoc: Writes the specified number of bytes to the current position.
  274. End Rem
  275. Method PutBytes:TByteBuffer(bytes:Byte Ptr, length:UInt) Abstract
  276. Rem
  277. bbdoc: Returns a sliced #TByteBuffer that shares its content with this one.
  278. about: TODO
  279. End Rem
  280. Method Slice:TByteBuffer() Abstract
  281. Rem
  282. bbdoc: Creates a duplicate #TByteBuffer that shares its content with this one.
  283. End Rem
  284. Method Duplicate:TByteBuffer() Abstract
  285. End Type
  286. Rem
  287. bbdoc: A #TBuffer whose data comes from a Byte Ptr.
  288. End Rem
  289. Type TBytePtrBuffer Extends TByteBuffer
  290. Field _readOnly:Int
  291. Field _data:Byte Ptr
  292. Field _offset:Int
  293. Method New(data:Byte Ptr, size:Int, offset:Int = 0, isReadOnly:Int = False)
  294. Super.New(size)
  295. Self._data = data
  296. Self._offset = offset
  297. Self._readOnly = isReadOnly
  298. End Method
  299. Method Get:Byte() Override
  300. If _position = _limit Then
  301. Throw New TBufferUnderflowException
  302. End If
  303. Local result:Byte = _data[_position]
  304. _position :+ 1
  305. Return result
  306. End Method
  307. Method GetShort:Short() Override
  308. Local newPosition:Int = _position + 2
  309. If newPosition > _limit Then
  310. Throw New TBufferUnderflowException
  311. End If
  312. Local result:Short
  313. Local pos:Int = _position + _offset
  314. If _order = EByteOrder.BigEndian Then
  315. result = (_data[pos] Shl 8) | (_data[pos + 1] & $ff)
  316. Else
  317. result = (_data[pos + 1] Shl 8) | (_data[pos] & $ff)
  318. End If
  319. _position = newPosition
  320. Return result
  321. End Method
  322. Method GetFloat:Float() Override
  323. Return bmx_bytebuffer_intbitstofloat(GetInt())
  324. End Method
  325. Method GetDouble:Double() Override
  326. Return bmx_bytebuffer_longbitstodouble(GetLong())
  327. End Method
  328. Method GetInt:Int() Override
  329. Local newPosition:Int = _position + 4
  330. If newPosition > _limit Then
  331. Throw New TBufferUnderflowException
  332. End If
  333. Local result:Int
  334. Local pos:Int = _position + _offset
  335. If _order = EByteOrder.BigEndian Then
  336. result = ((_data[pos] & $ff) Shl 24) | ((_data[pos + 1] & $ff) Shl 16) | ((_data[pos + 2] & $ff) Shl 8) | (_data[pos + 3] & $ff)
  337. Else
  338. result = (_data[pos] & $ff) | ((_data[pos + 1] & $ff) Shl 8) | ((_data[pos + 2] & $ff) Shl 16) | ((_data[pos + 3] & $ff) Shl 24)
  339. End If
  340. _position = newPosition
  341. Return result
  342. End Method
  343. Method GetUInt:UInt() Override
  344. Local newPosition:Int = _position + 4
  345. If newPosition > _limit Then
  346. Throw New TBufferUnderflowException
  347. End If
  348. Local result:UInt
  349. Local pos:Int = _position + _offset
  350. If _order = EByteOrder.BigEndian Then
  351. result = ((_data[pos] & $ff:UInt) Shl 24) | ((_data[pos + 1] & $ff:UInt) Shl 16) | ((_data[pos + 2] & $ff:UInt) Shl 8) | (_data[pos + 3] & $ff:UInt)
  352. Else
  353. result = (_data[pos] & $ff:UInt) | ((_data[pos + 1] & $ff:UInt) Shl 8) | ((_data[pos + 2] & $ff:UInt) Shl 16) | ((_data[pos + 3] & $ff:UInt) Shl 24)
  354. End If
  355. _position = newPosition
  356. Return result
  357. End Method
  358. Method GetLong:Long() Override
  359. Local newPosition:Int = _position + 8
  360. If newPosition > _limit Then
  361. Throw New TBufferUnderflowException
  362. End If
  363. Local result:Long
  364. Local pos:Int = _position + _offset
  365. If _order = EByteOrder.BigEndian Then
  366. Local high:Int = ((_data[pos] & $ff) Shl 24) | ((_data[pos + 1] & $ff) Shl 16) | ((_data[pos + 2] & $ff) Shl 8) | (_data[pos + 3] & $ff)
  367. Local low:Int = ((_data[pos + 4] & $ff) Shl 24) | ((_data[pos + 5] & $ff) Shl 16) | ((_data[pos + 6] & $ff) Shl 8) | (_data[pos + 7] & $ff)
  368. result = (Long(high) Shl 32) | (Long(low) & $ffffffff:Long)
  369. Else
  370. Local low:Int = (_data[pos] & $ff) | ((_data[pos + 1] & $ff) Shl 8) | ((_data[pos + 2] & $ff) Shl 16) | ((_data[pos + 3] & $ff) Shl 24)
  371. Local high:Int = (_data[pos + 4] & $ff) | ((_data[pos + 5] & $ff) Shl 8) | ((_data[pos + 6] & $ff) Shl 16) | ((_data[pos + 7] & $ff) Shl 24)
  372. result = (Long(high) Shl 32) | (Long(low) & $ffffffff:Long)
  373. End If
  374. _position = newPosition
  375. Return result
  376. End Method
  377. Method GetULong:ULong() Override
  378. Local newPosition:Int = _position + 8
  379. If newPosition > _limit Then
  380. Throw New TBufferUnderflowException
  381. End If
  382. Local result:ULong
  383. Local pos:Int = _position + _offset
  384. If _order = EByteOrder.BigEndian Then
  385. Local high:UInt = ((_data[pos] & $ff:UInt) Shl 24) | ((_data[pos + 1] & $ff:UInt) Shl 16) | ((_data[pos + 2] & $ff:UInt) Shl 8) | (_data[pos + 3] & $ff:UInt)
  386. Local low:UInt = ((_data[pos + 4] & $ff:UInt) Shl 24) | ((_data[pos + 5] & $ff:UInt) Shl 16) | ((_data[pos + 6] & $ff) Shl 8) | (_data[pos + 7] & $ff)
  387. result = (ULong(high) Shl 32) | (Long(low) & $ffffffff:ULong)
  388. Else
  389. Local low:UInt = (_data[pos] & $ff:UInt) | ((_data[pos + 1] & $ff:UInt) Shl 8) | ((_data[pos + 2] & $ff:UInt) Shl 16) | ((_data[pos + 3] & $ff:UInt) Shl 24)
  390. Local high:UInt = (_data[pos + 4] & $ff:UInt) | ((_data[pos + 5] & $ff:UInt) Shl 8) | ((_data[pos + 6] & $ff:UInt) Shl 16) | ((_data[pos + 7] & $ff:UInt) Shl 24)
  391. result = (ULong(high) Shl 32) | (ULong(low) & $ffffffff:ULong)
  392. End If
  393. _position = newPosition
  394. Return result
  395. End Method
  396. Method GetSizeT:Size_T() Override
  397. ?ptr64
  398. Return Size_T(GetULong())
  399. ?Not ptr64
  400. Return Size_T(GetUInt())
  401. ?
  402. End Method
  403. Method GetBytes(dst:Byte Ptr, length:UInt)
  404. Local newPosition:Int = _position + length
  405. If newPosition > _limit Then
  406. Throw New TBufferUnderflowException
  407. End If
  408. Local pos:Int = _position + _offset
  409. MemCopy(dst, _data + pos, Size_T(length))
  410. _position = newPosition
  411. End Method
  412. Method Put:TByteBuffer(value:Byte) Override
  413. If _readOnly Then
  414. Throw New TReadOnlyBufferException
  415. End If
  416. If _position = _limit Then
  417. Throw New TBufferOverflowException
  418. End If
  419. _data[_position] = value
  420. _position :+ 1
  421. Return Self
  422. End Method
  423. Method PutShort:TByteBuffer(value:Short) Override
  424. If _readOnly Then
  425. Throw New TReadOnlyBufferException
  426. End If
  427. Local newPosition:Int = _position + 2
  428. If newPosition > _limit Then
  429. Throw New TBufferOverflowException
  430. End If
  431. Local pos:Int = _offset + _position
  432. If _order = EByteOrder.BigEndian Then
  433. _data[pos] = Byte((value Shr 8) & $ff)
  434. _data[pos + 1] = Byte(value & $ff)
  435. Else
  436. _data[pos] = Byte(value & $ff)
  437. _data[pos + 1] = Byte((value Shr 8) & $ff)
  438. End If
  439. _position = newPosition
  440. Return Self
  441. End Method
  442. Method PutInt:TByteBuffer(value:Int) Override
  443. If _readOnly Then
  444. Throw New TReadOnlyBufferException
  445. End If
  446. Local newPosition:Int = _position + 4
  447. If newPosition > _limit Then
  448. Throw New TBufferOverflowException
  449. End If
  450. Local pos:Int = _offset + _position
  451. If _order = EByteOrder.BigEndian Then
  452. _data[pos] = Byte((value Shr 24) & $ff)
  453. _data[pos + 1] = Byte((value Shr 16) & $ff)
  454. _data[pos + 2] = Byte((value Shr 8) & $ff)
  455. _data[pos + 3] = Byte(value & $ff)
  456. Else
  457. _data[pos] = Byte(value & $ff)
  458. _data[pos + 1] = Byte((value Shr 8) & $ff)
  459. _data[pos + 2] = Byte((value Shr 16) & $ff)
  460. _data[pos + 3] = Byte((value Shr 24) & $ff)
  461. End If
  462. _position = newPosition
  463. Return Self
  464. End Method
  465. Method PutUInt:TByteBuffer(value:UInt) Override
  466. If _readOnly Then
  467. Throw New TReadOnlyBufferException
  468. End If
  469. Local newPosition:Int = _position + 4
  470. If newPosition > _limit Then
  471. Throw New TBufferOverflowException
  472. End If
  473. Local pos:Int = _offset + _position
  474. If _order = EByteOrder.BigEndian Then
  475. _data[pos] = Byte((value Shr 24) & $ff)
  476. _data[pos + 1] = Byte((value Shr 16) & $ff)
  477. _data[pos + 2] = Byte((value Shr 8) & $ff)
  478. _data[pos + 3] = Byte(value & $ff)
  479. Else
  480. _data[pos] = Byte(value & $ff)
  481. _data[pos + 1] = Byte((value Shr 8) & $ff)
  482. _data[pos + 2] = Byte((value Shr 16) & $ff)
  483. _data[pos + 3] = Byte((value Shr 24) & $ff)
  484. End If
  485. _position = newPosition
  486. Return Self
  487. End Method
  488. Method PutLong:TByteBuffer(value:Long) Override
  489. If _readOnly Then
  490. Throw New TReadOnlyBufferException
  491. End If
  492. Local newPosition:Int = _position + 8
  493. If newPosition > _limit Then
  494. Throw New TBufferOverflowException
  495. End If
  496. Local pos:Int = _offset + _position
  497. If _order = EByteOrder.BigEndian Then
  498. Local i:Int = Int(value Shr 32)
  499. _data[pos] = Byte((i Shr 24) & $ff)
  500. _data[pos + 1] = Byte((i Shr 16) & $ff)
  501. _data[pos + 2] = Byte((i Shr 8) & $ff)
  502. _data[pos + 3] = Byte(i & $ff)
  503. i = Int(value)
  504. _data[pos + 4] = Byte((i Shr 24) & $ff)
  505. _data[pos + 5] = Byte((i Shr 16) & $ff)
  506. _data[pos + 6] = Byte((i Shr 8) & $ff)
  507. _data[pos + 7] = Byte(i & $ff)
  508. Else
  509. Local i:Int = Int(value)
  510. _data[pos] = Byte(i & $ff)
  511. _data[pos + 1] = Byte((i Shr 8) & $ff)
  512. _data[pos + 2] = Byte((i Shr 16) & $ff)
  513. _data[pos + 3] = Byte((i Shr 24) & $ff)
  514. i = Int(value Shr 32)
  515. _data[pos + 4] = Byte(i & $ff)
  516. _data[pos + 5] = Byte((i Shr 8) & $ff)
  517. _data[pos + 6] = Byte((i Shr 16) & $ff)
  518. _data[pos + 7] = Byte((i Shr 24) & $ff)
  519. End If
  520. _position = newPosition
  521. Return Self
  522. End Method
  523. Method PutULong:TByteBuffer(value:ULong) Override
  524. If _readOnly Then
  525. Throw New TReadOnlyBufferException
  526. End If
  527. Local newPosition:Int = _position + 8
  528. If newPosition > _limit Then
  529. Throw New TBufferOverflowException
  530. End If
  531. Local pos:Int = _offset + _position
  532. If _order = EByteOrder.BigEndian Then
  533. Local i:UInt = UInt(value Shr 32)
  534. _data[pos] = Byte((i Shr 24) & $ff)
  535. _data[pos + 1] = Byte((i Shr 16) & $ff)
  536. _data[pos + 2] = Byte((i Shr 8) & $ff)
  537. _data[pos + 3] = Byte(i & $ff)
  538. i = UInt(value)
  539. _data[pos + 4] = Byte((i Shr 24) & $ff)
  540. _data[pos + 5] = Byte((i Shr 16) & $ff)
  541. _data[pos + 6] = Byte((i Shr 8) & $ff)
  542. _data[pos + 7] = Byte(i & $ff)
  543. Else
  544. Local i:UInt = UInt(value)
  545. _data[pos] = Byte(i & $ff)
  546. _data[pos + 1] = Byte((i Shr 8) & $ff)
  547. _data[pos + 2] = Byte((i Shr 16) & $ff)
  548. _data[pos + 3] = Byte((i Shr 24) & $ff)
  549. i = UInt(value Shr 32)
  550. _data[pos + 4] = Byte(i & $ff)
  551. _data[pos + 5] = Byte((i Shr 8) & $ff)
  552. _data[pos + 6] = Byte((i Shr 16) & $ff)
  553. _data[pos + 7] = Byte((i Shr 24) & $ff)
  554. End If
  555. _position = newPosition
  556. Return Self
  557. End Method
  558. Method PutSizeT:TByteBuffer(value:Size_T) Override
  559. ?ptr64
  560. Return PutULong(ULong(value))
  561. ?Not ptr64
  562. Return PutUInt(UInt(value))
  563. ?
  564. End Method
  565. Method PutFloat:TByteBuffer(value:Float) Override
  566. Return PutInt(bmx_bytebuffer_floattointbits(value))
  567. End Method
  568. Method PutDouble:TByteBuffer(value:Double) Override
  569. Return PutLong(bmx_bytebuffer_doubletolongbits(value))
  570. End Method
  571. Method PutBytes:TByteBuffer(bytes:Byte Ptr, length:UInt) Override
  572. If _readOnly Then
  573. Throw New TReadOnlyBufferException
  574. End If
  575. Local newPosition:Int = _position + length
  576. If newPosition > _limit Then
  577. Throw New TBufferOverflowException
  578. End If
  579. Local pos:Int = _offset + _position
  580. MemCopy(_data + pos, bytes, Size_T(length))
  581. _position = newPosition
  582. Return Self
  583. End Method
  584. Method Slice:TByteBuffer() Override
  585. Return New TBytePtrBuffer(_data, remaining(), _offset + _position, _readOnly)
  586. End Method
  587. Method Duplicate:TByteBuffer() Override
  588. Return Copy(Self, _mark, _readOnly)
  589. End Method
  590. Private
  591. Function Copy:TBytePtrBuffer(buffer:TBytePtrBuffer, mark:Int, isReadOnly:Int)
  592. Local bufCopy:TBytePtrBuffer = New TBytePtrBuffer(buffer._data, buffer._size, buffer._offset, isReadOnly)
  593. bufCopy._limit = buffer._limit
  594. bufCopy._position = buffer.Position()
  595. bufCopy._mark = mark
  596. Return bufCopy
  597. End Function
  598. End Type
  599. Rem
  600. bbdoc: A #TBuffer whose data comes from a #Byte array.
  601. End Rem
  602. Type TByteArrayBuffer Extends TBytePtrBuffer
  603. Field _array:Byte[]
  604. Method New(data:Byte[])
  605. Super.New(data, data.length)
  606. Self._array = data
  607. End Method
  608. Private
  609. Method New(data:Byte[], size:Int, offset:Int, isReadOnly:Int)
  610. Super.New(data, size)
  611. Self._array = data
  612. Self._offset = offset
  613. Self._readOnly = isReadOnly
  614. If offset + size > data.length Then
  615. Throw New TArrayBoundsException
  616. End If
  617. End Method
  618. Function Copy:TByteArrayBuffer(buffer:TByteArrayBuffer, mark:Int, isReadOnly:Int)
  619. Local bufCopy:TByteArrayBuffer = New TByteArrayBuffer(buffer._array, buffer._size, buffer._offset, isReadOnly)
  620. bufCopy._limit = buffer._limit
  621. bufCopy._position = buffer.Position()
  622. bufCopy._mark = mark
  623. Return bufCopy
  624. End Function
  625. Public
  626. Method Slice:TByteBuffer() Override
  627. Return New TByteArrayBuffer(_data, remaining(), _offset + _position, _readOnly)
  628. End Method
  629. Method Duplicate:TByteBuffer() Override
  630. Return Copy(Self, _mark, _readOnly)
  631. End Method
  632. Private
  633. End Type
  634. Type TBufferUnderflowException Extends TBlitzException
  635. End Type
  636. Type TBufferOverflowException Extends TBlitzException
  637. End Type
  638. Type TReadOnlyBufferException Extends TBlitzException
  639. End Type
  640. Extern
  641. Function bmx_bytebuffer_intbitstofloat:Float(value:Int)
  642. Function bmx_bytebuffer_floattointbits:Int(value:Float)
  643. Function bmx_bytebuffer_longbitstodouble:Double(value:Long)
  644. Function bmx_bytebuffer_doubletolongbits:Long(value:Double)
  645. End Extern