-
-
Save Noitidart/2d9b44b18493f9339629 to your computer and use it in GitHub Desktop.
_ff-addon-tutorial-JSCtypesMemmove - How to use memmove from js-ctypes. Tutorial by @nmaier.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cu.import('resource://gre/modules/ctypes.jsm'); | |
/* | |
* Alright then, lets start with copy array `a` into `b`, by reusing and modifying `memset`. | |
* Note: memset refered to is found here: http://stackoverflow.com/questions/24466228/memset-has-no-dll-so-how-ctype-it | |
*/ | |
function memcpy(dst, src, size) { | |
for (var i = 0; i < size; ++i) { | |
dst[i] = src[i]; | |
} | |
} | |
/* | |
* Now, thats nice, but does not actually make sure that the arrays have the same `CType`, better add a check for that. | |
*/ | |
function memcpy(dst, src, size) { | |
if (!dst.constructor.elementType && | |
dst.constructor.elementType != src.constructor.elementType) { | |
throw Error("Invalid CType: not an array, or array type mismatch"); | |
} | |
for (var i = 0; i < size; ++i) { | |
dst[i] = src[i]; | |
} | |
} | |
/* | |
* That would be in theory good enough and is a reasonable `memcpy` implementation (although we could test if both arrays are the same and skip the copy in that case). | |
* | |
* But we want [`memmove`](http://stackoverflow.com/a/3572519/484441), which makes sure that if the arrays overlap data will be still copied correctly. To do that, we need to compare the addresses and if `src.address() < dst.address()` then we'll need to copy back to front, else if `src.address() < dst.address()` then copy front to back, or if both are equal, it is actually the same array and we can skip the copy. | |
* | |
* So first, how do we compare pointers again? By some casting to a number and comparing the numbers. | |
* Note: Topic on comparing pointers: http://stackoverflow.com/a/24353278/1828637 | |
*/ | |
function comparePointers(a, b) { | |
return ctypes.UInt64.compare( | |
ctypes.cast(a, ctypes.uintptr_t).value, | |
ctypes.cast(b, ctypes.uintptr_t).value | |
); | |
} | |
/* | |
* Now, back to `memmove`: | |
*/ | |
function memmove(dst, src, size) { | |
if (!dst.constructor.elementType && | |
dst.constructor.elementType != src.constructor.elementType) { | |
throw Error("Invalid CType: not an array, or array type mismatch"); | |
} | |
let cmp = comparePointers(src.address(), dst.address()); | |
if (cmp == 0) { | |
// arrays point to the same memory location == are the same; skip | |
return; | |
} | |
if (cmp < 0) { // src < dst -> back to front | |
for (var i = size - 1; i >= 0; --i) { | |
dst[i] = src[i]; | |
} | |
return; | |
} | |
// else; src > dst -> front to back | |
for (var i = 0; i < size; ++i) { | |
dst[i] = src[i]; | |
} | |
} | |
/* | |
* Lets try it out. | |
*/ | |
// I chose uint8_t randomly, but it should work with all POD types. | |
// These cannot overlap, but that does not really matter | |
var src = ctypes.uint8_t.array(100)(); | |
memset(src, 0xee, src.length); | |
var dst = ctypes.uint8_t.array(90)(); | |
memset(dst, 0x33, dst.length); | |
console.log(src[0], dst[0]); | |
// Should be 0xee == 238; 0x33 = 51 | |
// Test 1; Copy a couple of bytes from src to dst | |
memmove(dst, src, 10); | |
console.log(dst[0], "==", src[0]); | |
console.log(dst[9], "==", src[9]); | |
console.log(dst[10], "!=", src[10]); | |
// Test2; Reset dst and copy dst to src | |
// This should trigger the other loop in memmove | |
memset(dst, 0x33, dst.length); | |
memmove(src, dst, 10); | |
console.log(dst[0], "==", src[0]); | |
console.log(dst[9], "==", src[9]); | |
console.log(dst[10], "!=", src[10]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
README
Rev1
Rev2
.js
and added inctypes.jsm
so when people search and are trying to target Firefox they will be able to find this gist_ff-addon-snippet
Rev3
ctypes.jsm
inRev2
so I did it nowRev4
_ff-addon-tutorial
as this is a tutorialmemset
SO Topic and Comparing Pointers SO Topic