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 "i_resource_compiler.h"
17 #include <algorithm>
18 #include <iostream>
19 #include "file_entry.h"
20 #include "id_worker.h"
21 #include "resource_util.h"
22 #include "restool_errors.h"
23
24 namespace OHOS {
25 namespace Global {
26 namespace Restool {
27 using namespace std;
IResourceCompiler(ResType type, const string &output)28 IResourceCompiler::IResourceCompiler(ResType type, const string &output)
29 :type_(type), output_(output)
30 {
31 }
32
~IResourceCompiler()33 IResourceCompiler::~IResourceCompiler()
34 {
35 nameInfos_.clear();
36 resourceInfos_.clear();
37 }
38
Compile(const vector<DirectoryInfo> &directoryInfos)39 uint32_t IResourceCompiler::Compile(const vector<DirectoryInfo> &directoryInfos)
40 {
41 vector<FileInfo> fileInfos;
42 map<string, vector<FileInfo>> setsByDirectory;
43 for (const auto &directoryInfo : directoryInfos) {
44 string outputFolder = GetOutputFolder(directoryInfo);
45 FileEntry f(directoryInfo.dirPath);
46 if (!f.Init()) {
47 return RESTOOL_ERROR;
48 }
49 for (const auto &it : f.GetChilds()) {
50 if (ResourceUtil::IsIgnoreFile(it->GetFilePath().GetFilename(), it->IsFile())) {
51 continue;
52 }
53
54 if (!it->IsFile()) {
55 cerr << "Error: '" << it->GetFilePath().GetPath() << "' must be a file." << endl;
56 return RESTOOL_ERROR;
57 }
58
59 FileInfo fileInfo = { directoryInfo, it->GetFilePath().GetPath(), it->GetFilePath().GetFilename() };
60 fileInfos.push_back(fileInfo);
61 setsByDirectory[outputFolder].push_back(fileInfo);
62 }
63 }
64
65 sort(fileInfos.begin(), fileInfos.end(), [](const auto &a, const auto &b) {
66 return a.filePath < b.filePath;
67 });
68 if (CompileFiles(fileInfos) != RESTOOL_SUCCESS) {
69 return RESTOOL_ERROR;
70 }
71 return PostCommit();
72 }
73
CompileFiles(const std::vector<FileInfo> &fileInfos)74 uint32_t IResourceCompiler::CompileFiles(const std::vector<FileInfo> &fileInfos)
75 {
76 for (const auto &fileInfo : fileInfos) {
77 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
78 return RESTOOL_ERROR;
79 }
80 }
81 return RESTOOL_SUCCESS;
82 }
83
GetResult() const84 const map<int64_t, vector<ResourceItem>> &IResourceCompiler::GetResult() const
85 {
86 return resourceInfos_;
87 }
88
Compile(const FileInfo &fileInfo)89 uint32_t IResourceCompiler::Compile(const FileInfo &fileInfo)
90 {
91 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
92 return RESTOOL_ERROR;
93 }
94 return PostCommit();
95 }
96
CompileForAppend(const FileInfo &fileInfo)97 uint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo)
98 {
99 return CompileSingleFile(fileInfo);
100 }
101
GetResourceItems() const102 const map<pair<ResType, string>, vector<ResourceItem>> &IResourceCompiler::GetResourceItems() const
103 {
104 return nameInfos_;
105 }
106
SetModuleName(const string &moduleName)107 void IResourceCompiler::SetModuleName(const string &moduleName)
108 {
109 moduleName_ = moduleName;
110 }
111
CompileSingleFile(const FileInfo &fileInfo)112 uint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
113 {
114 return RESTOOL_SUCCESS;
115 }
116
PostCommit()117 uint32_t IResourceCompiler::PostCommit()
118 {
119 IdWorker &idWorker = IdWorker::GetInstance();
120 for (const auto &nameInfo : nameInfos_) {
121 int64_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
122 if (id < 0) {
123 cerr << "Error: restype='" << ResourceUtil::ResTypeToString(nameInfo.first.first) << "' name='";
124 cerr << nameInfo.first.second << "' id not be defined." << endl;
125 return RESTOOL_ERROR;
126 }
127 resourceInfos_.emplace(id, nameInfo.second);
128 }
129 return RESTOOL_SUCCESS;
130 }
131
MergeResourceItem(const ResourceItem &resourceItem)132 bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
133 {
134 string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
135 if (!ResourceUtil::IsValidName(idName)) {
136 cerr << "Error: invalid idName '" << idName << "'."<< NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
137 cerr << SOLUTIONS << endl;
138 cerr << SOLUTIONS_ARROW << "Modify the name '" << idName << "' to match [a-zA-Z0-9_]." << endl;
139 return false;
140 }
141 auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
142 if (item == nameInfos_.end()) {
143 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
144 return true;
145 }
146
147 auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
148 return resourceItem.GetLimitKey() == iter.GetLimitKey();
149 });
150 if (ret != item->second.end()) {
151 cerr << "Error: resource '" << idName << "' first declared." << NEW_LINE_PATH << ret->GetFilePath() << endl;
152 cerr << "but declare again." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
153 return false;
154 }
155
156 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
157 return true;
158 }
159
GetOutputFolder(const DirectoryInfo &directoryInfo) const160 string IResourceCompiler::GetOutputFolder(const DirectoryInfo &directoryInfo) const
161 {
162 string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
163 .Append(directoryInfo.limitKey).Append(directoryInfo.fileCluster).GetPath();
164 return outputFolder;
165 }
166 }
167 }
168 }
169