// 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 "include/dart_api.h"
#include "include/dart_native_api.h"

#include "platform/assert.h"
#include "platform/globals.h"

#include "bin/extensions.h"
#include "bin/directory.h"
#include "bin/file.h"
#include "bin/io_buffer.h"
#include "bin/utils.h"
#include "bin/socket.h"

namespace dart {
namespace bin {

const char* DartUtils::original_working_directory = NULL;
const char* DartUtils::kDartScheme = "dart:";
const char* DartUtils::kDartExtensionScheme = "dart-ext:";
const char* DartUtils::kAsyncLibURL = "dart:async";
const char* DartUtils::kBuiltinLibURL = "dart:builtin";
const char* DartUtils::kCoreLibURL = "dart:core";
const char* DartUtils::kIOLibURL = "dart:io";
const char* DartUtils::kIOLibPatchURL = "dart:io-patch";
const char* DartUtils::kUriLibURL = "dart:uri";
const char* DartUtils::kHttpScheme = "http:";

const char* DartUtils::kIdFieldName = "_id";

uint8_t DartUtils::magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };

static bool IsWindowsHost() {
#if defined(TARGET_OS_WINDOWS)
  return true;
#else  // defined(TARGET_OS_WINDOWS)
  return false;
#endif  // defined(TARGET_OS_WINDOWS)
}


const char* DartUtils::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;
}


intptr_t DartUtils::GetIntptrValue(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 static_cast<intptr_t>(value);
}


bool DartUtils::GetInt64Value(Dart_Handle value_obj, int64_t* value) {
  bool valid = Dart_IsInteger(value_obj);
  if (valid) {
    Dart_Handle result = Dart_IntegerFitsIntoInt64(value_obj, &valid);
    ASSERT(!Dart_IsError(result));
  }
  if (!valid) return false;
  Dart_Handle result = Dart_IntegerToInt64(value_obj, value);
  ASSERT(!Dart_IsError(result));
  return true;
}


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,
                                     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, 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, NewString(name), 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::IsHttpSchemeURL(const char* url_name) {
  static const intptr_t kHttpSchemeLen = strlen(kHttpScheme);
  return (strncmp(url_name, kHttpScheme, kHttpSchemeLen) == 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::IsDartBuiltinLibURL(const char* url_name) {
  return (strcmp(url_name, kBuiltinLibURL) == 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_IsString(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 = NewString(canon_url_str);
  free(const_cast<char*>(canon_url_str));

  return canon_url;
}


void* DartUtils::OpenFile(const char* name, bool write) {
  File* file = File::Open(name, write ? File::kWriteTruncate : File::kRead);
  return reinterpret_cast<void*>(file);
}


void DartUtils::ReadFile(const uint8_t** data,
                         intptr_t* file_len,
                         void* stream) {
  ASSERT(data != NULL);
  ASSERT(file_len != NULL);
  ASSERT(stream != NULL);
  File* file_stream = reinterpret_cast<File*>(stream);
  *file_len = file_stream->Length();
  ASSERT(*file_len > 0);
  uint8_t* text_buffer = reinterpret_cast<uint8_t*>(malloc(*file_len));
  ASSERT(text_buffer != NULL);
  if (!file_stream->ReadFully(text_buffer, *file_len)) {
    *data = NULL;
    *file_len = -1;  // Indicates read was not successful.
    return;
  }
  *data = text_buffer;
}


void DartUtils::WriteFile(const void* buffer,
                          intptr_t num_bytes,
                          void* stream) {
  ASSERT(stream != NULL);
  File* file_stream = reinterpret_cast<File*>(stream);
  bool bytes_written = file_stream->WriteFully(buffer, num_bytes);
  ASSERT(bytes_written);
}


void DartUtils::CloseFile(void* stream) {
  delete reinterpret_cast<File*>(stream);
}


static Dart_Handle SingleArgDart_Invoke(Dart_Handle arg, Dart_Handle lib,
                                        const char* method) {
  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = arg;
  return Dart_Invoke(lib, DartUtils::NewString(method), kNumArgs, dart_args);
}


// TODO(iposva): Allocate from the zone instead of leaking error string
// here. On the other hand the binary is about the exit anyway.
#define SET_ERROR_MSG(error_msg, format, ...)                                  \
  intptr_t len = snprintf(NULL, 0, format, __VA_ARGS__);                       \
  char *msg = reinterpret_cast<char*>(malloc(len + 1));                        \
  snprintf(msg, len + 1, format, __VA_ARGS__);                                 \
  *error_msg = msg


Dart_Handle MakeHttpRequest(Dart_Handle uri, Dart_Handle builtin_lib,
                            uint8_t** buffer, intptr_t* buffer_len) {
  const intptr_t HttpResponseCodeOK = 200;
  ASSERT(buffer != NULL);
  ASSERT(buffer_len != NULL);
  ASSERT(!Dart_HasLivePorts());
  SingleArgDart_Invoke(uri, builtin_lib, "_makeHttpRequest");
  // Run until all ports to isolate are closed.
  Dart_Handle result = Dart_RunLoop();
  if (Dart_IsError(result)) {
    return result;
  }
  intptr_t responseCode =
    DartUtils::GetIntegerField(builtin_lib, "_httpRequestResponseCode");
  if (responseCode != HttpResponseCodeOK) {
    // Return error.
    Dart_Handle responseStatus =
        Dart_GetField(builtin_lib,
                      DartUtils::NewString("_httpRequestStatusString"));
    if (Dart_IsError(responseStatus)) {
      return responseStatus;
    }
    if (Dart_IsNull(responseStatus)) {
      return Dart_Error("HTTP error.");
    }
    return Dart_Error(DartUtils::GetStringValue(responseStatus));
  }
  Dart_Handle response =
    Dart_GetField(builtin_lib, DartUtils::NewString("_httpRequestResponse"));
  if (Dart_IsError(response)) {
    return response;
  }
  if (Dart_IsString(response)) {
    // Received response as string.
    uint8_t* responseString = NULL;
    intptr_t responseStringLength;
    Dart_Handle r = Dart_StringToUTF8(response, &responseString,
                                      &responseStringLength);
    if (Dart_IsError(r)) {
      *buffer = NULL;
      *buffer_len = 0;
      return r;
    }
    // Get payload as bytes.
    *buffer_len = responseStringLength;
    *buffer = reinterpret_cast<uint8_t*>(malloc(responseStringLength));
    memmove(*buffer, responseString, responseStringLength);
  } else {
    // Received response as list of bytes.
    ASSERT(Dart_IsList(response));
    // Query list length.
    result = Dart_ListLength(response, buffer_len);
    if (Dart_IsError(result)) {
      *buffer_len = 0;
      *buffer = NULL;
      return result;
    }
    // Get payload as bytes.
    *buffer = reinterpret_cast<uint8_t*>(malloc(*buffer_len));
    result = Dart_ListGetAsBytes(response, 0, *buffer, *buffer_len);
    if (Dart_IsError(result)) {
      free(*buffer);
      *buffer_len = 0;
      *buffer = NULL;
      return result;
    }
  }
  return result;
}


Dart_Handle DartUtils::ReadStringFromHttp(const char* script_uri) {
  Dart_Handle uri = NewString(script_uri);
  if (Dart_IsError(uri)) {
    return uri;
  }
  Dart_Handle builtin_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
  uint8_t* buffer;
  intptr_t bufferLen;
  Dart_Handle result = MakeHttpRequest(uri, builtin_lib, &buffer, &bufferLen);
  if (Dart_IsError(result)) {
    return result;
  }
  Dart_Handle str = Dart_NewStringFromUTF8(buffer,
                                           bufferLen);
  free(buffer);
  return str;
}


static const uint8_t* ReadFileFully(const char* filename,
                                    intptr_t* file_len,
                                    const char** error_msg) {
  void* stream = DartUtils::OpenFile(filename, false);
  if (stream == NULL) {
    SET_ERROR_MSG(error_msg, "Unable to open file: %s", filename);
    return NULL;
  }
  *file_len = -1;
  const uint8_t* text_buffer = NULL;
  DartUtils::ReadFile(&text_buffer, file_len, stream);
  if (text_buffer == NULL || *file_len == -1) {
    *error_msg = "Unable to read file contents";
    text_buffer = NULL;
  }
  DartUtils::CloseFile(stream);
  return text_buffer;
}


Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
  const char* error_msg = NULL;
  intptr_t len;
  const uint8_t* text_buffer = ReadFileFully(filename, &len, &error_msg);
  if (text_buffer == NULL) {
    return Dart_Error(error_msg);
  }
  Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
  return str;
}


Dart_Handle DartUtils::ResolveScriptUri(Dart_Handle script_uri,
                                        Dart_Handle builtin_lib) {
  const int kNumArgs = 3;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = NewString(original_working_directory);
  dart_args[1] = script_uri;
  dart_args[2] = (IsWindowsHost() ? Dart_True() : Dart_False());
  return Dart_Invoke(builtin_lib,
                     NewString("_resolveScriptUri"),
                     kNumArgs,
                     dart_args);
}


Dart_Handle DartUtils::FilePathFromUri(Dart_Handle script_uri,
                                       Dart_Handle builtin_lib) {
  const int kNumArgs = 2;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = script_uri;
  dart_args[1] = (IsWindowsHost() ? Dart_True() : Dart_False());
  return Dart_Invoke(builtin_lib,
                     NewString("_filePathFromUri"),
                     kNumArgs,
                     dart_args);
}


Dart_Handle DartUtils::ResolveUri(Dart_Handle library_url,
                                  Dart_Handle url,
                                  Dart_Handle builtin_lib) {
  const int kNumArgs = 2;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = library_url;
  dart_args[1] = url;
  return Dart_Invoke(
      builtin_lib, NewString("_resolveUri"), kNumArgs, dart_args);
}


Dart_Handle DartUtils::LibraryTagHandler(Dart_LibraryTag tag,
                                         Dart_Handle library,
                                         Dart_Handle url) {
  if (!Dart_IsLibrary(library)) {
    return Dart_Error("not a library");
  }
  if (!Dart_IsString(url)) {
    return Dart_Error("url is not a string");
  }
  const char* url_string = NULL;
  Dart_Handle result = Dart_StringToCString(url, &url_string);
  if (Dart_IsError(result)) {
    return result;
  }
  Dart_Handle library_url = Dart_LibraryUrl(library);
  const char* library_url_string = NULL;
  result = Dart_StringToCString(library_url, &library_url_string);
  if (Dart_IsError(result)) {
    return result;
  }

  bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
  bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string);
  bool is_dart_extension_url = DartUtils::IsDartExtensionSchemeURL(url_string);

  // Handle URI canonicalization requests.
  if (tag == Dart_kCanonicalizeUrl) {
    // If this is a Dart Scheme URL or 'part' of a io library
    // then it is not modified as it will be handled internally.
    if (is_dart_scheme_url || is_io_library) {
      return url;
    }
    // Resolve the url within the context of the library's URL.
    Dart_Handle builtin_lib =
        Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
    Dart_Handle library_url = Dart_LibraryUrl(library);
    if (Dart_IsError(library_url)) {
      return library_url;
    }
    return ResolveUri(library_url, url, builtin_lib);
  }

  // Handle 'import' of dart scheme URIs (i.e they start with 'dart:').
  if (is_dart_scheme_url) {
    if (tag == Dart_kImportTag) {
      // Handle imports of other built-in libraries present in the SDK.
      if (DartUtils::IsDartIOLibURL(url_string)) {
        return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
      }
      return Dart_Error("Do not know how to load '%s'", url_string);
    } else {
      ASSERT(tag == Dart_kSourceTag);
      return Dart_Error("Unable to load source '%s' ", url_string);
    }
  }

  // Handle 'part' of IO library.
  if (is_io_library) {
    if (tag == Dart_kSourceTag) {
      return Dart_LoadSource(
          library, url, Builtin::PartSource(Builtin::kIOLibrary, url_string));
    } else {
      ASSERT(tag == Dart_kImportTag);
      return Dart_Error("Unable to import '%s' ", url_string);
    }
  }

  // Handle 'import' or 'part' requests for all other URIs.
  // Get the file path out of the url.
  Dart_Handle builtin_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
  Dart_Handle file_path = FilePathFromUri(url, builtin_lib);
  if (Dart_IsError(file_path)) {
    return file_path;
  }
  Dart_StringToCString(file_path, &url_string);
  if (is_dart_extension_url) {
    if (tag != Dart_kImportTag) {
      return Dart_Error("Dart extensions must use import: '%s'", url_string);
    }
    return Extensions::LoadExtension(url_string, library);
  }
  result = DartUtils::LoadSource(NULL,
                                 library,
                                 url,
                                 tag,
                                 url_string);
  return result;
}


const uint8_t* DartUtils::SniffForMagicNumber(const uint8_t* text_buffer,
                                              intptr_t* buffer_len,
                                              bool* is_snapshot) {
  intptr_t len = sizeof(magic_number);
  for (intptr_t i = 0; i < len; i++) {
    if (text_buffer[i] != magic_number[i]) {
      *is_snapshot = false;
      return text_buffer;
    }
  }
  *is_snapshot = true;
  ASSERT(*buffer_len > len);
  *buffer_len -= len;
  return text_buffer + len;
}


void DartUtils::WriteMagicNumber(File* file) {
  // Write a magic number and version information into the snapshot file.
  bool bytes_written = file->WriteFully(magic_number, sizeof(magic_number));
  ASSERT(bytes_written);
}


Dart_Handle DartUtils::LoadScriptHttp(Dart_Handle uri,
                                      Dart_Handle builtin_lib) {
  intptr_t len = 0;
  uint8_t* buffer = NULL;
  Dart_Handle result = MakeHttpRequest(uri, builtin_lib, &buffer, &len);
  if (Dart_IsError(result)) {
    return result;
  }
  const uint8_t* payload = buffer;
  bool is_snapshot = false;
  payload = SniffForMagicNumber(payload, &len, &is_snapshot);
  if (is_snapshot) {
    return Dart_LoadScriptFromSnapshot(payload, len);
  } else {
    Dart_Handle source = Dart_NewStringFromUTF8(payload, len);
    free(buffer);
    if (Dart_IsError(source)) {
      return source;
    }
    return Dart_LoadScript(uri, source, 0, 0);
  }
}


Dart_Handle DartUtils::LoadScript(const char* script_uri,
                                  Dart_Handle builtin_lib) {
  // Always call ResolveScriptUri because as a side effect it sets
  // the script entry path which is used when automatically resolving
  // package root.
  Dart_Handle resolved_script_uri =
      ResolveScriptUri(NewString(script_uri), builtin_lib);
  if (Dart_IsError(resolved_script_uri)) {
    return resolved_script_uri;
  }
  // Handle http: requests separately.
  if (DartUtils::IsHttpSchemeURL(script_uri)) {
    return LoadScriptHttp(resolved_script_uri, builtin_lib);
  }
  Dart_Handle script_path = DartUtils::FilePathFromUri(resolved_script_uri,
                                                       builtin_lib);
  if (Dart_IsError(script_path)) {
    return script_path;
  }
  const char* script_path_cstr;
  Dart_StringToCString(script_path, &script_path_cstr);
  const char* error_msg = NULL;
  intptr_t len;
  const uint8_t* text_buffer = ReadFileFully(script_path_cstr,
                                             &len,
                                             &error_msg);
  if (text_buffer == NULL) {
    return Dart_Error(error_msg);
  }
  bool is_snapshot = false;
  text_buffer = SniffForMagicNumber(text_buffer, &len, &is_snapshot);
  if (is_snapshot) {
    return Dart_LoadScriptFromSnapshot(text_buffer, len);
  } else {
    Dart_Handle source = Dart_NewStringFromUTF8(text_buffer, len);
    if (Dart_IsError(source)) {
      return source;
    }
    return Dart_LoadScript(resolved_script_uri, source, 0, 0);
  }
}


Dart_Handle DartUtils::LoadSource(CommandLineOptions* url_mapping,
                                  Dart_Handle library,
                                  Dart_Handle url,
                                  Dart_LibraryTag tag,
                                  const char* url_string) {
  bool is_http_scheme_url = DartUtils::IsHttpSchemeURL(url_string);
  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;
  }
  Dart_Handle source;
  if (is_http_scheme_url) {
    // Read the file over http.
    source = DartUtils::ReadStringFromHttp(url_string);
  } else {
    // Read the file.
    source = DartUtils::ReadStringFromFile(url_string);
  }
  if (Dart_IsError(source)) {
    return source;  // source contains the error string.
  }
  // The tag is either an import or a source tag.
  // Load it according to the specified tag.
  if (tag == Dart_kImportTag) {
    // Return library object or an error string.
    return Dart_LoadLibrary(url, source);
  } else if (tag == Dart_kSourceTag) {
    return Dart_LoadSource(library, url, source);
  }
  return Dart_Error("wrong tag");
}


Dart_Handle DartUtils::PrepareForScriptLoading(const char* package_root,
                                               Dart_Handle builtin_lib) {
  // Setup the corelib 'print' function.
  Dart_Handle print = Dart_Invoke(
      builtin_lib, NewString("_getPrintClosure"), 0, 0);
  Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
  Dart_Handle result = Dart_SetField(corelib,
                                     NewString("_printClosure"),
                                     print);

  // Setup the 'timer' factory.
  Dart_Handle url = NewString(kAsyncLibURL);
  DART_CHECK_VALID(url);
  Dart_Handle async_lib = Dart_LookupLibrary(url);
  DART_CHECK_VALID(async_lib);
  Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
  Dart_Handle timer_closure =
      Dart_Invoke(io_lib, NewString("_getTimerFactoryClosure"), 0, NULL);
  Dart_Handle args[1];
  args[0] = timer_closure;
  DART_CHECK_VALID(Dart_Invoke(
      async_lib, NewString("_setTimerFactoryClosure"), 1, args));

  // Set up package root if specified.
  if (package_root != NULL) {
    result = NewString(package_root);
    if (!Dart_IsError(result)) {
      const int kNumArgs = 1;
      Dart_Handle dart_args[kNumArgs];
      dart_args[0] = result;
      return Dart_Invoke(builtin_lib,
                         NewString("_setPackageRoot"),
                         kNumArgs,
                         dart_args);
    }
  }
  return result;
}


const char* DartUtils::GetCanonicalPath(const char* reference_dir,
                                        const char* filename) {
  if (File::IsAbsolutePath(filename)) {
    return strdup(filename);
  }

  char* canonical_path = File::GetCanonicalPath(reference_dir);
  if  (canonical_path == NULL) {
    canonical_path = strdup(reference_dir);
    ASSERT(canonical_path != NULL);
  }
  ASSERT(File::PathSeparator() != NULL && strlen(File::PathSeparator()) == 1);
  char* path_sep = strrchr(canonical_path, File::PathSeparator()[0]);
  if (path_sep == NULL) {
    // No separator found: Reference is a file in local directory.
    free(canonical_path);
    return strdup(filename);
  }
  *path_sep = '\0';
  intptr_t len = snprintf(NULL, 0, "%s%s%s",
                          canonical_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",
           canonical_path, File::PathSeparator(), filename);
  free(canonical_path);
  canonical_path = File::GetCanonicalPath(absolute_filename);
  if (canonical_path == NULL) {
    return absolute_filename;
  }
  free(absolute_filename);
  return canonical_path;
}


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::GetDartClass(const char* library_url,
                                    const char* class_name) {
  return Dart_GetClass(Dart_LookupLibrary(NewString(library_url)),
                       NewString(class_name));
}


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:io OSError object with the information retrieved from the OS.
  Dart_Handle clazz = GetDartClass(kIOLibURL, "OSError");
  Dart_Handle args[2];
  args[0] = NewString(os_error->message());
  args[1] = Dart_NewInteger(os_error->code());
  return Dart_New(clazz, Dart_Null(), 2, args);
}


Dart_Handle DartUtils::NewDartSocketException(const char* message,
                                              Dart_Handle os_error) {
  // Create a dart:io SocketException object.
  Dart_Handle clazz = GetDartClass(kIOLibURL, "SocketException");
  Dart_Handle args[2];
  args[0] = NewString(message);
  args[1] = os_error;
  return Dart_New(clazz, Dart_Null(), 2, args);
}


Dart_Handle DartUtils::NewDartExceptionWithMessage(const char* library_url,
                                                   const char* exception_name,
                                                   const char* message) {
  // Create a Dart Exception object with a message.
  Dart_Handle clazz = GetDartClass(library_url, exception_name);
  if (message != NULL) {
    Dart_Handle args[1];
    args[0] = NewString(message);
    return Dart_New(clazz, Dart_Null(), 1, args);
  } else {
    return Dart_New(clazz, Dart_Null(), 0, NULL);
  }
}


Dart_Handle DartUtils::NewDartArgumentError(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL,
                                     "ArgumentError",
                                     message);
}


Dart_Handle DartUtils::NewInternalError(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL, "InternalError", message);
}


void DartUtils::SetOriginalWorkingDirectory() {
  original_working_directory = Directory::Current();
}


// 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::NewUint8Array(int length) {
  Dart_CObject* cobject = New(Dart_CObject_kTypedData, length);
  cobject->value.as_typed_data.type = Dart_TypedData_kUint8;
  cobject->value.as_typed_data.length = length;
  cobject->value.as_typed_data.values = reinterpret_cast<uint8_t*>(cobject + 1);
  return cobject;
}


Dart_CObject* CObject::NewExternalUint8Array(
    int64_t length, uint8_t* data, void* peer,
    Dart_WeakPersistentHandleFinalizer callback) {
  Dart_CObject* cobject = New(Dart_CObject_kExternalTypedData);
  cobject->value.as_external_typed_data.type = Dart_TypedData_kUint8;
  cobject->value.as_external_typed_data.length = length;
  cobject->value.as_external_typed_data.data = data;
  cobject->value.as_external_typed_data.peer = peer;
  cobject->value.as_external_typed_data.callback = callback;
  return cobject;
}


Dart_CObject* CObject::NewIOBuffer(int64_t length) {
  uint8_t* data = IOBuffer::Allocate(length);
  return NewExternalUint8Array(length, data, data, IOBuffer::Finalizer);
}


void CObject::FreeIOBufferData(Dart_CObject* cobject) {
  ASSERT(cobject->type == Dart_CObject_kExternalTypedData);
  cobject->value.as_external_typed_data.callback(
      NULL, cobject->value.as_external_typed_data.peer);
  cobject->value.as_external_typed_data.data = NULL;
}


CObject* CObject::IllegalArgumentError() {
  CObjectArray* result = new CObjectArray(CObject::NewArray(1));
  result->SetAt(0, new CObjectInt32(CObject::NewInt32(kArgumentError)));
  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;
}

}  // namespace bin
}  // namespace dart
