• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_util.h"
17 #include <algorithm>
18 #include <cstdlib>
19 #include <fstream>
20 #include <iostream>
21 #include <iomanip>
22 #include <regex>
23 #include "file_entry.h"
24 
25 namespace OHOS {
26 namespace Global {
27 namespace Restool {
28 using namespace std;
29 const map<string, ResourceUtil::IgnoreType> ResourceUtil::IGNORE_FILE_REGEX = {
30     { "\\.git", IgnoreType::IGNORE_ALL },
31     { "\\.svn", IgnoreType::IGNORE_ALL },
32     { ".+\\.scc", IgnoreType::IGNORE_ALL },
33     { "\\.ds_store", IgnoreType::IGNORE_ALL },
34     { "desktop\\.ini", IgnoreType::IGNORE_ALL },
35     { "picasa\\.ini", IgnoreType::IGNORE_ALL },
36     { "\\..+", IgnoreType::IGNORE_ALL },
37     { "_.+", IgnoreType::IGNORE_DIR },
38     { "cvs", IgnoreType::IGNORE_ALL },
39     { "thumbs\\.db", IgnoreType::IGNORE_ALL },
40     { ".+~", IgnoreType::IGNORE_ALL }
41 };
42 
Split(const string & str,vector<string> & out,const string & splitter)43 void ResourceUtil::Split(const string &str, vector<string> &out, const string &splitter)
44 {
45     string::size_type len = str.size();
46     string::size_type begin = 0;
47     string::size_type end = str.find(splitter, begin);
48     while (end != string::npos) {
49         string sub = str.substr(begin, end - begin);
50         out.push_back(sub);
51         begin = end + splitter.size();
52         if (begin >= len) {
53             break;
54         }
55         end = str.find(splitter, begin);
56     }
57 
58     if (begin < len) {
59         out.push_back(str.substr(begin));
60     }
61 }
62 
FileExist(const string & path)63 bool ResourceUtil::FileExist(const string &path)
64 {
65     return FileEntry::Exist(path);
66 }
67 
RmoveAllDir(const string & path)68 bool ResourceUtil::RmoveAllDir(const string &path)
69 {
70     return FileEntry::RemoveAllDir(path);
71 }
72 
OpenJsonFile(const string & path,Json::Value & root)73 bool ResourceUtil::OpenJsonFile(const string &path, Json::Value &root)
74 {
75     ifstream ifs(FileEntry::AdaptLongPath(path), ios::binary);
76     if (!ifs.is_open()) {
77         cerr << "Error: open json failed '" << path << "', reason: " << strerror(errno) << endl;
78         return false;
79     }
80 
81     Json::CharReaderBuilder readBuilder;
82     readBuilder["collectComments"] = false;
83     readBuilder["failIfExtra"] = true;
84     JSONCPP_STRING errs;
85     if (!parseFromStream(readBuilder, ifs, &root, &errs)) {
86         cerr << "Error: parseFromStream failed." << NEW_LINE_PATH << path;
87         cerr << "\n" << errs << endl;
88         ifs.close();
89         return false;
90     }
91     ifs.close();
92     return true;
93 }
94 
SaveToJsonFile(const string & path,const Json::Value & root)95 bool ResourceUtil::SaveToJsonFile(const string &path, const Json::Value &root)
96 {
97     Json::StreamWriterBuilder writerBuilder;
98     writerBuilder["indentation"] = "    ";
99     writerBuilder["emitUTF8"] = true;
100     unique_ptr<Json::StreamWriter> writer(writerBuilder.newStreamWriter());
101     ofstream out(FileEntry::AdaptLongPath(path), ofstream::out | ofstream::binary);
102     if (!out.is_open()) {
103         cerr << "Error: open failed '" << path <<"', reason: " << strerror(errno) << endl;
104         return false;
105     }
106     writer->write(root, &out);
107     out.close();
108     return true;
109 }
110 
GetResTypeByDir(const string & name)111 ResType ResourceUtil::GetResTypeByDir(const string &name)
112 {
113     auto ret = g_fileClusterMap.find(name);
114     if (ret == g_fileClusterMap.end()) {
115         return ResType::INVALID_RES_TYPE;
116     }
117     return ret->second;
118 }
119 
ResTypeToString(ResType type)120 string ResourceUtil::ResTypeToString(ResType type)
121 {
122     auto ret = find_if(g_fileClusterMap.begin(), g_fileClusterMap.end(), [type](auto iter) {
123         return iter.second == type;
124     });
125     if (ret != g_fileClusterMap.end()) {
126         return ret->first;
127     }
128 
129     ret = find_if(g_contentClusterMap.begin(), g_contentClusterMap.end(), [type](auto iter) {
130         return iter.second == type;
131     });
132     if (ret != g_contentClusterMap.end()) {
133         return ret->first;
134     }
135     return "";
136 }
137 
GetIdName(const string & name,ResType type)138 string ResourceUtil::GetIdName(const string &name, ResType type)
139 {
140     if (type != ResType::MEDIA && type != ResType::PROF) {
141         return name;
142     }
143 
144     string::size_type pos = name.find_last_of(".");
145     if (pos != string::npos) {
146         return name.substr(0, pos);
147     }
148     return name;
149 }
150 
ComposeStrings(const vector<string> & contents,bool addNull)151 string ResourceUtil::ComposeStrings(const vector<string> &contents, bool addNull)
152 {
153     string result;
154     for (const auto &iter : contents) {
155         if (iter.length() > UINT16_MAX) {
156             return "";
157         }
158 
159         uint16_t size = iter.length();
160         if (addNull) {
161             size += sizeof(char);
162         }
163         result.append(sizeof(char), (size & 0xff));
164         result.append(sizeof(char), (size >> 8)); // Move 8 bits to the right
165         result.append(iter);
166         result.append(sizeof(char), '\0');
167         if (result.length() > UINT16_MAX) {
168             return "";
169         }
170     }
171     return result;
172 }
173 
DecomposeStrings(const string & content)174 vector<string> ResourceUtil::DecomposeStrings(const string &content)
175 {
176     vector<string> result;
177     size_t length = content.length();
178     size_t pos = 0;
179     const size_t HEAD_LENGTH = 2;
180     while (pos < length) {
181         if (pos + HEAD_LENGTH >= length) {
182             result.clear();
183             return result;
184         }
185         uint16_t size = (content[pos] & 0xff) | ((content[pos + 1] & 0xff) << 8);
186         pos += HEAD_LENGTH;
187 
188         if (pos + size >= length) {
189             result.clear();
190             return result;
191         }
192         string buffer = content.substr(pos, size);
193         result.push_back(buffer);
194         pos += size + sizeof(char);
195     }
196     return result;
197 }
198 
GetResTypeFromString(const string & type)199 ResType ResourceUtil::GetResTypeFromString(const string &type)
200 {
201     ResType resType = GetResTypeByDir(type);
202     if (resType != ResType::INVALID_RES_TYPE) {
203         return resType;
204     }
205 
206     auto ret = g_contentClusterMap.find(type);
207     if (ret != g_contentClusterMap.end()) {
208         return ret->second;
209     }
210     return ResType::INVALID_RES_TYPE;
211 }
212 
CopyFleInner(const string & src,const string & dst)213 bool ResourceUtil::CopyFleInner(const string &src, const string &dst)
214 {
215     return FileEntry::CopyFileInner(src, dst);
216 }
217 
CreateDirs(const string & filePath)218 bool ResourceUtil::CreateDirs(const string &filePath)
219 {
220     if (FileExist(filePath)) {
221         return true;
222     }
223 
224     if (!FileEntry::CreateDirs(filePath)) {
225         cerr << "Error: create dir '" << filePath << "' failed, reason:" << strerror(errno) << endl;
226         return false;
227     }
228     return true;
229 }
230 
IsIgnoreFile(const string & filename,bool isFile)231 bool ResourceUtil::IsIgnoreFile(const string &filename, bool isFile)
232 {
233     string key = filename;
234     transform(key.begin(), key.end(), key.begin(), ::tolower);
235     for (const auto &iter : IGNORE_FILE_REGEX) {
236         if ((iter.second == IgnoreType::IGNORE_FILE && !isFile) ||
237             (iter.second == IgnoreType::IGNORE_DIR && isFile)) {
238             continue;
239         }
240         if (regex_match(key, regex(iter.first))) {
241             return true;
242         }
243     }
244     return false;
245 }
246 
GenerateHash(const string & key)247 string ResourceUtil::GenerateHash(const string &key)
248 {
249     hash<string> hash_function;
250     return to_string(hash_function(key));
251 }
252 
RealPath(const string & path)253 string ResourceUtil::RealPath(const string &path)
254 {
255     return FileEntry::RealPath(path);
256 }
257 
IslegalPath(const string & path)258 bool ResourceUtil::IslegalPath(const string &path)
259 {
260     return path == "element" || path == "media" || path == "profile";
261 }
262 
StringReplace(string & sourceStr,const string & oldStr,const string & newStr)263 void ResourceUtil::StringReplace(string &sourceStr, const string &oldStr, const string &newStr)
264 {
265     string::size_type pos = 0;
266     string::size_type oldSize = oldStr.size();
267     string::size_type newSize = newStr.size();
268     while ((pos = sourceStr.find(oldStr, pos)) != string::npos) {
269         sourceStr.replace(pos, oldSize, newStr.c_str());
270         pos += newSize;
271     }
272 }
273 
GetLocaleLimitkey(const KeyParam & KeyParam)274 string ResourceUtil::GetLocaleLimitkey(const KeyParam &KeyParam)
275 {
276     string str(reinterpret_cast<const char *>(&KeyParam.value));
277     reverse(str.begin(), str.end());
278     return str;
279 }
280 
GetDeviceTypeLimitkey(const KeyParam & KeyParam)281 string ResourceUtil::GetDeviceTypeLimitkey(const KeyParam &KeyParam)
282 {
283     auto ret = find_if(g_deviceMap.begin(), g_deviceMap.end(), [KeyParam](const auto &iter) {
284         return KeyParam.value == static_cast<const uint32_t>(iter.second);
285     });
286     if (ret == g_deviceMap.end()) {
287         return string();
288     }
289     return ret->first;
290 }
291 
GetResolutionLimitkey(const KeyParam & KeyParam)292 string ResourceUtil::GetResolutionLimitkey(const KeyParam &KeyParam)
293 {
294     auto ret = find_if(g_resolutionMap.begin(), g_resolutionMap.end(), [KeyParam](const auto &iter) {
295         return KeyParam.value == static_cast<const uint32_t>(iter.second);
296     });
297     if (ret == g_resolutionMap.end()) {
298         return string();
299     }
300     return ret->first;
301 }
302 
GetKeyParamValue(const KeyParam & KeyParam)303 string ResourceUtil::GetKeyParamValue(const KeyParam &KeyParam)
304 {
305     string val;
306     switch (KeyParam.keyType) {
307         case KeyType::ORIENTATION:
308             val = KeyParam.value == static_cast<const uint32_t>(OrientationType::VERTICAL) ? "vertical" : "horizontal";
309             break;
310         case KeyType::NIGHTMODE:
311             val = KeyParam.value == static_cast<const uint32_t>(NightMode::DARK) ? "dark" : "light";
312             break;
313         case KeyType::DEVICETYPE:
314             val = GetDeviceTypeLimitkey(KeyParam);
315             break;
316         case KeyType::RESOLUTION:
317             val = GetResolutionLimitkey(KeyParam);
318             break;
319         case KeyType::LANGUAGE:
320         case KeyType::REGION:
321             val = GetLocaleLimitkey(KeyParam);
322             break;
323         default:
324             val = to_string(KeyParam.value);
325             break;
326     }
327     return val;
328 }
329 
PaserKeyParam(const vector<KeyParam> & keyParams)330 string ResourceUtil::PaserKeyParam(const vector<KeyParam> &keyParams)
331 {
332     if (keyParams.size() == 0) {
333         return "base";
334     }
335     string result;
336     for (const auto &keyparam : keyParams) {
337         string limitKey = GetKeyParamValue(keyparam);
338         if (limitKey.empty()) {
339             continue;
340         }
341         if (keyparam.keyType == KeyType::MCC) {
342             limitKey = "mcc" + limitKey;
343         }
344         if (keyparam.keyType == KeyType::MNC) {
345             limitKey = "mnc" + limitKey;
346         }
347         if (keyparam.keyType == KeyType::REGION || keyparam.keyType == KeyType::MNC) {
348             result = result + "_" + limitKey;
349         } else {
350             result = result + "-" + limitKey;
351         }
352     }
353     if (!result.empty()) {
354         result = result.substr(1);
355     }
356     return result;
357 }
358 
DecToHexStr(const int32_t i)359 string ResourceUtil::DecToHexStr(const int32_t i)
360 {
361     stringstream ot;
362     string result;
363     ot << setiosflags(ios::uppercase) << "0x" << hex << setw(8) << setfill('0') << i; // 0x expadding 8 bit
364     ot >> result;
365     return result;
366 }
367 
CheckHexStr(const string & hex)368 bool ResourceUtil::CheckHexStr(const string &hex)
369 {
370     if (regex_match(hex, regex("^0[xX][0-9a-fA-F]{8}"))) {
371         return true;
372     }
373     return false;
374 }
375 
GetAllRestypeString()376 string ResourceUtil::GetAllRestypeString()
377 {
378     string result;
379     for (auto iter = g_contentClusterMap.begin(); iter != g_contentClusterMap.end(); ++iter) {
380         result = result + "," + iter->first;
381     }
382     return result;
383 }
384 
GetBaseElementPath(const string input)385 FileEntry::FilePath ResourceUtil::GetBaseElementPath(const string input)
386 {
387     return FileEntry::FilePath(input).Append("base").Append("element");
388 }
389 
GetMainPath(const string input)390 FileEntry::FilePath ResourceUtil::GetMainPath(const string input)
391 {
392     return FileEntry::FilePath(input).GetParent();
393 }
394 
GetNormalSize(const vector<KeyParam> & keyParams,uint32_t index)395 uint32_t ResourceUtil::GetNormalSize(const vector<KeyParam> &keyParams, uint32_t index)
396 {
397     string device;
398     string dpi;
399     if (keyParams.size() == 0) {
400         device = "phone";
401         dpi = "sdpi";
402     }
403     for (const auto &keyparam : keyParams) {
404         string limitKey = GetKeyParamValue(keyparam);
405         if (limitKey.empty()) {
406             continue;
407         }
408         if (keyparam.keyType == KeyType::DEVICETYPE) {
409             device = limitKey;
410         } else if (keyparam.keyType == KeyType::RESOLUTION) {
411             dpi = limitKey;
412         }
413     }
414     if (device.empty()) {
415         device = "phone";
416     }
417     if (dpi.empty()) {
418         dpi = "sdpi";
419     }
420     if (device != "phone" && device != "tablet") {
421         return 0;
422     }
423     return g_normalIconMap.find(dpi + "-" + device)->second[index];
424 }
425 
426 }
427 }
428 }
429