forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zip_asset_store.cc
129 lines (98 loc) · 3.19 KB
/
zip_asset_store.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/assets/zip_asset_store.h"
#include "flutter/fml/build_config.h"
#include <fcntl.h>
#if !defined(OS_WIN)
#include <unistd.h>
#endif
#include <string>
#include <utility>
#include "flutter/fml/trace_event.h"
namespace blink {
void UniqueUnzipperTraits::Free(void* file) {
unzClose(file);
}
ZipAssetStore::ZipAssetStore(std::string file_path, std::string directory)
: file_path_(std::move(file_path)), directory_(std::move(directory)) {
BuildStatCache();
}
ZipAssetStore::~ZipAssetStore() = default;
UniqueUnzipper ZipAssetStore::CreateUnzipper() const {
return UniqueUnzipper{::unzOpen2(file_path_.c_str(), nullptr)};
}
// |blink::AssetResolver|
bool ZipAssetStore::IsValid() const {
return stat_cache_.size() > 0;
}
// |blink::AssetResolver|
std::unique_ptr<fml::Mapping> ZipAssetStore::GetAsMapping(
const std::string& asset_name) const {
TRACE_EVENT1("flutter", "ZipAssetStore::GetAsMapping", "name",
asset_name.c_str());
auto found = stat_cache_.find(directory_ + "/" + asset_name);
if (found == stat_cache_.end()) {
return nullptr;
}
auto unzipper = CreateUnzipper();
if (!unzipper.is_valid()) {
return nullptr;
}
int result = UNZ_OK;
result = unzGoToFilePos(unzipper.get(), &(found->second.file_pos));
if (result != UNZ_OK) {
FML_LOG(WARNING) << "unzGetCurrentFileInfo failed, error=" << result;
return nullptr;
}
result = unzOpenCurrentFile(unzipper.get());
if (result != UNZ_OK) {
FML_LOG(WARNING) << "unzOpenCurrentFile failed, error=" << result;
return nullptr;
}
std::vector<uint8_t> data(found->second.uncompressed_size);
int total_read = 0;
while (total_read < static_cast<int>(data.size())) {
int bytes_read = unzReadCurrentFile(
unzipper.get(), data.data() + total_read, data.size() - total_read);
if (bytes_read <= 0) {
return nullptr;
}
total_read += bytes_read;
}
return std::make_unique<fml::DataMapping>(std::move(data));
}
void ZipAssetStore::BuildStatCache() {
TRACE_EVENT0("flutter", "ZipAssetStore::BuildStatCache");
auto unzipper = CreateUnzipper();
if (!unzipper.is_valid()) {
return;
}
if (unzGoToFirstFile(unzipper.get()) != UNZ_OK) {
return;
}
do {
int result = UNZ_OK;
// Get the current file name.
unz_file_info file_info = {};
char file_name[255];
result = unzGetCurrentFileInfo(unzipper.get(), &file_info, file_name,
sizeof(file_name), nullptr, 0, nullptr, 0);
if (result != UNZ_OK) {
continue;
}
if (file_info.uncompressed_size == 0) {
continue;
}
// Get the current file position.
unz_file_pos file_pos = {};
result = unzGetFilePos(unzipper.get(), &file_pos);
if (result != UNZ_OK) {
continue;
}
std::string file_name_key(file_name, file_info.size_filename);
CacheEntry entry(file_pos, file_info.uncompressed_size);
stat_cache_.emplace(std::move(file_name_key), std::move(entry));
} while (unzGoToNextFile(unzipper.get()) == UNZ_OK);
}
} // namespace blink