Chromium Code Reviews| 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 |