1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "resource_append.h"
17 #include <algorithm>
18 #include <iomanip>
19 #include <iostream>
20 #include <regex>
21 #include "config_parser.h"
22 #include "header.h"
23 #include "id_worker.h"
24 #include "key_parser.h"
25 #include "reference_parser.h"
26 #include "resource_table.h"
27 #include "resource_util.h"
28 #include "select_compile_parse.h"
29 #ifdef __WIN32
30 #include "windows.h"
31 #endif
32 #include "securec.h"
33
34 namespace OHOS {
35 namespace Global {
36 namespace Restool {
37 using namespace std;
38
ResourceAppend(const PackageParser & packageParser)39 ResourceAppend::ResourceAppend(const PackageParser &packageParser) : packageParser_(packageParser)
40 {
41 }
42
Append()43 uint32_t ResourceAppend::Append()
44 {
45 string outputPath = packageParser_.GetOutput();
46 for (const auto &iter : packageParser_.GetAppend()) {
47 if (!ScanResources(iter, outputPath)) {
48 return RESTOOL_ERROR;
49 }
50 }
51 return RESTOOL_SUCCESS;
52 }
53
Combine()54 uint32_t ResourceAppend::Combine()
55 {
56 vector<pair<ResType, string>> noBaseResource;
57 for (const auto &iter : packageParser_.GetInputs()) {
58 if (!Combine(iter)) {
59 return RESTOOL_ERROR;
60 }
61 CheckAllItems(noBaseResource);
62 }
63 if (!noBaseResource.empty()) {
64 ResourceUtil::PrintWarningMsg(noBaseResource);
65 }
66
67 if (!ParseRef()) {
68 return false;
69 }
70
71 ResourceTable resourceTable;
72 if (resourceTable.CreateResourceTable(items_) != RESTOOL_SUCCESS) {
73 return RESTOOL_ERROR;
74 }
75 return RESTOOL_SUCCESS;
76 }
77
78 // private
Combine(const string & folderPath)79 bool ResourceAppend::Combine(const string &folderPath)
80 {
81 FileEntry entry(folderPath);
82 if (!entry.Init()) {
83 return false;
84 }
85
86 itemsForModule_.clear();
87 for (const auto &child : entry.GetChilds()) {
88 if (!child->IsFile()) {
89 cerr << "Error:" << child->GetFilePath().GetPath() << " not file" << endl;
90 return false;
91 }
92 if (child->GetFilePath().GetFilename() == ID_DEFINED_FILE) {
93 continue;
94 }
95 if (!LoadResourceItem(child->GetFilePath().GetPath())) {
96 return false;
97 }
98 }
99 return true;
100 }
101
ParseRef()102 bool ResourceAppend::ParseRef()
103 {
104 for (auto &iter : refs_) {
105 ReferenceParser ref;
106 if (iter->GetResType() == ResType::PROF || iter->GetResType() == ResType::MEDIA) {
107 if (ref.ParseRefInJsonFile(*iter, packageParser_.GetOutput(), true) != RESTOOL_SUCCESS) {
108 return false;
109 }
110 } else if (ref.ParseRefInResourceItem(*iter) != RESTOOL_SUCCESS) {
111 return false;
112 }
113 }
114 return true;
115 }
116
ScanResources(const string & resourcePath,const string & outputPath)117 bool ResourceAppend::ScanResources(const string &resourcePath, const string &outputPath)
118 {
119 if (!ResourceUtil::FileExist(resourcePath)) {
120 string filePath = FileEntry::FilePath(outputPath).Append(ResourceUtil::GenerateHash(resourcePath)).GetPath();
121 if (remove(filePath.c_str()) != 0) {
122 cerr << "Error: remove failed '" << filePath << "', reason: " << strerror(errno) << endl;
123 return false;
124 }
125 return true;
126 }
127
128 FileEntry entry(resourcePath);
129 if (!entry.Init()) {
130 return false;
131 }
132
133 if (entry.IsFile()) {
134 return ScanSingleFile(resourcePath, outputPath);
135 }
136
137 return ScanSubResources(entry, resourcePath, outputPath);
138 }
139
ScanSubResources(const FileEntry entry,const string & resourcePath,const string & outputPath)140 bool ResourceAppend::ScanSubResources(const FileEntry entry, const string &resourcePath, const string &outputPath)
141 {
142 vector<KeyParam> keyParams;
143 if (KeyParser::Parse(entry.GetFilePath().GetFilename(), keyParams)) {
144 for (const auto &child : entry.GetChilds()) {
145 if (!ResourceUtil::IslegalPath(child->GetFilePath().GetFilename())) {
146 continue;
147 }
148 if (!ScanIegalResources(child->GetFilePath().GetPath(), outputPath)) {
149 return false;
150 }
151 }
152 return true;
153 }
154
155 if (ResourceUtil::IslegalPath(entry.GetFilePath().GetFilename())) {
156 return ScanIegalResources(resourcePath, outputPath);
157 }
158
159 return ScanSubLimitkeyResources(entry, resourcePath, outputPath);
160 }
161
ScanSubLimitkeyResources(const FileEntry entry,const string & resourcePath,const string & outputPath)162 bool ResourceAppend::ScanSubLimitkeyResources(const FileEntry entry, const string &resourcePath,
163 const string &outputPath)
164 {
165 for (const auto &child : entry.GetChilds()) {
166 string limitKey = child->GetFilePath().GetFilename();
167 if (ResourceUtil::IsIgnoreFile(limitKey, child->IsFile())) {
168 continue;
169 }
170
171 if (limitKey == RAW_FILE_DIR || limitKey == RES_FILE_DIR) {
172 if (!ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limitKey)) {
173 return false;
174 }
175 continue;
176 }
177
178 if (child->IsFile()) {
179 cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl;
180 return false;
181 }
182
183 if (!ScanLimitKey(child, limitKey, outputPath)) {
184 return false;
185 }
186 }
187 return true;
188 }
189
ScanIegalResources(const string & resourcePath,const string & outputPath)190 bool ResourceAppend::ScanIegalResources(const string &resourcePath, const string &outputPath)
191 {
192 FileEntry entry(resourcePath);
193 if (!entry.Init()) {
194 return false;
195 }
196 for (const auto &child : entry.GetChilds()) {
197 if (!ScanSingleFile(child->GetFilePath().GetPath(), outputPath)) {
198 return false;
199 }
200 }
201 return true;
202 }
ScanLimitKey(const unique_ptr<FileEntry> & entry,const string & limitKey,const string outputPath)203 bool ResourceAppend::ScanLimitKey(const unique_ptr<FileEntry> &entry,
204 const string &limitKey, const string outputPath)
205 {
206 vector<KeyParam> keyParams;
207 if (!KeyParser::Parse(limitKey, keyParams)) {
208 cerr << "Error: invalid limit key '" << limitKey << "'.";
209 cerr << NEW_LINE_PATH << entry->GetFilePath().GetPath() << endl;
210 return false;
211 }
212
213 for (const auto &child : entry->GetChilds()) {
214 string fileCuster = child->GetFilePath().GetFilename();
215 if (ResourceUtil::IsIgnoreFile(fileCuster, child->IsFile())) {
216 continue;
217 }
218
219 if (child->IsFile()) {
220 cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl;
221 return false;
222 }
223
224 ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
225 if (resType == ResType::INVALID_RES_TYPE) {
226 cerr << "Error: invalid resType." << NEW_LINE_PATH << child->GetFilePath().GetPath() << endl;
227 return false;
228 }
229
230 DirectoryInfo directoryInfo = { limitKey, fileCuster, child->GetFilePath().GetPath(), keyParams, resType};
231 if (!ScanFiles(child, directoryInfo, outputPath)) {
232 return false;
233 }
234 }
235 return true;
236 }
237
238
ScanFiles(const unique_ptr<FileEntry> & entry,const DirectoryInfo & directoryInfo,const string & outputPath)239 bool ResourceAppend::ScanFiles(const unique_ptr<FileEntry> &entry,
240 const DirectoryInfo &directoryInfo, const string &outputPath)
241 {
242 for (const auto &child : entry->GetChilds()) {
243 string filename = child->GetFilePath().GetFilename();
244 if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
245 continue;
246 }
247
248 if (!child->IsFile()) {
249 cerr << "Error: '" << child->GetFilePath().GetPath() << "' not file." << endl;
250 return false;
251 }
252
253 FileInfo fileInfo = {directoryInfo, child->GetFilePath().GetPath(), filename};
254 if (!ScanFile(fileInfo, outputPath)) {
255 return false;
256 }
257 }
258 return true;
259 }
260
ScanFile(const FileInfo & fileInfo,const string & outputPath)261 bool ResourceAppend::ScanFile(const FileInfo &fileInfo, const string &outputPath)
262 {
263 if (ResourceAppend::IsBaseIdDefined(fileInfo)) {
264 cout << "Warning: id_defined.json does not compile to generate intermediate files" << endl;
265 FileEntry::FilePath outPath(outputPath);
266 return ResourceUtil::CopyFileInner(fileInfo.filePath, outPath.Append(ID_DEFINED_FILE).GetPath());
267 }
268
269 unique_ptr<IResourceCompiler> resourceCompiler =
270 FactoryResourceCompiler::CreateCompilerForAppend(fileInfo.dirType, outputPath);
271 if (resourceCompiler == nullptr) {
272 return true;
273 }
274
275 if (resourceCompiler->CompileForAppend(fileInfo) != RESTOOL_SUCCESS) {
276 return false;
277 }
278
279 ostringstream outStream;
280 const auto &items = resourceCompiler->GetResourceItems();
281 for (const auto &item : items) {
282 for (const auto &resourceItem : item.second) {
283 if (!WriteResourceItem(resourceItem, outStream)) {
284 return false;
285 }
286 }
287 }
288
289 string hash = ResourceUtil::GenerateHash(fileInfo.filePath);
290 FileEntry::FilePath output(outputPath);
291 if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
292 return false;
293 }
294 return true;
295 }
296
ScanSingleFile(const string & filePath,const string & outputPath)297 bool ResourceAppend::ScanSingleFile(const string &filePath, const string &outputPath)
298 {
299 if (filePath.find(RAW_FILE_DIR) != string::npos) {
300 return WriteRawFilesOrResFiles(filePath, outputPath, RAW_FILE_DIR);
301 }
302
303 if (filePath.find(RES_FILE_DIR) != string::npos) {
304 return WriteRawFilesOrResFiles(filePath, outputPath, RES_FILE_DIR);
305 }
306
307 FileEntry::FilePath path(filePath);
308 string fileCuster = path.GetParent().GetFilename();
309 ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
310 if (resType == ResType::INVALID_RES_TYPE) {
311 cerr << "Error: invalid resType." << NEW_LINE_PATH << filePath << endl;
312 return false;
313 }
314
315 string limitKey = path.GetParent().GetParent().GetFilename();
316 vector<KeyParam> keyParams;
317 if (!KeyParser::Parse(limitKey, keyParams)) {
318 cerr << "Error: invalid limit key." << NEW_LINE_PATH << filePath << endl;
319 return false;
320 }
321
322 DirectoryInfo directoryInfo = {limitKey, fileCuster, path.GetParent().GetPath(), keyParams, resType};
323 FileInfo fileInfo = {directoryInfo, filePath, path.GetFilename() };
324 if (!ScanFile(fileInfo, outputPath)) {
325 return false;
326 }
327 return true;
328 }
329
WriteFileInner(ostringstream & outStream,const string & outputPath) const330 bool ResourceAppend::WriteFileInner(ostringstream &outStream, const string &outputPath) const
331 {
332 #ifdef __WIN32
333 HANDLE hWriteFile = CreateFile(outputPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
334 nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
335 if (hWriteFile == INVALID_HANDLE_VALUE) {
336 cerr << "Error: '" << outputPath << "' " << GetLastError() << endl;
337 return false;
338 }
339
340 DWORD writeBytes;
341 if (!WriteFile(hWriteFile, outStream.str().c_str(), outStream.tellp(), &writeBytes, nullptr)) {
342 cerr << "Error: write '" << outputPath << "' " << GetLastError() << endl;
343 CloseHandle(hWriteFile);
344 return false;
345 }
346 CloseHandle(hWriteFile);
347 #else
348 ofstream out(outputPath, ofstream::out | ofstream::binary);
349 if (!out.is_open()) {
350 cerr << "Error: open failed '" << outputPath << "', reason: " << strerror(errno) << endl;
351 return false;
352 }
353 out << outStream.str();
354 #endif
355 return true;
356 }
357
WriteResourceItem(const ResourceItem & resourceItem,ostringstream & out)358 bool ResourceAppend::WriteResourceItem(const ResourceItem &resourceItem, ostringstream &out)
359 {
360 uint32_t size = resourceItem.GetName().length();
361 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
362 out.write(reinterpret_cast<const char *>(resourceItem.GetName().c_str()), size);
363
364 size = resourceItem.GetLimitKey().length();
365 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
366 out.write(reinterpret_cast<const char *>(resourceItem.GetLimitKey().c_str()), size);
367
368 size = resourceItem.GetFilePath().length();
369 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
370 out.write(reinterpret_cast<const char *>(resourceItem.GetFilePath().c_str()), size);
371
372 int32_t type = static_cast<int32_t>(resourceItem.GetResType());
373 out.write(reinterpret_cast<const char *>(&type), sizeof(int32_t));
374
375 size = resourceItem.GetKeyParam().size();
376 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
377 for (const auto &keyParam : resourceItem.GetKeyParam()) {
378 out.write(reinterpret_cast<const char *>(&keyParam.keyType), sizeof(int32_t));
379 out.write(reinterpret_cast<const char *>(&keyParam.value), sizeof(int32_t));
380 }
381
382 size = resourceItem.GetDataLength();
383 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
384 out.write(reinterpret_cast<const char *>(resourceItem.GetData()), size);
385 return true;
386 }
387
LoadResourceItem(const string & filePath)388 bool ResourceAppend::LoadResourceItem(const string &filePath)
389 {
390 #ifdef __WIN32
391 return LoadResourceItemWin(filePath);
392 #else
393 ifstream in(filePath, ifstream::in | ifstream::binary);
394 if (!in.is_open()) {
395 cerr << "Error: open failed '" << filePath << "', reason: " << strerror(errno) << endl;
396 return false;
397 }
398
399 in.seekg(0, in.end);
400 int32_t length = in.tellg();
401 in.seekg(0, in.beg);
402 if (length <= 0) {
403 cerr << "Error: invalid file size = " << length << NEW_LINE_PATH << filePath << endl;
404 return false;
405 }
406 char buffer[length];
407 in.read(buffer, length);
408 return LoadResourceItemFromMem(buffer, length);
409 #endif
410 }
411
ScanRawFilesOrResFiles(const string & path,const string & outputPath,const string & limit)412 bool ResourceAppend::ScanRawFilesOrResFiles(const string &path, const string &outputPath, const string &limit)
413 {
414 FileEntry entry(path);
415 if (!entry.Init()) {
416 return false;
417 }
418
419 for (const auto &child : entry.GetChilds()) {
420 string filename = child->GetFilePath().GetFilename();
421 if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
422 continue;
423 }
424
425 bool ret = false;
426 if (child->IsFile()) {
427 ret = WriteRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
428 } else {
429 ret = ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
430 }
431
432 if (!ret) {
433 return false;
434 }
435 }
436 return true;
437 }
438
WriteRawFilesOrResFiles(const string & filePath,const string & outputPath,const string & limit)439 bool ResourceAppend::WriteRawFilesOrResFiles(const string &filePath, const string &outputPath, const string &limit)
440 {
441 string::size_type pos = filePath.find(limit);
442 if (pos == string::npos) {
443 cerr << "Error: invalid file path." << NEW_LINE_PATH << filePath << endl;
444 return false;
445 }
446
447 string sub = filePath.substr(pos);
448 sub = FileEntry::FilePath(RESOURCES_DIR).Append(sub).GetPath();
449 vector<KeyParam> keyParams;
450 auto iter = g_copyFileMap.find(limit);
451 ResourceItem resourceItem("", keyParams, iter->second);
452 resourceItem.SetData(sub);
453 resourceItem.SetFilePath(filePath);
454 resourceItem.SetLimitKey("");
455
456 ostringstream outStream;
457 if (!WriteResourceItem(resourceItem, outStream)) {
458 return false;
459 }
460
461 string hash = ResourceUtil::GenerateHash(filePath);
462 FileEntry::FilePath output(outputPath);
463 if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
464 return false;
465 }
466 return true;
467 }
468
Push(const shared_ptr<ResourceItem> & resourceItem)469 bool ResourceAppend::Push(const shared_ptr<ResourceItem> &resourceItem)
470 {
471 string idName = ResourceUtil::GetIdName(resourceItem->GetName(), resourceItem->GetResType());
472 int64_t id = IdWorker::GetInstance().GenerateId(resourceItem->GetResType(), idName);
473 if (id < 0) {
474 return false;
475 }
476
477 if (!CheckModuleResourceItem(resourceItem, id)) {
478 return false;
479 }
480
481 const auto &result = items_.find(id);
482 if (result == items_.end()) {
483 items_[id].push_back(resourceItem);
484 AddRef(resourceItem);
485 return true;
486 }
487
488 if (find_if(result->second.begin(), result->second.end(), [resourceItem](auto &iter) {
489 return resourceItem->GetLimitKey() == iter->GetLimitKey();
490 }) != result->second.end()) {
491 return true;
492 }
493
494 items_[id].push_back(resourceItem);
495 AddRef(resourceItem);
496 return true;
497 }
498
AddRef(const shared_ptr<ResourceItem> & resourceItem)499 void ResourceAppend::AddRef(const shared_ptr<ResourceItem> &resourceItem)
500 {
501 string data(reinterpret_cast<const char *>(resourceItem->GetData()), resourceItem->GetDataLength());
502 ResType resType = resourceItem->GetResType();
503 if (resType == ResType::MEDIA) {
504 if (FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() == JSON_EXTENSION) {
505 refs_.push_back(resourceItem);
506 }
507 return;
508 }
509
510 if (resType == ResType::PROF) {
511 if (resourceItem->GetLimitKey() != "base" ||
512 FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() != JSON_EXTENSION) {
513 return;
514 }
515 refs_.push_back(resourceItem);
516 return;
517 }
518
519 if (regex_match(data, regex(".*\\$.+:.*"))) {
520 refs_.push_back(resourceItem);
521 }
522 }
523
LoadResourceItemFromMem(const char buffer[],int32_t length)524 bool ResourceAppend::LoadResourceItemFromMem(const char buffer[], int32_t length)
525 {
526 int32_t offset = 0;
527 do {
528 // name
529 string nameStr = ParseString(buffer, length, offset);
530 // limit key
531 string limitKeyStr = ParseString(buffer, length, offset);
532 // file path
533 string filePathStr = ParseString(buffer, length, offset);
534 // ResType
535 int32_t type = ParseInt32(buffer, length, offset);
536 ResType resType = static_cast<ResType>(type);
537 // keyParam
538 int32_t keyParamSize = ParseInt32(buffer, length, offset);
539 vector<KeyParam> keyParams;
540 for (int i = 0; i < keyParamSize; i++) {
541 KeyParam keyParam;
542 keyParam.keyType = static_cast<KeyType>(ParseInt32(buffer, length, offset));
543 int32_t value = ParseInt32(buffer, length, offset);
544 if (value == -1) {
545 return false;
546 }
547 keyParam.value = static_cast<uint32_t>(value);
548 keyParams.push_back(keyParam);
549 }
550 if (limitKeyStr != "base" && !limitKeyStr.empty() && !SelectCompileParse::IsSelectCompile(keyParams)) {
551 return true;
552 }
553 // data
554 string data = ParseString(buffer, length, offset);
555 if (resType == ResType::RAW || resType == ResType::RES) {
556 FileEntry::FilePath outPath(packageParser_.GetOutput());
557 if (ResourceUtil::FileExist(outPath.Append(data).GetPath())) {
558 continue;
559 }
560 if (!ResourceUtil::CreateDirs(outPath.Append(data).GetParent().GetPath())) {
561 return false;
562 }
563
564 if (!ResourceUtil::FileExist(filePathStr)) {
565 continue;
566 }
567
568 if (!ResourceUtil::CopyFileInner(filePathStr, outPath.Append(data).GetPath())) {
569 return false;
570 }
571 continue;
572 }
573
574 shared_ptr<ResourceItem> resourceItem = make_shared<ResourceItem>(nameStr, keyParams, resType);
575 resourceItem->SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length());
576 resourceItem->SetLimitKey(limitKeyStr);
577 resourceItem->SetFilePath(filePathStr);
578 if (!Push(resourceItem)) {
579 return false;
580 }
581 } while (offset < length);
582 return true;
583 }
584
ParseString(const char buffer[],int32_t length,int32_t & offset) const585 string ResourceAppend::ParseString(const char buffer[], int32_t length, int32_t &offset) const
586 {
587 int32_t size = ParseInt32(buffer, length, offset);
588 if (size < 0 || offset + size > length) {
589 offset = length;
590 return "";
591 }
592
593 if (size == 0) {
594 return "";
595 }
596
597 string value(buffer + offset, size);
598 offset += size;
599 return value;
600 }
601
ParseInt32(const char buffer[],int32_t length,int32_t & offset) const602 int32_t ResourceAppend::ParseInt32(const char buffer[], int32_t length, int32_t &offset) const
603 {
604 if (offset + static_cast<int32_t>(sizeof(int32_t)) > length) {
605 offset = length;
606 return -1;
607 }
608
609 int32_t size = 0;
610 if (memcpy_s(&size, sizeof(int32_t), buffer + offset, sizeof(int32_t)) != EOK) {
611 offset = length;
612 return -1;
613 }
614 offset += sizeof(int32_t);
615 return size;
616 }
617
CheckModuleResourceItem(const shared_ptr<ResourceItem> & resourceItem,int64_t id)618 bool ResourceAppend::CheckModuleResourceItem(const shared_ptr<ResourceItem> &resourceItem, int64_t id)
619 {
620 const auto &result = itemsForModule_.find(id);
621 if (result == itemsForModule_.end()) {
622 itemsForModule_[id].push_back(resourceItem);
623 return true;
624 }
625
626 const auto &ret = find_if(result->second.begin(), result->second.end(), [resourceItem](auto iter) {
627 return resourceItem->GetLimitKey() == iter->GetLimitKey();
628 });
629
630 if (ret != result->second.end()) {
631 cerr << "Error: '" << resourceItem->GetName() << "' conflict, first declared.";
632 cerr << NEW_LINE_PATH << (*ret)->GetFilePath() << endl;
633 cerr << "but declared again." << NEW_LINE_PATH << resourceItem->GetFilePath() << endl;
634 return false;
635 }
636
637 itemsForModule_[id].push_back(resourceItem);
638 return true;
639 }
640
641 #ifdef __WIN32
LoadResourceItemWin(const string & filePath)642 bool ResourceAppend::LoadResourceItemWin(const string &filePath)
643 {
644 bool result = false;
645 HANDLE hReadFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
646 FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS, nullptr);
647 if (hReadFile == INVALID_HANDLE_VALUE) {
648 cerr << "Error: "<< GetLastError() << NEW_LINE_PATH << filePath << endl;
649 return result;
650 }
651
652 DWORD fileSize = GetFileSize(hReadFile, nullptr);
653 HANDLE hFileMap = CreateFileMapping(hReadFile, nullptr, PAGE_READONLY, 0, fileSize, nullptr);
654 if (hFileMap == INVALID_HANDLE_VALUE) {
655 cerr << "Error: create file mapping " << GetLastError() << endl;
656 CloseHandle(hReadFile);
657 return result;
658 }
659
660 void* pBuffer = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
661 if (pBuffer == nullptr) {
662 cerr << "Error: map view of file " << GetLastError() << endl;
663 CloseHandle(hReadFile);
664 return result;
665 }
666
667 char* buffer = reinterpret_cast<char *>(pBuffer);
668 result = LoadResourceItemFromMem(buffer, fileSize);
669 UnmapViewOfFile(hFileMap);
670 CloseHandle(hReadFile);
671 return result;
672 }
673 #endif
674
IsBaseIdDefined(const FileInfo & fileInfo)675 bool ResourceAppend::IsBaseIdDefined(const FileInfo &fileInfo)
676 {
677 FileEntry::FilePath filePath(fileInfo.filePath);
678 return filePath.GetParent().GetParent().GetFilename() == "base" &&
679 filePath.GetParent().GetFilename() == "element" &&
680 fileInfo.filename == ID_DEFINED_FILE;
681 }
682
CheckAllItems(vector<pair<ResType,string>> & noBaseResource)683 void ResourceAppend::CheckAllItems(vector<pair<ResType, string>> &noBaseResource)
684 {
685 for (const auto &item : items_) {
686 bool found = any_of(item.second.begin(), item.second.end(), [](const auto &iter) {
687 return iter->GetLimitKey() == "base";
688 });
689 if (!found) {
690 auto firstItem = item.second.front();
691 bool ret = any_of(noBaseResource.begin(), noBaseResource.end(), [firstItem](const auto &iterItem) {
692 return (firstItem->GetResType() == iterItem.first) &&
693 (firstItem->GetName() == iterItem.second);
694 });
695 if (!ret) {
696 noBaseResource.push_back(make_pair(firstItem->GetResType(), firstItem->GetName()));
697 }
698 }
699 }
700 }
701 }
702 }
703 }