• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 <sstream>
24 #include "file_entry.h"
25 
26 namespace OHOS {
27 namespace Global {
28 namespace Restool {
29 using namespace std;
30 const map<string, ResourceUtil::IgnoreType> ResourceUtil::IGNORE_FILE_REGEX = {
31     { "\\.git", IgnoreType::IGNORE_ALL },
32     { "\\.svn", IgnoreType::IGNORE_ALL },
33     { ".+\\.scc", IgnoreType::IGNORE_ALL },
34     { "\\.ds_store", IgnoreType::IGNORE_ALL },
35     { "desktop\\.ini", IgnoreType::IGNORE_ALL },
36     { "picasa\\.ini", IgnoreType::IGNORE_ALL },
37     { "\\..+", IgnoreType::IGNORE_ALL },
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 
RmoveFile(const string & path)73 bool ResourceUtil::RmoveFile(const string &path)
74 {
75     return FileEntry::RemoveFile(path);
76 }
77 
OpenJsonFile(const string & path,cJSON ** root)78 bool ResourceUtil::OpenJsonFile(const string &path, cJSON **root)
79 {
80     ifstream ifs(FileEntry::AdaptLongPath(path), ios::binary);
81     if (!ifs.is_open()) {
82         cerr << "Error: open json failed '" << path << "', reason: " << strerror(errno) << endl;
83         return false;
84     }
85 
86     string jsonString((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
87     *root = cJSON_Parse(jsonString.c_str());
88     if (!*root) {
89         cerr << "Error: cJSON_Parse failed, please check the JSON file." << NEW_LINE_PATH << path << endl;
90         cerr << SOLUTIONS << endl;
91         cerr << SOLUTIONS_ARROW << "Check the JSON file and delete unnecessary commas (,)." << endl;
92         cerr << SOLUTIONS_ARROW << "Check the JSON file to make sure the root bracket is {}" << endl;
93         ifs.close();
94         return false;
95     }
96     ifs.close();
97     return true;
98 }
99 
SaveToJsonFile(const string & path,const cJSON * root)100 bool ResourceUtil::SaveToJsonFile(const string &path, const cJSON *root)
101 {
102     ofstream out(FileEntry::AdaptLongPath(path), ofstream::out | ofstream::binary);
103     if (!out.is_open()) {
104         cerr << "Error: SaveToJsonFile open failed '" << path <<"', reason: " << strerror(errno) << endl;
105         return false;
106     }
107     char *jsonString = cJSON_Print(root);
108     out << jsonString;
109     free(jsonString);
110 
111     out.close();
112     return true;
113 }
114 
GetResTypeByDir(const string & name)115 ResType ResourceUtil::GetResTypeByDir(const string &name)
116 {
117     auto ret = g_fileClusterMap.find(name);
118     if (ret == g_fileClusterMap.end()) {
119         return ResType::INVALID_RES_TYPE;
120     }
121     return ret->second;
122 }
123 
ResTypeToString(ResType type)124 string ResourceUtil::ResTypeToString(ResType type)
125 {
126     auto ret = find_if(g_fileClusterMap.begin(), g_fileClusterMap.end(), [type](auto iter) {
127         return iter.second == type;
128     });
129     if (ret != g_fileClusterMap.end()) {
130         return ret->first;
131     }
132 
133     ret = find_if(g_contentClusterMap.begin(), g_contentClusterMap.end(), [type](auto iter) {
134         return iter.second == type;
135     });
136     if (ret != g_contentClusterMap.end()) {
137         return ret->first;
138     }
139     return "";
140 }
141 
GetIdName(const string & name,ResType type)142 string ResourceUtil::GetIdName(const string &name, ResType type)
143 {
144     if (type != ResType::MEDIA && type != ResType::PROF) {
145         return name;
146     }
147 
148     string::size_type pos = name.find_last_of(".");
149     if (pos != string::npos) {
150         return name.substr(0, pos);
151     }
152     return name;
153 }
154 
ComposeStrings(const vector<string> & contents,bool addNull)155 string ResourceUtil::ComposeStrings(const vector<string> &contents, bool addNull)
156 {
157     string result;
158     for (const auto &iter : contents) {
159         if (iter.length() > UINT16_MAX) {
160             return "";
161         }
162 
163         uint16_t size = iter.length();
164         if (addNull) {
165             size += sizeof(char);
166         }
167         result.append(sizeof(char), (size & 0xff));
168         result.append(sizeof(char), (size >> 8)); // Move 8 bits to the right
169         result.append(iter);
170         result.append(sizeof(char), '\0');
171         if (result.length() > UINT16_MAX) {
172             return "";
173         }
174     }
175     return result;
176 }
177 
DecomposeStrings(const string & content)178 vector<string> ResourceUtil::DecomposeStrings(const string &content)
179 {
180     vector<string> result;
181     size_t length = content.length();
182     size_t pos = 0;
183     const size_t HEAD_LENGTH = 2;
184     while (pos < length) {
185         if (pos + HEAD_LENGTH >= length) {
186             result.clear();
187             return result;
188         }
189         uint16_t size = (content[pos] & 0xff) | ((content[pos + 1] & 0xff) << 8); // Move 8 bits to the left
190         pos += HEAD_LENGTH;
191 
192         if (pos + size >= length) {
193             result.clear();
194             return result;
195         }
196         string buffer = content.substr(pos, size);
197         result.push_back(buffer);
198         pos += size + sizeof(char);
199     }
200     return result;
201 }
202 
GetResTypeFromString(const string & type)203 ResType ResourceUtil::GetResTypeFromString(const string &type)
204 {
205     ResType resType = GetResTypeByDir(type);
206     if (resType != ResType::INVALID_RES_TYPE) {
207         return resType;
208     }
209 
210     auto ret = g_contentClusterMap.find(type);
211     if (ret != g_contentClusterMap.end()) {
212         return ret->second;
213     }
214     return ResType::INVALID_RES_TYPE;
215 }
216 
CopyFileInner(const string & src,const string & dst)217 bool ResourceUtil::CopyFileInner(const string &src, const string &dst)
218 {
219     return FileEntry::CopyFileInner(src, dst);
220 }
221 
CreateDirs(const string & filePath)222 bool ResourceUtil::CreateDirs(const string &filePath)
223 {
224     if (FileExist(filePath)) {
225         return true;
226     }
227 
228     if (!FileEntry::CreateDirs(filePath)) {
229         cerr << "Error: create dir '" << filePath << "' failed, reason:" << strerror(errno) << endl;
230         return false;
231     }
232     return true;
233 }
234 
IsIgnoreFile(const string & filename,bool isFile)235 bool ResourceUtil::IsIgnoreFile(const string &filename, bool isFile)
236 {
237     string key = filename;
238     transform(key.begin(), key.end(), key.begin(), ::tolower);
239     for (const auto &iter : IGNORE_FILE_REGEX) {
240         if ((iter.second == IgnoreType::IGNORE_FILE && !isFile) ||
241             (iter.second == IgnoreType::IGNORE_DIR && isFile)) {
242             continue;
243         }
244         if (regex_match(key, regex(iter.first))) {
245             return true;
246         }
247     }
248     return false;
249 }
250 
GenerateHash(const string & key)251 string ResourceUtil::GenerateHash(const string &key)
252 {
253     hash<string> hash_function;
254     return to_string(hash_function(key));
255 }
256 
RealPath(const string & path)257 string ResourceUtil::RealPath(const string &path)
258 {
259     return FileEntry::RealPath(path);
260 }
261 
IslegalPath(const string & path)262 bool ResourceUtil::IslegalPath(const string &path)
263 {
264     return path == "element" || path == "media" || path == "profile";
265 }
266 
StringReplace(string & sourceStr,const string & oldStr,const string & newStr)267 void ResourceUtil::StringReplace(string &sourceStr, const string &oldStr, const string &newStr)
268 {
269     string::size_type pos = 0;
270     string::size_type oldSize = oldStr.size();
271     string::size_type newSize = newStr.size();
272     while ((pos = sourceStr.find(oldStr, pos)) != string::npos) {
273         sourceStr.replace(pos, oldSize, newStr.c_str());
274         pos += newSize;
275     }
276 }
277 
GetLocaleLimitkey(const KeyParam & KeyParam)278 string ResourceUtil::GetLocaleLimitkey(const KeyParam &KeyParam)
279 {
280     string str(reinterpret_cast<const char *>(&KeyParam.value));
281     reverse(str.begin(), str.end());
282     return str;
283 }
284 
GetDeviceTypeLimitkey(const KeyParam & KeyParam)285 string ResourceUtil::GetDeviceTypeLimitkey(const KeyParam &KeyParam)
286 {
287     auto ret = find_if(g_deviceMap.begin(), g_deviceMap.end(), [KeyParam](const auto &iter) {
288         return KeyParam.value == static_cast<const uint32_t>(iter.second);
289     });
290     if (ret == g_deviceMap.end()) {
291         return string();
292     }
293     return ret->first;
294 }
295 
GetResolutionLimitkey(const KeyParam & KeyParam)296 string ResourceUtil::GetResolutionLimitkey(const KeyParam &KeyParam)
297 {
298     auto ret = find_if(g_resolutionMap.begin(), g_resolutionMap.end(), [KeyParam](const auto &iter) {
299         return KeyParam.value == static_cast<const uint32_t>(iter.second);
300     });
301     if (ret == g_resolutionMap.end()) {
302         return string();
303     }
304     return ret->first;
305 }
306 
GetKeyParamValue(const KeyParam & KeyParam)307 string ResourceUtil::GetKeyParamValue(const KeyParam &KeyParam)
308 {
309     string val;
310     switch (KeyParam.keyType) {
311         case KeyType::ORIENTATION:
312             val = KeyParam.value == static_cast<const uint32_t>(OrientationType::VERTICAL) ? "vertical" : "horizontal";
313             break;
314         case KeyType::NIGHTMODE:
315             val = KeyParam.value == static_cast<const uint32_t>(NightMode::DARK) ? "dark" : "light";
316             break;
317         case KeyType::DEVICETYPE:
318             val = GetDeviceTypeLimitkey(KeyParam);
319             break;
320         case KeyType::RESOLUTION:
321             val = GetResolutionLimitkey(KeyParam);
322             break;
323         case KeyType::LANGUAGE:
324         case KeyType::REGION:
325             val = GetLocaleLimitkey(KeyParam);
326             break;
327         default:
328             val = to_string(KeyParam.value);
329             break;
330     }
331     return val;
332 }
333 
PaserKeyParam(const vector<KeyParam> & keyParams)334 string ResourceUtil::PaserKeyParam(const vector<KeyParam> &keyParams)
335 {
336     if (keyParams.size() == 0) {
337         return "base";
338     }
339     string result;
340     for (const auto &keyparam : keyParams) {
341         string limitKey = GetKeyParamValue(keyparam);
342         if (limitKey.empty()) {
343             continue;
344         }
345         if (keyparam.keyType == KeyType::MCC) {
346             limitKey = "mcc" + limitKey;
347         }
348         if (keyparam.keyType == KeyType::MNC) {
349             limitKey = "mnc" + limitKey;
350         }
351         if (keyparam.keyType == KeyType::REGION || keyparam.keyType == KeyType::MNC) {
352             result = result + "_" + limitKey;
353         } else {
354             result = result + "-" + limitKey;
355         }
356     }
357     if (!result.empty()) {
358         result = result.substr(1);
359     }
360     return result;
361 }
362 
DecToHexStr(const uint32_t i)363 string ResourceUtil::DecToHexStr(const uint32_t i)
364 {
365     stringstream ot;
366     string result;
367     ot << setiosflags(ios::uppercase) << "0x" << hex << setw(8) << setfill('0') << i; // 0x expadding 8 bit
368     ot >> result;
369     return result;
370 }
371 
CheckHexStr(const string & hex)372 bool ResourceUtil::CheckHexStr(const string &hex)
373 {
374     if (regex_match(hex, regex("^0[xX][0-9a-fA-F]{8}"))) {
375         return true;
376     }
377     return false;
378 }
379 
GetAllRestypeString()380 string ResourceUtil::GetAllRestypeString()
381 {
382     string result;
383     for (auto iter = g_contentClusterMap.begin(); iter != g_contentClusterMap.end(); ++iter) {
384         result = result + "," + iter->first;
385     }
386     return result;
387 }
388 
GetBaseElementPath(const string input)389 FileEntry::FilePath ResourceUtil::GetBaseElementPath(const string input)
390 {
391     return FileEntry::FilePath(input).Append("base").Append("element");
392 }
393 
GetMainPath(const string input)394 FileEntry::FilePath ResourceUtil::GetMainPath(const string input)
395 {
396     return FileEntry::FilePath(input).GetParent();
397 }
398 
GetNormalSize(const vector<KeyParam> & keyParams,uint32_t index)399 uint32_t ResourceUtil::GetNormalSize(const vector<KeyParam> &keyParams, uint32_t index)
400 {
401     string device;
402     string dpi;
403     if (keyParams.size() == 0) {
404         device = "phone";
405         dpi = "sdpi";
406     }
407     for (const auto &keyparam : keyParams) {
408         string limitKey = GetKeyParamValue(keyparam);
409         if (limitKey.empty()) {
410             continue;
411         }
412         if (keyparam.keyType == KeyType::DEVICETYPE) {
413             device = limitKey;
414         } else if (keyparam.keyType == KeyType::RESOLUTION) {
415             dpi = limitKey;
416         }
417     }
418     if (device.empty()) {
419         device = "phone";
420     }
421     if (dpi.empty()) {
422         dpi = "sdpi";
423     }
424     if (device != "phone" && device != "tablet") {
425         return 0;
426     }
427     return g_normalIconMap.find(dpi + "-" + device)->second[index];
428 }
429 
isUnicodeInPlane15or16(int unicode)430 bool ResourceUtil::isUnicodeInPlane15or16(int unicode)
431 {
432     return (unicode >= 0xF0000 && unicode <= 0xFFFFF) || (unicode >= 0x100000 && unicode <= 0x10FFFF);
433 }
434 
RemoveSpaces(string & str)435 void ResourceUtil::RemoveSpaces(string &str)
436 {
437     str.erase(0, str.find_first_not_of(" "));
438     str.erase(str.find_last_not_of(" ") + 1); // move back one place
439 }
440 
IsIntValue(const cJSON * node)441 bool ResourceUtil::IsIntValue(const cJSON *node)
442 {
443     if (node && cJSON_IsNumber(node)) {
444         double num = node->valuedouble;
445         if (num == static_cast<int>(num)) {
446             return true;
447         } else {
448             return false;
449         }
450     }
451     return false;
452 }
453 
IsValidName(const string & name)454 bool ResourceUtil::IsValidName(const string &name)
455 {
456     if (!regex_match(name, regex("[a-zA-Z0-9_]+"))) {
457         cerr << "Error: the name '" << name << "' can only contain [a-zA-Z0-9_]." << endl;
458         return false;
459     }
460     return true;
461 }
462 
PrintWarningMsg(vector<pair<ResType,string>> & noBaseResource)463 void ResourceUtil::PrintWarningMsg(vector<pair<ResType, string>> &noBaseResource)
464 {
465     for (const auto &item : noBaseResource) {
466         cerr << "Warning: the " << ResourceUtil::ResTypeToString(item.first);
467         cerr << " of '" << item.second << "' does not have a base resource." << endl;
468     }
469 }
470 }
471 }
472 }
473