Source code

Revision control

Copy as Markdown

Other Tools

load(libdir + 'asserts.js');
function typedArrayMatchesString(ta, str, uptoStringLength = false) {
if (ta.length != str.length && !uptoStringLength)
return false;
for (let i = 0; i < str.length; i++) {
if (ta[i] != str.charCodeAt(i))
return false;
}
return true;
}
function test() {
// Check that {signed,unsigned} -> {Int*Array, Uint*Array} for string types.
const shortU8 = ctypes.unsigned_char.array(10)("abc\0\0\0\0\0\0\0").readTypedArray();
assertEq(shortU8 instanceof Uint8Array, true);
assertEq(typedArrayMatchesString(shortU8, "abc\0\0\0\0\0\0\0"), true);
const shortI8 = ctypes.signed_char.array(10)("abc\0\0\0\0\0\0\0").readTypedArray();
assertEq(shortI8 instanceof Int8Array, true);
assertEq(typedArrayMatchesString(shortI8, "abc\0\0\0\0\0\0\0"), true);
const shortU16 = ctypes.char16_t.array(10)("千").readTypedArray();
assertEq(shortU16 instanceof Uint16Array, true);
assertEq(typedArrayMatchesString(shortU16, "千", 'ignore zero-padding, please'), true);
// ...and for (other) numeric types.
const I16 = ctypes.int16_t.array(10)().readTypedArray();
assertEq(I16 instanceof Int16Array, true);
const U32 = ctypes.uint32_t.array(10)().readTypedArray();
assertEq(U32 instanceof Uint32Array, true);
const I32 = ctypes.int32_t.array(10)().readTypedArray();
assertEq(I32 instanceof Int32Array, true);
// Check that pointers without associated length get truncated to strlen().
const unsignedCharArray = ctypes.unsigned_char.array(10)("abc\0\0\0");
const shortU8cs = unsignedCharArray.addressOfElement(0).readTypedArray();
assertEq(shortU8cs instanceof Uint8Array, true);
assertEq(shortU8cs.length, 3);
assertEq(typedArrayMatchesString(shortU8cs, "abc", 'stop at NUL, please'), true);
const signedCharArray = ctypes.signed_char.array(10)("abc\0\0\0");
const shortI8cs = signedCharArray.addressOfElement(0).readTypedArray();
assertEq(shortI8cs instanceof Int8Array, true);
assertEq(shortI8cs.length, 3);
assertEq(typedArrayMatchesString(shortI8cs, "abc", 'stop at NUL, please'), true);
const char16Array = ctypes.char16_t.array(10)("千\0");
const shortU16cs = char16Array.addressOfElement(0).readTypedArray();
assertEq(shortU16cs instanceof Uint16Array, true);
assertEq(shortU16cs.length, 1);
assertEq(typedArrayMatchesString(shortU16cs, "千", 'ignore zero-padding, please'), true);
// Other types should just fail if the length is not known.
assertTypeErrorMessage(() => { ctypes.int32_t.array(3)().addressOfElement(0).readTypedArray(); },
/base type .* is not an 8-bit or 16-bit integer or character type/);
assertTypeErrorMessage(() => { ctypes.float.array(3)().addressOfElement(0).readTypedArray(); },
/base type .* is not an 8-bit or 16-bit integer or character type/);
assertTypeErrorMessage(() => { ctypes.double.array(3)().addressOfElement(0).readTypedArray(); },
/base type .* is not an 8-bit or 16-bit integer or character type/);
// char16_t is unsigned, so this is not a string type.
assertTypeErrorMessage(() => { ctypes.int16_t.array(3)().addressOfElement(0).readTypedArray(); },
/base type .* is not an 8-bit or 16-bit integer or character type/);
// Wide string -> bytes -> UTF-8 encoded string in typed array
const input2 = "千千千千千千千千千千千千千千千千千千千千千千千千千";
const encoded = ctypes.char.array(input2.length * 3)(input2).readTypedArray();
// Each 千 character is encoded as 3 bytes.
assertEq(encoded.length, input2.length * 3);
// Wide string -> char16_t -> 16-bit encoded string in typed array
const encoded16 = ctypes.char16_t.array(input2.length)(input2).readTypedArray();
assertEq(encoded16.length, input2.length);
// Floats
const floats = ctypes.float.array(3)([10, 20, 30]).readTypedArray();
assertEq(floats instanceof Float32Array, true);
assertEq(floats.toString(), "10,20,30");
const doubles = ctypes.double.array(3)([10, 20, 30]).readTypedArray();
assertEq(doubles instanceof Float64Array, true);
assertEq(doubles.toString(), "10,20,30");
// Invalid
assertTypeErrorMessage(() => { ctypes.int64_t.array(3)([10, 20, 30]).readTypedArray() },
/base type ctypes.int64_t.array.*is not compatible with a typed array element type/);
}
if (typeof ctypes === "object")
test();