|
| 1 | +ref-napi |
| 2 | +======== |
| 3 | +### Turn Buffer instances into "pointers" |
| 4 | + |
| 5 | +[](https://greenkeeper.io/) |
| 6 | + |
| 7 | +[](https://npmjs.org/package/ref-napi) |
| 8 | +[](https://npmjs.org/package/ref-napi) |
| 9 | +[](https://travis-ci.org/node-ffi-napi/ref-napi?branch=latest) |
| 10 | +[](https://coveralls.io/r/node-ffi-napi/ref-napi?branch=latest) |
| 11 | +[](https://david-dm.org/node-ffi-napi/ref-napi) |
| 12 | + |
| 13 | +This module is inspired by the old `Pointer` class from node-ffi, but with the |
| 14 | +intent of using Node's fast `Buffer` instances instead of a slow C++ `Pointer` |
| 15 | +class. These two concepts were previously very similar, but now this module |
| 16 | +brings over the functionality that Pointers had and Buffers are missing, so |
| 17 | +now Buffers are a lot more powerful. |
| 18 | + |
| 19 | +### Features: |
| 20 | + |
| 21 | + * Get the memory address of any `Buffer` instance |
| 22 | + * Read/write references to JavaScript Objects into `Buffer` instances |
| 23 | + * Read/write `Buffer` instances' memory addresses to other `Buffer` instances |
| 24 | + * Read/write `int64_t` and `uint64_t` data values (Numbers or Strings) |
| 25 | + * A "type" convention, so that you can specify a buffer as an `int *`, |
| 26 | + and reference/dereference at will. |
| 27 | + * Offers a buffer instance representing the `NULL` pointer |
| 28 | + |
| 29 | + |
| 30 | +Installation |
| 31 | +------------ |
| 32 | + |
| 33 | +Install with `npm`: |
| 34 | + |
| 35 | +``` bash |
| 36 | +$ npm install ref-napi |
| 37 | +``` |
| 38 | + |
| 39 | + |
| 40 | +Examples |
| 41 | +-------- |
| 42 | + |
| 43 | +#### referencing and derefencing |
| 44 | + |
| 45 | +``` js |
| 46 | +var ref = require('ref-napi') |
| 47 | + |
| 48 | +// so we can all agree that a buffer with the int value written |
| 49 | +// to it could be represented as an "int *" |
| 50 | +var buf = new Buffer(4) |
| 51 | +buf.writeInt32LE(12345, 0) |
| 52 | + |
| 53 | +// first, what is the memory address of the buffer? |
| 54 | +console.log(buf.hexAddress()) // ← '7FA89D006FD8' |
| 55 | + |
| 56 | +// using `ref`, you can set the "type", and gain magic abilities! |
| 57 | +buf.type = ref.types.int |
| 58 | + |
| 59 | +// now we can dereference to get the "meaningful" value |
| 60 | +console.log(buf.deref()) // ← 12345 |
| 61 | + |
| 62 | + |
| 63 | +// you can also get references to the original buffer if you need it. |
| 64 | +// this buffer could be thought of as an "int **" |
| 65 | +var one = buf.ref() |
| 66 | + |
| 67 | +// and you can dereference all the way back down to an int |
| 68 | +console.log(one.deref().deref()) // ← 12345 |
| 69 | +``` |
| 70 | + |
| 71 | +See the [full API Docs][docs] for more examples. |
| 72 | + |
| 73 | + |
| 74 | +The "type" interface |
| 75 | +-------------------- |
| 76 | + |
| 77 | +You can easily define your own "type" objects at attach to `Buffer` instances. |
| 78 | +It just needs to be a regular JavaScript Object that contains the following |
| 79 | +properties: |
| 80 | + |
| 81 | +| **Name** | **Data Type** | **Description** |
| 82 | +|:--------------|:---------------------------------|:---------------------------------- |
| 83 | +| `size` | Number | The size in bytes required to hold this type. |
| 84 | +| `indirection` | Number | The current level of indirection of the buffer. Usually this would be _1_, and gets incremented on Buffers from `ref()` calls. A value of less than or equal to _0_ is invalid. |
| 85 | +| `get` | Function (buffer, offset) | The function to invoke when dereferencing this type when the indirection level is _1_. |
| 86 | +| `set` | Function (buffer, offset, value) | The function to invoke when setting a value to a buffer instance. |
| 87 | +| `name` | String | _(optional)_ The name to use during debugging for this type. |
| 88 | +| `alignment` | Number | _(optional)_ The alignment of this type when placed in a struct. Defaults to the type's `size`. |
| 89 | + |
| 90 | +Be sure to check out the Wiki page of ["Known |
| 91 | +Types"](https://github.com/TooTallNate/ref/wiki/Known-%22types%22), for the list |
| 92 | +of built-in ref types, as well as known external type implementations. |
| 93 | + |
| 94 | +For example, you could define a "bigint" type that dereferences into a |
| 95 | +[`bigint`](https://github.com/substack/node-bigint) instance: |
| 96 | + |
| 97 | +``` js |
| 98 | +var ref = require('ref-napi') |
| 99 | +var bigint = require('bigint') |
| 100 | + |
| 101 | +// define the "type" instance according to the spec |
| 102 | +var BigintType = { |
| 103 | + size: ref.sizeof.int64 |
| 104 | + , indirection: 1 |
| 105 | + , get: function (buffer, offset) { |
| 106 | + // return a bigint instance from the buffer |
| 107 | + return bigint.fromBuffer(buffer) |
| 108 | + } |
| 109 | + , set: function (buffer, offset, value) { |
| 110 | + // 'value' would be a bigint instance |
| 111 | + var val = value.toString() |
| 112 | + return ref.writeInt64(buffer, offset || 0, val) |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +// now we can create instances of the type from existing buffers. |
| 117 | +// "buf" is some Buffer instance returned from some external data |
| 118 | +// source, which should contain "bigint" binary data. |
| 119 | +buf.type = BigintType |
| 120 | + |
| 121 | +// and now you can create "bigint" instances using this generic "types" API |
| 122 | +var val = buf.deref() |
| 123 | + .add('1234') |
| 124 | + .sqrt() |
| 125 | + .shiftLeft(5) |
| 126 | +``` |
| 127 | + |
| 128 | +Build the docs |
| 129 | +-------------- |
| 130 | + |
| 131 | +Install the dev dependencies: |
| 132 | + |
| 133 | +``` bash |
| 134 | +$ npm install |
| 135 | +``` |
| 136 | + |
| 137 | +Generate the docs: |
| 138 | + |
| 139 | +``` bash |
| 140 | +$ npm run docs |
| 141 | +``` |
| 142 | + |
| 143 | +Incompatible packages |
| 144 | +-------------------- |
| 145 | + |
| 146 | +The [`ref-struct-napi`](https://www.npmjs.com/package/ref-struct-napi) and |
| 147 | +[`ref-array-napi`](https://www.npmjs.com/package/ref-array-napi) packages |
| 148 | +have names that sound like they are compatible with this module. |
| 149 | + |
| 150 | +They are not, and your application will experience crashes if you use |
| 151 | +them together with `ref-napi`. |
| 152 | +Use [`ref-struct-di`](https://www.npmjs.com/package/ref-struct-di) |
| 153 | +or [`ref-array-di`](https://www.npmjs.com/package/ref-array-di) instead. |
| 154 | + |
| 155 | +License |
| 156 | +------- |
| 157 | + |
| 158 | +(The MIT License) |
| 159 | + |
| 160 | +Copyright (c) 2012 Nathan Rajlich <[email protected]> |
| 161 | +Copyright (c) 2017 Anna Henningsen <[email protected]> (N-API port) |
| 162 | + |
| 163 | +Permission is hereby granted, free of charge, to any person obtaining |
| 164 | +a copy of this software and associated documentation files (the |
| 165 | +'Software'), to deal in the Software without restriction, including |
| 166 | +without limitation the rights to use, copy, modify, merge, publish, |
| 167 | +distribute, sublicense, and/or sell copies of the Software, and to |
| 168 | +permit persons to whom the Software is furnished to do so, subject to |
| 169 | +the following conditions: |
| 170 | + |
| 171 | +The above copyright notice and this permission notice shall be |
| 172 | +included in all copies or substantial portions of the Software. |
| 173 | + |
| 174 | +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, |
| 175 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 176 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 177 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 178 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 179 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 180 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 181 | + |
| 182 | +[docs]: http://tootallnate.github.com/ref |
0 commit comments