-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathLocalBundleReader.cpp
More file actions
133 lines (107 loc) · 4.21 KB
/
Copy pathLocalBundleReader.cpp
File metadata and controls
133 lines (107 loc) · 4.21 KB
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
130
131
132
133
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include <Utils/LocalBundleReader.h>
#include <fmt/format.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Storage.h>
#include "Unicode.h"
#if _MSC_VER <= 1913
// VC 19 (2015-2017.6) cannot optimize co_await/cppwinrt usage
#pragma optimize("", off)
#endif
namespace Microsoft::ReactNative {
std::string GetBundleFromEmbeddedResource(const winrt::Windows::Foundation::Uri &uri) {
auto moduleName = uri.Host();
auto path = uri.Path();
// skip past the leading / slash
auto resourceName = path.c_str() + 1;
auto hmodule = GetModuleHandle(moduleName != L"" ? moduleName.c_str() : nullptr);
if (!hmodule) {
throw std::invalid_argument(fmt::format("Couldn't find module {}", winrt::to_string(moduleName)));
}
auto resource = FindResourceW(hmodule, resourceName, RT_RCDATA);
if (!resource) {
throw std::invalid_argument(fmt::format(
"Couldn't find resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
}
auto hglobal = LoadResource(hmodule, resource);
if (!hglobal) {
throw std::invalid_argument(fmt::format(
"Couldn't load resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
}
auto start = static_cast<char *>(LockResource(hglobal));
if (!start) {
throw std::invalid_argument(fmt::format(
"Couldn't lock resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
}
auto size = SizeofResource(hmodule, resource);
if (!size) {
throw std::invalid_argument(fmt::format(
"Couldn't get size of resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
}
return std::string(start, start + size);
}
namespace {
std::string BufferToString(const winrt::Windows::Storage::Streams::IBuffer &buffer) {
std::string result(buffer.Length(), '\0');
if (!result.empty()) {
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
reader.ReadBytes(winrt::array_view<uint8_t>{
reinterpret_cast<uint8_t *>(&result[0]), reinterpret_cast<uint8_t *>(&result[result.length()])});
}
return result;
}
winrt::Windows::Storage::Streams::IBuffer BytesToBuffer(const void *data, uint32_t size) {
winrt::Windows::Storage::Streams::DataWriter writer;
auto bytes = static_cast<const uint8_t *>(data);
writer.WriteBytes(winrt::array_view<const uint8_t>(bytes, bytes + size));
return writer.DetachBuffer();
}
} // namespace
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer>
LocalBundleReader::LoadBundleAsync(const std::wstring bundleUri) {
try {
co_await winrt::resume_background();
winrt::Windows::Storage::StorageFile file{nullptr};
// Supports "ms-appx://" or "ms-appdata://"
if (bundleUri.starts_with(L"ms-app")) {
winrt::Windows::Foundation::Uri uri(bundleUri);
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(uri);
} else if (bundleUri.starts_with(L"resource://")) {
winrt::Windows::Foundation::Uri uri(bundleUri);
auto bytes = GetBundleFromEmbeddedResource(uri);
co_return BytesToBuffer(bytes.data(), static_cast<uint32_t>(bytes.size()));
} else {
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(bundleUri);
}
co_return co_await winrt::Windows::Storage::FileIO::ReadBufferAsync(file);
}
catch (winrt::hresult_error const &) {
throw;
}
}
std::string LocalBundleReader::LoadBundle(const std::wstring &bundlePath) {
return BufferToString(LoadBundleAsync(bundlePath).get());
}
StorageFileBigString::StorageFileBigString(const std::wstring &path) {
m_pendingLoad = LocalBundleReader::LoadBundleAsync(path);
}
bool StorageFileBigString::isAscii() const {
return false;
}
const char *StorageFileBigString::c_str() const {
ensure();
return m_string.c_str();
}
size_t StorageFileBigString::size() const {
ensure();
return m_string.size();
}
void StorageFileBigString::ensure() const {
if (m_pendingLoad) {
m_string = BufferToString(m_pendingLoad.get());
m_pendingLoad = nullptr;
}
}
} // namespace Microsoft::ReactNative