Files
sdk/runtime/bin/dartutils.cc
T
ager@google.com eafaf035d2 Make the temporary OSError allocation method private.
GetField, SetField, Invoke can now be called with a library target
and with private names. Using that we can make this temporary
utility function private as it should be.

Work is under way to support instance creation through the API.

R=sgjesse@google.com
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com//9773037

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5881 260f80e4-7a28-3924-810f-c04153c831b5
2012-03-27 15:31:00 +00:00

441 lines
14 KiB
C++

// 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 "bin/dartutils.h"
#include "bin/file.h"
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
const char* DartUtils::kDartScheme = "dart:";
const char* DartUtils::kDartExtensionScheme = "dart-ext:";
const char* DartUtils::kBuiltinLibURL = "dart:builtin";
const char* DartUtils::kCoreLibURL = "dart:core";
const char* DartUtils::kCoreImplLibURL = "dart:coreimpl";
const char* DartUtils::kIOLibURL = "dart:io";
const char* DartUtils::kJsonLibURL = "dart:json";
const char* DartUtils::kUriLibURL = "dart:uri";
const char* DartUtils::kUtfLibURL = "dart:utf";
const char* DartUtils::kIsolateLibURL = "dart:isolate";
const char* DartUtils::kIdFieldName = "_id";
static const char* MapLibraryUrl(CommandLineOptions* url_mapping,
const char* url_string) {
ASSERT(url_mapping != NULL);
// We need to check if the passed in url is found in the url_mapping array,
// in that case use the mapped entry.
int len = strlen(url_string);
for (int idx = 0; idx < url_mapping->count(); idx++) {
const char* url_name = url_mapping->GetArgument(idx);
if (!strncmp(url_string, url_name, len) && (url_name[len] == ',')) {
const char* url_mapped_name = url_name + len + 1;
if (strlen(url_mapped_name) != 0) {
return url_mapped_name; // Found a mapping for this URL.
}
}
}
return NULL; // Did not find a mapping for this URL.
}
int64_t DartUtils::GetIntegerValue(Dart_Handle value_obj) {
ASSERT(Dart_IsInteger(value_obj));
int64_t value = 0;
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
ASSERT(!Dart_IsError(result));
return value;
}
const char* DartUtils::GetStringValue(Dart_Handle str_obj) {
const char* cstring = NULL;
Dart_Handle result = Dart_StringToCString(str_obj, &cstring);
ASSERT(!Dart_IsError(result));
return cstring;
}
bool DartUtils::GetBooleanValue(Dart_Handle bool_obj) {
bool value = false;
Dart_Handle result = Dart_BooleanValue(bool_obj, &value);
ASSERT(!Dart_IsError(result));
return value;
}
void DartUtils::SetIntegerField(Dart_Handle handle,
const char* name,
intptr_t val) {
Dart_Handle result = Dart_SetField(handle,
Dart_NewString(name),
Dart_NewInteger(val));
ASSERT(!Dart_IsError(result));
}
intptr_t DartUtils::GetIntegerField(Dart_Handle handle,
const char* name) {
Dart_Handle result = Dart_GetField(handle, Dart_NewString(name));
ASSERT(!Dart_IsError(result));
intptr_t value = DartUtils::GetIntegerValue(result);
return value;
}
void DartUtils::SetStringField(Dart_Handle handle,
const char* name,
const char* val) {
Dart_Handle result = Dart_SetField(handle,
Dart_NewString(name),
Dart_NewString(val));
ASSERT(!Dart_IsError(result));
}
bool DartUtils::IsDartSchemeURL(const char* url_name) {
static const intptr_t kDartSchemeLen = strlen(kDartScheme);
// If the URL starts with "dart:" then it is considered as a special
// library URL which is handled differently from other URLs.
return (strncmp(url_name, kDartScheme, kDartSchemeLen) == 0);
}
bool DartUtils::IsDartExtensionSchemeURL(const char* url_name) {
static const intptr_t kDartExtensionSchemeLen = strlen(kDartExtensionScheme);
// If the URL starts with "dartext:" then it is considered as a special
// extension library URL which is handled differently from other URLs.
return
(strncmp(url_name, kDartExtensionScheme, kDartExtensionSchemeLen) == 0);
}
bool DartUtils::IsDartIOLibURL(const char* url_name) {
return (strcmp(url_name, kIOLibURL) == 0);
}
bool DartUtils::IsDartJsonLibURL(const char* url_name) {
return (strcmp(url_name, kJsonLibURL) == 0);
}
bool DartUtils::IsDartUriLibURL(const char* url_name) {
return (strcmp(url_name, kUriLibURL) == 0);
}
bool DartUtils::IsDartUtfLibURL(const char* url_name) {
return (strcmp(url_name, kUtfLibURL) == 0);
}
Dart_Handle DartUtils::CanonicalizeURL(CommandLineOptions* url_mapping,
Dart_Handle library,
const char* url_str) {
// Get the url of the including library.
Dart_Handle library_url = Dart_LibraryUrl(library);
if (Dart_IsError(library_url)) {
return Dart_Error("accessing library url failed");
}
if (!Dart_IsString8(library_url)) {
return Dart_Error("library url is not a string");
}
const char* library_url_str = NULL;
Dart_Handle result = Dart_StringToCString(library_url, &library_url_str);
if (Dart_IsError(result)) {
return Dart_Error("accessing library url characters failed");
}
if (url_mapping != NULL) {
const char* mapped_library_url_str = MapLibraryUrl(url_mapping,
library_url_str);
if (mapped_library_url_str != NULL) {
library_url_str = mapped_library_url_str;
}
}
// Calculate the canonical path.
const char* canon_url_str = GetCanonicalPath(library_url_str, url_str);
Dart_Handle canon_url = Dart_NewString(canon_url_str);
free(const_cast<char*>(canon_url_str));
return canon_url;
}
Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
File* file = File::Open(filename, File::kRead);
if (file == NULL) {
const char* format = "Unable to open file: %s";
intptr_t len = snprintf(NULL, 0, format, filename);
// TODO(iposva): Allocate from the zone instead of leaking error string
// here. On the other hand the binary is about the exit anyway.
char* error_msg = reinterpret_cast<char*>(malloc(len + 1));
snprintf(error_msg, len + 1, format, filename);
return Dart_Error(error_msg);
}
intptr_t len = file->Length();
char* text_buffer = reinterpret_cast<char*>(malloc(len + 1));
if (text_buffer == NULL) {
delete file;
return Dart_Error("Unable to allocate buffer");
}
if (!file->ReadFully(text_buffer, len)) {
delete file;
return Dart_Error("Unable to fully read contents");
}
text_buffer[len] = '\0';
delete file;
Dart_Handle str = Dart_NewString(text_buffer);
free(text_buffer);
return str;
}
Dart_Handle DartUtils::LoadSource(CommandLineOptions* url_mapping,
Dart_Handle library,
Dart_Handle url,
Dart_LibraryTag tag,
const char* url_string,
Dart_Handle import_map) {
if (url_mapping != NULL && IsDartSchemeURL(url_string)) {
const char* mapped_url_string = MapLibraryUrl(url_mapping, url_string);
if (mapped_url_string == NULL) {
return Dart_Error("Do not know how to load %s", url_string);
}
// We have a URL mapping specified, just read the file that the
// URL mapping specifies and load it.
url_string = mapped_url_string;
}
// The tag is either an import or a source tag.
// Read the file and load it according to the specified tag.
Dart_Handle source = DartUtils::ReadStringFromFile(url_string);
if (Dart_IsError(source)) {
return source; // source contains the error string.
}
if (tag == kImportTag) {
// Return library object or an error string.
return Dart_LoadLibrary(url, source, import_map);
} else if (tag == kSourceTag) {
return Dart_LoadSource(library, url, source);
}
return Dart_Error("wrong tag");
}
const char* DartUtils::GetCanonicalPath(const char* reference_dir,
const char* filename) {
if (File::IsAbsolutePath(filename)) {
return strdup(filename);
}
char* path = strdup(reference_dir);
if (path == NULL) {
return NULL;
}
char* path_sep = strrchr(path, File::PathSeparator()[0]);
if (path_sep == NULL) {
// No separator found: Reference is a file in local directory.
return strdup(filename);
}
*path_sep = '\0';
intptr_t len = snprintf(NULL, 0, "%s%s%s",
path, File::PathSeparator(), filename);
char* absolute_filename = reinterpret_cast<char*>(malloc(len + 1));
ASSERT(absolute_filename != NULL);
snprintf(absolute_filename, len + 1, "%s%s%s",
path, File::PathSeparator(), filename);
free(path);
char* canonical_filename = File::GetCanonicalPath(absolute_filename);
if (canonical_filename == NULL) {
return absolute_filename;
}
free(absolute_filename);
return canonical_filename;
}
bool DartUtils::PostNull(Dart_Port port_id) {
// Post a message with just the null object.
return Dart_PostCObject(port_id, CObject::Null()->AsApiCObject());
}
bool DartUtils::PostInt32(Dart_Port port_id, int32_t value) {
// Post a message with the integer value.
int32_t min = 0xc0000000; // -1073741824
int32_t max = 0x3fffffff; // 1073741823
ASSERT(min <= value && value < max);
Dart_CObject object;
object.type = Dart_CObject::kInt32;
object.value.as_int32 = value;
return Dart_PostCObject(port_id, &object);
}
Dart_Handle DartUtils::NewDartOSError() {
// Extract the current OS error.
OSError os_error;
return NewDartOSError(&os_error);
}
Dart_Handle DartUtils::NewDartOSError(OSError* os_error) {
// Create a Dart OSError object with the information retrieved from the OS.
Dart_Handle url = Dart_NewString("dart:io");
if (Dart_IsError(url)) return url;
Dart_Handle lib = Dart_LookupLibrary(url);
if (Dart_IsError(lib)) return lib;
Dart_Handle function_name = Dart_NewString("_makeOSError");
if (Dart_IsError(function_name)) return function_name;
Dart_Handle args[2];
args[0] = Dart_NewString(os_error->message());
if (Dart_IsError(args[0])) return args[0];
args[1] = Dart_NewInteger(os_error->code());
if (Dart_IsError(args[1])) return args[1];
Dart_Handle err = Dart_Invoke(lib, function_name, 2, args);
return err;
}
// Statically allocated Dart_CObject instances for immutable
// objects. As these will be used by different threads the use of
// these depends on the fact that the marking internally in the
// Dart_CObject structure is not marking simple value objects.
Dart_CObject CObject::api_null_ = { Dart_CObject::kNull , { 0 } };
Dart_CObject CObject::api_true_ = { Dart_CObject::kBool , { true } };
Dart_CObject CObject::api_false_ = { Dart_CObject::kBool, { false } };
CObject CObject::null_ = CObject(&api_null_);
CObject CObject::true_ = CObject(&api_true_);
CObject CObject::false_ = CObject(&api_false_);
CObject* CObject::Null() {
return &null_;
}
CObject* CObject::True() {
return &true_;
}
CObject* CObject::False() {
return &false_;
}
CObject* CObject::Bool(bool value) {
return value ? &true_ : &false_;
}
Dart_CObject* CObject::New(Dart_CObject::Type type, int additional_bytes) {
Dart_CObject* cobject = reinterpret_cast<Dart_CObject*>(
Dart_ScopeAllocate(sizeof(Dart_CObject) + additional_bytes));
cobject->type = type;
return cobject;
}
Dart_CObject* CObject::NewInt32(int32_t value) {
Dart_CObject* cobject = New(Dart_CObject::kInt32);
cobject->value.as_int32 = value;
return cobject;
}
Dart_CObject* CObject::NewInt64(int64_t value) {
Dart_CObject* cobject = New(Dart_CObject::kInt64);
cobject->value.as_int64 = value;
return cobject;
}
Dart_CObject* CObject::NewIntptr(intptr_t value) {
// Pointer values passed as intptr_t are always send as int64_t.
Dart_CObject* cobject = New(Dart_CObject::kInt64);
cobject->value.as_int64 = value;
return cobject;
}
Dart_CObject* CObject::NewDouble(double value) {
Dart_CObject* cobject = New(Dart_CObject::kDouble);
cobject->value.as_double = value;
return cobject;
}
Dart_CObject* CObject::NewString(int length) {
Dart_CObject* cobject = New(Dart_CObject::kString, length + 1);
cobject->value.as_string = reinterpret_cast<char*>(cobject + 1);
return cobject;
}
Dart_CObject* CObject::NewString(const char* str) {
int length = strlen(str);
Dart_CObject* cobject = NewString(length);
memmove(cobject->value.as_string, str, length + 1);
return cobject;
}
Dart_CObject* CObject::NewArray(int length) {
Dart_CObject* cobject =
New(Dart_CObject::kArray, length * sizeof(Dart_CObject*)); // NOLINT
cobject->value.as_array.length = length;
cobject->value.as_array.values =
reinterpret_cast<Dart_CObject**>(cobject + 1);
return cobject;
}
Dart_CObject* CObject::NewByteArray(int length) {
Dart_CObject* cobject = New(Dart_CObject::kByteArray, length);
cobject->value.as_byte_array.length = length;
cobject->value.as_byte_array.values = reinterpret_cast<uint8_t*>(cobject + 1);
return cobject;
}
static int kIllegalArgumentError = 1;
static int kOSError = 2;
static int kFileClosedError = 3;
CObject* CObject::IllegalArgumentError() {
CObjectArray* result = new CObjectArray(CObject::NewArray(1));
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kIllegalArgumentError)));
return result;
}
CObject* CObject::FileClosedError() {
CObjectArray* result = new CObjectArray(CObject::NewArray(1));
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kFileClosedError)));
return result;
}
CObject* CObject::NewOSError() {
OSError os_error;
return NewOSError(&os_error);
}
CObject* CObject::NewOSError(OSError* os_error) {
CObject* error_message =
new CObjectString(CObject::NewString(os_error->message()));
CObjectArray* result = new CObjectArray(CObject::NewArray(3));
result->SetAt(0, new CObjectInt32(CObject::NewInt32(kOSError)));
result->SetAt(1, new CObjectInt32(CObject::NewInt32(os_error->code())));
result->SetAt(2, error_message);
return result;
}