// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include #include #include #include "include/dart_api.h" #include "include/dart_native_api.h" Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope); DART_EXPORT Dart_Handle sample_extension_Init(Dart_Handle parent_library) { if (Dart_IsError(parent_library)) { return parent_library; } Dart_Handle result_code = Dart_SetNativeResolver(parent_library, ResolveName, NULL); if (Dart_IsError(result_code)) { return result_code; } return Dart_Null(); } Dart_Handle HandleError(Dart_Handle handle) { if (Dart_IsError(handle)) { Dart_PropagateError(handle); } return handle; } void SystemRand(Dart_NativeArguments arguments) { Dart_EnterScope(); Dart_Handle result = HandleError(Dart_NewInteger(rand())); Dart_SetReturnValue(arguments, result); Dart_ExitScope(); } void SystemSrand(Dart_NativeArguments arguments) { Dart_EnterScope(); bool success = false; Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0)); if (Dart_IsInteger(seed_object)) { bool fits; HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits)); if (fits) { int64_t seed; HandleError(Dart_IntegerToInt64(seed_object, &seed)); srand(static_cast(seed)); success = true; } } Dart_SetReturnValue(arguments, HandleError(Dart_NewBoolean(success))); Dart_ExitScope(); } uint8_t* randomArray(int seed, int length) { if (length <= 0 || length > 10000000) { return NULL; } uint8_t* values = reinterpret_cast(malloc(length)); if (NULL == values) { return NULL; } srand(seed); for (int i = 0; i < length; ++i) { values[i] = rand() % 256; } return values; } void wrappedRandomArray(Dart_Port dest_port_id, Dart_CObject* message) { Dart_Port reply_port_id = ILLEGAL_PORT; if (message->type == Dart_CObject_kArray && 3 == message->value.as_array.length) { // Use .as_array and .as_int32 to access the data in the Dart_CObject. Dart_CObject* param0 = message->value.as_array.values[0]; Dart_CObject* param1 = message->value.as_array.values[1]; Dart_CObject* param2 = message->value.as_array.values[2]; if (param0->type == Dart_CObject_kInt32 && param1->type == Dart_CObject_kInt32 && param2->type == Dart_CObject_kSendPort) { int seed = param0->value.as_int32; int length = param1->value.as_int32; reply_port_id = param2->value.as_send_port.id; uint8_t* values = randomArray(seed, length); if (values != NULL) { Dart_CObject result; result.type = Dart_CObject_kTypedData; result.value.as_typed_data.type = Dart_TypedData_kUint8; result.value.as_typed_data.values = values; result.value.as_typed_data.length = length; if (Dart_PostCObject(reply_port_id, &result)) { Dart_CObject error; error.type = Dart_CObject_kNull; Dart_PostCObject(reply_port_id, &error); } free(values); // It is OK that result is destroyed when function exits. // Dart_PostCObject has copied its data. return; } } } fprintf(stderr, "Invalid message received, cannot proceed. Aborting the process.\n"); abort(); } void randomArrayServicePort(Dart_NativeArguments arguments) { Dart_EnterScope(); Dart_SetReturnValue(arguments, Dart_Null()); Dart_Port service_port = Dart_NewNativePort("RandomArrayService", wrappedRandomArray, true); if (service_port != ILLEGAL_PORT) { Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port)); Dart_SetReturnValue(arguments, send_port); } Dart_ExitScope(); } struct FunctionLookup { const char* name; Dart_NativeFunction function; }; FunctionLookup function_list[] = { {"SystemRand", SystemRand}, {"SystemSrand", SystemSrand}, {"RandomArray_ServicePort", randomArrayServicePort}, {NULL, NULL}}; FunctionLookup no_scope_function_list[] = { {"NoScopeSystemRand", SystemRand}, {NULL, NULL} }; Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) { if (!Dart_IsString(name)) { return NULL; } Dart_NativeFunction result = NULL; if (auto_setup_scope == NULL) { return NULL; } Dart_EnterScope(); const char* cname; HandleError(Dart_StringToCString(name, &cname)); for (int i=0; function_list[i].name != NULL; ++i) { if (strcmp(function_list[i].name, cname) == 0) { *auto_setup_scope = true; result = function_list[i].function; break; } } if (result != NULL) { Dart_ExitScope(); return result; } for (int i=0; no_scope_function_list[i].name != NULL; ++i) { if (strcmp(no_scope_function_list[i].name, cname) == 0) { *auto_setup_scope = false; result = no_scope_function_list[i].function; break; } } Dart_ExitScope(); return result; }