OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | |
7 #include "vm/dart_api_impl.h" | 6 #include "vm/dart_api_impl.h" |
8 #include "vm/exceptions.h" | 7 #include "vm/exceptions.h" |
8 #include "vm/growable_array.h" | |
9 #include "vm/message.h" | 9 #include "vm/message.h" |
10 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/port.h" | 12 #include "vm/port.h" |
13 #include "vm/service_isolate.h" | 13 #include "vm/service_isolate.h" |
14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DECLARE_FLAG(bool, trace_service); | 18 DECLARE_FLAG(bool, trace_service); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0)); | 144 GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0)); |
145 Service::CancelStream(stream_id.ToCString()); | 145 Service::CancelStream(stream_id.ToCString()); |
146 return Object::null(); | 146 return Object::null(); |
147 } | 147 } |
148 | 148 |
149 | 149 |
150 DEFINE_NATIVE_ENTRY(VMService_RequestAssets, 0) { | 150 DEFINE_NATIVE_ENTRY(VMService_RequestAssets, 0) { |
151 return Service::RequestAssets(); | 151 return Service::RequestAssets(); |
152 } | 152 } |
153 | 153 |
154 | |
155 class ByteStream { | |
Ivan Posva
2015/11/25 17:09:04
How does this differ from class ReadStream in data
zra
2015/11/25 19:06:15
There isn't a big difference, and I changed to use
| |
156 public: | |
157 ByteStream(uint8_t* bytes, intptr_t bytes_length) : | |
158 bytes_(bytes), bytes_length_(bytes_length), cursor_(0) {} | |
159 | |
160 intptr_t length() const { return bytes_length_; } | |
161 | |
162 intptr_t remaining() const { return length() - cursor_; } | |
163 | |
164 intptr_t cursor() const { return cursor_; } | |
165 | |
166 uint8_t* current() const { | |
167 return bytes_ + cursor_; | |
168 } | |
169 | |
170 uint8_t PeekByte(intptr_t index = 0) const { | |
171 return bytes_[cursor_ + index]; | |
172 } | |
173 | |
174 uint8_t ReadByte() { | |
175 uint8_t r = PeekByte(); | |
176 advance(1); | |
177 return r; | |
178 } | |
179 | |
180 intptr_t ReadBytes(uint8_t* bytes, intptr_t num_bytes) { | |
181 uint8_t* src = bytes_ + cursor_; | |
182 num_bytes = num_bytes > remaining() ? remaining() : num_bytes; | |
183 memmove(bytes, src, num_bytes); | |
184 advance(num_bytes); | |
185 return num_bytes; | |
186 } | |
187 | |
188 void Skip(intptr_t bytes) { | |
189 advance(bytes); | |
190 } | |
191 | |
192 void SeekToNextBlock(intptr_t blockSize) { | |
193 intptr_t remainder = blockSize - (cursor_ % blockSize); | |
194 advance(remainder); | |
195 } | |
196 | |
197 void SetCursor(intptr_t cursor) { | |
198 cursor_ = cursor; | |
199 if (cursor_ > length()) { | |
200 cursor_ = length(); | |
201 } | |
202 } | |
203 | |
204 private: | |
205 void advance(intptr_t bytes) { | |
206 cursor_ += bytes; | |
207 if (cursor_ > length()) { | |
208 cursor_ = length(); | |
209 } | |
210 } | |
211 | |
212 uint8_t* bytes_; | |
213 intptr_t bytes_length_; | |
214 intptr_t cursor_; | |
215 | |
216 DISALLOW_COPY_AND_ASSIGN(ByteStream); | |
217 }; | |
218 | |
219 | |
220 class TarArchive { | |
221 public: | |
222 static const intptr_t tarHeaderSize = 512; | |
Ivan Posva
2015/11/25 17:09:04
enum instead of a set of constants? Then you can a
zra
2015/11/25 19:06:15
Changed to private enums.
| |
223 static const intptr_t tarHeaderFilenameSize = 100; | |
224 static const intptr_t tarHeaderFilenameOffset = 0; | |
225 static const intptr_t tarHeaderSizeSize = 12; | |
226 static const intptr_t tarHeaderSizeOffset = 124; | |
227 static const intptr_t tarHeaderTypeSize = 1; | |
228 static const intptr_t tarHeaderTypeOffset = 156; | |
229 static const intptr_t tarHeaderFileType = 0x30; | |
230 | |
231 TarArchive(uint8_t* bytes, intptr_t bytes_length) | |
232 : bs_(bytes, bytes_length) {} | |
233 | |
234 void Read() { | |
235 while (HasNext()) { | |
236 char* filename; | |
237 uint8_t* data; | |
238 intptr_t data_length; | |
239 if (Next(&filename, &data, &data_length)) { | |
240 filenames_.Add(filename); | |
241 contents_.Add(data); | |
242 content_lengths_.Add(data_length); | |
243 } | |
244 } | |
245 } | |
246 | |
247 char* NextFilename() { | |
248 return filenames_.RemoveLast(); | |
249 } | |
250 | |
251 uint8_t* NextContent() { | |
252 return contents_.RemoveLast(); | |
253 } | |
254 | |
255 intptr_t NextContentLength() { | |
256 return content_lengths_.RemoveLast(); | |
257 } | |
258 | |
259 bool HasMore() const { | |
260 return filenames_.length() > 0; | |
261 } | |
262 | |
263 intptr_t Length() const { return filenames_.length(); } | |
264 | |
265 private: | |
266 bool HasNext() const { | |
267 return !EndOfArchive(); | |
268 } | |
269 | |
270 bool Next(char** filename, uint8_t** data, intptr_t* data_length) { | |
271 intptr_t startOfBlock = bs_.cursor(); | |
272 *filename = ReadFilename(); | |
273 bs_.SetCursor(startOfBlock + tarHeaderSizeOffset); | |
274 intptr_t size = ReadSize(); | |
275 bs_.SetCursor(startOfBlock + tarHeaderTypeOffset); | |
276 uint8_t type = ReadType(); | |
277 bs_.SeekToNextBlock(tarHeaderSize); | |
278 if (type != tarHeaderFileType) { | |
279 SkipContents(size); | |
280 return false; | |
281 } | |
282 ReadContents(data, size); | |
283 *data_length = size; | |
284 return true; | |
285 } | |
286 | |
287 bool EndOfArchive() const { | |
288 if (bs_.remaining() < (tarHeaderSize * 2)) { | |
289 return true; | |
290 } | |
291 for (intptr_t i = 0; i < (tarHeaderSize * 2); i++) { | |
292 if (bs_.PeekByte(i) != 0) { | |
293 return false; | |
294 } | |
295 } | |
296 return true; | |
297 } | |
298 | |
299 uint8_t ReadType() { | |
300 return bs_.ReadByte(); | |
301 } | |
302 | |
303 void SkipContents(intptr_t size) { | |
304 bs_.Skip(size); | |
305 bs_.SeekToNextBlock(tarHeaderSize); | |
306 } | |
307 | |
308 intptr_t ReadCString(char** s, intptr_t length) { | |
309 intptr_t to_read = Utils::Minimum(length, bs_.remaining()); | |
310 char* result = new char[to_read + 1]; | |
311 strncpy(result, reinterpret_cast<char*>(bs_.current()), to_read); | |
312 result[to_read] = '\0'; | |
313 bs_.SetCursor(bs_.cursor() + to_read); | |
314 *s = result; | |
315 return to_read; | |
316 } | |
317 | |
318 intptr_t ReadSize() { | |
319 char* octalSize; | |
320 unsigned int size; | |
321 | |
322 ReadCString(&octalSize, tarHeaderSizeSize); | |
323 int result = sscanf(octalSize, "%o", &size); | |
324 delete[] octalSize; | |
325 | |
326 if (result != 1) { | |
327 return 0; | |
328 } | |
329 return size; | |
330 } | |
331 | |
332 char* ReadFilename() { | |
333 char* result; | |
334 intptr_t result_length = ReadCString(&result, tarHeaderFilenameSize); | |
335 if (result[0] == '/') { | |
336 return result; | |
337 } | |
338 char* fixed_result = new char[result_length + 2]; // '/' + '\0'. | |
339 fixed_result[0] = '/'; | |
340 strncpy(&fixed_result[1], result, result_length); | |
341 fixed_result[result_length + 1] = '\0'; | |
342 delete[] result; | |
343 return fixed_result; | |
344 } | |
345 | |
346 void ReadContents(uint8_t** data, intptr_t size) { | |
347 uint8_t* result = new uint8_t[size]; | |
348 bs_.ReadBytes(result, size); | |
349 bs_.SeekToNextBlock(tarHeaderSize); | |
350 *data = result; | |
351 } | |
352 | |
353 ByteStream bs_; | |
354 GrowableArray<char*> filenames_; | |
355 GrowableArray<uint8_t*> contents_; | |
356 GrowableArray<intptr_t> content_lengths_; | |
357 | |
358 DISALLOW_COPY_AND_ASSIGN(TarArchive); | |
359 }; | |
360 | |
361 static void ContentsFinalizer(void* isolate_callback_data, | |
362 Dart_WeakPersistentHandle handle, | |
363 void* peer) { | |
364 uint8_t* data = reinterpret_cast<uint8_t*>(peer); | |
Ivan Posva
2015/11/25 17:36:44
You also should delete the handle here. No?
zra
2015/11/25 19:06:15
Looking at //runtime/bin/io_buffer.h the Finalizer
zra
2015/11/25 20:52:58
We verified offline that WeakPersistentHandles are
| |
365 delete[] data; | |
366 } | |
367 | |
368 DEFINE_NATIVE_ENTRY(VMService_DecodeAssets, 1) { | |
369 GET_NON_NULL_NATIVE_ARGUMENT(TypedData, data, arguments->NativeArgAt(0)); | |
370 Api::Scope scope(thread); | |
371 | |
372 Dart_Handle data_handle = Api::NewHandle(thread->isolate(), data.raw()); | |
373 | |
374 Dart_TypedData_Type typ; | |
375 void* bytes; | |
376 intptr_t length; | |
377 Dart_Handle err = Dart_TypedDataAcquireData( | |
378 data_handle, &typ, &bytes, &length); | |
Ivan Posva
2015/11/25 17:36:44
As discussed we should check if there is a possibi
zra
2015/11/25 19:06:16
Filed issue #25041 and added a TODO.
| |
379 ASSERT(!Dart_IsError(err)); | |
380 | |
381 TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length); | |
382 archive.Read(); | |
383 | |
384 err = Dart_TypedDataReleaseData(data_handle); | |
385 ASSERT(!Dart_IsError(err)); | |
386 | |
387 intptr_t archive_size = archive.Length(); | |
388 | |
389 const Array& result_list = Array::Handle(thread->zone(), | |
390 Array::New(archive_size)); | |
391 | |
392 intptr_t idx = 0; | |
393 while (archive.HasMore()) { | |
394 char* filename = archive.NextFilename(); | |
395 uint8_t* contents = archive.NextContent(); | |
396 intptr_t contents_length = archive.NextContentLength(); | |
397 | |
398 const Array& pair = Array::Handle(thread->zone(), Array::New(2)); | |
399 | |
400 const String& dart_filename = String::Handle(thread->zone(), | |
401 String::New(filename)); | |
402 delete[] filename; | |
403 | |
404 Dart_Handle dart_contents = Dart_NewExternalTypedData( | |
405 Dart_TypedData_kUint8, contents, contents_length); | |
406 ASSERT(!Dart_IsError(dart_contents)); | |
407 Dart_NewWeakPersistentHandle( | |
408 dart_contents, contents, contents_length, ContentsFinalizer); | |
409 | |
410 pair.SetAt(0, dart_filename); | |
411 pair.SetAt(1, Api::UnwrapExternalTypedDataHandle( | |
412 thread->zone(), dart_contents)); | |
413 result_list.SetAt(idx, pair); | |
414 idx++; | |
415 } | |
416 | |
417 return result_list.raw(); | |
418 } | |
419 | |
154 } // namespace dart | 420 } // namespace dart |
OLD | NEW |