Handle<Value> CreateExternalArrayBuffer(const Arguments& args) { if (args.Length() == 0) { return ThrowException( String::New("ArrayBuffer constructor must have one parameter.")); } if (args[0]->IsObject() && IS_BINARY(args[0])) { return CreateExternalArrayBuffer(args[0]); } TryCatch try_catch; int32_t length = convertToUint(args[0], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); return CreateExternalArrayBuffer(length); }
// This command is complex because it only allows setting of frequency for channel 1 // This is because only the tilt motor can be controlled by frequency void onCommandFrequencyOutput() { if (isChannelCorrect(gParameters[0])) { uint8_t channel = convertToInt(gParameters[0]); uint16_t frequency = convertToUint(gParameters[1]); if (channel == TILT_CHANNEL) { if (isReadCommand(gParameters[1])) { sendInt(currentFrequency); sendAck(); } else { if (!isSafetyOn) { if (isIntWithinRange(frequency, MOTOR_MIN_FREQUENCY, MOTOR_MAX_FREQUENCY)) { setFrequency(frequency); sendAck(); } else { sendIntRangeError(MOTOR_MIN_FREQUENCY, MOTOR_MAX_FREQUENCY, HERTZ_UNIT); } } else { Serial.println(F("Cannot change frequency output while safety is on.")); sendNack(); } } } else { Serial.println(F("Changing or reading of frequency only applies to channel 1")); sendNack(); } } else { sendChannelError(); } }
//by default memory buffers have direct access Handle<Value> MemoryBuffer(const Arguments& args) { HandleScope scope; if (args.Length() < 2) { return ThrowException( String::New("MemoryBuffer constructor must have two parameters (address and size).")); } TryCatch try_catch; uint32_t address = NumberToUint32(args[0], &try_catch); uint32_t length = convertToUint(args[1], &try_catch); uint8_t* data; bool is_external = false; if (try_catch.HasCaught()) return try_catch.Exception(); static const int32_t kMaxSize = 0x7fffffff; // Make sure the total size fits into a (signed) int. if (length < 0 || length > kMaxSize) { return ThrowException(String::New("ArrayBuffer exceeds maximum size (2G)")); } //check if we should snapshot the value if (args.Length() > 2 && args[2]->IsTrue()) { data = new uint8_t[length]; if (data == NULL) { return ThrowException(String::New("Memory allocation failed.")); } V8::AdjustAmountOfExternalAllocatedMemory(length); PIN_SafeCopy(data, reinterpret_cast<uint8_t *>(address), length); } else { data = reinterpret_cast<uint8_t *>(address); is_external = true; } Handle<Value> buffer = CreateExternalArrayBuffer(length, data); buffer->ToObject()->Set(String::New("snapshot"), (is_external ? False() : True()), ReadOnly); if (is_external) buffer->ToObject()->Set(String::New("externalBuffer"), True(), ReadOnly); return scope.Close(buffer); }
Handle<Value> CreateExternalArray(const Arguments& args, ExternalArrayType type, size_t element_size) { TryCatch try_catch; ASSERT_PIN(element_size == 1 || element_size == 2 || element_size == 4 || element_size == 8, "CreateExternalArray"); // Currently, only the following constructors are supported: // TypedArray(unsigned long length) // TypedArray(ArrayBuffer buffer, // optional unsigned long byteOffset, // optional unsigned long length) Handle<Object> buffer; int32_t length; int32_t byteLength; int32_t byteOffset; int32_t bufferLength; if (args.Length() == 0) { return ThrowException( String::New("Array constructor must have at least one parameter.")); } if (args[0]->IsObject() && (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) || (IS_BINARY(args[0]))) { if (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) { buffer = args[0]->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } else { buffer = CreateExternalArrayBuffer(args[0])->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } if (args.Length() < 2 || args[1]->IsUndefined()) { byteOffset = 0; } else { byteOffset = convertToUint(args[1], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); if (byteOffset > bufferLength) { return ThrowException(String::New("byteOffset out of bounds")); } if (byteOffset % element_size != 0) { return ThrowException( String::New("byteOffset must be multiple of element_size")); } } if (args.Length() < 3 || args[2]->IsUndefined()) { byteLength = bufferLength - byteOffset; length = byteLength / element_size; if (byteLength % element_size != 0) { return ThrowException( String::New("buffer size must be multiple of element_size")); } } else { length = convertToUint(args[2], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); byteLength = length * element_size; if (byteOffset + byteLength > bufferLength) { return ThrowException(String::New("length out of bounds")); } } } else { length = convertToUint(args[0], &try_catch); byteLength = length * element_size; byteOffset = 0; Handle<Value> result = CreateExternalArrayBuffer(byteLength); if (!result->IsObject()) return result; buffer = result->ToObject(); } void* data = buffer->GetIndexedPropertiesExternalArrayData(); ASSERT_PIN(data != NULL, "CreateExternalArray data != NULL"); Handle<Object> array = Object::New(); array->SetIndexedPropertiesToExternalArrayData( static_cast<uint8_t*>(data) + byteOffset, type, length); array->Set(String::New("byteLength"), Int32::New(byteLength), ReadOnly); array->Set(String::New("byteOffset"), Int32::New(byteOffset), ReadOnly); array->Set(String::New("length"), Int32::New(length), ReadOnly); array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size)); array->Set(String::New("buffer"), buffer, ReadOnly); return array; }