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,bool isOverlap)28 IResourceCompiler::IResourceCompiler(ResType type, const string &output, bool isOverlap)
29 :type_(type), output_(output), isOverlap_(isOverlap)
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 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH)
56 .FormatCause(it->GetFilePath().GetPath().c_str(), "not a file"));
57 return RESTOOL_ERROR;
58 }
59
60 FileInfo fileInfo = { directoryInfo, it->GetFilePath().GetPath(), it->GetFilePath().GetFilename() };
61 fileInfos.push_back(fileInfo);
62 setsByDirectory[outputFolder].push_back(fileInfo);
63 }
64 }
65
66 sort(fileInfos.begin(), fileInfos.end(), [](const auto &a, const auto &b) {
67 return a.filePath < b.filePath;
68 });
69 if (CompileFiles(fileInfos) != RESTOOL_SUCCESS) {
70 return RESTOOL_ERROR;
71 }
72 return PostCommit();
73 }
74
CompileFiles(const std::vector<FileInfo> & fileInfos)75 uint32_t IResourceCompiler::CompileFiles(const std::vector<FileInfo> &fileInfos)
76 {
77 for (const auto &fileInfo : fileInfos) {
78 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
79 return RESTOOL_ERROR;
80 }
81 }
82 return RESTOOL_SUCCESS;
83 }
84
GetResult() const85 const map<int64_t, vector<ResourceItem>> &IResourceCompiler::GetResult() const
86 {
87 return resourceInfos_;
88 }
89
Compile(const FileInfo & fileInfo)90 uint32_t IResourceCompiler::Compile(const FileInfo &fileInfo)
91 {
92 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
93 return RESTOOL_ERROR;
94 }
95 return PostCommit();
96 }
97
CompileForAppend(const FileInfo & fileInfo)98 uint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo)
99 {
100 return CompileSingleFile(fileInfo);
101 }
102
GetResourceItems() const103 const map<pair<ResType, string>, vector<ResourceItem>> &IResourceCompiler::GetResourceItems() const
104 {
105 return nameInfos_;
106 }
107
SetModuleName(const string & moduleName)108 void IResourceCompiler::SetModuleName(const string &moduleName)
109 {
110 moduleName_ = moduleName;
111 }
112
CompileSingleFile(const FileInfo & fileInfo)113 uint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
114 {
115 return RESTOOL_SUCCESS;
116 }
117
PostCommit()118 uint32_t IResourceCompiler::PostCommit()
119 {
120 IdWorker &idWorker = IdWorker::GetInstance();
121 for (const auto &nameInfo : nameInfos_) {
122 int64_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
123 if (id < 0) {
124 PrintError(GetError(ERR_CODE_RESOURCE_ID_NOT_DEFINED)
125 .FormatCause(nameInfo.first.second.c_str(),
126 ResourceUtil::ResTypeToString(nameInfo.first.first).c_str()));
127 return RESTOOL_ERROR;
128 }
129 resourceInfos_.emplace(id, nameInfo.second);
130 }
131 return RESTOOL_SUCCESS;
132 }
133
MergeResourceItem(const ResourceItem & resourceItem)134 bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
135 {
136 string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
137 if (!ResourceUtil::IsValidName(idName)) {
138 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_NAME).FormatCause(idName.c_str())
139 .SetPosition(resourceItem.GetFilePath()));
140 return false;
141 }
142 auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
143 if (item == nameInfos_.end()) {
144 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
145 return true;
146 }
147
148 auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
149 return resourceItem.GetLimitKey() == iter.GetLimitKey();
150 });
151 if (ret != item->second.end()) {
152 PrintError(GetError(ERR_CODE_RESOURCE_DUPLICATE)
153 .FormatCause(idName.c_str(), ret->GetFilePath().c_str(), resourceItem.GetFilePath().c_str()));
154 return false;
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