• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH)
90                 .FormatCause(child->GetFilePath().GetPath().c_str(), "not a file"));
91             return false;
92         }
93         if (child->GetFilePath().GetFilename() == ID_DEFINED_FILE) {
94             continue;
95         }
96         if (!LoadResourceItem(child->GetFilePath().GetPath())) {
97             return false;
98         }
99     }
100     return true;
101 }
102 
ParseRef()103 bool ResourceAppend::ParseRef()
104 {
105     for (auto &iter : refs_) {
106         ReferenceParser ref;
107         if (iter->GetResType() == ResType::PROF || iter->GetResType() == ResType::MEDIA) {
108             if (ref.ParseRefInJsonFile(*iter, packageParser_.GetOutput(), true) != RESTOOL_SUCCESS) {
109                 return false;
110             }
111         } else if (ref.ParseRefInResourceItem(*iter) != RESTOOL_SUCCESS) {
112             return false;
113         }
114     }
115     return true;
116 }
117 
ScanResources(const string & resourcePath,const string & outputPath)118 bool ResourceAppend::ScanResources(const string &resourcePath, const string &outputPath)
119 {
120     if (!ResourceUtil::FileExist(resourcePath)) {
121         string filePath = FileEntry::FilePath(outputPath).Append(ResourceUtil::GenerateHash(resourcePath)).GetPath();
122         if (remove(filePath.c_str()) != 0) {
123             PrintError(GetError(ERR_CODE_REMOVE_FILE_ERROR).FormatCause(filePath.c_str(), strerror(errno)));
124             return false;
125         }
126         return true;
127     }
128 
129     FileEntry entry(resourcePath);
130     if (!entry.Init()) {
131         return false;
132     }
133 
134     if (entry.IsFile()) {
135         return ScanSingleFile(resourcePath, outputPath);
136     }
137 
138     return ScanSubResources(entry, resourcePath, outputPath);
139 }
140 
ScanSubResources(const FileEntry entry,const string & resourcePath,const string & outputPath)141 bool ResourceAppend::ScanSubResources(const FileEntry entry, const string &resourcePath, const string &outputPath)
142 {
143     vector<KeyParam> keyParams;
144     if (KeyParser::Parse(entry.GetFilePath().GetFilename(), keyParams)) {
145         for (const auto &child : entry.GetChilds()) {
146             if (!ResourceUtil::IslegalPath(child->GetFilePath().GetFilename())) {
147                 continue;
148             }
149             if (!ScanIegalResources(child->GetFilePath().GetPath(), outputPath)) {
150                 return false;
151             }
152         }
153         return true;
154     }
155 
156     if (ResourceUtil::IslegalPath(entry.GetFilePath().GetFilename())) {
157         return ScanIegalResources(resourcePath, outputPath);
158     }
159 
160     return ScanSubLimitkeyResources(entry, resourcePath, outputPath);
161 }
162 
ScanSubLimitkeyResources(const FileEntry entry,const string & resourcePath,const string & outputPath)163 bool ResourceAppend::ScanSubLimitkeyResources(const FileEntry entry, const string &resourcePath,
164     const string &outputPath)
165 {
166     for (const auto &child : entry.GetChilds()) {
167         string limitKey = child->GetFilePath().GetFilename();
168         if (ResourceUtil::IsIgnoreFile(limitKey, child->IsFile())) {
169             continue;
170         }
171 
172         if (limitKey == RAW_FILE_DIR || limitKey == RES_FILE_DIR) {
173             if (!ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limitKey)) {
174                 return false;
175             }
176             continue;
177         }
178 
179         if (child->IsFile()) {
180             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH)
181                 .FormatCause(child->GetFilePath().GetPath().c_str(), "not a directory"));
182             return false;
183         }
184 
185         if (!ScanLimitKey(child, limitKey, outputPath)) {
186             return false;
187         }
188     }
189     return true;
190 }
191 
ScanIegalResources(const string & resourcePath,const string & outputPath)192 bool ResourceAppend::ScanIegalResources(const string &resourcePath, const string &outputPath)
193 {
194     FileEntry entry(resourcePath);
195     if (!entry.Init()) {
196         return false;
197     }
198     for (const auto &child : entry.GetChilds()) {
199         if (!ScanSingleFile(child->GetFilePath().GetPath(), outputPath)) {
200             return false;
201         }
202     }
203     return true;
204 }
ScanLimitKey(const unique_ptr<FileEntry> & entry,const string & limitKey,const string outputPath)205 bool ResourceAppend::ScanLimitKey(const unique_ptr<FileEntry> &entry,
206     const string &limitKey, const string outputPath)
207 {
208     vector<KeyParam> keyParams;
209     if (!KeyParser::Parse(limitKey, keyParams)) {
210         PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(limitKey.c_str())
211             .SetPosition(entry->GetFilePath().GetPath().c_str()));
212         return false;
213     }
214 
215     for (const auto &child : entry->GetChilds()) {
216         string fileCuster = child->GetFilePath().GetFilename();
217         if (ResourceUtil::IsIgnoreFile(fileCuster, child->IsFile())) {
218             continue;
219         }
220 
221         if (child->IsFile()) {
222             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH)
223                 .FormatCause(child->GetFilePath().GetPath().c_str(), "not a directory"));
224             return false;
225         }
226 
227         ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
228         if (resType == ResType::INVALID_RES_TYPE) {
229             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_DIR)
230                            .FormatCause(fileCuster.c_str(), ResourceUtil::GetAllResTypeDirs().c_str())
231                            .SetPosition(child->GetFilePath().GetPath().c_str()));
232             return false;
233         }
234 
235         DirectoryInfo directoryInfo = { limitKey, fileCuster, child->GetFilePath().GetPath(), keyParams, resType};
236         if (!ScanFiles(child, directoryInfo, outputPath)) {
237             return false;
238         }
239     }
240     return true;
241 }
242 
243 
ScanFiles(const unique_ptr<FileEntry> & entry,const DirectoryInfo & directoryInfo,const string & outputPath)244 bool ResourceAppend::ScanFiles(const unique_ptr<FileEntry> &entry,
245     const DirectoryInfo &directoryInfo, const string &outputPath)
246 {
247     for (const auto &child : entry->GetChilds()) {
248         string filename =  child->GetFilePath().GetFilename();
249         if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
250             continue;
251         }
252 
253         if (!child->IsFile()) {
254             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH)
255                 .FormatCause(child->GetFilePath().GetPath().c_str(), "not a file"));
256             return false;
257         }
258 
259         FileInfo fileInfo = {directoryInfo, child->GetFilePath().GetPath(), filename};
260         if (!ScanFile(fileInfo, outputPath)) {
261             return false;
262         }
263     }
264     return true;
265 }
266 
ScanFile(const FileInfo & fileInfo,const string & outputPath)267 bool ResourceAppend::ScanFile(const FileInfo &fileInfo, const string &outputPath)
268 {
269     if (ResourceAppend::IsBaseIdDefined(fileInfo)) {
270         cout << "Warning: id_defined.json does not compile to generate intermediate files" << endl;
271         FileEntry::FilePath outPath(outputPath);
272         return ResourceUtil::CopyFileInner(fileInfo.filePath, outPath.Append(ID_DEFINED_FILE).GetPath());
273     }
274 
275     unique_ptr<IResourceCompiler> resourceCompiler =
276         ResourceCompilerFactory::CreateCompilerForAppend(fileInfo.dirType, outputPath);
277     if (resourceCompiler == nullptr) {
278         return true;
279     }
280 
281     if (resourceCompiler->CompileForAppend(fileInfo) != RESTOOL_SUCCESS) {
282         return false;
283     }
284 
285     ostringstream outStream;
286     const auto &items = resourceCompiler->GetResourceItems();
287     for (const auto &item : items) {
288         for (const auto &resourceItem : item.second) {
289             if (!WriteResourceItem(resourceItem, outStream)) {
290                 return false;
291             }
292         }
293     }
294 
295     string hash = ResourceUtil::GenerateHash(fileInfo.filePath);
296     FileEntry::FilePath output(outputPath);
297     if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
298         return false;
299     }
300     return true;
301 }
302 
ScanSingleFile(const string & filePath,const string & outputPath)303 bool ResourceAppend::ScanSingleFile(const string &filePath, const string &outputPath)
304 {
305     if (filePath.find(RAW_FILE_DIR) != string::npos) {
306         return WriteRawFilesOrResFiles(filePath, outputPath, RAW_FILE_DIR);
307     }
308 
309     if (filePath.find(RES_FILE_DIR) != string::npos) {
310         return WriteRawFilesOrResFiles(filePath, outputPath, RES_FILE_DIR);
311     }
312 
313     FileEntry::FilePath path(filePath);
314     string fileCuster = path.GetParent().GetFilename();
315     ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
316     if (resType == ResType::INVALID_RES_TYPE) {
317         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_DIR)
318                        .FormatCause(fileCuster.c_str(), ResourceUtil::GetAllResTypeDirs().c_str())
319                        .SetPosition(filePath));
320         return false;
321     }
322 
323     string limitKey = path.GetParent().GetParent().GetFilename();
324     vector<KeyParam> keyParams;
325     if (!KeyParser::Parse(limitKey, keyParams)) {
326         PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(limitKey.c_str()).SetPosition(filePath));
327         return false;
328     }
329 
330     DirectoryInfo directoryInfo = {limitKey, fileCuster, path.GetParent().GetPath(), keyParams, resType};
331     FileInfo fileInfo = {directoryInfo, filePath, path.GetFilename() };
332     if (!ScanFile(fileInfo, outputPath)) {
333         return false;
334     }
335     return true;
336 }
337 
WriteFileInner(ostringstream & outStream,const string & outputPath) const338 bool ResourceAppend::WriteFileInner(ostringstream &outStream, const string &outputPath) const
339 {
340 #ifdef __WIN32
341     HANDLE hWriteFile = CreateFile(outputPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
342         nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
343     if (hWriteFile == INVALID_HANDLE_VALUE) {
344         PrintError(GetError(ERR_CODE_CREATE_FILE_ERROR)
345             .FormatCause(outputPath.c_str(), to_string(GetLastError()).c_str()));
346         return false;
347     }
348 
349     DWORD writeBytes;
350     if (!WriteFile(hWriteFile, outStream.str().c_str(), outStream.tellp(), &writeBytes, nullptr)) {
351         PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR)
352             .FormatCause(outputPath.c_str(), to_string(GetLastError()).c_str()));
353         CloseHandle(hWriteFile);
354         return false;
355     }
356     CloseHandle(hWriteFile);
357 #else
358     ofstream out(outputPath, ofstream::out | ofstream::binary);
359     if (!out.is_open()) {
360         PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(outputPath.c_str(), strerror(errno)));
361         return false;
362     }
363     out << outStream.str();
364 #endif
365     return true;
366 }
367 
WriteResourceItem(const ResourceItem & resourceItem,ostringstream & out)368 bool ResourceAppend::WriteResourceItem(const ResourceItem &resourceItem, ostringstream &out)
369 {
370     uint32_t size = resourceItem.GetName().length();
371     out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
372     out.write(reinterpret_cast<const char *>(resourceItem.GetName().c_str()), size);
373 
374     size = resourceItem.GetLimitKey().length();
375     out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
376     out.write(reinterpret_cast<const char *>(resourceItem.GetLimitKey().c_str()), size);
377 
378     size = resourceItem.GetFilePath().length();
379     out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
380     out.write(reinterpret_cast<const char *>(resourceItem.GetFilePath().c_str()), size);
381 
382     int32_t type = static_cast<int32_t>(resourceItem.GetResType());
383     out.write(reinterpret_cast<const char *>(&type), sizeof(int32_t));
384 
385     size = resourceItem.GetKeyParam().size();
386     out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
387     for (const auto &keyParam : resourceItem.GetKeyParam()) {
388         out.write(reinterpret_cast<const char *>(&keyParam.keyType), sizeof(int32_t));
389         out.write(reinterpret_cast<const char *>(&keyParam.value), sizeof(int32_t));
390     }
391 
392     size =  resourceItem.GetDataLength();
393     out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
394     out.write(reinterpret_cast<const char *>(resourceItem.GetData()), size);
395     return true;
396 }
397 
LoadResourceItem(const string & filePath)398 bool ResourceAppend::LoadResourceItem(const string &filePath)
399 {
400 #ifdef __WIN32
401     return LoadResourceItemWin(filePath);
402 #else
403     ifstream in(filePath, ifstream::in | ifstream::binary);
404     if (!in.is_open()) {
405         PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(filePath.c_str(), strerror(errno)));
406         return false;
407     }
408 
409     in.seekg(0, in.end);
410     int32_t length = in.tellg();
411     in.seekg(0, in.beg);
412     if (length <= 0) {
413         PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(filePath.c_str(), "file is empty"));
414         return false;
415     }
416     char buffer[length];
417     in.read(buffer, length);
418     return LoadResourceItemFromMem(buffer, length);
419 #endif
420 }
421 
ScanRawFilesOrResFiles(const string & path,const string & outputPath,const string & limit)422 bool ResourceAppend::ScanRawFilesOrResFiles(const string &path, const string &outputPath, const string &limit)
423 {
424     FileEntry entry(path);
425     if (!entry.Init()) {
426         return false;
427     }
428 
429     for (const auto &child : entry.GetChilds()) {
430         string filename =  child->GetFilePath().GetFilename();
431         if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
432             continue;
433         }
434 
435         bool ret = false;
436         if (child->IsFile()) {
437             ret = WriteRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
438         } else {
439             ret = ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
440         }
441 
442         if (!ret) {
443             return false;
444         }
445     }
446     return true;
447 }
448 
WriteRawFilesOrResFiles(const string & filePath,const string & outputPath,const string & limit)449 bool ResourceAppend::WriteRawFilesOrResFiles(const string &filePath, const string &outputPath, const string &limit)
450 {
451     string::size_type pos = filePath.find(limit);
452     if (pos == string::npos) {
453         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH).FormatCause(filePath.c_str(), "missing separator"));
454         return false;
455     }
456 
457     string sub = filePath.substr(pos);
458     sub = FileEntry::FilePath(RESOURCES_DIR).Append(sub).GetPath();
459     vector<KeyParam> keyParams;
460     auto iter = g_copyFileMap.find(limit);
461     ResourceItem resourceItem("", keyParams, iter->second);
462     resourceItem.SetData(sub);
463     resourceItem.SetFilePath(filePath);
464     resourceItem.SetLimitKey("");
465 
466     ostringstream outStream;
467     if (!WriteResourceItem(resourceItem, outStream)) {
468         return false;
469     }
470 
471     string hash = ResourceUtil::GenerateHash(filePath);
472     FileEntry::FilePath output(outputPath);
473     if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
474         return false;
475     }
476     return true;
477 }
478 
Push(const shared_ptr<ResourceItem> & resourceItem)479 bool ResourceAppend::Push(const shared_ptr<ResourceItem> &resourceItem)
480 {
481     string idName = ResourceUtil::GetIdName(resourceItem->GetName(), resourceItem->GetResType());
482     int64_t id = IdWorker::GetInstance().GenerateId(resourceItem->GetResType(), idName);
483     if (id < 0) {
484         PrintError(GetError(ERR_CODE_RESOURCE_ID_NOT_DEFINED)
485                        .FormatCause(resourceItem->GetName().c_str(),
486                                     ResourceUtil::ResTypeToString(resourceItem->GetResType()).c_str()));
487         return false;
488     }
489 
490     if (!CheckModuleResourceItem(resourceItem, id)) {
491         return false;
492     }
493 
494     const auto &result = items_.find(id);
495     if (result == items_.end()) {
496         items_[id].push_back(resourceItem);
497         AddRef(resourceItem);
498         return true;
499     }
500 
501     if (find_if(result->second.begin(), result->second.end(), [resourceItem](auto &iter) {
502               return resourceItem->GetLimitKey() == iter->GetLimitKey();
503         }) != result->second.end()) {
504         return true;
505     }
506 
507     items_[id].push_back(resourceItem);
508     AddRef(resourceItem);
509     return true;
510 }
511 
AddRef(const shared_ptr<ResourceItem> & resourceItem)512 void ResourceAppend::AddRef(const shared_ptr<ResourceItem> &resourceItem)
513 {
514     string data(reinterpret_cast<const char *>(resourceItem->GetData()), resourceItem->GetDataLength());
515     ResType resType = resourceItem->GetResType();
516     if (resType == ResType::MEDIA) {
517         if (FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() == JSON_EXTENSION) {
518             refs_.push_back(resourceItem);
519         }
520         return;
521     }
522 
523     if (resType == ResType::PROF) {
524         if (resourceItem->GetLimitKey() != "base" ||
525             FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() != JSON_EXTENSION) {
526             return;
527         }
528         refs_.push_back(resourceItem);
529         return;
530     }
531 
532     if (regex_match(data, regex(".*\\$.+:.*"))) {
533         refs_.push_back(resourceItem);
534     }
535 }
536 
LoadResourceItemFromMem(const char buffer[],int32_t length)537 bool ResourceAppend::LoadResourceItemFromMem(const char buffer[], int32_t length)
538 {
539     int32_t offset = 0;
540     do {
541         // name
542         string nameStr = ParseString(buffer, length, offset);
543         // limit key
544         string limitKeyStr = ParseString(buffer, length, offset);
545         // file path
546         string filePathStr = ParseString(buffer, length, offset);
547         // ResType
548         int32_t type = ParseInt32(buffer, length, offset);
549         ResType resType = static_cast<ResType>(type);
550         // keyParam
551         int32_t keyParamSize = ParseInt32(buffer, length, offset);
552         vector<KeyParam> keyParams;
553         for (int i = 0; i < keyParamSize; i++) {
554             KeyParam keyParam;
555             keyParam.keyType = static_cast<KeyType>(ParseInt32(buffer, length, offset));
556             int32_t value = ParseInt32(buffer, length, offset);
557             if (value == -1) {
558                 return false;
559             }
560             keyParam.value = static_cast<uint32_t>(value);
561             keyParams.push_back(keyParam);
562         }
563         if (limitKeyStr != "base" && !limitKeyStr.empty() && !SelectCompileParse::IsSelectCompile(keyParams)) {
564             return true;
565         }
566         // data
567         string data = ParseString(buffer, length, offset);
568         if (resType ==  ResType::RAW || resType ==  ResType::RES) {
569             FileEntry::FilePath outPath(packageParser_.GetOutput());
570             if (ResourceUtil::FileExist(outPath.Append(data).GetPath())) {
571                 continue;
572             }
573             if (!ResourceUtil::CreateDirs(outPath.Append(data).GetParent().GetPath())) {
574                 return false;
575             }
576 
577             if (!ResourceUtil::FileExist(filePathStr)) {
578                 continue;
579             }
580 
581             if (!ResourceUtil::CopyFileInner(filePathStr, outPath.Append(data).GetPath())) {
582                 return false;
583             }
584             continue;
585         }
586 
587         shared_ptr<ResourceItem> resourceItem = make_shared<ResourceItem>(nameStr, keyParams, resType);
588         resourceItem->SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length());
589         resourceItem->SetLimitKey(limitKeyStr);
590         resourceItem->SetFilePath(filePathStr);
591         if (!Push(resourceItem)) {
592             return false;
593         }
594     } while (offset < length);
595     return true;
596 }
597 
ParseString(const char buffer[],int32_t length,int32_t & offset) const598 string ResourceAppend::ParseString(const char buffer[], int32_t length, int32_t &offset) const
599 {
600     int32_t size = ParseInt32(buffer, length, offset);
601     if (size < 0 || offset + size > length) {
602         offset = length;
603         return "";
604     }
605 
606     if (size == 0) {
607         return "";
608     }
609 
610     string value(buffer + offset, size);
611     offset += size;
612     return value;
613 }
614 
ParseInt32(const char buffer[],int32_t length,int32_t & offset) const615 int32_t ResourceAppend::ParseInt32(const char buffer[], int32_t length, int32_t &offset) const
616 {
617     if (offset + static_cast<int32_t>(sizeof(int32_t)) > length) {
618         offset = length;
619         return -1;
620     }
621 
622     int32_t size = 0;
623     if (memcpy_s(&size, sizeof(int32_t), buffer  + offset, sizeof(int32_t)) != EOK) {
624         offset = length;
625         return -1;
626     }
627     offset += sizeof(int32_t);
628     return size;
629 }
630 
CheckModuleResourceItem(const shared_ptr<ResourceItem> & resourceItem,int64_t id)631 bool ResourceAppend::CheckModuleResourceItem(const shared_ptr<ResourceItem> &resourceItem, int64_t id)
632 {
633     const auto &result = itemsForModule_.find(id);
634     if (result == itemsForModule_.end()) {
635         itemsForModule_[id].push_back(resourceItem);
636         return true;
637     }
638 
639     const auto &ret = find_if(result->second.begin(), result->second.end(), [resourceItem](auto iter) {
640              return  resourceItem->GetLimitKey() == iter->GetLimitKey();
641     });
642 
643     if (ret != result->second.end()) {
644         PrintError(GetError(ERR_CODE_RESOURCE_DUPLICATE)
645                        .FormatCause(resourceItem->GetName().c_str(), (*ret)->GetFilePath().c_str(),
646                                     resourceItem->GetFilePath().c_str()));
647         return false;
648     }
649 
650     itemsForModule_[id].push_back(resourceItem);
651     return true;
652 }
653 
654 #ifdef __WIN32
LoadResourceItemWin(const string & filePath)655 bool ResourceAppend::LoadResourceItemWin(const string &filePath)
656 {
657     bool result = false;
658     HANDLE hReadFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
659         FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS, nullptr);
660     if (hReadFile == INVALID_HANDLE_VALUE) {
661         PrintError(GetError(ERR_CODE_CREATE_FILE_ERROR)
662             .FormatCause(filePath.c_str(), to_string(GetLastError()).c_str()).SetPosition(filePath));
663         return result;
664     }
665 
666     DWORD fileSize = GetFileSize(hReadFile, nullptr);
667     HANDLE hFileMap = CreateFileMapping(hReadFile, nullptr, PAGE_READONLY, 0, fileSize, nullptr);
668     if (hFileMap == INVALID_HANDLE_VALUE) {
669         string errMsg = "create mapping error: " + to_string(GetLastError());
670         PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(filePath.c_str(), errMsg.c_str()));
671         CloseHandle(hReadFile);
672         return result;
673     }
674 
675     void* pBuffer = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
676     if (pBuffer == nullptr) {
677         string errMsg = "map view of file error: " + to_string(GetLastError());
678         PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(filePath.c_str(), errMsg.c_str()));
679         CloseHandle(hReadFile);
680         return result;
681     }
682 
683     char* buffer = reinterpret_cast<char *>(pBuffer);
684     result = LoadResourceItemFromMem(buffer, fileSize);
685     UnmapViewOfFile(hFileMap);
686     CloseHandle(hReadFile);
687     return result;
688 }
689 #endif
690 
IsBaseIdDefined(const FileInfo & fileInfo)691 bool ResourceAppend::IsBaseIdDefined(const FileInfo &fileInfo)
692 {
693     FileEntry::FilePath filePath(fileInfo.filePath);
694     return filePath.GetParent().GetParent().GetFilename() == "base" &&
695         filePath.GetParent().GetFilename() == "element" &&
696         fileInfo.filename == ID_DEFINED_FILE;
697 }
698 
CheckAllItems(vector<pair<ResType,string>> & noBaseResource)699 void ResourceAppend::CheckAllItems(vector<pair<ResType, string>> &noBaseResource)
700 {
701     for (const auto &item : items_) {
702         bool found = any_of(item.second.begin(), item.second.end(), [](const auto &iter) {
703             return iter->GetLimitKey() == "base";
704         });
705         if (!found) {
706             auto firstItem = item.second.front();
707             bool ret = any_of(noBaseResource.begin(), noBaseResource.end(), [firstItem](const auto &iterItem) {
708                 return (firstItem->GetResType() == iterItem.first)  &&
709                     (firstItem->GetName() == iterItem.second);
710             });
711             if (!ret) {
712                 noBaseResource.push_back(make_pair(firstItem->GetResType(), firstItem->GetName()));
713             }
714         }
715     }
716 }
717 }
718 }
719 }