Alright then, lets start with copy array a
into b
, by reusing and modifying memset
.
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
, 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.
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]);
Awwww mann thanks!! I tried to figure out memmove by finding the python library implementation:
And on the py hg thing i cant manage to search that crap then i downloaded the whole repo then searched it. And came across:
http://hg.python.org/cpython/rev/c0f165e1dbc0
They removed it from python library or something so i was having the hardest time doing it :(
Thanks so much man!!