summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/datamodel/ecmascript
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-09-02 10:09:43 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-09-02 10:09:43 (GMT)
commit9caba3540b4d64a5277040f43bdaabde7ba227a0 (patch)
tree2712243810a35adb7c89a560d78eada632ce442e /src/uscxml/plugins/datamodel/ecmascript
parentddd9db10907ee4cee6c44b24b96d81b062521752 (diff)
downloaduscxml-9caba3540b4d64a5277040f43bdaabde7ba227a0.zip
uscxml-9caba3540b4d64a5277040f43bdaabde7ba227a0.tar.gz
uscxml-9caba3540b4d64a5277040f43bdaabde7ba227a0.tar.bz2
Support for endianness in DataView
Diffstat (limited to 'src/uscxml/plugins/datamodel/ecmascript')
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp48
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCArrayBuffer.h6
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCTypedArrayCustom.cpp12
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/TypedArray.cpp142
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/TypedArray.h410
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp38
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8ArrayBuffer.h3
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8TypedArrayCustom.cpp18
8 files changed, 542 insertions, 135 deletions
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index f8e0479..c5aec92 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -292,32 +292,32 @@ JSValueRef JSCDataModel::getDataAsValue(const Data& data) {
handleException(exception);
return value;
}
-
+
switch (data.type) {
- case Data::VERBATIM: {
- JSStringRef stringRef = JSStringCreateWithUTF8CString(data.atom.c_str());
- JSValueRef value = JSValueMakeString(_ctx, stringRef);
- JSStringRelease(stringRef);
- return value;
- break;
- }
- case Data::INTERPRETED: {
- return evalAsValue(data.atom);
- break;
- }
- case Data::BINARY: {
- uscxml::ArrayBuffer* localInstance = new uscxml::ArrayBuffer((void*)data.atom.c_str(), data.atom.size());
-
- JSClassRef retClass = JSCArrayBuffer::getTmpl();
- struct JSCArrayBuffer::JSCArrayBufferPrivate* retPrivData = new JSCArrayBuffer::JSCArrayBufferPrivate();
- retPrivData->nativeObj = localInstance;
-
- JSObjectRef retObj = JSObjectMake(_ctx, retClass, retPrivData);
- return retObj;
- break;
- }
+ case Data::VERBATIM: {
+ JSStringRef stringRef = JSStringCreateWithUTF8CString(data.atom.c_str());
+ JSValueRef value = JSValueMakeString(_ctx, stringRef);
+ JSStringRelease(stringRef);
+ return value;
+ break;
}
-
+ case Data::INTERPRETED: {
+ return evalAsValue(data.atom);
+ break;
+ }
+ case Data::BINARY: {
+ uscxml::ArrayBuffer* localInstance = new uscxml::ArrayBuffer((void*)data.atom.c_str(), data.atom.size());
+
+ JSClassRef retClass = JSCArrayBuffer::getTmpl();
+ struct JSCArrayBuffer::JSCArrayBufferPrivate* retPrivData = new JSCArrayBuffer::JSCArrayBufferPrivate();
+ retPrivData->nativeObj = localInstance;
+
+ JSObjectRef retObj = JSObjectMake(_ctx, retClass, retPrivData);
+ return retObj;
+ break;
+ }
+ }
+
}
Data JSCDataModel::getValueAsData(const JSValueRef value) {
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCArrayBuffer.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCArrayBuffer.h
index b3fa8ea..452b652 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCArrayBuffer.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCArrayBuffer.h
@@ -44,9 +44,6 @@ public:
static JSObjectRef jsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSValueRef byteLengthAttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);
- static bool hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
- static JSValueRef getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
- static bool setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
static JSStaticValue staticValues[];
@@ -59,9 +56,6 @@ public:
classDef.staticValues = staticValues;
classDef.staticFunctions = staticFunctions;
classDef.finalize = jsDestructor;
- classDef.hasProperty = hasPropertyCustomCallback;
- classDef.getProperty = getPropertyCustomCallback;
- classDef.setProperty = setPropertyCustomCallback;
classDef.callAsConstructor = jsConstructor;
Tmpl = JSClassCreate(&classDef);
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCTypedArrayCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCTypedArrayCustom.cpp
index 4ef0b8e..3c0f3d5 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCTypedArrayCustom.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCTypedArrayCustom.cpp
@@ -150,10 +150,6 @@ bool JSCUint8ClampedArray::hasPropertyCustomCallback(JSContextRef ctx, JSObjectR
JSC_TYPED_ARRAY_HAS_PROP_RETURN(Uint8ClampedArray);
}
-bool JSCArrayBuffer::hasPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
- JSC_TYPED_ARRAY_HAS_PROP_RETURN(ArrayBuffer);
-}
-
// -----------------
JSValueRef JSCInt8Array::getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
@@ -192,10 +188,6 @@ JSValueRef JSCUint8ClampedArray::getPropertyCustomCallback(JSContextRef ctx, JSO
JSC_TYPED_ARRAY_GET_PROP_RETURN(Uint8ClampedArray);
}
-JSValueRef JSCArrayBuffer::getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
- JSC_TYPED_ARRAY_GET_PROP_RETURN(ArrayBuffer);
-}
-
// ----------------
bool JSCInt8Array::setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) {
@@ -234,10 +226,6 @@ bool JSCUint8ClampedArray::setPropertyCustomCallback(JSContextRef ctx, JSObjectR
JSC_TYPED_ARRAY_SET_PROP_RETURN(Uint8ClampedArray);
}
-bool JSCArrayBuffer::setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) {
- JSC_TYPED_ARRAY_SET_PROP_RETURN(ArrayBuffer);
-}
-
}
} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/TypedArray.cpp b/src/uscxml/plugins/datamodel/ecmascript/TypedArray.cpp
index 16ee766..e52dfd3 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/TypedArray.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/TypedArray.cpp
@@ -1,10 +1,10 @@
#include "TypedArray.h"
#include <iostream>
+#include <boost/detail/endian.hpp>
-#define DATAVIEW_TYPED_RETURN(type) \
+#define DATAVIEW_TYPED_GET(type) \
type retVal;\
-memcpy(&retVal, _buffer->_data + (_start + index), sizeof(type));\
-return retVal;
+memcpy(&retVal, _buffer->_data + (_start + index), sizeof(type));
#define DATAVIEW_TYPED_SET(type) \
memcpy(_buffer->_data + (_start + index), &value, sizeof(type));
@@ -39,17 +39,28 @@ ArrayBuffer::ArrayBuffer(void* data, unsigned int size) {
}
unsigned long ArrayBuffer::getByteLength() {
+ if (!_buffer)
+ return 0;
return _buffer->_size;
}
-ArrayBuffer ArrayBuffer::slice(long begin, long length) {
- ArrayBuffer arrBuffer(length);
- memcpy(arrBuffer._buffer->_data, _buffer->_data + begin, length);
+ArrayBuffer ArrayBuffer::slice(long begin, long end) {
+ if (!_buffer) {
+ return ArrayBuffer(0);
+ }
+ unsigned int realBegin = (begin + _buffer->_size) % _buffer->_size;
+ unsigned int realEnd = (end + _buffer->_size) % _buffer->_size;
+ if (realEnd < realBegin) {
+ return ArrayBuffer(0);
+ }
+
+ ArrayBuffer arrBuffer(realEnd - realBegin);
+ memcpy(arrBuffer._buffer->_data, _buffer->_data + realBegin, realEnd - realBegin);
return arrBuffer;
}
ArrayBuffer ArrayBuffer::slice(long begin) {
- return slice(begin, _buffer->_size - begin);
+ return slice(begin, _buffer->_size);
}
bool ArrayBuffer::isView(void*) {
@@ -95,35 +106,91 @@ unsigned long DataView::getLength() {
}
char DataView::getInt8(unsigned long index) {
- DATAVIEW_TYPED_RETURN(int8_t);
+ DATAVIEW_TYPED_GET(int8_t);
+ return retVal;
}
unsigned char DataView::getUint8(unsigned long index) {
- DATAVIEW_TYPED_RETURN(uint8_t);
+ DATAVIEW_TYPED_GET(uint8_t);
+ return retVal;
}
short DataView::getInt16(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(int16_t);
+ DATAVIEW_TYPED_GET(int16_t);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
unsigned short DataView::getUint16(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(uint16_t);
+ DATAVIEW_TYPED_GET(uint16_t);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
long DataView::getInt32(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(int32_t);
+ DATAVIEW_TYPED_GET(int32_t);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
unsigned long DataView::getUint32(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(uint32_t);
+ DATAVIEW_TYPED_GET(uint32_t);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
float DataView::getFloat32(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(float);
+ DATAVIEW_TYPED_GET(float);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
double DataView::getFloat64(unsigned long index, bool littleEndian) {
- DATAVIEW_TYPED_RETURN(double);
+ DATAVIEW_TYPED_GET(double);
+#ifdef BOOST_LITTLE_ENDIAN
+ if (littleEndian)
+ return retVal;
+ return byte_swap<little_endian, big_endian>(retVal);
+#else
+ if (littleEndian)
+ return byte_swap<big_endian, little_endian>(retVal);
+ return retVal;
+#endif
}
void DataView::setInt8(long index, char value) {
@@ -134,26 +201,69 @@ void DataView::setUint8(long index, unsigned char value) {
DATAVIEW_TYPED_SET(uint8_t);
}
-void DataView::setInt16(long index, short value, bool) {
+void DataView::setInt16(long index, short value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(int16_t);
}
+
void DataView::setUint16(long index, unsigned short value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(uint16_t);
}
void DataView::setInt32(long index, long value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(int32_t);
}
void DataView::setUint32(long index, unsigned long value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(uint32_t);
}
void DataView::setFloat32(long index, float value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(float);
}
void DataView::setFloat64(long index, double value, bool littleEndian) {
+#ifdef BOOST_LITTLE_ENDIAN
+ if (!littleEndian)
+ value = byte_swap<little_endian, big_endian>(value);
+#else
+ if (littleEndian)
+ value = byte_swap<big_endian, little_endian>(value);
+#endif
DATAVIEW_TYPED_SET(double);
}
diff --git a/src/uscxml/plugins/datamodel/ecmascript/TypedArray.h b/src/uscxml/plugins/datamodel/ecmascript/TypedArray.h
index 229ae70..e238d15 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/TypedArray.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/TypedArray.h
@@ -7,9 +7,18 @@
#include <string.h>
#include <inttypes.h>
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/endian.hpp>
+#include <stdexcept>
+
namespace uscxml {
+/**
+ * https://www.khronos.org/registry/typedarray/specs/latest/
+ */
+
class ArrayBuffer {
public:
class Buffer {
@@ -22,10 +31,33 @@ public:
};
ArrayBuffer(void* data, unsigned int size);
+
+ /**
+ * Creates a new ArrayBuffer of the given length in bytes. The contents of the
+ * ArrayBuffer are initialized to 0. If the requested number of bytes could not
+ * be allocated an exception is raised.
+ */
ArrayBuffer(unsigned long length);
ArrayBuffer(boost::shared_ptr<ArrayBuffer::Buffer>);
+
+ /**
+ * The length of the ArrayBuffer in bytes, as fixed at construction time.
+ * Reading this property returns 0 if this ArrayBuffer has been neutered.
+ */
unsigned long getByteLength();
- ArrayBuffer slice(long begin, long length);
+
+ /**
+ * Returns a new ArrayBuffer whose contents are a copy of this ArrayBuffer's
+ * bytes from begin, inclusive, up to end, exclusive. If either begin or end
+ * is negative, it refers to an index from the end of the array, as opposed
+ * to from the beginning.
+ * If end is unspecified, the new ArrayBuffer contains all bytes from begin
+ * to the end of this ArrayBuffer.
+ * The range specified by the begin and end values is clamped to the valid
+ * index range for the current array. If the computed length of the new
+ * ArrayBuffer would be negative, it is clamped to zero.
+ */
+ ArrayBuffer slice(long begin, long end);
ArrayBuffer slice(long begin);
static bool isView(void*);
unsigned long getLength() {
@@ -35,17 +67,17 @@ public:
bool operator== (const ArrayBuffer& other) {
return other._buffer == _buffer;
}
- unsigned char get(unsigned long index) {
- if (index >= getLength())
- return 0;
- unsigned char retVal;
- memcpy(&retVal, _buffer->_data + index * sizeof(unsigned char), sizeof(unsigned char));
- return retVal;
- }
-
- void set(unsigned long index, unsigned char value) {
- memcpy(_buffer->_data + index * sizeof(unsigned char), &value, sizeof(unsigned char));
- }
+// unsigned char get(unsigned long index) {
+// if (index >= getLength())
+// return 0;
+// unsigned char retVal;
+// memcpy(&retVal, _buffer->_data + index * sizeof(unsigned char), sizeof(unsigned char));
+// return retVal;
+// }
+//
+// void set(unsigned long index, unsigned char value) {
+// memcpy(_buffer->_data + index * sizeof(unsigned char), &value, sizeof(unsigned char));
+// }
boost::shared_ptr<Buffer> _buffer;
};
@@ -53,8 +85,23 @@ public:
class ArrayBufferView {
public:
virtual ~ArrayBufferView() {}
+ /**
+ * The ArrayBuffer that this ArrayBufferView references.
+ */
ArrayBuffer getBuffer();
+
+ /**
+ * The offset of this ArrayBufferView from the start of its ArrayBuffer, in
+ * bytes, as fixed at construction time. Reading this property returns 0 if
+ * the referenced ArrayBuffer has been neutered.
+ */
virtual unsigned long getByteOffset() = 0;
+
+ /**
+ * The length of the ArrayBufferView in bytes, as fixed at construction time.
+ * Reading this property returns 0 if the referenced ArrayBuffer has been
+ * neutered.
+ */
virtual unsigned long getByteLength() = 0;
virtual unsigned long getLength() = 0;
protected:
@@ -63,6 +110,7 @@ protected:
unsigned long _end;
};
+
class DataView : ArrayBufferView {
public:
DataView(ArrayBuffer*, unsigned long, unsigned long);
@@ -73,6 +121,17 @@ public:
unsigned long getByteLength();
unsigned long getLength();
+ /**
+ * 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.
+ */
+
char getInt8(unsigned long);
unsigned char getUint8(unsigned long);
short getInt16(unsigned long, bool = false);
@@ -82,6 +141,18 @@ public:
float getFloat32(unsigned long, bool = false);
double getFloat64(unsigned long, bool = 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(long, char);
void setUint8(long, unsigned char);
void setInt16(long, short, bool = false);
@@ -96,13 +167,41 @@ public:
template<class T, class S> class TypedArray : public ArrayBufferView {
public:
virtual ~TypedArray() {}
- TypedArray(uscxml::ArrayBuffer* buffer, unsigned long start, unsigned long length) {
- _start = start;
- _end = start + length;
+
+ /**
+ * Create a new TypedArray object using the passed ArrayBuffer for its storage.
+ * Optional byteOffset and length can be used to limit the section of the buffer
+ * referenced. The byteOffset indicates the offset in bytes from the start of
+ * the ArrayBuffer, and the length is the count of elements from the offset
+ * that this TypedArray will reference. If both byteOffset and length are
+ * omitted, the TypedArray spans the entire ArrayBuffer range. If the length
+ * is omitted, the TypedArray extends from the given byteOffset until the end
+ * of the ArrayBuffer.
+ * The given byteOffset must be a multiple of the element size of the specific
+ * type, otherwise an exception is raised.
+ * If a given byteOffset and length references an area beyond the end of the
+ * ArrayBuffer an exception is raised.
+ * If length is not explicitly specified, the length of the ArrayBuffer minus
+ * the byteOffset must be a multiple of the element size of the specific type,
+ * or an exception is raised.
+ */
+ TypedArray(uscxml::ArrayBuffer* buffer, unsigned long byteOffset, unsigned long length) {
+ if (byteOffset % sizeof(S))
+ return;
+
+ _start = byteOffset / sizeof(S);
+ _end = _start + length;
+
+ if (_end > buffer->_buffer->_size / sizeof(S))
+ return;
+
_buffer = buffer->_buffer;
}
- TypedArray(uscxml::ArrayBuffer* buffer, unsigned long start) {
- _start = start / sizeof(S);
+ TypedArray(uscxml::ArrayBuffer* buffer, unsigned long byteOffset) {
+ if (byteOffset % sizeof(S))
+ return;
+
+ _start = byteOffset / sizeof(S);
_end = buffer->_buffer->_size / sizeof(S);
_buffer = buffer->_buffer;
}
@@ -112,38 +211,55 @@ public:
_buffer = buffer->_buffer;
}
- TypedArray(boost::shared_ptr<ArrayBuffer::Buffer> buffer, unsigned long start, unsigned long length) {
- _start = start;
- _end = start + length;
+ TypedArray(boost::shared_ptr<ArrayBuffer::Buffer> buffer, unsigned long byteOffset, unsigned long length) {
+ if (byteOffset % sizeof(S))
+ return;
+
+ _start = byteOffset / sizeof(S);
+ _end = _start + length;
+
+ if (_end > buffer->_size / sizeof(S))
+ return;
+
_buffer = buffer;
}
+
+ /**
+ * Create a new ArrayBuffer with enough bytes to hold length elements of this
+ * typed array, then creates a typed array view referring to the full buffer.
+ * As with a directly constructed ArrayBuffer, the contents are initialized
+ * to 0. If the requested number of bytes could not be allocated an exception
+ * is raised.
+ */
TypedArray(unsigned long length) {
_start = 0;
_end = length;
_buffer = boost::shared_ptr<ArrayBuffer::Buffer>(new ArrayBuffer::Buffer(length * sizeof(S)));
}
+
+ /**
+ * Create a new ArrayBuffer with enough bytes to hold array.length elements of
+ * this typed array, then creates a typed array view referring to the full
+ * buffer. The contents of the new view are initialized to the contents of the
+ * given array or typed array, with each element converted to the appropriate
+ * typed array type.
+ */
TypedArray(std::vector<T> data) {
_start = 0;
_end = data.size();
- if (sizeof(T) == sizeof(S)) {
- _buffer = boost::shared_ptr<ArrayBuffer::Buffer>(new ArrayBuffer::Buffer(((void*)&data[0]), data.size() * sizeof(T)));
- } else {
- S* buffer = (S*)malloc(data.size() * sizeof(S));
- typename std::vector<T>::const_iterator dataIter = data.begin();
- unsigned long i = 0;
- while(dataIter != data.end()) {
- buffer[i] = *dataIter;
- dataIter++;
- i++;
- }
- _buffer = boost::shared_ptr<ArrayBuffer::Buffer>(new ArrayBuffer::Buffer(buffer, data.size() * sizeof(S)));
- }
+ _buffer = boost::shared_ptr<ArrayBuffer::Buffer>(new ArrayBuffer::Buffer(data.size() * sizeof(S)));
+ set(data, 0);
}
TypedArray(TypedArray* other) {
_start = other->_start;
_end = other->_end;
_buffer = other->_buffer;
}
+
+ /**
+ * This is an index getter.
+ * Returns the element at the given numeric index.
+ */
T get(unsigned long index) {
if (index >= getLength())
return static_cast<T>(0);
@@ -151,44 +267,129 @@ public:
memcpy(&retVal, _buffer->_data + (_start + index) * sizeof(S), sizeof(S));
return retVal;
}
+
+ /**
+ * This is an index setter.
+ * Sets the element at the given numeric index to the given value.
+ */
void set(unsigned long index, T value) {
memcpy(_buffer->_data + (_start + index) * sizeof(S), &value, sizeof(S));
}
+ /**
+ * Set multiple values, reading input values from the array.
+ * The optional offset value indicates the index in the current array where
+ * values are written. If omitted, it is assumed to be 0.
+ * If the input array is a TypedArray, the two arrays may use the same
+ * underlying ArrayBuffer. In this situation, setting the values takes place
+ * as if all the data is first copied into a temporary buffer that does not
+ * overlap either of the arrays, and then the data from the temporary buffer
+ * is copied into the current array.
+ * If the offset plus the length of the given array is out of range for the
+ * current TypedArray, an exception is raised.
+ */
void set(TypedArray<T, S>* value, unsigned long offset) {
- memcpy(_buffer->_data + (_start) * sizeof(S), &value->_buffer->_data[offset], value->_buffer->_size);
+ if (!_buffer)
+ return;
+ if (offset * sizeof(S) + value->_buffer->_size > _buffer->_size)
+ return;
+
+ // will this work if we use the same buffer?
+ memcpy(_buffer->_data + (_start + offset) * sizeof(S), &value->_buffer->_data, value->_buffer->_size);
}
void set(TypedArray<T, S>* value) {
set(value, 0);
}
+ /**
+ * Set multiple values, reading input values from the array.
+ * The optional offset value indicates the index in the current array where
+ * values are written. If omitted, it is assumed to be 0.
+ * If the input array is a TypedArray, the two arrays may use the same
+ * underlying ArrayBuffer. In this situation, setting the values takes place
+ * as if all the data is first copied into a temporary buffer that does not
+ * overlap either of the arrays, and then the data from the temporary buffer
+ * is copied into the current array.
+ * If the offset plus the length of the given array is out of range for the
+ * current TypedArray, an exception is raised.
+ */
void set(std::vector<T> data, unsigned long offset) {
+ if (!_buffer)
+ return;
+ if (data.size() + offset > _end)
+ return;
+
+ if (sizeof(T) == sizeof(S)) {
+ memcpy(_buffer->_data + offset, (void*)&data[0], data.size());
+ } else {
+ S* buffer = (S*)malloc(data.size() * sizeof(S));
+ typename std::vector<T>::const_iterator dataIter = data.begin();
+ unsigned long i = 0;
+ while(dataIter != data.end()) {
+ buffer[i] = *dataIter;
+ dataIter++;
+ i++;
+ }
+ memcpy(_buffer->_data + offset, buffer, data.size());
+ free (buffer);
+ }
}
void set(std::vector<T> data) {
set(data, 0);
}
- TypedArray* subarray(long start, long end) {
- return new TypedArray<T, S>(_buffer, start, end);
+ /**
+ * Returns a new TypedArray view of the ArrayBuffer store for this TypedArray,
+ * referencing the elements at begin, inclusive, up to end, exclusive. If
+ * either begin or end is negative, it refers to an index from the end of the
+ * array, as opposed to from the beginning.
+ * If end is unspecified, the subarray contains all elements from begin to the
+ * end of the TypedArray.
+ * The range specified by the begin and end values is clamped to the valid
+ * index range for the current array. If the computed length of the new
+ * TypedArray would be negative, it is clamped to zero.
+ * The returned TypedArray will be of the same type as the array on which this
+ * method is invoked.
+ */
+ TypedArray* subarray(long begin, long end) {
+ if (!_buffer)
+ return NULL;
+ unsigned int realBegin = (begin + _buffer->_size) % _buffer->_size;
+ unsigned int realEnd = (end + _buffer->_size) % _buffer->_size;
+
+ if (realEnd < realBegin)
+ return NULL;
+
+ return new TypedArray<T, S>(_buffer, realBegin, realEnd);
}
unsigned long getLength() {
+ if (!_buffer)
+ return 0;
return _end - _start;
}
unsigned long getByteLength() {
+ if (!_buffer)
+ return 0;
return (_end - _start) * sizeof(S);
}
unsigned long getByteOffset() {
+ if (!_buffer)
+ return 0;
return _start * sizeof(S);
}
-
};
+/**
+ * Define actual types as template instances.
+ * First argument is representation from JavaScript, second type maybe smaller to
+ * exactly specify the byte width ot the TypedArray.
+ */
typedef TypedArray<unsigned char, uint8_t> Uint8Array;
typedef TypedArray<unsigned char, uint8_t> Uint8ClampedArray;
typedef TypedArray<char, int8_t> Int8Array;
@@ -199,6 +400,141 @@ typedef TypedArray<unsigned long, uint32_t> Uint32Array;
typedef TypedArray<float, float> Float32Array;
typedef TypedArray<double, double> Float64Array;
+
+// see http://www.cplusplus.com/forum/general/27544/
+
+// Little-endian operating systems:
+//---------------------------------
+// Linux on x86, x64, Alpha and Itanium
+// Mac OS on x86, x64
+// Solaris on x86, x64, PowerPC
+// Tru64 on Alpha
+// Windows on x86, x64 and Itanium
+
+// Big-endian operating systems:
+//------------------------------
+// AIX on POWER
+// AmigaOS on PowerPC and 680x0
+// HP-UX on Itanium and PA-RISC
+// Linux on MIPS, SPARC, PA-RISC, POWER, PowerPC, and 680x0
+// Mac OS on PowerPC and 680x0
+// Solaris on SPARC
+
+enum endianness {
+ little_endian,
+ big_endian,
+ network_endian = big_endian,
+
+#if defined(BOOST_LITTLE_ENDIAN)
+ host_endian = little_endian
+#elif defined(BOOST_BIG_ENDIAN)
+ host_endian = big_endian
+#else
+#error "unable to determine system endianness"
+#endif
+};
+
+namespace detail {
+
+template<typename T, size_t sz>
+struct swap_bytes {
+ inline T operator()(T val) {
+ throw std::out_of_range("data size");
+ }
+};
+
+template<typename T>
+struct swap_bytes<T, 1> {
+ inline T operator()(T val) {
+ return val;
+ }
+};
+
+template<typename T>
+struct swap_bytes<T, 2> { // for 16 bit
+ inline T operator()(T val) {
+ return ((((val) >> 8) & 0xff) | (((val) & 0xff) << 8));
+ }
+};
+
+template<typename T>
+struct swap_bytes<T, 4> { // for 32 bit
+ inline T operator()(T val) {
+#if defined(_USE_BUILTIN_BSWAPS) && defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4)
+ return __builtin_bswap32(val);
+#else
+ return ((((val) & 0xff000000) >> 24) |
+ (((val) & 0x00ff0000) >> 8) |
+ (((val) & 0x0000ff00) << 8) |
+ (((val) & 0x000000ff) << 24));
+#endif
+ }
+};
+
+template<>
+struct swap_bytes<float, 4> {
+ inline float operator()(float val) {
+ uint32_t mem = swap_bytes<uint32_t, sizeof(uint32_t)>()(*(uint32_t*)&val);
+ return *(float*)&mem;
+ }
+};
+
+template<typename T>
+struct swap_bytes<T, 8> { // for 64 bit
+ inline T operator()(T val) {
+#if defined(_USE_BUILTIN_BSWAPS) && defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4)
+ return __builtin_bswap64(val);
+#else
+ return ((((val) & 0xff00000000000000ull) >> 56) |
+ (((val) & 0x00ff000000000000ull) >> 40) |
+ (((val) & 0x0000ff0000000000ull) >> 24) |
+ (((val) & 0x000000ff00000000ull) >> 8 ) |
+ (((val) & 0x00000000ff000000ull) << 8 ) |
+ (((val) & 0x0000000000ff0000ull) << 24) |
+ (((val) & 0x000000000000ff00ull) << 40) |
+ (((val) & 0x00000000000000ffull) << 56));
+#endif
+ }
+};
+
+template<>
+struct swap_bytes<double, 8> {
+ inline double operator()(double val) {
+ uint64_t mem = swap_bytes<uint64_t, sizeof(uint64_t)>()(*(uint64_t*)&val);
+ return *(double*)&mem;
+ }
+};
+
+template<endianness from, endianness to, class T>
+struct do_byte_swap {
+ inline T operator()(T value) {
+ return swap_bytes<T, sizeof(T)>()(value);
+ }
+};
+// specialisations when attempting to swap to the same endianess
+template<class T> struct do_byte_swap<little_endian, little_endian, T> {
+ inline T operator()(T value) {
+ return value;
+ }
+};
+template<class T> struct do_byte_swap<big_endian, big_endian, T> {
+ inline T operator()(T value) {
+ return value;
+ }
+};
+
+} // namespace detail
+
+template<endianness from, endianness to, class T>
+inline T byte_swap(T value) {
+ // ensure the data is only 1, 2, 4 or 8 bytes
+ BOOST_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
+ // ensure we're only swapping arithmetic types
+ BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
+
+ return detail::do_byte_swap<from, to, T>()(value);
+}
+
}
#endif /* end of include guard: TYPEDARRAY_H_99815BLY */
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index 919f4a1..caf482b 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -351,25 +351,25 @@ v8::Handle<v8::Value> V8DataModel::getDataAsValue(const Data& data) {
return value;
}
switch (data.type) {
- case Data::VERBATIM:
- return v8::String::New(data.atom.c_str());
- break;
- case Data::INTERPRETED:
- return evalAsValue(data.atom);
- break;
- case Data::BINARY: {
- uscxml::ArrayBuffer* arrBuffer = new uscxml::ArrayBuffer((void*)data.atom.c_str(), data.atom.size());
- v8::Handle<v8::Function> retCtor = V8ArrayBuffer::getTmpl()->GetFunction();
- v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());
-
- struct V8ArrayBuffer::V8ArrayBufferPrivate* retPrivData = new V8ArrayBuffer::V8ArrayBufferPrivate();
- retPrivData->nativeObj = arrBuffer;
- retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
-
- retObj.MakeWeak(0, V8ArrayBuffer::jsDestructor);
- return retObj;
- break;
- }
+ case Data::VERBATIM:
+ return v8::String::New(data.atom.c_str());
+ break;
+ case Data::INTERPRETED:
+ return evalAsValue(data.atom);
+ break;
+ case Data::BINARY: {
+ uscxml::ArrayBuffer* arrBuffer = new uscxml::ArrayBuffer((void*)data.atom.c_str(), data.atom.size());
+ v8::Handle<v8::Function> retCtor = V8ArrayBuffer::getTmpl()->GetFunction();
+ v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());
+
+ struct V8ArrayBuffer::V8ArrayBufferPrivate* retPrivData = new V8ArrayBuffer::V8ArrayBufferPrivate();
+ retPrivData->nativeObj = arrBuffer;
+ retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
+
+ retObj.MakeWeak(0, V8ArrayBuffer::jsDestructor);
+ return retObj;
+ break;
+ }
}
// this will never be reached
return v8::Undefined();
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8ArrayBuffer.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8ArrayBuffer.h
index d4229eb..767d520 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8ArrayBuffer.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8ArrayBuffer.h
@@ -45,8 +45,6 @@ public:
static v8::Handle<v8::Value> isViewCallback(const v8::Arguments&);
static v8::Handle<v8::Value> byteLengthAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
- static v8::Handle<v8::Value> indexedPropertyCustomGetter(uint32_t, const v8::AccessorInfo&);
- static v8::Handle<v8::Value> indexedPropertyCustomSetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);
static v8::Handle<v8::Value> constructor(const v8::Arguments&);
static v8::Persistent<v8::FunctionTemplate> Constr;
@@ -74,7 +72,6 @@ public:
instance->SetAccessor(v8::String::NewSymbol("byteLength"), V8ArrayBuffer::byteLengthAttrGetter, 0,
v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
- instance->SetIndexedPropertyHandler(V8ArrayBuffer::indexedPropertyCustomGetter, V8ArrayBuffer::indexedPropertyCustomSetter);
prototype->Set(v8::String::NewSymbol("slice"),
v8::FunctionTemplate::New(V8ArrayBuffer::sliceCallback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete));
prototype->Set(v8::String::NewSymbol("isView"),
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8TypedArrayCustom.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8TypedArrayCustom.cpp
index 118eb46..95e86de 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8TypedArrayCustom.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8TypedArrayCustom.cpp
@@ -75,16 +75,6 @@ v8::Handle<v8::Value> V8Uint8ClampedArray::indexedPropertyCustomSetter(unsigned
return value;
}
-v8::Handle<v8::Value> V8ArrayBuffer::indexedPropertyCustomSetter(unsigned int index, v8::Local<v8::Value> value, const v8::AccessorInfo &info) {
- v8::Local<v8::Object> self = info.Holder();
- uscxml::ArrayBuffer* array = V8DOM::toClassPtr<V8ArrayBufferPrivate >(self->GetInternalField(0))->nativeObj;
- if (index > array->getByteLength())
- return v8::Undefined();
- array->_buffer->_data[index] = value->ToInt32()->Value() & 0xff;
- return value;
-
-}
-
// ----------------
v8::Handle<v8::Value> V8Int8Array::indexedPropertyCustomGetter(unsigned int index, const v8::AccessorInfo &info) {
@@ -132,13 +122,5 @@ v8::Handle<v8::Value> V8Uint8ClampedArray::indexedPropertyCustomGetter(unsigned
return v8::Uint32::New(array->get(index));
}
-v8::Handle<v8::Value> V8ArrayBuffer::indexedPropertyCustomGetter(unsigned int index, const v8::AccessorInfo &info) {
- v8::Local<v8::Object> self = info.Holder();
- uscxml::ArrayBuffer* array = V8DOM::toClassPtr<V8ArrayBufferPrivate >(self->GetInternalField(0))->nativeObj;
- if (index > array->getByteLength())
- return v8::Undefined();
- return v8::Int32::New(array->_buffer->_data[index]);
-}
-
}
} \ No newline at end of file