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 for (const auto &fileInfo : fileInfos) {
69 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
70 return RESTOOL_ERROR;
71 }
72 }
73 return PostCommit();
74 }
75
GetResult() const76 const map<int64_t, vector<ResourceItem>> &IResourceCompiler::GetResult() const
77 {
78 return resourceInfos_;
79 }
80
Compile(const FileInfo & fileInfo)81 uint32_t IResourceCompiler::Compile(const FileInfo &fileInfo)
82 {
83 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
84 return RESTOOL_ERROR;
85 }
86 return PostCommit();
87 }
88
CompileForAppend(const FileInfo & fileInfo)89 uint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo)
90 {
91 return CompileSingleFile(fileInfo);
92 }
93
GetResourceItems() const94 const map<pair<ResType, string>, vector<ResourceItem>> &IResourceCompiler::GetResourceItems() const
95 {
96 return nameInfos_;
97 }
98
SetModuleName(const string & moduleName)99 void IResourceCompiler::SetModuleName(const string &moduleName)
100 {
101 moduleName_ = moduleName;
102 }
103
CompileSingleFile(const FileInfo & fileInfo)104 uint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
105 {
106 return RESTOOL_SUCCESS;
107 }
108
PostCommit()109 uint32_t IResourceCompiler::PostCommit()
110 {
111 IdWorker &idWorker = IdWorker::GetInstance();
112 for (const auto &nameInfo : nameInfos_) {
113 int64_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
114 if (id < 0) {
115 cerr << "Error: restype='" << ResourceUtil::ResTypeToString(nameInfo.first.first) << "' name='";
116 cerr << nameInfo.first.second << "' id not be defined." << endl;
117 return RESTOOL_ERROR;
118 }
119 resourceInfos_.emplace(id, nameInfo.second);
120 }
121 return RESTOOL_SUCCESS;
122 }
123
MergeResourceItem(const ResourceItem & resourceItem)124 bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
125 {
126 string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
127 if (!ResourceUtil::IsValidName(idName)) {
128 cerr << "Error: invalid idName '" << idName << "'."<< NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
129 cerr << SOLUTIONS << endl;
130 cerr << SOLUTIONS_ARROW << "Modify the name '" << idName << "' to match [a-zA-Z0-9_]." << endl;
131 return false;
132 }
133 auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
134 if (item == nameInfos_.end()) {
135 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
136 return true;
137 }
138
139 auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
140 return resourceItem.GetLimitKey() == iter.GetLimitKey();
141 });
142 if (ret != item->second.end()) {
143 cerr << "Error: resource '" << idName << "' first declared." << NEW_LINE_PATH << ret->GetFilePath() << endl;
144 cerr << "but declare again." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
145 return false;
146 }
147
148 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
149 return true;
150 }
151
GetOutputFolder(const DirectoryInfo & directoryInfo) const152 string IResourceCompiler::GetOutputFolder(const DirectoryInfo &directoryInfo) const
153 {
154 string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
155 .Append(directoryInfo.limitKey).Append(directoryInfo.fileCluster).GetPath();
156 return outputFolder;
157 }
158 }
159 }
160 }
161