| Index: runtime/vm/dev_fs.cc
|
| diff --git a/runtime/vm/dev_fs.cc b/runtime/vm/dev_fs.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bde13c3d20f0e09ffe499cc97228ebc0c40121e9
|
| --- /dev/null
|
| +++ b/runtime/vm/dev_fs.cc
|
| @@ -0,0 +1,187 @@
|
| +// Copyright (c) 2016, 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 "vm/dev_fs.h"
|
| +
|
| +#include "vm/hash_table.h"
|
| +#include "vm/json_stream.h"
|
| +#include "vm/object.h"
|
| +
|
| +namespace dart {
|
| +
|
| +class StringMapTraits {
|
| + public:
|
| + static bool ReportStats() { return false; }
|
| + static const char* Name() { return "StringMapTraits"; }
|
| +
|
| + static bool IsMatch(const Object& a, const Object& b) {
|
| + return String::Cast(a).Equals(String::Cast(b));
|
| + }
|
| +
|
| + static uword Hash(const Object& obj) {
|
| + return String::Cast(obj).Hash();
|
| + }
|
| +};
|
| +
|
| +
|
| +Mutex* DevFS::mutex_ = NULL;
|
| +RawArray* DevFS::fs_map_storage_ = NULL;
|
| +
|
| +
|
| +void DevFS::VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
| + visitor->VisitPointers(from(), to());
|
| +}
|
| +
|
| +
|
| +void DevFS::Init() {
|
| + mutex_ = new Mutex();
|
| +}
|
| +
|
| +
|
| +void DevFS::EnsureStorage() {
|
| + if (fs_map_storage_ == NULL) {
|
| + fs_map_storage_ = HashTables::New<UnorderedHashMap<StringMapTraits> >(4);
|
| + }
|
| +}
|
| +
|
| +
|
| +void DevFS::ListFileSystems(JSONStream* js) {
|
| + EnsureStorage();
|
| +
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "FSList");
|
| + JSONArray jsarr(&jsobj, "ids");
|
| +
|
| + String& fs_name = String::Handle();
|
| + UnorderedHashMap<StringMapTraits> fs_map(fs_map_storage_);
|
| + {
|
| + UnorderedHashMap<StringMapTraits>::Iterator it(&fs_map);
|
| + while (it.MoveNext()) {
|
| + const intptr_t entry = it.Current();
|
| + fs_name = String::RawCast(fs_map.GetKey(entry));
|
| + jsarr.AddValue(fs_name.ToCString());
|
| + }
|
| + }
|
| + fs_map.Release();
|
| + return;
|
| +}
|
| +
|
| +
|
| +RawArray* DevFS::LookupFileSystem(const String& fs_name) {
|
| + EnsureStorage();
|
| + UnorderedHashMap<StringMapTraits> map(fs_map_storage_);
|
| + Array& fs = Array::Handle();
|
| + fs ^= map.GetOrNull(fs_name);
|
| + // No need to update storage address because no mutation occurred.
|
| + map.Release();
|
| + return fs.raw();
|
| +}
|
| +
|
| +
|
| +bool DevFS::UpdateFileSystem(const String& fs_name,
|
| + const Array& fs_contents) {
|
| + UnorderedHashMap<StringMapTraits> map(fs_map_storage_);
|
| + bool updated = map.UpdateOrInsert(fs_name, fs_contents);
|
| + fs_map_storage_ = map.Release().raw();
|
| + return updated;
|
| +}
|
| +
|
| +
|
| +void DevFS::CreateFileSystem(JSONStream* js, const char* fs_name) {
|
| + EnsureStorage();
|
| + // TODO(turnidge): Ensure that fs_name is a legal URI host value, i.e. ascii.
|
| + const String& fs = String::Handle(String::New(fs_name));
|
| + if (LookupFileSystem(fs) != Array::null()) {
|
| + js->PrintError(kFileSystemAlreadyExists,
|
| + "%s: file system '%s' already exists",
|
| + js->method(), fs_name);
|
| + return;
|
| + }
|
| +
|
| + bool update = UpdateFileSystem(
|
| + fs,
|
| + Array::Handle(HashTables::New<UnorderedHashMap<StringMapTraits> >(4)));
|
| + ASSERT(!update);
|
| +
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "Success");
|
| +}
|
| +
|
| +
|
| +void DevFS::DeleteFileSystem(JSONStream* js, const char* fs_name) {
|
| + EnsureStorage();
|
| + const String& fs = String::Handle(String::New(fs_name));
|
| + if (LookupFileSystem(fs) == Array::null()) {
|
| + js->PrintError(kFileSystemDoesNotExist,
|
| + "%s: file system '%s' does not exist",
|
| + js->method(), fs_name);
|
| + return;
|
| + }
|
| +
|
| + UnorderedHashMap<StringMapTraits> map(fs_map_storage_);
|
| + map.Remove(fs);
|
| + fs_map_storage_ = map.Release().raw();
|
| +
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "Success");
|
| +}
|
| +
|
| +
|
| +void DevFS::WriteFile(JSONStream* js,
|
| + const char* fs_name,
|
| + const char* path_param,
|
| + const char* file_contents) {
|
| + EnsureStorage();
|
| + const String& fs = String::Handle(String::New(fs_name));
|
| + const Array& fs_contents = Array::Handle(LookupFileSystem(fs));
|
| + if (fs_contents.IsNull()) {
|
| + js->PrintError(kFileSystemDoesNotExist,
|
| + "%s: file system '%s' does not exist",
|
| + js->method(), fs_name);
|
| + return;
|
| + }
|
| +
|
| + const String& path = String::Handle(String::New(path_param));
|
| + UnorderedHashMap<StringMapTraits> map(fs_contents.raw());
|
| + map.UpdateOrInsert(path, String::Handle(String::New(file_contents)));
|
| + UpdateFileSystem(fs, map.Release());
|
| +
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "Success");
|
| +}
|
| +
|
| +
|
| +void DevFS::ReadFile(JSONStream* js,
|
| + const char* fs_name,
|
| + const char* path_param) {
|
| + EnsureStorage();
|
| + const String& fs = String::Handle(String::New(fs_name));
|
| + const Array& fs_contents = Array::Handle(LookupFileSystem(fs));
|
| + if (fs_contents.IsNull()) {
|
| + js->PrintError(kFileSystemDoesNotExist,
|
| + "%s: file system '%s' does not exist",
|
| + js->method(), fs_name);
|
| + return;
|
| + }
|
| +
|
| + const String& path = String::Handle(String::New(path_param));
|
| + UnorderedHashMap<StringMapTraits> map(fs_contents.raw());
|
| + String& file_contents = String::Handle();
|
| + file_contents ^= map.GetOrNull(path);
|
| + // No need to update storage address because no mutation occurred.
|
| + map.Release();
|
| +
|
| + if (file_contents.IsNull()) {
|
| + js->PrintError(kFileDoesNotExist,
|
| + "%s: file 'dart-devfs://%s/%s' does not exist",
|
| + js->method(), fs_name, path_param);
|
| + return;
|
| + }
|
| +
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "FSFile");
|
| + jsobj.AddProperty("fileContents", file_contents.ToCString());
|
| +}
|
| +
|
| +} // namespace dart
|
|
|