“初始化俯视角工程,带puerts,未编过”
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms.
|
||||
* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package.
|
||||
*/
|
||||
|
||||
const ffi_bindings = require('ffi_bindings');
|
||||
const typeInfo = require('type').typeInfo;
|
||||
const pointer = typeInfo('pointer');
|
||||
const ffi_call = ffi_bindings.ffi_call;
|
||||
const UTF8Length = ffi_bindings.UTF8Length;
|
||||
const writeUTF8String = ffi_bindings.writeUTF8String;
|
||||
const readUTF8String = ffi_bindings.readUTF8String;
|
||||
|
||||
function stringToCString(str) {
|
||||
let buffLen = UTF8Length(str);
|
||||
let buff = new Uint8Array(buffLen + 1);
|
||||
writeUTF8String(buff, str);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
function id(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
function allocCif(returnType, parameterTypes, abi, fixArgNum) {
|
||||
let param_ffi_types = parameterTypes.map(t => t.ffi_type);
|
||||
|
||||
let cifPtr = new Uint8Array(ffi_bindings.FFI_CIF_SIZE);
|
||||
let status
|
||||
if (typeof fixArgNum === 'number') {
|
||||
status = ffi_bindings.ffi_prep_cif_var(cifPtr, abi, fixArgNum, parameterTypes.length, returnType.ffi_type, pointer.alloc(...param_ffi_types));
|
||||
} else {
|
||||
status = ffi_bindings.ffi_prep_cif(cifPtr, abi, parameterTypes.length, returnType.ffi_type, pointer.alloc(...param_ffi_types));
|
||||
}
|
||||
if (status != 0) {
|
||||
throw new Error(`call ffi_prep_cif fail, status=${status}`);
|
||||
}
|
||||
return cifPtr;
|
||||
}
|
||||
|
||||
function binding(func, abi, returnType, parameterTypes, fixArgNum) {
|
||||
if (typeof abi !== 'number') {
|
||||
fixArgNum = parameterTypes;
|
||||
parameterTypes = returnType;
|
||||
returnType = abi;
|
||||
abi = ffi_bindings.FFI_DEFAULT_ABI;
|
||||
}
|
||||
|
||||
const argsProcessers = parameterTypes.map(t => t === 'cstring' ? stringToCString : id);
|
||||
const resultProcesser = returnType === 'cstring' ? readUTF8String : id;
|
||||
returnType = typeInfo(returnType);
|
||||
parameterTypes = parameterTypes.map(t => typeInfo(t));
|
||||
const cifPtr = allocCif(returnType, parameterTypes, abi, fixArgNum);
|
||||
let argPtrs = parameterTypes.map(t => t.alloc());
|
||||
let retPtr = returnType.alloc();
|
||||
const ffi_call_args = pointer.alloc(...argPtrs);
|
||||
const expectArgNum = parameterTypes.length;
|
||||
|
||||
function wrap(...args) {
|
||||
if (args.length != expectArgNum) {
|
||||
throw new Error(`expect ${expectArgNum} argument but got ${args.length}`);
|
||||
}
|
||||
for (var i = 0; i < expectArgNum; i++) {
|
||||
args[i] = argsProcessers[i](args[i]);
|
||||
parameterTypes[i].write(argPtrs[i], args[i]);
|
||||
}
|
||||
ffi_call(cifPtr, func, retPtr, ffi_call_args);
|
||||
return resultProcesser(returnType.read(retPtr));
|
||||
}
|
||||
return wrap;
|
||||
}
|
||||
|
||||
function allocClosure(func, abi, returnType, parameterTypes) {
|
||||
if (typeof abi !== 'number') {
|
||||
parameterTypes = returnType;
|
||||
returnType = abi;
|
||||
abi = ffi_bindings.FFI_DEFAULT_ABI;
|
||||
}
|
||||
returnType = typeInfo(returnType);
|
||||
parameterTypes = parameterTypes.map(t => typeInfo(t));
|
||||
const cifPtr = allocCif(returnType, parameterTypes, abi);
|
||||
|
||||
return ffi_bindings.ffi_alloc_closure(cifPtr, function(retPtr, argPtrs) {
|
||||
try {
|
||||
var args = [];
|
||||
for (var i = 0; i < parameterTypes.length; i++) {
|
||||
var argPtr = pointer.read(argPtrs, i * pointer.size, parameterTypes[i].size);
|
||||
args.push(parameterTypes[i].read(argPtr));
|
||||
}
|
||||
var result = func.apply(null, args);
|
||||
returnType.write(retPtr, result);
|
||||
} catch (e) {
|
||||
console.error('js callback exception, msg=', e);
|
||||
}
|
||||
}, returnType.size);
|
||||
}
|
||||
|
||||
function nativeFunctionPtr(cl) {
|
||||
return pointer.read(cl);
|
||||
}
|
||||
|
||||
function freeClosure(cl) {
|
||||
ffi_bindings.ffi_free_closure(cl);
|
||||
}
|
||||
|
||||
exports.binding = binding;
|
||||
exports.closure = {
|
||||
alloc: allocClosure,
|
||||
func: nativeFunctionPtr,
|
||||
free: freeClosure
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms.
|
||||
* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package.
|
||||
*/
|
||||
|
||||
function validateNumber(value, type) {
|
||||
if (typeof value !== 'number')
|
||||
throw new Error(type + " expect an number but got " + value);
|
||||
}
|
||||
|
||||
function boundsError(value, length, type) {
|
||||
if (Math.floor(value) !== value) {
|
||||
validateNumber(value, type);
|
||||
throw new Error((type || 'offset') + ' expect an integer but got ' + value);
|
||||
}
|
||||
|
||||
if (length < 0)
|
||||
throw new Error("out of bound");
|
||||
|
||||
throw new Error(type || 'offset' +
|
||||
`expect >= ${type ? 1 : 0} and <= ${length} but got` + value);
|
||||
}
|
||||
|
||||
function checkBounds(buf, offset, byteLength) {
|
||||
validateNumber(offset, 'offset');
|
||||
if (buf[offset] === undefined || buf[offset + byteLength] === undefined)
|
||||
boundsError(offset, buf.length - (byteLength + 1));
|
||||
}
|
||||
|
||||
|
||||
function writeU_Int8(buf, value, offset, min, max) {
|
||||
value = +value;
|
||||
// `checkInt()` can not be used here because it checks two entries.
|
||||
validateNumber(offset, 'offset');
|
||||
if (value > max || value < min) {
|
||||
throw new Error(`value expect >= ${min} and <= ${max} but got ` + value);
|
||||
}
|
||||
if (buf[offset] === undefined)
|
||||
boundsError(offset, buf.length - 1);
|
||||
|
||||
buf[offset] = value;
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
function readInt8(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const val = buff[offset];
|
||||
if (val === undefined)
|
||||
boundsError(offset, buff.length - 1);
|
||||
|
||||
return val | (val & 2 ** 7) * 0x1fffffe;
|
||||
}
|
||||
|
||||
function writeInt8(buf, value, offset = 0) {
|
||||
return writeU_Int8(buf, value, offset, -0x80, 0x7f);
|
||||
}
|
||||
|
||||
function readUInt8(offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const val = this[offset];
|
||||
if (val === undefined)
|
||||
boundsError(offset, this.length - 1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
function writeUInt8(value, offset = 0) {
|
||||
return writeU_Int8(this, value, offset, 0, 0xff);
|
||||
}
|
||||
|
||||
const int16Array = new Int16Array(1);
|
||||
const uInt8Int6Array = new Uint8Array(int16Array.buffer);
|
||||
|
||||
function readInt16(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 1];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 2);
|
||||
|
||||
uInt8Int6Array[0] = first;
|
||||
uInt8Int6Array[1] = last;
|
||||
return int16Array[0];
|
||||
}
|
||||
|
||||
function writeInt16(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 1);
|
||||
|
||||
int16Array[0] = val;
|
||||
buff[offset++] = uInt8Int6Array[0];
|
||||
buff[offset++] = uInt8Int6Array[1];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const uint16Array = new Uint16Array(1);
|
||||
const uint8Uint16Array = new Uint8Array(uint16Array.buffer);
|
||||
|
||||
function readUInt16(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 1];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 2);
|
||||
|
||||
uint8Uint16Array[0] = first;
|
||||
uint8Uint16Array[1] = last;
|
||||
return uint16Array[0];
|
||||
}
|
||||
|
||||
function writeUInt16(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 1);
|
||||
|
||||
uint16Array[0] = val;
|
||||
buff[offset++] = uint8Uint16Array[0];
|
||||
buff[offset++] = uint8Uint16Array[1];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const int32Array = new Int32Array(1);
|
||||
const uint8Int32Array = new Uint8Array(int32Array.buffer);
|
||||
|
||||
function readInt32(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 3];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 4);
|
||||
|
||||
uint8Int32Array[0] = first;
|
||||
uint8Int32Array[1] = buff[++offset];
|
||||
uint8Int32Array[2] = buff[++offset];
|
||||
uint8Int32Array[3] = last;
|
||||
return int32Array[0];
|
||||
}
|
||||
|
||||
function writeInt32(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 3);
|
||||
|
||||
int32Array[0] = val;
|
||||
buff[offset++] = uint8Int32Array[0];
|
||||
buff[offset++] = uint8Int32Array[1];
|
||||
buff[offset++] = uint8Int32Array[2];
|
||||
buff[offset++] = uint8Int32Array[3];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const uint32Array = new Uint32Array(1);
|
||||
const uint8Uint32Array = new Uint8Array(uint32Array.buffer);
|
||||
|
||||
function readUInt32(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 3];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 4);
|
||||
|
||||
uint8Uint32Array[0] = first;
|
||||
uint8Uint32Array[1] = buff[++offset];
|
||||
uint8Uint32Array[2] = buff[++offset];
|
||||
uint8Uint32Array[3] = last;
|
||||
return uint32Array[0];
|
||||
}
|
||||
|
||||
function writeUInt32(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 3);
|
||||
|
||||
uint32Array[0] = val;
|
||||
buff[offset++] = uint8Uint32Array[0];
|
||||
buff[offset++] = uint8Uint32Array[1];
|
||||
buff[offset++] = uint8Uint32Array[2];
|
||||
buff[offset++] = uint8Uint32Array[3];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const float32Array = new Float32Array(1);
|
||||
const uInt8Float32Array = new Uint8Array(float32Array.buffer);
|
||||
|
||||
function readFloat(buff, offset = 0) {
|
||||
validateNumber(offset, 'offset');
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 3];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 4);
|
||||
|
||||
uInt8Float32Array[0] = first;
|
||||
uInt8Float32Array[1] = buff[++offset];
|
||||
uInt8Float32Array[2] = buff[++offset];
|
||||
uInt8Float32Array[3] = last;
|
||||
return float32Array[0];
|
||||
}
|
||||
|
||||
function writeFloat(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 3);
|
||||
|
||||
float32Array[0] = val;
|
||||
buff[offset++] = uInt8Float32Array[0];
|
||||
buff[offset++] = uInt8Float32Array[1];
|
||||
buff[offset++] = uInt8Float32Array[2];
|
||||
buff[offset++] = uInt8Float32Array[3];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const float64Array = new Float64Array(1);
|
||||
const uInt8Float64Array = new Uint8Array(float64Array.buffer);
|
||||
|
||||
function readDouble(buff, offset = 0) {
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 7];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 8);
|
||||
|
||||
uInt8Float64Array[0] = first;
|
||||
uInt8Float64Array[1] = buff[++offset];
|
||||
uInt8Float64Array[2] = buff[++offset];
|
||||
uInt8Float64Array[3] = buff[++offset];
|
||||
uInt8Float64Array[4] = buff[++offset];
|
||||
uInt8Float64Array[5] = buff[++offset];
|
||||
uInt8Float64Array[6] = buff[++offset];
|
||||
uInt8Float64Array[7] = last;
|
||||
return float64Array[0];
|
||||
}
|
||||
|
||||
function writeDouble(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
checkBounds(buff, offset, 7);
|
||||
|
||||
float64Array[0] = val;
|
||||
buff[offset++] = uInt8Float64Array[0];
|
||||
buff[offset++] = uInt8Float64Array[1];
|
||||
buff[offset++] = uInt8Float64Array[2];
|
||||
buff[offset++] = uInt8Float64Array[3];
|
||||
buff[offset++] = uInt8Float64Array[4];
|
||||
buff[offset++] = uInt8Float64Array[5];
|
||||
buff[offset++] = uInt8Float64Array[6];
|
||||
buff[offset++] = uInt8Float64Array[7];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const bigInt64Array = new BigInt64Array(1);
|
||||
const uint8BigInt64Array = new Uint8Array(bigInt64Array.buffer);
|
||||
|
||||
function readInt64(buff, offset = 0) {
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 7];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 8);
|
||||
|
||||
uint8BigInt64Array[0] = first;
|
||||
uint8BigInt64Array[1] = buff[++offset];
|
||||
uint8BigInt64Array[2] = buff[++offset];
|
||||
uint8BigInt64Array[3] = buff[++offset];
|
||||
uint8BigInt64Array[4] = buff[++offset];
|
||||
uint8BigInt64Array[5] = buff[++offset];
|
||||
uint8BigInt64Array[6] = buff[++offset];
|
||||
uint8BigInt64Array[7] = last;
|
||||
return bigInt64Array[0];
|
||||
}
|
||||
|
||||
function writeInt64(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
if (typeof val === 'number') val = BigInt(val);
|
||||
checkBounds(buff, offset, 7);
|
||||
|
||||
bigInt64Array[0] = val;
|
||||
buff[offset++] = uint8BigInt64Array[0];
|
||||
buff[offset++] = uint8BigInt64Array[1];
|
||||
buff[offset++] = uint8BigInt64Array[2];
|
||||
buff[offset++] = uint8BigInt64Array[3];
|
||||
buff[offset++] = uint8BigInt64Array[4];
|
||||
buff[offset++] = uint8BigInt64Array[5];
|
||||
buff[offset++] = uint8BigInt64Array[6];
|
||||
buff[offset++] = uint8BigInt64Array[7];
|
||||
return offset;
|
||||
}
|
||||
|
||||
const bigUint64Array = new BigUint64Array(1);
|
||||
const uint8BigUint64Array = new Uint8Array(bigUint64Array.buffer);
|
||||
|
||||
function readUInt64(buff, offset = 0) {
|
||||
const first = buff[offset];
|
||||
const last = buff[offset + 7];
|
||||
if (first === undefined || last === undefined)
|
||||
boundsError(offset, buff.length - 8);
|
||||
|
||||
uint8BigUint64Array[0] = first;
|
||||
uint8BigUint64Array[1] = buff[++offset];
|
||||
uint8BigUint64Array[2] = buff[++offset];
|
||||
uint8BigUint64Array[3] = buff[++offset];
|
||||
uint8BigUint64Array[4] = buff[++offset];
|
||||
uint8BigUint64Array[5] = buff[++offset];
|
||||
uint8BigUint64Array[6] = buff[++offset];
|
||||
uint8BigUint64Array[7] = last;
|
||||
return bigUint64Array[0];
|
||||
}
|
||||
|
||||
function writeUInt64(buff, val, offset = 0) {
|
||||
val = +val;
|
||||
if (typeof val === 'number') val = BigInt(val);
|
||||
checkBounds(buff, offset, 7);
|
||||
|
||||
bigUint64Array[0] = val;
|
||||
buff[offset++] = uint8BigUint64Array[0];
|
||||
buff[offset++] = uint8BigUint64Array[1];
|
||||
buff[offset++] = uint8BigUint64Array[2];
|
||||
buff[offset++] = uint8BigUint64Array[3];
|
||||
buff[offset++] = uint8BigUint64Array[4];
|
||||
buff[offset++] = uint8BigUint64Array[5];
|
||||
buff[offset++] = uint8BigUint64Array[6];
|
||||
buff[offset++] = uint8BigUint64Array[7];
|
||||
return offset;
|
||||
}
|
||||
|
||||
let ffi_bindings = require('ffi_bindings');
|
||||
|
||||
ffi_bindings.readInt8 = readInt8;
|
||||
ffi_bindings.readUInt8 = readUInt8;
|
||||
ffi_bindings.readInt16 = readInt16;
|
||||
ffi_bindings.readUInt16 = readUInt16;
|
||||
ffi_bindings.readInt32 = readInt32;
|
||||
ffi_bindings.readUInt32 = readUInt32;
|
||||
ffi_bindings.readInt64 = readInt64;
|
||||
ffi_bindings.readUInt64 = readUInt64;
|
||||
ffi_bindings.readFloat = readFloat;
|
||||
ffi_bindings.readDouble = readDouble;
|
||||
|
||||
ffi_bindings.writeInt8 = writeInt8;
|
||||
ffi_bindings.writeUInt8 = writeUInt8;
|
||||
ffi_bindings.writeInt16 = writeInt16;
|
||||
ffi_bindings.writeUInt16 = writeUInt16;
|
||||
ffi_bindings.writeInt32 = writeInt32;
|
||||
ffi_bindings.writeUInt32 = writeUInt32;
|
||||
ffi_bindings.writeInt64 = writeInt64;
|
||||
ffi_bindings.writeUInt64 = writeUInt64;
|
||||
ffi_bindings.writeFloat = writeFloat;
|
||||
ffi_bindings.writeDouble = writeDouble;
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms.
|
||||
* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package.
|
||||
*/
|
||||
|
||||
module.exports = require('ffi_bindings');
|
||||
module.exports.binding = require('binding').binding;
|
||||
module.exports.closure= require('binding').closure;
|
||||
module.exports.typeInfo = require('type').typeInfo;
|
||||
module.exports.makeStruct = require('type').makeStruct;
|
||||
module.exports.makePointer = require('type').makePointer;
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms.
|
||||
* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package.
|
||||
*/
|
||||
|
||||
let ffi_bindings = require('ffi_bindings');
|
||||
require('buffer-ext.js');
|
||||
|
||||
let primitiveTypes = Object.create(null);
|
||||
|
||||
Object.keys(ffi_bindings.sizeof).forEach(function (name) {
|
||||
let uname;
|
||||
if (name.startsWith("ui")) {
|
||||
uname = name.slice(0, 2).toUpperCase() + name.slice(2);
|
||||
} else {
|
||||
uname = name.charAt(0).toUpperCase() + name.slice(1);
|
||||
}
|
||||
primitiveTypes[name] = {
|
||||
ffi_type: ffi_bindings.FFI_TYPES[name],
|
||||
size: ffi_bindings.sizeof[name],
|
||||
align: ffi_bindings.alignof[name],
|
||||
write: ffi_bindings["write" + uname],
|
||||
read: ffi_bindings["read" + uname],
|
||||
set: set,
|
||||
get: get,
|
||||
alloc: alloc
|
||||
}
|
||||
});
|
||||
|
||||
primitiveTypes.cstring = primitiveTypes.pointer;
|
||||
function doNothing(){}
|
||||
primitiveTypes["void"] = {
|
||||
ffi_type: ffi_bindings.FFI_TYPES['void'],
|
||||
size: 0,
|
||||
align: 0,
|
||||
write: doNothing,
|
||||
read: doNothing,
|
||||
set: doNothing,
|
||||
get: doNothing,
|
||||
alloc: doNothing
|
||||
}
|
||||
|
||||
function typeInfo(t) {
|
||||
return (typeof t === 'string') ? primitiveTypes[t] : t;
|
||||
}
|
||||
|
||||
const pointer = primitiveTypes.pointer;
|
||||
|
||||
const sizeType = pointer.size == 4 ? "uint32" : "uint64";
|
||||
|
||||
primitiveTypes.size_t = {
|
||||
ffi_type: pointer.ffi_type,
|
||||
size: pointer.size,
|
||||
align: pointer.align,
|
||||
write: primitiveTypes[sizeType].write,
|
||||
read: primitiveTypes[sizeType].read,
|
||||
set: set,
|
||||
get: get,
|
||||
alloc: alloc
|
||||
}
|
||||
|
||||
function makePointer(t) {
|
||||
t = typeInfo(t);
|
||||
let ret = Object.assign({}, pointer);
|
||||
const orgRead = ret.read;
|
||||
function readTypedPointer(buffer, offset) {
|
||||
return orgRead(buffer, offset, t.size);
|
||||
}
|
||||
|
||||
function ref(value) {
|
||||
return t.alloc(value);
|
||||
}
|
||||
|
||||
function unref(buff) {
|
||||
return t.read(buff);
|
||||
}
|
||||
|
||||
ret.read = readTypedPointer;
|
||||
ret.ref = ref;
|
||||
ret.unref = unref;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function makeStruct(info, noFfiType) {
|
||||
function structType (buff, data) {
|
||||
if (!(this instanceof structType)) {
|
||||
return new structType(buff, data);
|
||||
}
|
||||
|
||||
if (!(buff instanceof Uint8Array)) {
|
||||
data = buff;
|
||||
buff = new Uint8Array(structType.size);
|
||||
}
|
||||
|
||||
this._buff = buff;
|
||||
if (data) {
|
||||
for (var key in data) {
|
||||
this[key] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function propertyDesc(name, type, offset) {
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return type.read(this._buff, offset);
|
||||
},
|
||||
set: function(value) {
|
||||
type.write(this._buff, value, offset);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
let structSize = 0;
|
||||
let structAlign = 0;
|
||||
let elem_ffi_types = [];
|
||||
|
||||
Object.keys(info).forEach(function (name) {
|
||||
fieldType = typeInfo(info[name]);
|
||||
const align = fieldType.align;
|
||||
const padding = (align - (structSize % align)) % align;
|
||||
const desc = propertyDesc(name, fieldType, structSize + padding);
|
||||
Object.defineProperty(structType.prototype, name, desc);
|
||||
structSize += (padding + fieldType.size);
|
||||
structAlign = Math.max(structAlign, align);
|
||||
elem_ffi_types.push(fieldType.ffi_type);
|
||||
});
|
||||
|
||||
var left = structSize % structAlign;
|
||||
if (left > 0) {
|
||||
structSize += structAlign - left;
|
||||
}
|
||||
structType.size = structSize;
|
||||
structType.align = structAlign;
|
||||
structType.read = structRead;
|
||||
structType.write = structWrite;
|
||||
structType.set = set;
|
||||
structType.get = get;
|
||||
structType.alloc = alloc;
|
||||
|
||||
if (!noFfiType) {
|
||||
let ffi_type = new FFI_TYPE();
|
||||
ffi_type.size = 0;
|
||||
ffi_type.alignment = 0;
|
||||
ffi_type.type = ffi_bindings.FFI_TYPE_STRUCT;
|
||||
|
||||
let elements = pointer.alloc(...elem_ffi_types, null);
|
||||
ffi_type.elements = elements;
|
||||
structType._elems_array = elements;//prevent gc;
|
||||
structType.ffi_type = ffi_type._buff;
|
||||
}
|
||||
|
||||
return structType;
|
||||
}
|
||||
|
||||
var FFI_TYPE = makeStruct({
|
||||
size: 'size_t',
|
||||
alignment: 'uint16',
|
||||
type: 'uint16',
|
||||
elements: 'pointer'
|
||||
}, true);
|
||||
|
||||
function structRead(buffer, offset) {
|
||||
if (typeof offset === 'number' && offset > 0) {
|
||||
buffer = new Uint8Array(buffer.buffer, offset);
|
||||
}
|
||||
return new this(buffer);
|
||||
}
|
||||
|
||||
function structWrite(buffer, value, offset) {
|
||||
if (value instanceof this) {
|
||||
let src = value._buff;
|
||||
if (typeof offset !== 'number') offset = 0;
|
||||
for(var i = 0; i < this.size; i++) {
|
||||
buffer[offset++] = src[i];
|
||||
}
|
||||
} else {
|
||||
if (typeof offset === 'number' && offset > 0) {
|
||||
buffer = new Uint8Array(buffer.buffer, offset);
|
||||
}
|
||||
new this(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
function set(buff, val, index) {
|
||||
this.write(buff, val, index * this.size);
|
||||
}
|
||||
|
||||
function get(buff, index) {
|
||||
return this.read(buff, index * this.size);
|
||||
}
|
||||
|
||||
function alloc(...values) {
|
||||
if (values.length == 0) return new Uint8Array(this.size);
|
||||
let buff = new Uint8Array(values.length * this.size);
|
||||
for(var i = 0; i < values.length; i++) {
|
||||
this.set(buff, values[i], i);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
exports.typeInfo = typeInfo;
|
||||
exports.makeStruct = makeStruct;
|
||||
exports.makePointer = makePointer;
|
||||
Reference in New Issue
Block a user