ref.js 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. var assert = require('assert')
  2. var inspect = require('util').inspect
  3. var debug = require('debug')('ref')
  4. exports = module.exports = require('bindings')('binding')
  5. /**
  6. * A `Buffer` that references the C NULL pointer. That is, its memory address
  7. * points to 0. Its `length` is 0 because accessing any data from this buffer
  8. * would cause a _segmentation fault_.
  9. *
  10. * ```
  11. * console.log(ref.NULL);
  12. * <SlowBuffer@0x0 >
  13. * ```
  14. *
  15. * @name NULL
  16. * @type Buffer
  17. */
  18. /**
  19. * A string that represents the native endianness of the machine's processor.
  20. * The possible values are either `"LE"` or `"BE"`.
  21. *
  22. * ```
  23. * console.log(ref.endianness);
  24. * 'LE'
  25. * ```
  26. *
  27. * @name endianness
  28. * @type String
  29. */
  30. /**
  31. * Accepts a `Buffer` instance and returns the memory address of the buffer
  32. * instance.
  33. *
  34. * ```
  35. * console.log(ref.address(new Buffer(1)));
  36. * 4320233616
  37. *
  38. * console.log(ref.address(ref.NULL)));
  39. * 0
  40. * ```
  41. *
  42. * @param {Buffer} buffer The buffer to get the memory address of.
  43. * @return {Number} The memory address the buffer instance.
  44. * @name address
  45. * @type method
  46. */
  47. /**
  48. * Accepts a `Buffer` instance and returns _true_ if the buffer represents the
  49. * NULL pointer, _false_ otherwise.
  50. *
  51. * ```
  52. * console.log(ref.isNull(new Buffer(1)));
  53. * false
  54. *
  55. * console.log(ref.isNull(ref.NULL));
  56. * true
  57. * ```
  58. *
  59. * @param {Buffer} buffer The buffer to check for NULL.
  60. * @return {Boolean} true or false.
  61. * @name isNull
  62. * @type method
  63. */
  64. /**
  65. * Reads a JavaScript Object that has previously been written to the given
  66. * _buffer_ at the given _offset_.
  67. *
  68. * ```
  69. * var obj = { foo: 'bar' };
  70. * var buf = ref.alloc('Object', obj);
  71. *
  72. * var obj2 = ref.readObject(buf, 0);
  73. * console.log(obj === obj2);
  74. * true
  75. * ```
  76. *
  77. * @param {Buffer} buffer The buffer to read an Object from.
  78. * @param {Number} offset The offset to begin reading from.
  79. * @return {Object} The Object that was read from _buffer_.
  80. * @name readObject
  81. * @type method
  82. */
  83. /**
  84. * Reads a Buffer instance from the given _buffer_ at the given _offset_.
  85. * The _size_ parameter specifies the `length` of the returned Buffer instance,
  86. * which defaults to __0__.
  87. *
  88. * ```
  89. * var buf = new Buffer('hello world');
  90. * var pointer = ref.alloc('pointer');
  91. *
  92. * var buf2 = ref.readPointer(pointer, 0, buf.length);
  93. * console.log(buf.toString());
  94. * 'hello world'
  95. * ```
  96. *
  97. * @param {Buffer} buffer The buffer to read a Buffer from.
  98. * @param {Number} offset The offset to begin reading from.
  99. * @param {Number} length (optional) The length of the returned Buffer. Defaults to 0.
  100. * @return {Buffer} The Buffer instance that was read from _buffer_.
  101. * @name readPointer
  102. * @type method
  103. */
  104. /**
  105. * Returns a JavaScript String read from _buffer_ at the given _offset_. The
  106. * C String is read until the first NULL byte, which indicates the end of the
  107. * String.
  108. *
  109. * This function can read beyond the `length` of a Buffer.
  110. *
  111. * ```
  112. * var buf = new Buffer('hello\0world\0');
  113. *
  114. * var str = ref.readCString(buf, 0);
  115. * console.log(str);
  116. * 'hello'
  117. * ```
  118. *
  119. * @param {Buffer} buffer The buffer to read a Buffer from.
  120. * @param {Number} offset The offset to begin reading from.
  121. * @return {String} The String that was read from _buffer_.
  122. * @name readCString
  123. * @type method
  124. */
  125. /**
  126. * Returns a big-endian signed 64-bit int read from _buffer_ at the given
  127. * _offset_.
  128. *
  129. * If the returned value will fit inside a JavaScript Number without losing
  130. * precision, then a Number is returned, otherwise a String is returned.
  131. *
  132. * ```
  133. * var buf = ref.alloc('int64');
  134. * ref.writeInt64BE(buf, 0, '9223372036854775807');
  135. *
  136. * var val = ref.readInt64BE(buf, 0)
  137. * console.log(val)
  138. * '9223372036854775807'
  139. * ```
  140. *
  141. * @param {Buffer} buffer The buffer to read a Buffer from.
  142. * @param {Number} offset The offset to begin reading from.
  143. * @return {Number|String} The Number or String that was read from _buffer_.
  144. * @name readInt64BE
  145. * @type method
  146. */
  147. /**
  148. * Returns a little-endian signed 64-bit int read from _buffer_ at the given
  149. * _offset_.
  150. *
  151. * If the returned value will fit inside a JavaScript Number without losing
  152. * precision, then a Number is returned, otherwise a String is returned.
  153. *
  154. * ```
  155. * var buf = ref.alloc('int64');
  156. * ref.writeInt64LE(buf, 0, '9223372036854775807');
  157. *
  158. * var val = ref.readInt64LE(buf, 0)
  159. * console.log(val)
  160. * '9223372036854775807'
  161. * ```
  162. *
  163. * @param {Buffer} buffer The buffer to read a Buffer from.
  164. * @param {Number} offset The offset to begin reading from.
  165. * @return {Number|String} The Number or String that was read from _buffer_.
  166. * @name readInt64LE
  167. * @type method
  168. */
  169. /**
  170. * Returns a big-endian unsigned 64-bit int read from _buffer_ at the given
  171. * _offset_.
  172. *
  173. * If the returned value will fit inside a JavaScript Number without losing
  174. * precision, then a Number is returned, otherwise a String is returned.
  175. *
  176. * ```
  177. * var buf = ref.alloc('uint64');
  178. * ref.writeUInt64BE(buf, 0, '18446744073709551615');
  179. *
  180. * var val = ref.readUInt64BE(buf, 0)
  181. * console.log(val)
  182. * '18446744073709551615'
  183. * ```
  184. *
  185. * @param {Buffer} buffer The buffer to read a Buffer from.
  186. * @param {Number} offset The offset to begin reading from.
  187. * @return {Number|String} The Number or String that was read from _buffer_.
  188. * @name readUInt64BE
  189. * @type method
  190. */
  191. /**
  192. * Returns a little-endian unsigned 64-bit int read from _buffer_ at the given
  193. * _offset_.
  194. *
  195. * If the returned value will fit inside a JavaScript Number without losing
  196. * precision, then a Number is returned, otherwise a String is returned.
  197. *
  198. * ```
  199. * var buf = ref.alloc('uint64');
  200. * ref.writeUInt64LE(buf, 0, '18446744073709551615');
  201. *
  202. * var val = ref.readUInt64LE(buf, 0)
  203. * console.log(val)
  204. * '18446744073709551615'
  205. * ```
  206. *
  207. * @param {Buffer} buffer The buffer to read a Buffer from.
  208. * @param {Number} offset The offset to begin reading from.
  209. * @return {Number|String} The Number or String that was read from _buffer_.
  210. * @name readUInt64LE
  211. * @type method
  212. */
  213. /**
  214. * Writes the _input_ Number or String as a big-endian signed 64-bit int into
  215. * _buffer_ at the given _offset_.
  216. *
  217. * ```
  218. * var buf = ref.alloc('int64');
  219. * ref.writeInt64BE(buf, 0, '9223372036854775807');
  220. * ```
  221. *
  222. * @param {Buffer} buffer The buffer to write to.
  223. * @param {Number} offset The offset to begin writing from.
  224. * @param {Number|String} input This String or Number which gets written.
  225. * @name writeInt64BE
  226. * @type method
  227. */
  228. /**
  229. * Writes the _input_ Number or String as a little-endian signed 64-bit int into
  230. * _buffer_ at the given _offset_.
  231. *
  232. * ```
  233. * var buf = ref.alloc('int64');
  234. * ref.writeInt64LE(buf, 0, '9223372036854775807');
  235. * ```
  236. *
  237. * @param {Buffer} buffer The buffer to write to.
  238. * @param {Number} offset The offset to begin writing from.
  239. * @param {Number|String} input This String or Number which gets written.
  240. * @name writeInt64LE
  241. * @type method
  242. */
  243. /**
  244. * Writes the _input_ Number or String as a big-endian unsigned 64-bit int into
  245. * _buffer_ at the given _offset_.
  246. *
  247. * ```
  248. * var buf = ref.alloc('uint64');
  249. * ref.writeUInt64BE(buf, 0, '18446744073709551615');
  250. * ```
  251. *
  252. * @param {Buffer} buffer The buffer to write to.
  253. * @param {Number} offset The offset to begin writing from.
  254. * @param {Number|String} input This String or Number which gets written.
  255. * @name writeUInt64BE
  256. * @type method
  257. */
  258. /**
  259. * Writes the _input_ Number or String as a little-endian unsigned 64-bit int
  260. * into _buffer_ at the given _offset_.
  261. *
  262. * ```
  263. * var buf = ref.alloc('uint64');
  264. * ref.writeUInt64LE(buf, 0, '18446744073709551615');
  265. * ```
  266. *
  267. * @param {Buffer} buffer The buffer to write to.
  268. * @param {Number} offset The offset to begin writing from.
  269. * @param {Number|String} input This String or Number which gets written.
  270. * @name writeUInt64LE
  271. * @type method
  272. */
  273. /**
  274. * Returns a new clone of the given "type" object, with its
  275. * `indirection` level incremented by **1**.
  276. *
  277. * Say you wanted to create a type representing a `void *`:
  278. *
  279. * ```
  280. * var voidPtrType = ref.refType(ref.types.void);
  281. * ```
  282. *
  283. * @param {Object|String} type The "type" object to create a reference type from. Strings get coerced first.
  284. * @return {Object} The new "type" object with its `indirection` incremented by 1.
  285. */
  286. exports.refType = function refType (type) {
  287. var _type = exports.coerceType(type)
  288. var rtn = Object.create(_type)
  289. rtn.indirection++
  290. if (_type.name) {
  291. Object.defineProperty(rtn, 'name', {
  292. value: _type.name + '*',
  293. configurable: true,
  294. enumerable: true,
  295. writable: true
  296. })
  297. }
  298. return rtn
  299. }
  300. /**
  301. * Returns a new clone of the given "type" object, with its
  302. * `indirection` level decremented by 1.
  303. *
  304. * @param {Object|String} type The "type" object to create a dereference type from. Strings get coerced first.
  305. * @return {Object} The new "type" object with its `indirection` decremented by 1.
  306. */
  307. exports.derefType = function derefType (type) {
  308. var _type = exports.coerceType(type)
  309. if (_type.indirection === 1) {
  310. throw new Error('Cannot create deref\'d type for type with indirection 1')
  311. }
  312. var rtn = Object.getPrototypeOf(_type)
  313. if (rtn.indirection !== _type.indirection - 1) {
  314. // slow case
  315. rtn = Object.create(_type)
  316. rtn.indirection--
  317. }
  318. return rtn
  319. }
  320. /**
  321. * Coerces a "type" object from a String or an actual "type" object. String values
  322. * are looked up from the `ref.types` Object. So:
  323. *
  324. * * `"int"` gets coerced into `ref.types.int`.
  325. * * `"int *"` gets translated into `ref.refType(ref.types.int)`
  326. * * `ref.types.int` gets translated into `ref.types.int` (returns itself)
  327. *
  328. * Throws an Error if no valid "type" object could be determined. Most `ref`
  329. * functions use this function under the hood, so anywhere a "type" object is
  330. * expected, a String may be passed as well, including simply setting the
  331. * `buffer.type` property.
  332. *
  333. * ```
  334. * var type = ref.coerceType('int **');
  335. *
  336. * console.log(type.indirection);
  337. * 3
  338. * ```
  339. *
  340. * @param {Object|String} type The "type" Object or String to coerce.
  341. * @return {Object} A "type" object
  342. */
  343. exports.coerceType = function coerceType (type) {
  344. var rtn = type
  345. if (typeof rtn === 'string') {
  346. rtn = exports.types[type]
  347. if (rtn) return rtn
  348. // strip whitespace
  349. rtn = type.replace(/\s+/g, '').toLowerCase()
  350. if (rtn === 'pointer') {
  351. // legacy "pointer" being used :(
  352. rtn = exports.refType(exports.types.void) // void *
  353. } else if (rtn === 'string') {
  354. rtn = exports.types.CString // special char * type
  355. } else {
  356. var refCount = 0
  357. rtn = rtn.replace(/\*/g, function () {
  358. refCount++
  359. return ''
  360. })
  361. // allow string names to be passed in
  362. rtn = exports.types[rtn]
  363. if (refCount > 0) {
  364. if (!(rtn && 'size' in rtn && 'indirection' in rtn)) {
  365. throw new TypeError('could not determine a proper "type" from: ' + JSON.stringify(type))
  366. }
  367. for (var i = 0; i < refCount; i++) {
  368. rtn = exports.refType(rtn)
  369. }
  370. }
  371. }
  372. }
  373. if (!(rtn && 'size' in rtn && 'indirection' in rtn)) {
  374. throw new TypeError('could not determine a proper "type" from: ' + JSON.stringify(type))
  375. }
  376. return rtn
  377. }
  378. /**
  379. * Returns the "type" property of the given Buffer.
  380. * Creates a default type for the buffer when none exists.
  381. *
  382. * @param {Buffer} buffer The Buffer instance to get the "type" object from.
  383. * @return {Object} The "type" object from the given Buffer.
  384. */
  385. exports.getType = function getType (buffer) {
  386. if (!buffer.type) {
  387. debug('WARN: no "type" found on buffer, setting default "type"', buffer)
  388. buffer.type = {}
  389. buffer.type.size = buffer.length
  390. buffer.type.indirection = 1
  391. buffer.type.get = function get () {
  392. throw new Error('unknown "type"; cannot get()')
  393. }
  394. buffer.type.set = function set () {
  395. throw new Error('unknown "type"; cannot set()')
  396. }
  397. }
  398. return exports.coerceType(buffer.type)
  399. }
  400. /**
  401. * Calls the `get()` function of the Buffer's current "type" (or the
  402. * passed in _type_ if present) at the given _offset_.
  403. *
  404. * This function handles checking the "indirection" level and returning a
  405. * proper "dereferenced" Bufffer instance when necessary.
  406. *
  407. * @param {Buffer} buffer The Buffer instance to read from.
  408. * @param {Number} offset (optional) The offset on the Buffer to start reading from. Defaults to 0.
  409. * @param {Object|String} type (optional) The "type" object to use when reading. Defaults to calling `getType()` on the buffer.
  410. * @return {?} Whatever value the "type" used when reading returns.
  411. */
  412. exports.get = function get (buffer, offset, type) {
  413. if (!offset) {
  414. offset = 0
  415. }
  416. if (type) {
  417. type = exports.coerceType(type)
  418. } else {
  419. type = exports.getType(buffer)
  420. }
  421. debug('get(): (offset: %d)', offset, buffer)
  422. assert(type.indirection > 0, '"indirection" level must be at least 1')
  423. if (type.indirection === 1) {
  424. // need to check "type"
  425. return type.get(buffer, offset)
  426. } else {
  427. // need to create a deref'd Buffer
  428. var size = type.indirection === 2 ? type.size : exports.sizeof.pointer
  429. var reference = exports.readPointer(buffer, offset, size)
  430. reference.type = exports.derefType(type)
  431. return reference
  432. }
  433. }
  434. /**
  435. * Calls the `set()` function of the Buffer's current "type" (or the
  436. * passed in _type_ if present) at the given _offset_.
  437. *
  438. * This function handles checking the "indirection" level writing a pointer rather
  439. * than calling the `set()` function if the indirection is greater than 1.
  440. *
  441. * @param {Buffer} buffer The Buffer instance to write to.
  442. * @param {Number} offset The offset on the Buffer to start writing to.
  443. * @param {?} value The value to write to the Buffer instance.
  444. * @param {Object|String} type (optional) The "type" object to use when reading. Defaults to calling `getType()` on the buffer.
  445. */
  446. exports.set = function set (buffer, offset, value, type) {
  447. if (!offset) {
  448. offset = 0
  449. }
  450. if (type) {
  451. type = exports.coerceType(type)
  452. } else {
  453. type = exports.getType(buffer)
  454. }
  455. debug('set(): (offset: %d)', offset, buffer, value)
  456. assert(type.indirection >= 1, '"indirection" level must be at least 1')
  457. if (type.indirection === 1) {
  458. type.set(buffer, offset, value)
  459. } else {
  460. exports.writePointer(buffer, offset, value)
  461. }
  462. }
  463. /**
  464. * Returns a new Buffer instance big enough to hold `type`,
  465. * with the given `value` written to it.
  466. *
  467. * ``` js
  468. * var intBuf = ref.alloc(ref.types.int)
  469. * var int_with_4 = ref.alloc(ref.types.int, 4)
  470. * ```
  471. *
  472. * @param {Object|String} type The "type" object to allocate. Strings get coerced first.
  473. * @param {?} value (optional) The initial value set on the returned Buffer, using _type_'s `set()` function.
  474. * @return {Buffer} A new Buffer instance with it's `type` set to "type", and (optionally) "value" written to it.
  475. */
  476. exports.alloc = function alloc (_type, value) {
  477. var type = exports.coerceType(_type)
  478. debug('allocating Buffer for type with "size"', type.size)
  479. var size
  480. if (type.indirection === 1) {
  481. size = type.size
  482. } else {
  483. size = exports.sizeof.pointer
  484. }
  485. var buffer = new Buffer(size)
  486. buffer.type = type
  487. if (arguments.length >= 2) {
  488. debug('setting value on allocated buffer', value)
  489. exports.set(buffer, 0, value, type)
  490. }
  491. return buffer
  492. }
  493. /**
  494. * Returns a new `Buffer` instance with the given String written to it with the
  495. * given encoding (defaults to __'utf8'__). The buffer is 1 byte longer than the
  496. * string itself, and is NUL terminated.
  497. *
  498. * ```
  499. * var buf = ref.allocCString('hello world');
  500. *
  501. * console.log(buf.toString());
  502. * 'hello world\u0000'
  503. * ```
  504. *
  505. * @param {String} string The JavaScript string to be converted to a C string.
  506. * @param {String} encoding (optional) The encoding to use for the C string. Defaults to __'utf8'__.
  507. * @return {Buffer} The new `Buffer` instance with the specified String wrtten to it, and a trailing NUL byte.
  508. */
  509. exports.allocCString = function allocCString (string, encoding) {
  510. if (null == string || (Buffer.isBuffer(string) && exports.isNull(string))) {
  511. return exports.NULL
  512. }
  513. var size = Buffer.byteLength(string, encoding) + 1
  514. var buffer = new Buffer(size)
  515. exports.writeCString(buffer, 0, string, encoding)
  516. buffer.type = charPtrType
  517. return buffer
  518. }
  519. /**
  520. * Writes the given string as a C String (NULL terminated) to the given buffer
  521. * at the given offset. "encoding" is optional and defaults to __'utf8'__.
  522. *
  523. * Unlike `readCString()`, this function requires the buffer to actually have the
  524. * proper length.
  525. *
  526. * @param {Buffer} buffer The Buffer instance to write to.
  527. * @param {Number} offset The offset of the buffer to begin writing at.
  528. * @param {String} string The JavaScript String to write that will be written to the buffer.
  529. * @param {String} encoding (optional) The encoding to read the C string as. Defaults to __'utf8'__.
  530. */
  531. exports.writeCString = function writeCString (buffer, offset, string, encoding) {
  532. assert(Buffer.isBuffer(buffer), 'expected a Buffer as the first argument')
  533. assert.equal('string', typeof string, 'expected a "string" as the third argument')
  534. if (!offset) {
  535. offset = 0
  536. }
  537. if (!encoding) {
  538. encoding = 'utf8'
  539. }
  540. var size = buffer.length - offset
  541. var len = buffer.write(string, offset, size, encoding)
  542. buffer.writeUInt8(0, offset + len) // NUL terminate
  543. }
  544. exports['readInt64' + exports.endianness] = exports.readInt64
  545. exports['readUInt64' + exports.endianness] = exports.readUInt64
  546. exports['writeInt64' + exports.endianness] = exports.writeInt64
  547. exports['writeUInt64' + exports.endianness] = exports.writeUInt64
  548. var opposite = exports.endianness == 'LE' ? 'BE' : 'LE'
  549. var int64temp = new Buffer(exports.sizeof.int64)
  550. var uint64temp = new Buffer(exports.sizeof.uint64)
  551. exports['readInt64' + opposite] = function (buffer, offset) {
  552. for (var i = 0; i < exports.sizeof.int64; i++) {
  553. int64temp[i] = buffer[offset + exports.sizeof.int64 - i - 1]
  554. }
  555. return exports.readInt64(int64temp, 0)
  556. }
  557. exports['readUInt64' + opposite] = function (buffer, offset) {
  558. for (var i = 0; i < exports.sizeof.uint64; i++) {
  559. uint64temp[i] = buffer[offset + exports.sizeof.uint64 - i - 1]
  560. }
  561. return exports.readUInt64(uint64temp, 0)
  562. }
  563. exports['writeInt64' + opposite] = function (buffer, offset, value) {
  564. exports.writeInt64(int64temp, 0, value)
  565. for (var i = 0; i < exports.sizeof.int64; i++) {
  566. buffer[offset + i] = int64temp[exports.sizeof.int64 - i - 1]
  567. }
  568. }
  569. exports['writeUInt64' + opposite] = function (buffer, offset, value) {
  570. exports.writeUInt64(uint64temp, 0, value)
  571. for (var i = 0; i < exports.sizeof.uint64; i++) {
  572. buffer[offset + i] = uint64temp[exports.sizeof.uint64 - i - 1]
  573. }
  574. }
  575. /**
  576. * `ref()` accepts a Buffer instance and returns a new Buffer
  577. * instance that is "pointer" sized and has its data pointing to the given
  578. * Buffer instance. Essentially the created Buffer is a "reference" to the
  579. * original pointer, equivalent to the following C code:
  580. *
  581. * ``` c
  582. * char *buf = buffer;
  583. * char **ref = &buf;
  584. * ```
  585. *
  586. * @param {Buffer} buffer A Buffer instance to create a reference to.
  587. * @return {Buffer} A new Buffer instance pointing to _buffer_.
  588. */
  589. exports.ref = function ref (buffer) {
  590. debug('creating a reference to buffer', buffer)
  591. var type = exports.refType(exports.getType(buffer))
  592. return exports.alloc(type, buffer)
  593. }
  594. /**
  595. * Accepts a Buffer instance and attempts to "dereference" it.
  596. * That is, first it checks the `indirection` count of _buffer_'s "type", and if
  597. * it's greater than __1__ then it merely returns another Buffer, but with one
  598. * level less `indirection`.
  599. *
  600. * When _buffer_'s indirection is at __1__, then it checks for `buffer.type`
  601. * which should be an Object with its own `get()` function.
  602. *
  603. * ```
  604. * var buf = ref.alloc('int', 6);
  605. *
  606. * var val = ref.deref(buf);
  607. * console.log(val);
  608. * 6
  609. * ```
  610. *
  611. *
  612. * @param {Buffer} buffer A Buffer instance to dereference.
  613. * @return {?} The returned value after dereferencing _buffer_.
  614. */
  615. exports.deref = function deref (buffer) {
  616. debug('dereferencing buffer', buffer)
  617. return exports.get(buffer)
  618. }
  619. /**
  620. * Attaches _object_ to _buffer_ such that it prevents _object_ from being garbage
  621. * collected until _buffer_ does.
  622. *
  623. * @param {Buffer} buffer A Buffer instance to attach _object_ to.
  624. * @param {Object|Buffer} object An Object or Buffer to prevent from being garbage collected until _buffer_ does.
  625. * @api private
  626. */
  627. exports._attach = function _attach (buf, obj) {
  628. if (!buf._refs) {
  629. buf._refs = []
  630. }
  631. buf._refs.push(obj)
  632. }
  633. /**
  634. * Same as `ref.writeObject()`, except that this version does not _attach_ the
  635. * Object to the Buffer, which is potentially unsafe if the garbage collector
  636. * runs.
  637. *
  638. * @param {Buffer} buffer A Buffer instance to write _object_ to.
  639. * @param {Number} offset The offset on the Buffer to start writing at.
  640. * @param {Object} object The Object to be written into _buffer_.
  641. * @api private
  642. */
  643. exports._writeObject = exports.writeObject
  644. /**
  645. * Writes a pointer to _object_ into _buffer_ at the specified _offset.
  646. *
  647. * This function "attaches" _object_ to _buffer_ to prevent it from being garbage
  648. * collected.
  649. *
  650. * ```
  651. * var buf = ref.alloc('Object');
  652. * ref.writeObject(buf, 0, { foo: 'bar' });
  653. *
  654. * ```
  655. *
  656. * @param {Buffer} buffer A Buffer instance to write _object_ to.
  657. * @param {Number} offset The offset on the Buffer to start writing at.
  658. * @param {Object} object The Object to be written into _buffer_.
  659. */
  660. exports.writeObject = function writeObject (buf, offset, obj, persistent) {
  661. debug('writing Object to buffer', buf, offset, obj, persistent)
  662. exports._writeObject(buf, offset, obj, persistent)
  663. exports._attach(buf, obj)
  664. }
  665. /**
  666. * Same as `ref.writePointer()`, except that this version does not attach
  667. * _pointer_ to _buffer_, which is potentially unsafe if the garbage collector
  668. * runs.
  669. *
  670. * @param {Buffer} buffer A Buffer instance to write _pointer to.
  671. * @param {Number} offset The offset on the Buffer to start writing at.
  672. * @param {Buffer} pointer The Buffer instance whose memory address will be written to _buffer_.
  673. * @api private
  674. */
  675. exports._writePointer = exports.writePointer
  676. /**
  677. * Writes the memory address of _pointer_ to _buffer_ at the specified _offset_.
  678. *
  679. * This function "attaches" _object_ to _buffer_ to prevent it from being garbage
  680. * collected.
  681. *
  682. * ```
  683. * var someBuffer = new Buffer('whatever');
  684. * var buf = ref.alloc('pointer');
  685. * ref.writePointer(buf, 0, someBuffer);
  686. * ```
  687. *
  688. * @param {Buffer} buffer A Buffer instance to write _pointer to.
  689. * @param {Number} offset The offset on the Buffer to start writing at.
  690. * @param {Buffer} pointer The Buffer instance whose memory address will be written to _buffer_.
  691. */
  692. exports.writePointer = function writePointer (buf, offset, ptr) {
  693. debug('writing pointer to buffer', buf, offset, ptr)
  694. exports._writePointer(buf, offset, ptr)
  695. exports._attach(buf, ptr)
  696. }
  697. /**
  698. * Same as `ref.reinterpret()`, except that this version does not attach
  699. * _buffer_ to the returned Buffer, which is potentially unsafe if the
  700. * garbage collector runs.
  701. *
  702. * @param {Buffer} buffer A Buffer instance to base the returned Buffer off of.
  703. * @param {Number} size The `length` property of the returned Buffer.
  704. * @param {Number} offset The offset of the Buffer to begin from.
  705. * @return {Buffer} A new Buffer instance with the same memory address as _buffer_, and the requested _size_.
  706. * @api private
  707. */
  708. exports._reinterpret = exports.reinterpret
  709. /**
  710. * Returns a new Buffer instance with the specified _size_, with the same memory
  711. * address as _buffer_.
  712. *
  713. * This function "attaches" _buffer_ to the returned Buffer to prevent it from
  714. * being garbage collected.
  715. *
  716. * @param {Buffer} buffer A Buffer instance to base the returned Buffer off of.
  717. * @param {Number} size The `length` property of the returned Buffer.
  718. * @param {Number} offset The offset of the Buffer to begin from.
  719. * @return {Buffer} A new Buffer instance with the same memory address as _buffer_, and the requested _size_.
  720. */
  721. exports.reinterpret = function reinterpret (buffer, size, offset) {
  722. debug('reinterpreting buffer to "%d" bytes', size)
  723. var rtn = exports._reinterpret(buffer, size, offset || 0)
  724. exports._attach(rtn, buffer)
  725. return rtn
  726. }
  727. /**
  728. * Same as `ref.reinterpretUntilZeros()`, except that this version does not
  729. * attach _buffer_ to the returned Buffer, which is potentially unsafe if the
  730. * garbage collector runs.
  731. *
  732. * @param {Buffer} buffer A Buffer instance to base the returned Buffer off of.
  733. * @param {Number} size The number of sequential, aligned `NULL` bytes that are required to terminate the buffer.
  734. * @param {Number} offset The offset of the Buffer to begin from.
  735. * @return {Buffer} A new Buffer instance with the same memory address as _buffer_, and a variable `length` that is terminated by _size_ NUL bytes.
  736. * @api private
  737. */
  738. exports._reinterpretUntilZeros = exports.reinterpretUntilZeros
  739. /**
  740. * Accepts a `Buffer` instance and a number of `NULL` bytes to read from the
  741. * pointer. This function will scan past the boundary of the Buffer's `length`
  742. * until it finds `size` number of aligned `NULL` bytes.
  743. *
  744. * This is useful for finding the end of NUL-termintated array or C string. For
  745. * example, the `readCString()` function _could_ be implemented like:
  746. *
  747. * ```
  748. * function readCString (buf) {
  749. * return ref.reinterpretUntilZeros(buf, 1).toString('utf8')
  750. * }
  751. * ```
  752. *
  753. * This function "attaches" _buffer_ to the returned Buffer to prevent it from
  754. * being garbage collected.
  755. *
  756. * @param {Buffer} buffer A Buffer instance to base the returned Buffer off of.
  757. * @param {Number} size The number of sequential, aligned `NULL` bytes are required to terminate the buffer.
  758. * @param {Number} offset The offset of the Buffer to begin from.
  759. * @return {Buffer} A new Buffer instance with the same memory address as _buffer_, and a variable `length` that is terminated by _size_ NUL bytes.
  760. */
  761. exports.reinterpretUntilZeros = function reinterpretUntilZeros (buffer, size, offset) {
  762. debug('reinterpreting buffer to until "%d" NULL (0) bytes are found', size)
  763. var rtn = exports._reinterpretUntilZeros(buffer, size, offset || 0)
  764. exports._attach(rtn, buffer)
  765. return rtn
  766. }
  767. // the built-in "types"
  768. var types = exports.types = {}
  769. /**
  770. * The `void` type.
  771. *
  772. * @section types
  773. */
  774. types.void = {
  775. size: 0
  776. , indirection: 1
  777. , get: function get (buf, offset) {
  778. debug('getting `void` type (returns `null`)')
  779. return null
  780. }
  781. , set: function set (buf, offset, val) {
  782. debug('setting `void` type (no-op)')
  783. }
  784. }
  785. /**
  786. * The `int8` type.
  787. */
  788. types.int8 = {
  789. size: exports.sizeof.int8
  790. , indirection: 1
  791. , get: function get (buf, offset) {
  792. return buf.readInt8(offset || 0)
  793. }
  794. , set: function set (buf, offset, val) {
  795. if (typeof val === 'string') {
  796. val = val.charCodeAt(0)
  797. }
  798. return buf.writeInt8(val, offset || 0)
  799. }
  800. }
  801. /**
  802. * The `uint8` type.
  803. */
  804. types.uint8 = {
  805. size: exports.sizeof.uint8
  806. , indirection: 1
  807. , get: function get (buf, offset) {
  808. return buf.readUInt8(offset || 0)
  809. }
  810. , set: function set (buf, offset, val) {
  811. if (typeof val === 'string') {
  812. val = val.charCodeAt(0)
  813. }
  814. return buf.writeUInt8(val, offset || 0)
  815. }
  816. }
  817. /**
  818. * The `int16` type.
  819. */
  820. types.int16 = {
  821. size: exports.sizeof.int16
  822. , indirection: 1
  823. , get: function get (buf, offset) {
  824. return buf['readInt16' + exports.endianness](offset || 0)
  825. }
  826. , set: function set (buf, offset, val) {
  827. return buf['writeInt16' + exports.endianness](val, offset || 0)
  828. }
  829. }
  830. /**
  831. * The `uint16` type.
  832. */
  833. types.uint16 = {
  834. size: exports.sizeof.uint16
  835. , indirection: 1
  836. , get: function get (buf, offset) {
  837. return buf['readUInt16' + exports.endianness](offset || 0)
  838. }
  839. , set: function set (buf, offset, val) {
  840. return buf['writeUInt16' + exports.endianness](val, offset || 0)
  841. }
  842. }
  843. /**
  844. * The `int32` type.
  845. */
  846. types.int32 = {
  847. size: exports.sizeof.int32
  848. , indirection: 1
  849. , get: function get (buf, offset) {
  850. return buf['readInt32' + exports.endianness](offset || 0)
  851. }
  852. , set: function set (buf, offset, val) {
  853. return buf['writeInt32' + exports.endianness](val, offset || 0)
  854. }
  855. }
  856. /**
  857. * The `uint32` type.
  858. */
  859. types.uint32 = {
  860. size: exports.sizeof.uint32
  861. , indirection: 1
  862. , get: function get (buf, offset) {
  863. return buf['readUInt32' + exports.endianness](offset || 0)
  864. }
  865. , set: function set (buf, offset, val) {
  866. return buf['writeUInt32' + exports.endianness](val, offset || 0)
  867. }
  868. }
  869. /**
  870. * The `int64` type.
  871. */
  872. types.int64 = {
  873. size: exports.sizeof.int64
  874. , indirection: 1
  875. , get: function get (buf, offset) {
  876. return buf['readInt64' + exports.endianness](offset || 0)
  877. }
  878. , set: function set (buf, offset, val) {
  879. return buf['writeInt64' + exports.endianness](val, offset || 0)
  880. }
  881. }
  882. /**
  883. * The `uint64` type.
  884. */
  885. types.uint64 = {
  886. size: exports.sizeof.uint64
  887. , indirection: 1
  888. , get: function get (buf, offset) {
  889. return buf['readUInt64' + exports.endianness](offset || 0)
  890. }
  891. , set: function set (buf, offset, val) {
  892. return buf['writeUInt64' + exports.endianness](val, offset || 0)
  893. }
  894. }
  895. /**
  896. * The `float` type.
  897. */
  898. types.float = {
  899. size: exports.sizeof.float
  900. , indirection: 1
  901. , get: function get (buf, offset) {
  902. return buf['readFloat' + exports.endianness](offset || 0)
  903. }
  904. , set: function set (buf, offset, val) {
  905. return buf['writeFloat' + exports.endianness](val, offset || 0)
  906. }
  907. }
  908. /**
  909. * The `double` type.
  910. */
  911. types.double = {
  912. size: exports.sizeof.double
  913. , indirection: 1
  914. , get: function get (buf, offset) {
  915. return buf['readDouble' + exports.endianness](offset || 0)
  916. }
  917. , set: function set (buf, offset, val) {
  918. return buf['writeDouble' + exports.endianness](val, offset || 0)
  919. }
  920. }
  921. /**
  922. * The `Object` type. This can be used to read/write regular JS Objects
  923. * into raw memory.
  924. */
  925. types.Object = {
  926. size: exports.sizeof.Object
  927. , indirection: 1
  928. , get: function get (buf, offset) {
  929. return buf.readObject(offset || 0)
  930. }
  931. , set: function set (buf, offset, val) {
  932. return buf.writeObject(val, offset || 0)
  933. }
  934. }
  935. /**
  936. * The `CString` (a.k.a `"string"`) type.
  937. *
  938. * CStrings are a kind of weird thing. We say it's `sizeof(char *)`, and
  939. * `indirection` level of 1, which means that we have to return a Buffer that
  940. * is pointer sized, and points to a some utf8 string data, so we have to create
  941. * a 2nd "in-between" buffer.
  942. */
  943. types.CString = {
  944. size: exports.sizeof.pointer
  945. , alignment: exports.alignof.pointer
  946. , indirection: 1
  947. , get: function get (buf, offset) {
  948. var _buf = exports.readPointer(buf, offset)
  949. if (exports.isNull(_buf)) {
  950. return null
  951. }
  952. return exports.readCString(_buf, 0)
  953. }
  954. , set: function set (buf, offset, val) {
  955. var _buf
  956. if (Buffer.isBuffer(val)) {
  957. _buf = val
  958. } else {
  959. // assume string
  960. _buf = exports.allocCString(val)
  961. }
  962. return exports.writePointer(buf, offset, _buf)
  963. }
  964. }
  965. // alias Utf8String
  966. var utfstringwarned = false
  967. Object.defineProperty(types, 'Utf8String', {
  968. enumerable: false
  969. , configurable: true
  970. , get: function () {
  971. if (!utfstringwarned) {
  972. utfstringwarned = true
  973. console.error('"Utf8String" type is deprecated, use "CString" instead')
  974. }
  975. return types.CString
  976. }
  977. })
  978. /**
  979. * The `bool` type.
  980. *
  981. * Wrapper type around `types.uint8` that accepts/returns `true` or
  982. * `false` Boolean JavaScript values.
  983. *
  984. * @name bool
  985. *
  986. */
  987. /**
  988. * The `byte` type.
  989. *
  990. * @name byte
  991. */
  992. /**
  993. * The `char` type.
  994. *
  995. * @name char
  996. */
  997. /**
  998. * The `uchar` type.
  999. *
  1000. * @name uchar
  1001. */
  1002. /**
  1003. * The `short` type.
  1004. *
  1005. * @name short
  1006. */
  1007. /**
  1008. * The `ushort` type.
  1009. *
  1010. * @name ushort
  1011. */
  1012. /**
  1013. * The `int` type.
  1014. *
  1015. * @name int
  1016. */
  1017. /**
  1018. * The `uint` type.
  1019. *
  1020. * @name uint
  1021. */
  1022. /**
  1023. * The `long` type.
  1024. *
  1025. * @name long
  1026. */
  1027. /**
  1028. * The `ulong` type.
  1029. *
  1030. * @name ulong
  1031. */
  1032. /**
  1033. * The `longlong` type.
  1034. *
  1035. * @name longlong
  1036. */
  1037. /**
  1038. * The `ulonglong` type.
  1039. *
  1040. * @name ulonglong
  1041. */
  1042. /**
  1043. * The `size_t` type.
  1044. *
  1045. * @name size_t
  1046. */
  1047. // "typedef"s for the variable-sized types
  1048. ;[ 'bool', 'byte', 'char', 'uchar', 'short', 'ushort', 'int', 'uint', 'long'
  1049. , 'ulong', 'longlong', 'ulonglong', 'size_t' ].forEach(function (name) {
  1050. var unsigned = name === 'bool'
  1051. || name === 'byte'
  1052. || name === 'size_t'
  1053. || name[0] === 'u'
  1054. var size = exports.sizeof[name]
  1055. assert(size >= 1 && size <= 8)
  1056. var typeName = 'int' + (size * 8)
  1057. if (unsigned) {
  1058. typeName = 'u' + typeName
  1059. }
  1060. var type = exports.types[typeName]
  1061. assert(type)
  1062. exports.types[name] = Object.create(type)
  1063. })
  1064. // set the "alignment" property on the built-in types
  1065. Object.keys(exports.alignof).forEach(function (name) {
  1066. if (name === 'pointer') return
  1067. exports.types[name].alignment = exports.alignof[name]
  1068. assert(exports.types[name].alignment > 0)
  1069. })
  1070. // make the `bool` type work with JS true/false values
  1071. exports.types.bool.get = (function (_get) {
  1072. return function get (buf, offset) {
  1073. return _get(buf, offset) ? true : false
  1074. }
  1075. })(exports.types.bool.get)
  1076. exports.types.bool.set = (function (_set) {
  1077. return function set (buf, offset, val) {
  1078. if (typeof val !== 'number') {
  1079. val = val ? 1 : 0
  1080. }
  1081. return _set(buf, offset, val)
  1082. }
  1083. })(exports.types.bool.set)
  1084. /*!
  1085. * Set the `name` property of the types. Used for debugging...
  1086. */
  1087. Object.keys(exports.types).forEach(function (name) {
  1088. exports.types[name].name = name
  1089. })
  1090. /*!
  1091. * This `char *` type is used by "allocCString()" above.
  1092. */
  1093. var charPtrType = exports.refType(exports.types.char)
  1094. /*!
  1095. * Set the `type` property of the `NULL` pointer Buffer object.
  1096. */
  1097. exports.NULL.type = exports.types.void
  1098. /**
  1099. * `NULL_POINTER` is a pointer-sized `Buffer` instance pointing to `NULL`.
  1100. * Conceptually, it's equivalent to the following C code:
  1101. *
  1102. * ``` c
  1103. * char *null_pointer;
  1104. * null_pointer = NULL;
  1105. * ```
  1106. *
  1107. * @type Buffer
  1108. */
  1109. exports.NULL_POINTER = exports.ref(exports.NULL)
  1110. /**
  1111. * All these '...' comment blocks below are for the documentation generator.
  1112. *
  1113. * @section buffer
  1114. */
  1115. Buffer.prototype.address = function address () {
  1116. return exports.address(this, 0)
  1117. }
  1118. /**
  1119. * ...
  1120. */
  1121. Buffer.prototype.hexAddress = function hexAddress () {
  1122. return exports.hexAddress(this, 0)
  1123. }
  1124. /**
  1125. * ...
  1126. */
  1127. Buffer.prototype.isNull = function isNull () {
  1128. return exports.isNull(this, 0)
  1129. }
  1130. /**
  1131. * ...
  1132. */
  1133. Buffer.prototype.ref = function ref () {
  1134. return exports.ref(this)
  1135. }
  1136. /**
  1137. * ...
  1138. */
  1139. Buffer.prototype.deref = function deref () {
  1140. return exports.deref(this)
  1141. }
  1142. /**
  1143. * ...
  1144. */
  1145. Buffer.prototype.readObject = function readObject (offset) {
  1146. return exports.readObject(this, offset)
  1147. }
  1148. /**
  1149. * ...
  1150. */
  1151. Buffer.prototype.writeObject = function writeObject (obj, offset) {
  1152. return exports.writeObject(this, offset, obj)
  1153. }
  1154. /**
  1155. * ...
  1156. */
  1157. Buffer.prototype.readPointer = function readPointer (offset, size) {
  1158. return exports.readPointer(this, offset, size)
  1159. }
  1160. /**
  1161. * ...
  1162. */
  1163. Buffer.prototype.writePointer = function writePointer (ptr, offset) {
  1164. return exports.writePointer(this, offset, ptr)
  1165. }
  1166. /**
  1167. * ...
  1168. */
  1169. Buffer.prototype.readCString = function readCString (offset) {
  1170. return exports.readCString(this, offset)
  1171. }
  1172. /**
  1173. * ...
  1174. */
  1175. Buffer.prototype.writeCString = function writeCString (string, offset, encoding) {
  1176. return exports.writeCString(this, offset, string, encoding)
  1177. }
  1178. /**
  1179. * ...
  1180. */
  1181. Buffer.prototype.readInt64BE = function readInt64BE (offset) {
  1182. return exports.readInt64BE(this, offset)
  1183. }
  1184. /**
  1185. * ...
  1186. */
  1187. Buffer.prototype.writeInt64BE = function writeInt64BE (val, offset) {
  1188. return exports.writeInt64BE(this, offset, val)
  1189. }
  1190. /**
  1191. * ...
  1192. */
  1193. Buffer.prototype.readUInt64BE = function readUInt64BE (offset) {
  1194. return exports.readUInt64BE(this, offset)
  1195. }
  1196. /**
  1197. * ...
  1198. */
  1199. Buffer.prototype.writeUInt64BE = function writeUInt64BE (val, offset) {
  1200. return exports.writeUInt64BE(this, offset, val)
  1201. }
  1202. /**
  1203. * ...
  1204. */
  1205. Buffer.prototype.readInt64LE = function readInt64LE (offset) {
  1206. return exports.readInt64LE(this, offset)
  1207. }
  1208. /**
  1209. * ...
  1210. */
  1211. Buffer.prototype.writeInt64LE = function writeInt64LE (val, offset) {
  1212. return exports.writeInt64LE(this, offset, val)
  1213. }
  1214. /**
  1215. * ...
  1216. */
  1217. Buffer.prototype.readUInt64LE = function readUInt64LE (offset) {
  1218. return exports.readUInt64LE(this, offset)
  1219. }
  1220. /**
  1221. * ...
  1222. */
  1223. Buffer.prototype.writeUInt64LE = function writeUInt64LE (val, offset) {
  1224. return exports.writeUInt64LE(this, offset, val)
  1225. }
  1226. /**
  1227. * ...
  1228. */
  1229. Buffer.prototype.reinterpret = function reinterpret (size, offset) {
  1230. return exports.reinterpret(this, size, offset)
  1231. }
  1232. /**
  1233. * ...
  1234. */
  1235. Buffer.prototype.reinterpretUntilZeros = function reinterpretUntilZeros (size, offset) {
  1236. return exports.reinterpretUntilZeros(this, size, offset)
  1237. }
  1238. /**
  1239. * `ref` overwrites the default `Buffer#inspect()` function to include the
  1240. * hex-encoded memory address of the Buffer instance when invoked.
  1241. *
  1242. * This is simply a nice-to-have.
  1243. *
  1244. * **Before**:
  1245. *
  1246. * ``` js
  1247. * console.log(new Buffer('ref'));
  1248. * <Buffer 72 65 66>
  1249. * ```
  1250. *
  1251. * **After**:
  1252. *
  1253. * ``` js
  1254. * console.log(new Buffer('ref'));
  1255. * <Buffer@0x103015490 72 65 66>
  1256. * ```
  1257. */
  1258. var inspectSym = inspect.custom || 'inspect'
  1259. Buffer.prototype[inspectSym] = overwriteInspect(Buffer.prototype[inspectSym])
  1260. // does SlowBuffer inherit from Buffer? (node >= v0.7.9)
  1261. if (!(exports.NULL instanceof Buffer)) {
  1262. debug('extending SlowBuffer\'s prototype since it doesn\'t inherit from Buffer.prototype')
  1263. /*!
  1264. * SlowBuffer convenience methods.
  1265. */
  1266. var SlowBuffer = require('buffer').SlowBuffer
  1267. SlowBuffer.prototype.address = Buffer.prototype.address
  1268. SlowBuffer.prototype.hexAddress = Buffer.prototype.hexAddress
  1269. SlowBuffer.prototype.isNull = Buffer.prototype.isNull
  1270. SlowBuffer.prototype.ref = Buffer.prototype.ref
  1271. SlowBuffer.prototype.deref = Buffer.prototype.deref
  1272. SlowBuffer.prototype.readObject = Buffer.prototype.readObject
  1273. SlowBuffer.prototype.writeObject = Buffer.prototype.writeObject
  1274. SlowBuffer.prototype.readPointer = Buffer.prototype.readPointer
  1275. SlowBuffer.prototype.writePointer = Buffer.prototype.writePointer
  1276. SlowBuffer.prototype.readCString = Buffer.prototype.readCString
  1277. SlowBuffer.prototype.writeCString = Buffer.prototype.writeCString
  1278. SlowBuffer.prototype.reinterpret = Buffer.prototype.reinterpret
  1279. SlowBuffer.prototype.reinterpretUntilZeros = Buffer.prototype.reinterpretUntilZeros
  1280. SlowBuffer.prototype.readInt64BE = Buffer.prototype.readInt64BE
  1281. SlowBuffer.prototype.writeInt64BE = Buffer.prototype.writeInt64BE
  1282. SlowBuffer.prototype.readUInt64BE = Buffer.prototype.readUInt64BE
  1283. SlowBuffer.prototype.writeUInt64BE = Buffer.prototype.writeUInt64BE
  1284. SlowBuffer.prototype.readInt64LE = Buffer.prototype.readInt64LE
  1285. SlowBuffer.prototype.writeInt64LE = Buffer.prototype.writeInt64LE
  1286. SlowBuffer.prototype.readUInt64LE = Buffer.prototype.readUInt64LE
  1287. SlowBuffer.prototype.writeUInt64LE = Buffer.prototype.writeUInt64LE
  1288. SlowBuffer.prototype[inspectSym] = overwriteInspect(SlowBuffer.prototype[inspectSym])
  1289. }
  1290. function overwriteInspect (inspect) {
  1291. if (inspect.name === 'refinspect') {
  1292. return inspect
  1293. } else {
  1294. return function refinspect () {
  1295. var v = inspect.apply(this, arguments)
  1296. return v.replace('Buffer', 'Buffer@0x' + this.hexAddress())
  1297. }
  1298. }
  1299. }