Source: util/ByteBuffer.js

  1. /*
  2. * Copyright 2003-2006, 2009, 2017, United States Government, as represented by the Administrator of the
  3. * National Aeronautics and Space Administration. All rights reserved.
  4. *
  5. * The NASAWorldWind/WebWorldWind platform is licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @exports ByteBuffer
  19. */
  20. define(['../error/ArgumentError',
  21. '../util/Logger'
  22. ],
  23. function (ArgumentError,
  24. Logger) {
  25. "use strict";
  26. /**
  27. * Constructs a wrapper around an array buffer that enables byte-level access to its data.
  28. * This wrapper strives to minimize secondary allocations when subarrays are accessed.
  29. * The one exception is when double precision floating point data is access that is not properly aligned.
  30. * @alias ByteBuffer
  31. * @classdesc A structured wrapper around an array buffer that provides byte-level access to its data.
  32. * @param {ArrayBuffer} array An array buffer containing source data.
  33. * @constructor
  34. */
  35. var ByteBuffer = function(array) {
  36. if (!array) {
  37. throw new ArgumentError(
  38. Logger.logMessage(Logger.LEVEL_SEVERE, "ByteBuffer", "constructor", "missingArray"));
  39. }
  40. /**
  41. * The raw data of the array buffer.
  42. * @type {ArrayBuffer}
  43. */
  44. this.array = array;
  45. /**
  46. * A data view on the array buffer.
  47. * This data view is used to extract integer and floating point data from that array buffer.
  48. * @type {DataView}
  49. */
  50. this.data = new DataView(array);
  51. /**
  52. * The current position in the array buffer.
  53. * This position is implicitly used to access all data.
  54. * @type {Number}
  55. */
  56. this.position = 0;
  57. /**
  58. * The byte order in which the data is encoded.
  59. * Byte order will either be big endian or little endian.
  60. * @type {Boolean}
  61. * @default ByteByffer.LITTLE_ENDIAN
  62. * @private
  63. */
  64. this._order = ByteBuffer.LITTLE_ENDIAN;
  65. };
  66. /**
  67. * Get a byte from the current position and advance the position.
  68. * @returns {Number}
  69. */
  70. ByteBuffer.prototype.getByte = function() {
  71. var result = this.data.getUint8(this.position);
  72. this.position += ByteBuffer.BYTE_SIZE;
  73. return result;
  74. };
  75. /**
  76. * Get a byte array from the current position and advance the position.
  77. * To avoid secondary allocation, a TypedArray shadows the underlying ArrayBuffer.
  78. * @param {Number} numBytes The number of bytes in the desired array.
  79. * @returns {Uint8Array}
  80. */
  81. ByteBuffer.prototype.getByteArray = function(numBytes) {
  82. var result = new Uint8Array(this.array, this.position, numBytes);
  83. this.position += ByteBuffer.BYTE_SIZE * numBytes;
  84. return result;
  85. };
  86. /**
  87. * Get a 16-bit integer from the current position and advance the position.
  88. * @returns {Number}
  89. */
  90. ByteBuffer.prototype.getInt16 = function() {
  91. var result = this.data.getInt16(this.position, this._order);
  92. this.position += ByteBuffer.INT16_SIZE;
  93. return result;
  94. };
  95. /**
  96. * Get a 16-bit integer array from the current position and advance the position.
  97. * To avoid secondary allocation, a TypedArray shadows the underlying ArrayBuffer.
  98. * @param {Number} numInt16s The number of 16-bit integers in the desired array.
  99. * @returns {Int16Array}
  100. */
  101. ByteBuffer.prototype.getInt16Array = function(numInt16s) {
  102. var result = new Int16Array(this.array, this.position, numInt16s);
  103. this.position += ByteBuffer.INT16_SIZE * numInt16s;
  104. return result;
  105. };
  106. /**
  107. * Get a 32-bit integer from the current position and advance the position.
  108. * @returns {Number}
  109. */
  110. ByteBuffer.prototype.getInt32 = function() {
  111. var result = this.data.getInt32(this.position, this._order);
  112. this.position += ByteBuffer.INT32_SIZE;
  113. return result;
  114. };
  115. /**
  116. * Get a single precision floating point array from the current position and advance the position.
  117. * To avoid secondary allocation, a TypedArray shadows the underlying ArrayBuffer.
  118. * @param {Number} numInt32s The number of 32-bit integers in the desired array.
  119. * @returns {Int32Array}
  120. */
  121. ByteBuffer.prototype.getInt32Array = function(numInt32s) {
  122. var result = new Int32Array(this.array, this.position, numInt32s);
  123. this.position += ByteBuffer.INT32_SIZE * numInt32s;
  124. return result;
  125. };
  126. /**
  127. * Get a single precision floating point number from the current position and advance the position.
  128. * @returns {Number}
  129. */
  130. ByteBuffer.prototype.getFloat = function() {
  131. var result = this.data.getFloat32(this.position, this._order);
  132. this.position += ByteBuffer.FLOAT_SIZE;
  133. return result;
  134. };
  135. /**
  136. * Get a single precision floating point array from the current position and advance the position.
  137. * To avoid secondary allocation, a TypedArray shadows the underlying ArrayBuffer.
  138. * @param {Number} numFloats The number of single precision floating point numbers in the desired array.
  139. * @returns {Float32Array}
  140. */
  141. ByteBuffer.prototype.getFloatArray = function(numFloats) {
  142. var result = new Float32Array(this.array, this.position, numFloats);
  143. this.position += ByteBuffer.FLOAT_SIZE * numFloats;
  144. return result;
  145. };
  146. /**
  147. * Get a double precision floating point number from the current position and advance the position.
  148. * @returns {Number}
  149. */
  150. ByteBuffer.prototype.getDouble = function() {
  151. var result = this.data.getFloat64(this.position, this._order);
  152. this.position += ByteBuffer.DOUBLE_SIZE;
  153. return result;
  154. };
  155. /**
  156. * Get a single precision floating point array from the current position and advance the position.
  157. * To avoid secondary allocation, a TypedArray shadows the underlying ArrayBuffer.
  158. * @param {Number} numDoubles The number of double precision floating point numbers in the desired array.
  159. * @returns {Float64Array}
  160. */
  161. ByteBuffer.prototype.getDoubleArray = function(numDoubles) {
  162. // Issue: Float64Array c'tor throws an exception if the starting offset is not a multiple of 8.
  163. // We see this in shapefiles.
  164. var result;
  165. // If the data is not DWORD aligned, ...
  166. if (this.position % 8 != 0) {
  167. var bytes = this.array.slice(this.position, this.position + numDoubles * ByteBuffer.DOUBLE_SIZE);
  168. result = new Float64Array(bytes);
  169. }
  170. else {
  171. result = new Float64Array(this.array, this.position, numDoubles);
  172. }
  173. this.position += ByteBuffer.DOUBLE_SIZE * numDoubles;
  174. return result;
  175. };
  176. /**
  177. * Skip over the specified number of bytes.
  178. * @param {Number} numBytes The number of bytes to skip.
  179. */
  180. ByteBuffer.prototype.skipBytes = function(numBytes) {
  181. this.position += numBytes * ByteBuffer.BYTE_SIZE;
  182. };
  183. /**
  184. * Skip over the specified number of 16-bit integers.
  185. * @param {Number} numInt16s The number of 16-bit integers to skip.
  186. */
  187. ByteBuffer.prototype.skipInt16s = function(numInt16s) {
  188. this.position += numInt16s * ByteBuffer.INT16_SIZE;
  189. };
  190. /**
  191. * Skip over the specified number of 32-bit integers.
  192. * @param {Number} numInt32s The number of 32-bit integers to skip.
  193. */
  194. ByteBuffer.prototype.skipInt32s = function(numInt32s) {
  195. this.position += numInt32s * ByteBuffer.INT32_SIZE;
  196. };
  197. /**
  198. * Skip over the specified number of single precision floating point numbers.
  199. * @param {Number} numFloats The number of single precision floating point numbers to skip.
  200. */
  201. ByteBuffer.prototype.skipFloats = function(numFloats) {
  202. this.position += numFloats * ByteBuffer.FLOAT_SIZE;
  203. };
  204. /**
  205. * Skip over the specified number of double precision floating point numbers.
  206. * @param {Number} numDoubles The number of double precision floating point numbers to skip.
  207. */
  208. ByteBuffer.prototype.skipDoubles = function(numDoubles) {
  209. this.position += numDoubles * ByteBuffer.DOUBLE_SIZE;
  210. };
  211. /**
  212. * Advance to a specific position.
  213. * @param {Number} position The specified position.
  214. */
  215. ByteBuffer.prototype.seek = function(position) {
  216. this.position = position;
  217. };
  218. /**
  219. * Set the byte order of the underlying data.
  220. * @param {Boolean} order The byte order of the underlying data.
  221. */
  222. ByteBuffer.prototype.order = function(order) {
  223. this._order = order;
  224. };
  225. /**
  226. * Return the total size of the underlying data.
  227. * @returns {Number} The size of the underlying data.
  228. */
  229. ByteBuffer.prototype.limit = function() {
  230. return this.data.byteLength;
  231. };
  232. /**
  233. * Indicates whether there remains any data to be accessed sequentially.
  234. * @returns {Boolean} True if more data can be accessed sequentially.
  235. */
  236. ByteBuffer.prototype.hasRemaining = function() {
  237. return this.position < this.data.byteLength;
  238. };
  239. /**
  240. * Access the underlying data in big endian order, where the most significant bits of the data are encountered first.
  241. * @type {Boolean}
  242. * @constant
  243. */
  244. ByteBuffer.BIG_ENDIAN = false;
  245. /**
  246. * Access the underlying data in little endian order, where the least significant bits of the data are encountered first.
  247. * @type {Boolean}
  248. * @constant
  249. */
  250. ByteBuffer.LITTLE_ENDIAN = true;
  251. /**
  252. * The size of a byte.
  253. * @type {Number}
  254. * @constant
  255. */
  256. ByteBuffer.BYTE_SIZE = 1;
  257. /**
  258. * The size of a 16-bit integer.
  259. * @type {Number}
  260. * @constant
  261. */
  262. ByteBuffer.INT16_SIZE = 2;
  263. /**
  264. * The size of a 32-bit integer.
  265. * @type {Number}
  266. * @constant
  267. */
  268. ByteBuffer.INT32_SIZE = 4;
  269. /**
  270. * The size of a single precision floating point number.
  271. * @type {Number}
  272. * @constant
  273. */
  274. ByteBuffer.FLOAT_SIZE = 4;
  275. /**
  276. * The size of a double precision floating point number.
  277. * @type {Number}
  278. * @constant
  279. */
  280. ByteBuffer.DOUBLE_SIZE = 8;
  281. return ByteBuffer;
  282. }
  283. );