Last active
August 29, 2015 14:14
-
-
Save shibukawa/18c04fce35eda662edaa to your computer and use it in GitHub Desktop.
memcpy for JS
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
var endIndex = srcIndex + length; | |
while (srcIndex < endIndex) { | |
buffer[dstIndex++] = buffer[srcIndex++]; | |
} |
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
var length = 200; | |
function makeBuffer() { | |
var array = []; | |
for (var i = 0; i < length; i++) { | |
array[i] = i; | |
} | |
return array; | |
} | |
function memcpy(array, srcIndex, dstIndex, length) { | |
if ((dstIndex - srcIndex) < length) { | |
copyUint8(array, srcIndex, dstIndex, length); | |
return; | |
} | |
switch ((srcIndex % 4) * 4 + dstIndex % 4) { | |
case 0: // 0 vs 0 | |
copyUint32(array, srcIndex >>> 2, dstIndex >>> 2, length >>> 2); | |
switch (length % 4) { | |
case 1: | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
case 2: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
break; | |
case 3: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 1: // 0 vs 1 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 2: // 0 vs 2 | |
copyUint16(array, srcIndex >>> 1, dstIndex >>> 1, length >>> 1); | |
if (length % 2) { | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
} | |
break; | |
case 3: // 0 vs 3 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 4: // 1 vs 0 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 5: // 1 vs 1 | |
array[dstIndex] = array[srcIndex]; | |
copyUint16(array, (srcIndex + 1) >>> 1, (dstIndex + 1 ) >>> 1, 1); | |
copyUint32(array, (3 + srcIndex) >>> 2, (3 + dstIndex >>> 2), (length - 3) >>> 2); | |
switch (length % 4) { | |
case 0: | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
case 1: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
break; | |
case 2: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 6: // 1 vs 2 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 7: // 1 vs 3 | |
copyUint8(array, srcIndex, dstIndex, length); | |
array[dstIndex] = array[srcIndex]; | |
copyUint16(array, (1 + srcIndex) >>> 1, (1 + dstIndex) >>> 1, (length - 1) >>> 1); | |
if ((srcIndex + length) % 2) { | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
} | |
break; | |
case 8: // 2 vs 0 | |
copyUint16(array, srcIndex >>> 1, dstIndex >>> 1, length >>> 1); | |
if (length % 2) { | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
} | |
break; | |
case 9: // 2 vs 1 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 10: // 2 vs 2 | |
copyUint16(array, srcIndex >>> 1, dstIndex >>> 1, 1); | |
copyUint32(array, (2 + srcIndex) >>> 2, (2 + dstIndex >>> 2), (length - 2) >>> 2); | |
switch (length % 4) { | |
case 0: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
break; | |
case 1: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
case 3: | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 11: // 2 vs 3 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 12: // 3 vs 0 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 13: // 3 vs 1 | |
copyUint8(array, srcIndex, dstIndex, length); | |
array[dstIndex] = array[srcIndex]; | |
copyUint16(array, (1 + srcIndex) >>> 1, (1 + dstIndex) >>> 1, (length - 1) >>> 1); | |
if ((srcIndex + length) % 2) { | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
} | |
break; | |
case 14: // 3 vs 2 | |
copyUint8(array, srcIndex, dstIndex, length); | |
break; | |
case 15: // 3 vs 3 | |
array[dstIndex] = array[srcIndex]; | |
copyUint32(array, (1 + srcIndex) >>> 2, (1 + dstIndex >>> 2), (length - 1) >>> 2); | |
switch (length % 4) { | |
case 0: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
case 2: | |
array[dstIndex + length - 1] = array[srcIndex + length - 1]; | |
break; | |
case 3: | |
copyUint16(array, (srcIndex + length - 2) >>> 1, (dstIndex + length - 2) >>> 1, 1); | |
break; | |
} | |
break; | |
} | |
} | |
function copyUint8(array, srcIndex, dstIndex, length) { | |
var endIndex = srcIndex + length; | |
while(srcIndex < endIndex) { | |
array[dstIndex++] = array[srcIndex++]; | |
} | |
} | |
function copyUint16(array, srcIndex, dstIndex, length) { | |
var srcIndex = srcIndex * 2; | |
var dstIndex = dstIndex * 2; | |
var endIndex = srcIndex + length * 2; | |
while(srcIndex < endIndex) { | |
array[dstIndex++] = array[srcIndex++]; | |
} | |
} | |
function copyUint32(array, srcIndex, dstIndex, length) { | |
var srcIndex = srcIndex * 4; | |
var dstIndex = dstIndex * 4; | |
var endIndex = srcIndex + length * 4; | |
while(srcIndex < endIndex) { | |
array[dstIndex++] = array[srcIndex++]; | |
} | |
} | |
function dump(src, dst, l, array1, array2) { | |
console.log("src:", src, "dst:", dst, "length:", l); | |
console.log("memcpy:", array1.join(", ")); | |
console.log("original :", array2.join(", ")); | |
console.log("\n"); | |
} | |
function compare(src, dst, l, array1, array2) { | |
for (var i = 0; i < length; i++) { | |
if (array1[i] !== array2[i]) { | |
dump(src, dst, l, array1, array2); | |
return; | |
} | |
} | |
} | |
function test(callback) { | |
for (var s=0; s < length - 8; s++) { | |
for (var l=4; l * 2 + s < length; l++) { | |
for (var o=0; l + s + o < length; o++) { | |
var src = s; | |
var dst = s + o; | |
callback(src, dst, l); | |
} | |
} | |
} | |
} | |
test(function(src, dst, l) { | |
var buffer1 = makeBuffer(); | |
var buffer2 = makeBuffer(); | |
memcpy(buffer1, src, dst, l); | |
copyUint8(buffer2, src, dst, l); | |
compare(src, dst, l, buffer1, buffer2); | |
}); |
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
/* | |
* Copy memory block within same ArrayBuffer like ArrayBuffer.copyWithin() | |
*/ | |
function _memcpy(output8 : Uint8Array, output16 : Uint16Array, output32 : Uint32Array, dstIndex : int, srcIndex : int, length : int) : void { | |
if ((dstIndex - srcIndex) < length) { | |
var endIndex = srcIndex + length; | |
while (srcIndex < endIndex) { | |
output8[dstIndex++] = output8[srcIndex++]; | |
} | |
return; | |
} | |
switch ((srcIndex % 4) * 4 + dstIndex % 4) { | |
case 1: // 0 vs 1 | |
case 3: // 0 vs 3 | |
case 4: // 1 vs 0 | |
case 6: // 1 vs 2 | |
case 9: // 2 vs 1 | |
case 11: // 2 vs 3 | |
case 12: // 3 vs 0 | |
case 14: // 3 vs 2 | |
var endIndex = srcIndex + length; | |
while (srcIndex < endIndex) { | |
output8[dstIndex++] = output8[srcIndex++]; | |
} | |
break; | |
case 2: // 0 vs 2 | |
case 8: // 2 vs 0 | |
var dstIndex2 = dstIndex >>> 1; | |
var srcIndex2 = srcIndex >>> 1; | |
var endIndex2 = srcIndex2 + (length >>> 1); | |
while (srcIndex2 < endIndex2) { | |
output16[dstIndex2++] = output16[srcIndex2++]; | |
} | |
if (length % 2) { | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
} | |
break; | |
case 7: // 1 vs 3 | |
case 13: // 3 vs 1 | |
output8[dstIndex] = output8[srcIndex]; | |
var dstIndex2 = (1 + dstIndex) >>> 1; | |
var srcIndex2 = (1 + srcIndex) >>> 1; | |
var endIndex2 = srcIndex2 + ((length - 1) >>> 1); | |
while (srcIndex2 < endIndex2) { | |
output16[dstIndex2++] = output16[srcIndex2++]; | |
} | |
if ((srcIndex + length) % 2) { | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
} | |
break; | |
case 0: // 0 vs 0 | |
var dstIndex4 = dstIndex >>> 2; | |
var srcIndex4 = srcIndex >>> 2; | |
var endIndex4 = srcIndex4 + (length >>> 2); | |
while (srcIndex4 < endIndex4) { | |
output32[dstIndex4++] = output32[srcIndex4++]; | |
} | |
switch (length % 4) { | |
case 1: | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
case 2: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
break; | |
case 3: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 5: // 1 vs 1 | |
output8[dstIndex] = output8[srcIndex]; | |
output16[(dstIndex + 1) >>> 1] = output16[(srcIndex + 1) >>> 1]; | |
var dstIndex4 = (3 + dstIndex) >>> 2; | |
var srcIndex4 = (3 + srcIndex) >>> 2; | |
var endIndex4 = srcIndex4 + ((length - 3) >>> 2); | |
while (srcIndex4 < endIndex4) { | |
output32[dstIndex4++] = output32[srcIndex4++]; | |
} | |
switch (length % 4) { | |
case 0: | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
case 1: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
break; | |
case 2: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 10: // 2 vs 2 | |
output16[dstIndex >>> 1] = output16[srcIndex >>> 1]; | |
var dstIndex4 = (2 + dstIndex) >>> 2; | |
var srcIndex4 = (2 + srcIndex) >>> 2; | |
var endIndex4 = srcIndex4 + ((length - 2) >>> 2); | |
while (srcIndex4 < endIndex4) { | |
output32[dstIndex4++] = output32[srcIndex4++]; | |
} | |
switch (length % 4) { | |
case 0: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
break; | |
case 1: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
case 3: | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
} | |
break; | |
case 15: // 3 vs 3 | |
output8[dstIndex] = output8[srcIndex]; | |
var dstIndex4 = (1 + dstIndex) >>> 2; | |
var srcIndex4 = (1 + srcIndex) >>> 2; | |
var endIndex4 = srcIndex4 + ((length - 1) >>> 2); | |
while (srcIndex4 < endIndex4) { | |
output32[dstIndex4++] = output32[srcIndex4++]; | |
} | |
switch (length % 4) { | |
case 0: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
case 2: | |
output8[dstIndex + length - 1] = output8[srcIndex + length - 1]; | |
break; | |
case 3: | |
output16[(dstIndex + length - 2) >>> 1] = output16[(srcIndex + length - 2) >>> 1]; | |
break; | |
} | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment