From 9efaa018bd60fec9d29b81aab394824625e468bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Murias?= Date: Wed, 26 Dec 2018 15:09:50 +0100 Subject: [PATCH] [js] Implement nqp::writenum and nqp::readnum --- src/vm/js/Operations.nqp | 2 ++ src/vm/js/nqp-runtime/core.js | 63 +++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/vm/js/Operations.nqp b/src/vm/js/Operations.nqp index 23ba0bc03e..6975f6c9e0 100644 --- a/src/vm/js/Operations.nqp +++ b/src/vm/js/Operations.nqp @@ -1925,6 +1925,8 @@ class QAST::OperationsJS { add_simple_op('writeuint', $T_VOID, [$T_OBJ, $T_INT, $T_UINT32, $T_INT], :side_effects); add_simple_op('readint', $T_INT, [$T_OBJ, $T_INT, $T_INT]); add_simple_op('readuint', $T_UINT32, [$T_OBJ, $T_INT, $T_INT]); + add_simple_op('writenum', $T_VOID, [$T_OBJ, $T_INT, $T_NUM, $T_INT], :side_effects); + add_simple_op('readnum', $T_NUM, [$T_OBJ, $T_INT, $T_INT]); method add_hll_unbox($hll, $type, $method_name) { unless nqp::existskey(%hll_unbox, $hll) { diff --git a/src/vm/js/nqp-runtime/core.js b/src/vm/js/nqp-runtime/core.js index 7ae584e972..a00171a6d8 100644 --- a/src/vm/js/nqp-runtime/core.js +++ b/src/vm/js/nqp-runtime/core.js @@ -1138,15 +1138,23 @@ function sizeFromFlags(flags) { } else if (sizeFlags == BINARY_SIZE_32_BIT) { return 4; } else if (sizeFlags == BINARY_SIZE_64_BIT) { - throw new NQPException('64bit writeint is not supported'); + return 8; } else { throw new NQPException('unsupported flags: ' + flags); } } +function intSizeFromFlags(flags) { + const size = sizeFromFlags(flags); + if (size === 8) { + throw new NQPException('BINARY_SIZE_64_BIT for (u)ints is not supported'); + } + return size; +} + function writeIntToBuffer(isSigned, buffer, offset, value, flags) { - const sizeInBytes = sizeFromFlags(flags); + const sizeInBytes = intSizeFromFlags(flags); const lowlevelBuffer = Buffer.alloc(sizeInBytes); const isBigEndian = isBigEndianFromFlags(flags); @@ -1181,11 +1189,60 @@ op.writeuint = function(buffer, offset, value, flags) { }; op.readuint = function(buffer, offset, flags) { - const sizeInBytes = sizeFromFlags(flags); + const sizeInBytes = intSizeFromFlags(flags); const rawData = rawSlice(buffer, offset, offset + sizeInBytes / byteSize(buffer)); return isBigEndianFromFlags(flags) ? rawData.readUIntBE(0, sizeInBytes) : rawData.readUIntLE(0, sizeInBytes); }; +op.writenum = function(buffer, offset, value, flags) { + const isBigEndian = isBigEndianFromFlags(flags); + + const sizeInBytes = sizeFromFlags(flags); + const lowlevelBuffer = Buffer.alloc(sizeInBytes); + + if (sizeInBytes == 4) { + if (isBigEndian) { + lowlevelBuffer.writeFloatBE(value, 0); + } else { + lowlevelBuffer.writeFloatLE(value, 0); + } + } else if (sizeInBytes == 8) { + if (isBigEndian) { + lowlevelBuffer.writeDoubleBE(value, 0); + } else { + lowlevelBuffer.writeDoubleLE(value, 0); + } + } else { + throw new NQPException('unsupported size: ' + sizeInBytes*8 + 'bits'); + } + + writeBuffer(buffer, offset, lowlevelBuffer); + +}; + +op.readnum = function(buffer, offset, flags) { + const sizeInBytes = sizeFromFlags(flags); + const rawData = rawSlice(buffer, offset, offset + sizeInBytes / byteSize(buffer)); + const isBigEndian = isBigEndianFromFlags(flags); + + if (sizeInBytes == 4) { + if (isBigEndian) { + return rawData.readFloatBE(0); + } else { + return rawData.readFloatLE(0); + } + } else if (sizeInBytes == 8) { + if (isBigEndian) { + return rawData.readDoubleBE(0); + } else { + return rawData.readDoubleLE(0); + } + } else { + throw new NQPException('unsupported size: ' + sizeInBytes*8 + 'bits'); + } +}; + + op.encodeconf = function(str, encoding_, output, permissive) { if (output.array.length) { throw new NQPException('encode requires an empty array');