Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: runtime/vm/dev_fs.cc

Issue 2059883003: DevFS initial implementation (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/dev_fs.h ('k') | runtime/vm/isolate.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include <map>
6 #include <string>
7 #include <vector>
8
9 #include "vm/dev_fs.h"
10
11 #include "vm/hash_table.h"
12 #include "vm/json_stream.h"
13 #include "vm/lockers.h"
14 #include "vm/object.h"
15 #include "vm/unicode.h"
16
17 namespace dart {
18
19 static const uint8_t decode_table[256] = {
20 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
21 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
22 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
23 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
24 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
25 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
26 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
27 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
28 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
29 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
30 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
31 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
32 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
33 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
35 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
36 };
37
38 class Base64 {
39 public:
40 static void decode(const char* base64,
41 std::vector<uint8_t>* output) {
42 ASSERT(output != NULL);
43 ASSERT(base64 != NULL);
44 const intptr_t base64_len = strlen(base64);
45 int b[4];
46 for (intptr_t i = 0; i < base64_len; i += 4) {
47 b[0] = decode_table[static_cast<uint8_t>(base64[i])];
48 b[1] = decode_table[static_cast<uint8_t>(base64[i + 1])];
49 b[2] = decode_table[static_cast<uint8_t>(base64[i + 2])];
50 b[3] = decode_table[static_cast<uint8_t>(base64[i + 3])];
51 output->push_back((b[0] << 2) | (b[1] >> 4));
52 if (b[2] < 64) {
53 output->push_back((b[1] << 4) | (b[2] >> 2));
54 if (b[3] < 64) {
55 output->push_back((b[2] << 6) | b[3]);
56 }
57 }
58 }
59 }
60 };
61
62
63 class FileSystem {
64 public:
65 explicit FileSystem(const std::string& name)
66 : name_(name) {
67 }
68
69 ~FileSystem() {
70 }
71
72 bool ReadFile(const std::string& path,
73 std::vector<uint8_t>** file_contents) {
74 *file_contents = NULL;
75 std::map<std::string, std::vector<uint8_t>*>::iterator iter;
76 iter = files_.find(path);
77 if (iter == files_.end()) {
78 return false;
79 }
80 *file_contents = iter->second;
81 return true;
82 }
83
84 void DeleteFile(const std::string& path) {
85 std::map<std::string, std::vector<uint8_t>*>::iterator iter;
86 iter = files_.find(path);
87 if (iter == files_.end()) {
88 return;
89 }
90 std::vector<uint8_t>* contents = iter->second;
91 files_.erase(iter);
92 delete contents;
93 }
94
95 void WriteFile(const std::string& path,
96 const char* file_contents) {
97 DeleteFile(path);
98 std::vector<uint8_t>* data = new std::vector<uint8_t>();
99 Base64::decode(file_contents, data);
100 files_[path] = data;
101 }
102
103 void ListFiles(JSONStream* js) {
104 JSONObject jsobj(js);
105 jsobj.AddProperty("type", "FSFilesList");
106 JSONArray jsarr(&jsobj, "files");
107 std::map<std::string, std::vector<uint8_t>*>::iterator iter;
108 for (iter = files_.begin(); iter != files_.end(); iter++) {
109 JSONObject file_info(&jsarr);
110 file_info.AddProperty("name", iter->first.c_str());
111 file_info.AddProperty("size", static_cast<int64_t>(iter->second->size()));
112 }
113 }
114
115 private:
116 std::string name_;
117
118 std::map<std::string, std::vector<uint8_t>*> files_;
119 };
120
121 // Some static state is held outside of the DevFS class so that we don't
122 // have to include stl headers in our vm/ headers.
123 static std::map<std::string, FileSystem*>* file_systems_;
124
125 Mutex* DevFS::mutex_ = NULL;
126
127
128 void DevFS::Init() {
129 if (mutex_ != NULL) {
130 // Already initialized.
131 ASSERT(file_systems_ != NULL);
132 return;
133 }
134 mutex_ = new Mutex();
135 file_systems_ = new std::map<std::string, FileSystem*>();
136 ASSERT(mutex_ != NULL);
137 ASSERT(file_systems_ != NULL);
138 }
139
140
141 void DevFS::Cleanup() {
142 delete mutex_;
143 mutex_ = NULL;
144 std::map<std::string, FileSystem*>::iterator iter;
145 for (iter = file_systems_->begin(); iter != file_systems_->end(); iter++) {
146 FileSystem* fs = iter->second;
147 delete fs;
148 }
149 delete file_systems_;
150 file_systems_ = NULL;
151 }
152
153
154 void DevFS::ListFileSystems(JSONStream* js) {
155 SafepointMutexLocker ml(mutex_);
156 JSONObject jsobj(js);
157 jsobj.AddProperty("type", "FSList");
158 JSONArray jsarr(&jsobj, "fsNames");
159
160 std::map<std::string, FileSystem*>::iterator iter;
161 for (iter = file_systems_->begin(); iter != file_systems_->end(); iter++) {
162 const std::string& key = iter->first;
163 jsarr.AddValue(key.c_str());
164 }
165 }
166
167
168 FileSystem* DevFS::LookupFileSystem(const char* fs_name) {
169 std::string key = std::string(fs_name);
170 std::map<std::string, FileSystem*>::iterator iter;
171 iter = file_systems_->find(key);
172 if (iter != file_systems_->end()) {
173 return iter->second;
174 }
175 return NULL;
176 }
177
178
179 FileSystem* DevFS::LookupFileSystem(const String& fs_name) {
180 return LookupFileSystem(fs_name.ToCString());
181 }
182
183
184 void DevFS::CreateFileSystem(JSONStream* js, const String& fs_name) {
185 SafepointMutexLocker ml(mutex_);
186 // TODO(turnidge): Ensure that fs_name is a legal URI host value, i.e. ascii.
187 if (LookupFileSystem(fs_name) != NULL) {
188 js->PrintError(kFileSystemAlreadyExists,
189 "%s: file system '%s' already exists",
190 js->method(), fs_name.ToCString());
191 return;
192 }
193
194 std::string key = std::string(fs_name.ToCString());
195 FileSystem* file_system = new FileSystem(key);
196 (*file_systems_)[key] = file_system;
197
198 JSONObject jsobj(js);
199 jsobj.AddProperty("type", "Success");
200 }
201
202
203 void DevFS::DeleteFileSystem(JSONStream* js, const String& fs_name) {
204 SafepointMutexLocker ml(mutex_);
205 FileSystem* file_system = LookupFileSystem(fs_name);
206 if (file_system == NULL) {
207 js->PrintError(kFileSystemDoesNotExist,
208 "%s: file system '%s' does not exist",
209 js->method(), fs_name.ToCString());
210 return;
211 }
212 std::string key = std::string(fs_name.ToCString());
213 file_systems_->erase(key);
214 delete file_system;
215 JSONObject jsobj(js);
216 jsobj.AddProperty("type", "Success");
217 }
218
219
220 void DevFS::ListFiles(JSONStream* js, const String& fs_name) {
221 SafepointMutexLocker ml(mutex_);
222 FileSystem* file_system = LookupFileSystem(fs_name);
223 if (file_system == NULL) {
224 js->PrintError(kFileSystemDoesNotExist,
225 "%s: file system '%s' does not exist",
226 js->method(), fs_name.ToCString());
227 return;
228 }
229
230 file_system->ListFiles(js);
231 }
232
233
234 static void PrintWriteFilesError(JSONStream* js,
235 intptr_t i) {
236 js->PrintError(kInvalidParams,
237 "%s: files array invalid at index '%" Pd "'",
238 js->method(), i);
239 }
240
241
242 void DevFS::WriteFiles(JSONStream* js,
243 const String& fs_name,
244 const Array& files) {
245 SafepointMutexLocker ml(mutex_);
246 FileSystem* file_system = LookupFileSystem(fs_name);
247 if (file_system == NULL) {
248 js->PrintError(kFileSystemDoesNotExist,
249 "%s: file system '%s' does not exist",
250 js->method(), fs_name.ToCString());
251 return;
252 }
253
254 Object& test = Object::Handle();
255 GrowableObjectArray& file_info = GrowableObjectArray::Handle();
256 String& path = String::Handle();
257 String& file_contents = String::Handle();
258
259 // First, validate the array of files is properly formed.
260 for (intptr_t i = 0; i < files.Length(); i++) {
261 test = files.At(i);
262 if (!test.IsGrowableObjectArray()) {
263 PrintWriteFilesError(js, i);
264 return;
265 }
266 file_info ^= test.raw();
267 if (file_info.Length() != 2) {
268 PrintWriteFilesError(js, i);
269 return;
270 }
271 test = file_info.At(0);
272 if (!test.IsString()) {
273 PrintWriteFilesError(js, i);
274 return;
275 }
276 std::string key = std::string(String::Cast(test).ToCString());
277 if ((key.size() == 0) || (key[0] != '/')) {
278 js->PrintError(kInvalidParams,
279 "%s: file system path '%s' must begin with a /",
280 js->method(), String::Cast(test).ToCString());
281 return;
282 }
283 test = file_info.At(1);
284 if (!test.IsString()) {
285 PrintWriteFilesError(js, i);
286 return;
287 }
288 }
289
290 // Now atomically update the file system.
291 for (intptr_t i = 0; i < files.Length(); i++) {
292 file_info = GrowableObjectArray::RawCast(files.At(i));
293 path = String::RawCast(file_info.At(0));
294 file_contents = String::RawCast(file_info.At(1));
295 file_system->WriteFile(path.ToCString(),
296 file_contents.ToCString());
297 }
298
299 JSONObject jsobj(js);
300 jsobj.AddProperty("type", "Success");
301 }
302
303
304 void DevFS::WriteFile(JSONStream* js,
305 const String& fs_name,
306 const String& path,
307 const String& file_contents) {
308 SafepointMutexLocker ml(mutex_);
309 FileSystem* file_system = LookupFileSystem(fs_name);
310 if (file_system == NULL) {
311 js->PrintError(kFileSystemDoesNotExist,
312 "%s: file system '%s' does not exist",
313 js->method(), fs_name.ToCString());
314 return;
315 }
316
317 std::string key = std::string(path.ToCString());
318 if ((key.size() == 0) || (key[0] != '/')) {
319 js->PrintError(kInvalidParams,
320 "%s: file system path '%s' must begin with a /",
321 js->method(), path.ToCString());
322 return;
323 }
324
325 file_system->WriteFile(path.ToCString(),
326 file_contents.ToCString());
327
328 JSONObject jsobj(js);
329 jsobj.AddProperty("type", "Success");
330 }
331
332
333 void DevFS::ReadFile(JSONStream* js,
334 const String& fs_name,
335 const String& path) {
336 SafepointMutexLocker ml(mutex_);
337 FileSystem* file_system = LookupFileSystem(fs_name);
338 if (file_system == NULL) {
339 js->PrintError(kFileSystemDoesNotExist,
340 "%s: file system '%s' does not exist",
341 js->method(), fs_name.ToCString());
342 return;
343 }
344
345 std::string key = std::string(path.ToCString());
346 if ((key.size() == 0) || (key[0] != '/')) {
347 js->PrintError(kInvalidParams,
348 "%s: file system path '%s' must begin with a /",
349 js->method(), path.ToCString());
350 return;
351 }
352 std::vector<uint8_t>* file_contents;
353
354 bool success = file_system->ReadFile(key, &file_contents);
355
356 if (!success) {
357 js->PrintError(kFileDoesNotExist,
358 "%s: file 'dart-devfs://%s/%s' does not exist",
359 js->method(), fs_name.ToCString(), path.ToCString());
360 return;
361 }
362
363 JSONObject jsobj(js);
364 jsobj.AddProperty("type", "FSFile");
365 jsobj.AddPropertyBase64("fileContents",
366 &((*file_contents)[0]),
367 file_contents->size());
368 }
369
370 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/dev_fs.h ('k') | runtime/vm/isolate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698