1 /*
2 * Copyright (c) 2021 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_pack.h"
17 #include <algorithm>
18 #include <iomanip>
19 #include "file_entry.h"
20 #include "file_manager.h"
21 #include "header.h"
22 #include "resource_merge.h"
23 #include "resource_table.h"
24 #include "resource_check.h"
25
26 namespace OHOS {
27 namespace Global {
28 namespace Restool {
29 using namespace std;
ResourcePack(const PackageParser & packageParser)30 ResourcePack::ResourcePack(const PackageParser &packageParser):packageParser_(packageParser)
31 {
32 }
33
Package()34 uint32_t ResourcePack::Package()
35 {
36 if (!packageParser_.GetAppend().empty()) {
37 return PackAppend();
38 }
39
40 if (packageParser_.GetCombine()) {
41 return PackCombine();
42 }
43 return PackNormal();
44 }
45
46 // below private founction
Init()47 uint32_t ResourcePack::Init()
48 {
49 InitHeaderCreater();
50 if (InitOutput() != RESTOOL_SUCCESS) {
51 return RESTOOL_ERROR;
52 }
53
54 if (InitConfigJson() != RESTOOL_SUCCESS) {
55 return RESTOOL_ERROR;
56 }
57
58 if (InitModule() != RESTOOL_SUCCESS) {
59 return RESTOOL_ERROR;
60 }
61 return RESTOOL_SUCCESS;
62 }
63
InitModule()64 uint32_t ResourcePack::InitModule()
65 {
66 IdWorker::ResourceIdCluster hapType = IdWorker::ResourceIdCluster::RES_ID_APP;
67 string packageName = packageParser_.GetPackageName();
68 if (packageName == "ohos.global.systemres") {
69 hapType = IdWorker::ResourceIdCluster::RES_ID_SYS;
70 }
71
72 moduleName_ = configJson_.GetModuleName();
73 vector<string> moduleNames = packageParser_.GetModuleNames();
74 IdWorker &idWorker = IdWorker::GetInstance();
75 int32_t startId = packageParser_.GetStartId();
76 if (startId > 0) {
77 return idWorker.Init(hapType, startId);
78 }
79
80 if (moduleNames.empty()) {
81 return idWorker.Init(hapType);
82 } else {
83 sort(moduleNames.begin(), moduleNames.end());
84 auto it = find_if(moduleNames.begin(), moduleNames.end(), [this](auto iter) {
85 return moduleName_ == iter;
86 });
87 if (it == moduleNames.end()) {
88 string buffer(" ");
89 for_each(moduleNames.begin(), moduleNames.end(), [&buffer](const auto &iter) {
90 buffer.append(" " + iter + " ");
91 });
92 cerr << "Error: module name '" << moduleName_ << "' not in [" << buffer << "]" << endl;
93 return RESTOOL_ERROR;
94 }
95
96 startId = ((it - moduleNames.begin()) + 1) * 0x01000000;
97 if (startId >= 0x07000000) {
98 startId = startId + 0x01000000;
99 }
100 return idWorker.Init(hapType, startId);
101 }
102 return RESTOOL_SUCCESS;
103 }
104
InitHeaderCreater()105 void ResourcePack::InitHeaderCreater()
106 {
107 using namespace placeholders;
108 headerCreaters_.emplace(".txt", bind(&ResourcePack::GenerateTextHeader, this, _1));
109 headerCreaters_.emplace(".js", bind(&ResourcePack::GenerateJsHeader, this, _1));
110 headerCreaters_.emplace(".h", bind(&ResourcePack::GenerateCplusHeader, this, _1));
111 }
112
InitOutput() const113 uint32_t ResourcePack::InitOutput() const
114 {
115 bool forceWrite = packageParser_.GetForceWrite();
116 bool combine = packageParser_.GetCombine();
117 string output = packageParser_.GetOutput();
118 string resourcesPath = FileEntry::FilePath(output).Append(RESOURCES_DIR).GetPath();
119 if (ResourceUtil::FileExist(resourcesPath)) {
120 if (!forceWrite) {
121 cerr << "Error: output path exists." << NEW_LINE_PATH << resourcesPath << endl;
122 return RESTOOL_ERROR;
123 }
124
125 if (!ResourceUtil::RmoveAllDir(resourcesPath)) {
126 return combine ? RESTOOL_SUCCESS : RESTOOL_ERROR;
127 }
128 }
129 return RESTOOL_SUCCESS;
130 }
131
GenerateHeader() const132 uint32_t ResourcePack::GenerateHeader() const
133 {
134 auto headerPaths = packageParser_.GetResourceHeaders();
135 string textPath = FileEntry::FilePath(packageParser_.GetOutput()).Append("ResourceTable.txt").GetPath();
136 headerPaths.push_back(textPath);
137 for (const auto &headerPath : headerPaths) {
138 string extension = FileEntry::FilePath(headerPath).GetExtension();
139 auto it = headerCreaters_.find(extension);
140 if (it == headerCreaters_.end()) {
141 cout << "Warning: don't support header file format '" << headerPath << "'" << endl;
142 continue;
143 }
144 if (it->second(headerPath) != RESTOOL_SUCCESS) {
145 return RESTOOL_ERROR;
146 }
147 }
148 return RESTOOL_SUCCESS;
149 }
150
InitConfigJson()151 uint32_t ResourcePack::InitConfigJson()
152 {
153 string config = packageParser_.GetConfig();
154 if (config.empty()) {
155 if (packageParser_.GetInputs().size() > 1) {
156 cerr << "Error: more input path, -j config.json empty" << endl;
157 return RESTOOL_ERROR;
158 }
159 config = ResourceUtil::GetMainPath(packageParser_.GetInputs()[0]).Append(CONFIG_JSON).GetPath();
160 if (!ResourceUtil::FileExist(config)) {
161 config = ResourceUtil::GetMainPath(packageParser_.GetInputs()[0]).Append(MODULE_JSON).GetPath();
162 }
163 }
164
165 if (FileEntry::FilePath(config).GetFilename() == MODULE_JSON) {
166 ConfigParser::SetUseModule();
167 }
168 configJson_ = ConfigParser(config);
169 if (configJson_.Init() != RESTOOL_SUCCESS) {
170 return RESTOOL_ERROR;
171 }
172 return RESTOOL_SUCCESS;
173 }
174
GenerateTextHeader(const string & headerPath) const175 uint32_t ResourcePack::GenerateTextHeader(const string &headerPath) const
176 {
177 Header textHeader(headerPath);
178 bool first = true;
179 uint32_t result = textHeader.Create([](stringstream &buffer) {},
180 [&first](stringstream &buffer, const IdWorker::ResourceId& resourceId) {
181 if (first) {
182 first = false;
183 } else {
184 buffer << "\n";
185 }
186 buffer << resourceId.type << " " << resourceId.name;
187 buffer << " 0x" << hex << setw(8) << setfill('0') << resourceId.id;
188 }, [](stringstream &buffer) {});
189 if (result != RESTOOL_SUCCESS) {
190 return RESTOOL_ERROR;
191 }
192 return RESTOOL_SUCCESS;
193 }
194
GenerateCplusHeader(const string & headerPath) const195 uint32_t ResourcePack::GenerateCplusHeader(const string &headerPath) const
196 {
197 Header cplusHeader(headerPath);
198 uint32_t result = cplusHeader.Create([](stringstream &buffer) {
199 buffer << Header::LICENSE_HEADER << "\n";
200 buffer << "#ifndef RESOURCE_TABLE_H\n";
201 buffer << "#define RESOURCE_TABLE_H\n\n";
202 buffer << "#include<stdint.h>\n\n";
203 buffer << "namespace OHOS {\n";
204 }, [](stringstream &buffer, const IdWorker::ResourceId& resourceId) {
205 string name = resourceId.type + "_" + resourceId.name;
206 transform(name.begin(), name.end(), name.begin(), ::toupper);
207 buffer << "const int32_t " << name << " = ";
208 buffer << "0x" << hex << setw(8) << setfill('0') << resourceId.id << ";\n";
209 }, [](stringstream &buffer) {
210 buffer << "}\n";
211 buffer << "#endif";
212 });
213 return result;
214 }
215
GenerateJsHeader(const std::string & headerPath) const216 uint32_t ResourcePack::GenerateJsHeader(const std::string &headerPath) const
217 {
218 Header JsHeader(headerPath);
219 string itemType;
220 uint32_t result = JsHeader.Create([](stringstream &buffer) {
221 buffer << Header::LICENSE_HEADER << "\n";
222 buffer << "export default {\n";
223 }, [&itemType](stringstream &buffer, const IdWorker::ResourceId& resourceId) {
224 if (itemType != resourceId.type) {
225 if (!itemType.empty()) {
226 buffer << "\n" << " " << "},\n";
227 }
228 buffer << " " << resourceId.type << " : {\n";
229 itemType = resourceId.type;
230 } else {
231 buffer << ",\n";
232 }
233 buffer << " " << resourceId.name << " : " << resourceId.id;
234 }, [](stringstream &buffer) {
235 buffer << "\n" << " " << "}\n";
236 buffer << "}\n";
237 });
238 return result;
239 }
240
CopyRawFileOrResFile(const string & filePath,const string & fileType) const241 uint32_t ResourcePack::CopyRawFileOrResFile(const string &filePath, const string &fileType) const
242 {
243 if (!ResourceUtil::FileExist(filePath)) {
244 return RESTOOL_SUCCESS;
245 }
246
247 if (!FileEntry::IsDirectory(filePath)) {
248 cerr << "Error: '" << filePath << "' not directory." << endl;
249 return RESTOOL_ERROR;
250 }
251
252 string dst = FileEntry::FilePath(packageParser_.GetOutput())
253 .Append(RESOURCES_DIR).Append(fileType).GetPath();
254 if (CopyRawFileOrResFileImpl(filePath, dst) != RESTOOL_SUCCESS) {
255 return RESTOOL_ERROR;
256 }
257 return RESTOOL_SUCCESS;
258 }
259
CopyRawFileOrResFile(const vector<string> & inputs) const260 uint32_t ResourcePack::CopyRawFileOrResFile(const vector<string> &inputs) const
261 {
262 for (const auto &input : inputs) {
263 string rawfilePath = FileEntry::FilePath(input).Append(RAW_FILE_DIR).GetPath();
264 if (CopyRawFileOrResFile(rawfilePath, RAW_FILE_DIR) == RESTOOL_ERROR) {
265 return RESTOOL_ERROR;
266 }
267 string resfilePath = FileEntry::FilePath(input).Append(RES_FILE_DIR).GetPath();
268 if (CopyRawFileOrResFile(resfilePath, RES_FILE_DIR) == RESTOOL_ERROR) {
269 return RESTOOL_ERROR;
270 }
271 }
272 return RESTOOL_SUCCESS;
273 }
274
CopyRawFileOrResFileImpl(const string & src,const string & dst) const275 uint32_t ResourcePack::CopyRawFileOrResFileImpl(const string &src, const string &dst) const
276 {
277 if (!ResourceUtil::CreateDirs(dst)) {
278 return RESTOOL_ERROR;
279 }
280
281 FileEntry f(src);
282 if (!f.Init()) {
283 return RESTOOL_ERROR;
284 }
285 for (const auto &entry : f.GetChilds()) {
286 string filename = entry->GetFilePath().GetFilename();
287 if (ResourceUtil::IsIgnoreFile(filename, entry->IsFile())) {
288 continue;
289 }
290
291 string subPath = FileEntry::FilePath(dst).Append(filename).GetPath();
292 if (!entry->IsFile()) {
293 if (CopyRawFileOrResFileImpl(entry->GetFilePath().GetPath(), subPath) != RESTOOL_SUCCESS) {
294 return RESTOOL_ERROR;
295 }
296 } else {
297 if (ResourceUtil::FileExist(subPath)) {
298 continue;
299 }
300 if (!ResourceUtil::CopyFleInner(entry->GetFilePath().GetPath(), subPath)) {
301 return RESTOOL_ERROR;
302 }
303 }
304 }
305 return RESTOOL_SUCCESS;
306 }
307
GenerateConfigJson()308 uint32_t ResourcePack::GenerateConfigJson()
309 {
310 if (configJson_.ParseRefence() != RESTOOL_SUCCESS) {
311 return RESTOOL_ERROR;
312 }
313 string outputPath = FileEntry::FilePath(packageParser_.GetOutput())
314 .Append(ConfigParser::GetConfigName()).GetPath();
315 return configJson_.Save(outputPath);
316 }
317
CheckConfigJson()318 void ResourcePack::CheckConfigJson()
319 {
320 ResourceCheck resourceCheck(configJson_);
321 resourceCheck.CheckConfigJson();
322 }
323
ScanResources(const vector<string> & inputs,const string & output)324 uint32_t ResourcePack::ScanResources(const vector<string> &inputs, const string &output)
325 {
326 auto &fileManager = FileManager::GetInstance();
327 fileManager.SetModuleName(moduleName_);
328 if (fileManager.ScanModules(inputs, output) != RESTOOL_SUCCESS) {
329 return RESTOOL_ERROR;
330 }
331 return RESTOOL_SUCCESS;
332 }
333
PackNormal()334 uint32_t ResourcePack::PackNormal()
335 {
336 if (Init() != RESTOOL_SUCCESS) {
337 return RESTOOL_ERROR;
338 }
339
340 ResourceMerge resourceMerge;
341 if (resourceMerge.Init() != RESTOOL_SUCCESS) {
342 return RESTOOL_ERROR;
343 }
344
345 if (ScanResources(resourceMerge.GetInputs(), packageParser_.GetOutput()) != RESTOOL_SUCCESS) {
346 return RESTOOL_ERROR;
347 }
348
349 if (GenerateHeader() != RESTOOL_SUCCESS) {
350 return RESTOOL_ERROR;
351 }
352
353 if (CopyRawFileOrResFile(resourceMerge.GetInputs()) != RESTOOL_SUCCESS) {
354 return RESTOOL_ERROR;
355 }
356
357 if (GenerateConfigJson() != RESTOOL_SUCCESS) {
358 return RESTOOL_ERROR;
359 }
360
361 if (packageParser_.GetIconCheck()) {
362 CheckConfigJson();
363 }
364
365 ResourceTable resourceTable;
366 if (!packageParser_.GetDependEntry().empty()) {
367 if (HandleFeature() != RESTOOL_SUCCESS) {
368 return RESTOOL_ERROR;
369 }
370 if (GenerateHeader() != RESTOOL_SUCCESS) {
371 return RESTOOL_ERROR;
372 }
373 }
374
375 if (resourceTable.CreateResourceTable() != RESTOOL_SUCCESS) {
376 return RESTOOL_ERROR;
377 }
378 return RESTOOL_SUCCESS;
379 }
380
HandleFeature()381 uint32_t ResourcePack::HandleFeature()
382 {
383 string output = packageParser_.GetOutput();
384 string featureDependEntry = packageParser_.GetDependEntry();
385 if (featureDependEntry.empty()) {
386 return RESTOOL_SUCCESS;
387 }
388 string jsonFile = FileEntry::FilePath(featureDependEntry).Append(CONFIG_JSON).GetPath();
389 ConfigParser entryJson(jsonFile);
390 entryJson.SetDependEntry(true);
391 if (entryJson.Init() != RESTOOL_SUCCESS) {
392 cerr << "Error: config json invalid." << NEW_LINE_PATH << jsonFile << endl;
393 return RESTOOL_ERROR;
394 }
395
396 int32_t labelId = entryJson.GetAbilityLabelId();
397 int32_t iconId = entryJson.GetAbilityIconId();
398 if (labelId <= 0 || iconId <= 0) {
399 cerr << "Error: Entry MainAbility must have 'icon' and 'label'." << endl;
400 return RESTOOL_ERROR;
401 }
402 string path = FileEntry::FilePath(featureDependEntry).Append(RESOURCE_INDEX_FILE).GetPath();
403 map<int32_t, vector<ResourceItem>> resInfoLocal;
404 ResourceTable resourceTable;
405 if (resourceTable.LoadResTable(path, resInfoLocal) != RESTOOL_SUCCESS) {
406 cerr << "Error: LoadResTable fail." << endl;
407 return RESTOOL_ERROR;
408 }
409 jsonFile = FileEntry::FilePath(output).Append(CONFIG_JSON).GetPath();
410 ConfigParser config(jsonFile);
411 if (config.Init() != RESTOOL_SUCCESS) {
412 cerr << "Error: config json invalid." << NEW_LINE_PATH << jsonFile << endl;
413 return RESTOOL_ERROR;
414 }
415 vector<ResourceItem> items;
416 if (FindResourceItems(resInfoLocal, items, labelId) != RESTOOL_SUCCESS ||
417 HandleLabel(items, config) != RESTOOL_SUCCESS) {
418 return RESTOOL_ERROR;
419 }
420 items.clear();
421 if (FindResourceItems(resInfoLocal, items, iconId) != RESTOOL_SUCCESS ||
422 HandleIcon(items, config) != RESTOOL_SUCCESS) {
423 return RESTOOL_ERROR;
424 }
425 string outputPath = FileEntry::FilePath(output).Append(ConfigParser::GetConfigName()).GetPath();
426 if (config.Save(outputPath) != RESTOOL_SUCCESS) {
427 return RESTOOL_ERROR;
428 }
429 entryJson.SetDependEntry(false);
430 return RESTOOL_SUCCESS;
431 }
432
FindResourceItems(const map<int32_t,vector<ResourceItem>> & resInfoLocal,vector<ResourceItem> & items,int32_t id) const433 uint32_t ResourcePack::FindResourceItems(const map<int32_t, vector<ResourceItem>> &resInfoLocal,
434 vector<ResourceItem> &items, int32_t id) const
435 {
436 auto ret = resInfoLocal.find(id);
437 if (ret == resInfoLocal.end()) {
438 cerr << "Error: FindResourceItems don't found '" << id << "'." << endl;
439 return RESTOOL_ERROR;
440 }
441 ResType type = ResType::INVALID_RES_TYPE;
442 items = ret->second;
443 if (items.empty()) {
444 cerr << "Error: FindResourceItems resource item empty '" << id << "'." << endl;
445 return RESTOOL_ERROR;
446 }
447 for (auto &it : items) {
448 if (type == ResType::INVALID_RES_TYPE) {
449 type = it.GetResType();
450 }
451 if (type != it.GetResType()) {
452 cerr << "Error: FindResourceItems invalid restype '" << ResourceUtil::ResTypeToString(type);
453 cerr << "' vs '" << ResourceUtil::ResTypeToString(it.GetResType()) << "'." << endl;
454 return RESTOOL_ERROR;
455 }
456 }
457 return RESTOOL_SUCCESS;
458 }
459
HandleLabel(vector<ResourceItem> & items,ConfigParser & config) const460 uint32_t ResourcePack::HandleLabel(vector<ResourceItem> &items, ConfigParser &config) const
461 {
462 int32_t nextId = 0;
463 string idName;
464 for (auto it : items) {
465 if (it.GetResType() != ResType::STRING) {
466 cerr << "Error: HandleLabel invalid restype '";
467 cerr << ResourceUtil::ResTypeToString(it.GetResType()) << "'." << endl;
468 return RESTOOL_ERROR;
469 }
470 idName = it.GetName() + "_entry";
471 it.SetName(idName);
472 string data(reinterpret_cast<const char *>(it.GetData()));
473 if (!it.SetData(reinterpret_cast<const int8_t *>(data.c_str()), it.GetDataLength()-1)) {
474 return RESTOOL_ERROR;
475 }
476 if (nextId <= 0) {
477 nextId = IdWorker::GetInstance().GenerateId(ResType::STRING, idName);
478 }
479 SaveResourceItem(it, nextId);
480 }
481 string label = "$string:" +idName;
482 config.SetAppLabel(label, nextId);
483 return RESTOOL_SUCCESS;
484 }
485
CopyIcon(string & dataPath,const string & idName,string & fileName) const486 bool ResourcePack::CopyIcon(string &dataPath, const string &idName, string &fileName) const
487 {
488 string featureDependEntry = packageParser_.GetDependEntry();
489 string source = FileEntry::FilePath(featureDependEntry).Append(dataPath).GetPath();
490 string suffix = FileEntry::FilePath(source).GetExtension();
491 fileName = idName + suffix;
492 string output = packageParser_.GetOutput();
493 #ifdef _WIN32
494 ResourceUtil::StringReplace(dataPath, SEPARATOR, WIN_SEPARATOR);
495 #endif
496 string dstDir = FileEntry::FilePath(output).Append(dataPath).GetParent().GetPath();
497 string dst = FileEntry::FilePath(dstDir).Append(fileName).GetPath();
498 if (!ResourceUtil::CreateDirs(dstDir)) {
499 cerr << "Error: Create Dirs fail '" << dstDir << "'."<< endl;
500 return false;
501 }
502 if (!ResourceUtil::CopyFleInner(source, dst)) {
503 cerr << "Error: copy file fail from '" << source << "' to '" << dst << "'." << endl;
504 return false;
505 }
506 return true;
507 }
508
HandleIcon(vector<ResourceItem> & items,ConfigParser & config) const509 uint32_t ResourcePack::HandleIcon(vector<ResourceItem> &items, ConfigParser &config) const
510 {
511 int32_t nextId = 0;
512 string idName;
513 for (auto it : items) {
514 if (it.GetResType() != ResType::MEDIA) {
515 cerr << "Error: HandleLabel invalid restype '";
516 cerr << ResourceUtil::ResTypeToString(it.GetResType()) << "'." << endl;
517 return RESTOOL_ERROR;
518 }
519 string dataPath(reinterpret_cast<const char *>(it.GetData()));
520 string::size_type pos = dataPath.find_first_of(SEPARATOR);
521 if (pos == string::npos) {
522 cerr << "Error: HandleIcon invalid '" << dataPath << "'."<< endl;
523 return RESTOOL_ERROR;
524 }
525 dataPath = dataPath.substr(pos + 1);
526 idName = it.GetName() + "_entry";
527 string fileName;
528 if (!CopyIcon(dataPath, idName, fileName)) {
529 return RESTOOL_ERROR;
530 }
531 string data = FileEntry::FilePath(moduleName_).Append(dataPath).GetParent().Append(fileName).GetPath();
532 ResourceUtil::StringReplace(data, WIN_SEPARATOR, SEPARATOR);
533 ResourceItem resourceItem(fileName, it.GetKeyParam(), ResType::MEDIA);
534 resourceItem.SetLimitKey(it.GetLimitKey());
535 if (!resourceItem.SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length())) {
536 return RESTOOL_ERROR;
537 }
538 if (nextId <= 0) {
539 nextId = IdWorker::GetInstance().GenerateId(ResType::MEDIA, idName);
540 }
541 SaveResourceItem(resourceItem, nextId);
542 }
543 string icon = "$media:" + idName;
544 config.SetAppIcon(icon, nextId);
545 return RESTOOL_SUCCESS;
546 }
547
SaveResourceItem(const ResourceItem & resourceItem,int32_t nextId) const548 void ResourcePack::SaveResourceItem(const ResourceItem &resourceItem, int32_t nextId) const
549 {
550 map<int32_t, vector<ResourceItem>> resInfo;
551 vector<ResourceItem> vet;
552 vet.push_back(resourceItem);
553 resInfo.insert(make_pair(nextId, vet));
554 FileManager &fileManager = FileManager::GetInstance();
555 fileManager.MergeResourceItem(resInfo);
556 }
557
PackAppend()558 uint32_t ResourcePack::PackAppend()
559 {
560 ResourceAppend resourceAppend(packageParser_);
561 if (!packageParser_.GetAppend().empty()) {
562 return resourceAppend.Append();
563 }
564 return RESTOOL_SUCCESS;
565 }
566
PackCombine()567 uint32_t ResourcePack::PackCombine()
568 {
569 if (Init() != RESTOOL_SUCCESS) {
570 return RESTOOL_ERROR;
571 }
572
573 ResourceAppend resourceAppend(packageParser_);
574 if (resourceAppend.Combine() != RESTOOL_SUCCESS) {
575 return RESTOOL_ERROR;
576 }
577
578 if (GenerateConfigJson() != RESTOOL_SUCCESS) {
579 return RESTOOL_ERROR;
580 }
581
582 if (packageParser_.GetIconCheck()) {
583 CheckConfigJsonForCombine(resourceAppend);
584 }
585
586 if (GenerateHeader() != RESTOOL_SUCCESS) {
587 return RESTOOL_ERROR;
588 }
589 return RESTOOL_SUCCESS;
590 }
591
CheckConfigJsonForCombine(ResourceAppend & resourceAppend)592 void ResourcePack::CheckConfigJsonForCombine(ResourceAppend &resourceAppend)
593 {
594 ResourceCheck resourceCheck(configJson_, make_shared<ResourceAppend>(resourceAppend));
595 resourceCheck.CheckConfigJsonForCombine();
596 }
597
598 }
599 }
600 }
601