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 "generic_compiler.h"
17 #include <iostream>
18 #include "file_entry.h"
19 #include "resource_util.h"
20 #include "restool_errors.h"
21 #include "compression_parser.h"
22 #include "thread_pool.h"
23 
24 namespace OHOS {
25 namespace Global {
26 namespace Restool {
27 using namespace std;
GenericCompiler(ResType type, const string &output)28 GenericCompiler::GenericCompiler(ResType type, const string &output)
29     : IResourceCompiler(type, output)
30 {
31 }
~GenericCompiler()32 GenericCompiler::~GenericCompiler()
33 {
34 }
35 
CompileFiles(const std::vector<FileInfo> &fileInfos)36 uint32_t GenericCompiler::CompileFiles(const std::vector<FileInfo> &fileInfos)
37 {
38     cout << "Info: GenericCompiler::CompileFiles" << endl;
39     ThreadPool pool(THREAD_POOL_SIZE);
40     pool.Start();
41     std::vector<std::future<uint32_t>> results;
42     for (const auto &fileInfo : fileInfos) {
43         auto taskFunc = [this](const FileInfo &fileInfo) { return this->CompileSingleFile(fileInfo); };
44         results.push_back(pool.Enqueue(taskFunc, fileInfo));
45     }
46     for (auto &ret : results) {
47         if (ret.get() != RESTOOL_SUCCESS) {
48             return RESTOOL_ERROR;
49         }
50     }
51     return RESTOOL_SUCCESS;
52 }
53 
CompileSingleFile(const FileInfo &fileInfo)54 uint32_t GenericCompiler::CompileSingleFile(const FileInfo &fileInfo)
55 {
56     if (IsIgnore(fileInfo)) {
57         return RESTOOL_SUCCESS;
58     }
59 
60     string output = "";
61     if (!CopyMediaFile(fileInfo, output)) {
62         return RESTOOL_ERROR;
63     }
64 
65     if (!PostMediaFile(fileInfo, output)) {
66         return RESTOOL_ERROR;
67     }
68     return RESTOOL_SUCCESS;
69 }
70 
PostMediaFile(const FileInfo &fileInfo, const std::string &output)71 bool GenericCompiler::PostMediaFile(const FileInfo &fileInfo, const std::string &output)
72 {
73     std::lock_guard<std::mutex> lock(mutex_);
74     ResourceItem resourceItem(fileInfo.filename, fileInfo.keyParams, type_);
75     resourceItem.SetFilePath(fileInfo.filePath);
76     resourceItem.SetLimitKey(fileInfo.limitKey);
77 
78     auto index = output.find_last_of(SEPARATOR_FILE);
79     if (index == string::npos) {
80         cerr << "Error: invalid output path." << NEW_LINE_PATH << output << endl;
81         return false;
82     }
83     string data = output.substr(index + 1);
84     data = moduleName_ + SEPARATOR + RESOURCES_DIR + SEPARATOR + \
85         fileInfo.limitKey + SEPARATOR + fileInfo.fileCluster + SEPARATOR + data;
86     if (!resourceItem.SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length())) {
87         cerr << "Error: resource item set data fail, data: " << data << NEW_LINE_PATH << fileInfo.filePath << endl;
88         return false;
89     }
90     return MergeResourceItem(resourceItem);
91 }
92 
GetOutputFilePath(const FileInfo &fileInfo) const93 string GenericCompiler::GetOutputFilePath(const FileInfo &fileInfo) const
94 {
95     string outputFolder = GetOutputFolder(fileInfo);
96     string outputFilePath = FileEntry::FilePath(outputFolder).Append(fileInfo.filename).GetPath();
97     return outputFilePath;
98 }
99 
IsIgnore(const FileInfo &fileInfo)100 bool GenericCompiler::IsIgnore(const FileInfo &fileInfo)
101 {
102     std::lock_guard<std::mutex> lock(mutex_);
103     string output = GetOutputFilePath(fileInfo);
104     if (!g_resourceSet.emplace(output).second) {
105         cerr << "Warning: '" << fileInfo.filePath << "' is defined repeatedly." << endl;
106         return true;
107     }
108     return false;
109 }
110 
CopyMediaFile(const FileInfo &fileInfo, std::string &output)111 bool GenericCompiler::CopyMediaFile(const FileInfo &fileInfo, std::string &output)
112 {
113     string outputFolder = GetOutputFolder(fileInfo);
114     if (!ResourceUtil::CreateDirs(outputFolder)) {
115         cerr << "Error: CopyMediaFile create dirs failed." << NEW_LINE_PATH << outputFolder << endl;
116         return false;
117     }
118     output = GetOutputFilePath(fileInfo);
119     if (moduleName_ == "har" || type_ != ResType::MEDIA) {
120         return ResourceUtil::CopyFileInner(fileInfo.filePath, output);
121     } else {
122         return CompressionParser::GetCompressionParser()->CopyAndTranscode(fileInfo.filePath, output);
123     }
124 }
125 }
126 }
127 }