diff --git a/libraries/script-engine/src/DataViewClass.cpp b/libraries/script-engine/src/DataViewClass.cpp new file mode 100644 index 0000000000..7afd43e71c --- /dev/null +++ b/libraries/script-engine/src/DataViewClass.cpp @@ -0,0 +1,81 @@ +// +// DataViewClass.cpp +// +// +// Created by Clement on 7/8/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "DataViewPrototype.h" + +#include "DataViewClass.h" + +Q_DECLARE_METATYPE(QByteArray*) + +static const QString DATA_VIEW_NAME = "DataView"; + +DataViewClass::DataViewClass(QScriptEngine* engine) : ArrayBufferViewClass(engine) { + QScriptValue global = engine->globalObject(); + + // Save string handles for quick lookup + _name = engine->toStringHandle(DATA_VIEW_NAME.toLatin1()); + + // build prototype + _proto = engine->newQObject(new DataViewPrototype(this), + QScriptEngine::QtOwnership, + QScriptEngine::SkipMethodsInEnumeration | + QScriptEngine::ExcludeSuperClassMethods | + QScriptEngine::ExcludeSuperClassProperties); + + _proto.setPrototype(global.property("Object").property("prototype")); + + _ctor = engine->newFunction(construct, _proto); + _ctor.setData(engine->toScriptValue(this)); + + engine->globalObject().setProperty(name(), _ctor); +} + +QScriptValue DataViewClass::newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLentgh) { + QScriptValue data = engine()->newObject(); + data.setProperty(_bufferName, buffer); + data.setProperty(_byteOffsetName, byteOffset); + data.setProperty(_byteLengthName, byteLentgh); + + return engine()->newObject(this, data); +} + +QScriptValue DataViewClass::construct(QScriptContext *context, QScriptEngine *engine) { + DataViewClass* cls = qscriptvalue_cast(context->callee().data()); + if (!cls || context->argumentCount() < 1) { + return QScriptValue(); + } + + QScriptValue bufferArg = context->argument(0); + QScriptValue byteOffsetArg = (context->argumentCount() >= 2) ? context->argument(1) : QScriptValue(-1); + QScriptValue byteLengthArg = (context->argumentCount() >= 3) ? context->argument(2) : QScriptValue(-1); + + QByteArray* arrayBuffer = (bufferArg.isValid()) ? qscriptvalue_cast(bufferArg.data()) :NULL; + if (!arrayBuffer) { + return QScriptValue(); + } + + QScriptValue newObject = cls->newInstance(bufferArg, byteOffsetArg.toInt32(), byteLengthArg.toInt32()); + + if (context->isCalledAsConstructor()) { + context->setThisObject(newObject); + return engine->undefinedValue(); + } + + return newObject; +} + +QString DataViewClass::name() const { + return _name.toString(); +} + +QScriptValue DataViewClass::prototype() const { + return _proto; +} \ No newline at end of file diff --git a/libraries/script-engine/src/DataViewClass.h b/libraries/script-engine/src/DataViewClass.h new file mode 100644 index 0000000000..7e4d427f09 --- /dev/null +++ b/libraries/script-engine/src/DataViewClass.h @@ -0,0 +1,36 @@ +// +// DataViewClass.h +// +// +// Created by Clement on 7/8/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DataViewClass_h +#define hifi_DataViewClass_h + +#include "ArrayBufferViewClass.h" + +class DataViewClass : public ArrayBufferViewClass { + Q_OBJECT +public: + DataViewClass(QScriptEngine* engine); + QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset = -1, quint32 byteLength = -1); + + QString name() const; + QScriptValue prototype() const; + +private: + static QScriptValue construct(QScriptContext* context, QScriptEngine* engine); + + QScriptValue _proto; + QScriptValue _ctor; + + QScriptString _name; +}; + + +#endif // hifi_DataViewClass_h \ No newline at end of file diff --git a/libraries/script-engine/src/DataViewPrototype.cpp b/libraries/script-engine/src/DataViewPrototype.cpp new file mode 100644 index 0000000000..345df743b4 --- /dev/null +++ b/libraries/script-engine/src/DataViewPrototype.cpp @@ -0,0 +1,209 @@ +// +// DataViewPrototype.cpp +// +// +// Created by Clement on 7/8/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include + +#include + +#include "DataViewClass.h" + +#include "DataViewPrototype.h" + +Q_DECLARE_METATYPE(QByteArray*) + +DataViewPrototype::DataViewPrototype(QObject* parent) : QObject(parent) { +} + +QByteArray* DataViewPrototype::thisArrayBuffer() const { + QScriptValue bufferObject = thisObject().data().property(BUFFER_PROPERTY_NAME); + return qscriptvalue_cast(bufferObject.data()); +} + +bool DataViewPrototype::realOffset(quint32& offset, size_t size) const { + quint32 viewOffset = thisObject().data().property(BYTE_OFFSET_PROPERTY_NAME).toInt32(); + quint32 viewLength = thisObject().data().property(BYTE_LENGTH_PROPERTY_NAME).toInt32(); + qDebug() << "View Offset: " << viewOffset << ", View Lenght: " << viewLength; + qDebug() << "Offset: " << offset << ", Size: " << size; + offset += viewOffset; + qDebug() << "New offset: " << offset << ", bool: " << ((offset + size) <= viewOffset + viewLength); + return (offset + size) <= viewOffset + viewLength; +} + +///////////////// GETTERS //////////////////////////// + +qint8 DataViewPrototype::getInt8(quint32 byteOffset) { + if (realOffset(byteOffset, sizeof(qint8))) { + qDebug() << "Value: " << (qint8)thisArrayBuffer()->at(byteOffset); + + return (qint8)thisArrayBuffer()->at(byteOffset); + } + qDebug() << "42 powaaaa!!!"; + return 42; +} + +quint8 DataViewPrototype::getUint8(quint32 byteOffset) { + if (realOffset(byteOffset, sizeof(quint8))) { return thisArrayBuffer()->at(byteOffset); + } + return 42; +} + +qint16 DataViewPrototype::getInt16(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(qint16))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +quint16 DataViewPrototype::getUint16(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(quint16))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +qint32 DataViewPrototype::getInt32(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(qint32))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +quint32 DataViewPrototype::getUint32(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(quint32))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +float DataViewPrototype::getFloat32(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(float))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +double DataViewPrototype::getFloat64(quint32 byteOffset, bool littleEndian) { + if (realOffset(byteOffset, sizeof(double))) { + QDataStream stream(*thisArrayBuffer()); + stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian); + stream.skipRawData(byteOffset); + + qint16 result; + stream >> result; + return result; + } + return 42; +} + +///////////////// SETTERS //////////////////////////// + +void DataViewPrototype::setInt8(quint32 byteOffset, qint8 value) { + if (realOffset(byteOffset, sizeof(qint8))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setUint8(quint32 byteOffset, quint8 value) { + if (realOffset(byteOffset, sizeof(quint8))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setInt16(quint32 byteOffset, qint16 value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(qint16))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setUint16(quint32 byteOffset, quint16 value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(quint16))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setInt32(quint32 byteOffset, quint32 value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(qint32))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setUint32(quint32 byteOffset, quint32 value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(quint32))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setFloat32(quint32 byteOffset, float value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(float))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + +void DataViewPrototype::setFloat64(quint32 byteOffset, double value, bool littleEndian) { + if (realOffset(byteOffset, sizeof(double))) { + QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); + stream.skipRawData(byteOffset); + + stream << value; + } +} + + diff --git a/libraries/script-engine/src/DataViewPrototype.h b/libraries/script-engine/src/DataViewPrototype.h new file mode 100644 index 0000000000..a024e8938f --- /dev/null +++ b/libraries/script-engine/src/DataViewPrototype.h @@ -0,0 +1,68 @@ +// +// DataViewPrototype.h +// +// +// Created by Clement on 7/8/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DataViewPrototype_h +#define hifi_DataViewPrototype_h + +#include +#include + +class DataViewPrototype : public QObject, public QScriptable { + Q_OBJECT +public: + DataViewPrototype(QObject* parent = NULL); + +public slots: + // Gets the value of the given type at the specified byte offset + // from the start of the view. There is no alignment constraint; + // multi-byte values may be fetched from any offset. + // + // For multi-byte values, the optional littleEndian argument + // indicates whether a big-endian or little-endian value should be + // read. If false or undefined, a big-endian value is read. + // + // These methods raise an exception if they would read + // beyond the end of the view. + qint8 getInt8(quint32 byteOffset); + quint8 getUint8(quint32 byteOffset); + qint16 getInt16(quint32 byteOffset, bool littleEndian = false); + quint16 getUint16(quint32 byteOffset, bool littleEndian = false); + qint32 getInt32(quint32 byteOffset, bool littleEndian = false); + quint32 getUint32(quint32 byteOffset, bool littleEndian = false); + float getFloat32(quint32 byteOffset, bool littleEndian = false); + double getFloat64(quint32 byteOffset, bool littleEndian = false); + + // Stores a value of the given type at the specified byte offset + // from the start of the view. There is no alignment constraint; + // multi-byte values may be stored at any offset. + // + // For multi-byte values, the optional littleEndian argument + // indicates whether the value should be stored in big-endian or + // little-endian byte order. If false or undefined, the value is + // stored in big-endian byte order. + // + // These methods raise an exception if they would write + // beyond the end of the view. + void setInt8(quint32 byteOffset, qint8 value); + void setUint8(quint32 byteOffset, quint8 value); + void setInt16(quint32 byteOffset, qint16 value, bool littleEndian = false); + void setUint16(quint32 byteOffset, quint16 value, bool littleEndian = false); + void setInt32(quint32 byteOffset, quint32 value, bool littleEndian = false); + void setUint32(quint32 byteOffset, quint32 value, bool littleEndian = false); + void setFloat32(quint32 byteOffset, float value, bool littleEndian = false); + void setFloat64(quint32 byteOffset, double value, bool littleEndian = false); + +private: + QByteArray* thisArrayBuffer() const; + bool realOffset(quint32& offset, size_t size) const; +}; + +#endif // hifi_DataViewPrototype_h \ No newline at end of file