• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "router_map_helper.h"
16 #include "regex.h"
17 #include "app_log_wrapper.h"
18 #include "router_item_compare.h"
19 
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 const char* ALNUM_PATTERN = "^[a-zA-Z0-9]*$";
24 const char* NUM_PATTERN = "^[0-9]+$";
25 }
26 
MergeRouter(BundleInfo & info)27 void RouterMapHelper::MergeRouter(BundleInfo &info)
28 {
29     if (info.hapModuleInfos.empty()) {
30         APP_LOGW("hapModuleInfos in bundleInfo is empty");
31         return;
32     }
33     std::vector<RouterItem> routerArrayList;
34     std::set<std::string> moduleNameSet;
35     for (const auto &hapModuleInfo : info.hapModuleInfos) {
36         if (hapModuleInfo.moduleType == ModuleType::ENTRY || hapModuleInfo.moduleType == ModuleType::FEATURE) {
37             moduleNameSet.insert(hapModuleInfo.name);
38         }
39         for (const auto &routerItem : hapModuleInfo.routerArray) {
40             routerArrayList.emplace_back(routerItem);
41         }
42     }
43     if (routerArrayList.empty()) {
44         return;
45     }
46     MergeRouter(routerArrayList, info.routerArray, moduleNameSet);
47 }
48 
ExtractVersionFromOhmurl(const std::string & ohmurl)49 std::string RouterMapHelper::ExtractVersionFromOhmurl(const std::string &ohmurl)
50 {
51     size_t lastAmpersandPos = ohmurl.rfind('&');
52     std::string versionString;
53     if (lastAmpersandPos == std::string::npos) {
54         APP_LOGI_NOFUNC("No ampersand found in the input ohmurl");
55         return versionString;
56     }
57     // "+1" for start intercepting after the "&" character
58     versionString =  ohmurl.substr(lastAmpersandPos + 1);
59     return versionString;
60 }
61 
MergeRouter(const std::vector<RouterItem> & routerArrayList,std::vector<RouterItem> & routerArray,const std::set<std::string> & moduleNameSet)62 void RouterMapHelper::MergeRouter(const std::vector<RouterItem>& routerArrayList,
63     std::vector<RouterItem>& routerArray, const std::set<std::string>& moduleNameSet)
64 {
65     std::map<RouterItem, std::string, RouterItemCompare> routerMap((RouterItemCompare(moduleNameSet)));
66 
67     for (const auto& item : routerArrayList) {
68         routerMap.emplace(item, item.name);
69     }
70 
71     std::vector<RouterItem> routerArraySorted;
72 
73     routerArraySorted.reserve(routerMap.size());
74     for (const auto& pair : routerMap) {
75         routerArraySorted.push_back(pair.first);
76     }
77     routerArray.clear();
78     for (size_t i = 0; i < routerArraySorted.size(); i++) {
79         if ((i == 0) || (routerArraySorted[i].name != routerArray[routerArray.size() - 1].name)) {
80             routerArray.emplace_back(routerArraySorted[i]);
81         }
82     }
83 }
84 
IsRegexMatch(const std::string & str,const char * pattern)85 bool RouterMapHelper::IsRegexMatch(const std::string& str, const char* pattern)
86 {
87     regex_t regex;
88     if (regcomp(&regex, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
89         APP_LOGE("regex compilation failed");
90         return false;
91     }
92     int32_t ret = regexec(&regex, str.c_str(), 0, NULL, 0);
93     if (ret == 0) {
94         regfree(&regex);
95         return true;
96     }
97     APP_LOGE("failed to perform a match");
98     regfree(&regex);
99     return false;
100 }
101 
CompareIdentifiers(const std::string & a,const std::string & b)102 int32_t RouterMapHelper::CompareIdentifiers(const std::string& a, const std::string& b)
103 {
104     bool aAlnum = IsRegexMatch(a, ALNUM_PATTERN);
105     bool bAlnum = IsRegexMatch(b, ALNUM_PATTERN);
106     if (!aAlnum || !bAlnum) {
107         return 1;
108     }
109 
110     bool anum = IsRegexMatch(a, NUM_PATTERN);
111     bool bnum = IsRegexMatch(b, NUM_PATTERN);
112     if (anum && bnum) {
113         auto diff = atoi(a.c_str()) - atoi(b.c_str());
114         if (diff) {
115             return diff > 0 ? 1 : -1;
116         }
117         return 0;
118     }
119 
120     if (anum && !bnum) {
121         return -1;
122     }
123     if (bnum && !anum) {
124         return 1;
125     }
126     if (a < b) {
127         return -1;
128     }
129     if (a > b) {
130         return 1;
131     }
132     return 0;
133 }
134 
CompareMain(const SemVer & semVer1,const SemVer & semVer2)135 int32_t RouterMapHelper::CompareMain(const SemVer &semVer1, const SemVer &semVer2)
136 {
137     auto res = CompareIdentifiers(semVer1.major, semVer2.major);
138     if (res) {
139         return res;
140     }
141     res = CompareIdentifiers(semVer1.minor, semVer2.minor);
142     if (res) {
143         return res;
144     }
145     return CompareIdentifiers(semVer1.patch, semVer2.patch);
146 }
147 
ComparePre(const SemVer & semVer1,const SemVer & semVer2)148 int32_t RouterMapHelper::ComparePre(const SemVer &semVer1, const SemVer &semVer2)
149 {
150     // NOT having a prerelease is > having one
151     if (!semVer1.prerelease.empty() && semVer2.prerelease.empty()) {
152         return -1;
153     } else if (semVer1.prerelease.empty() && !semVer2.prerelease.empty()) {
154         return 1;
155     } else if (semVer1.prerelease.empty() && semVer2.prerelease.empty()) {
156         return 0;
157     }
158     size_t i = 0;
159     do {
160         if ((i >= semVer1.prerelease.size()) && (i >= semVer2.prerelease.size())) {
161             return 0;
162         } else if (i >= semVer2.prerelease.size()) {
163             return 1;
164         } else if (i >= semVer1.prerelease.size()) {
165             return -1;
166         }
167         std::string a = semVer1.prerelease[i];
168         std::string b = semVer2.prerelease[i];
169         if (a == b || !CompareIdentifiers(a, b)) {
170             continue;
171         }
172         return CompareIdentifiers(a, b);
173     } while (++i);
174     return 0;
175 }
176 
Compare(const std::string & version1,const std::string & version2)177 int32_t RouterMapHelper::Compare(const std::string &version1, const std::string &version2)
178 {
179     SemVer semver1(version1);
180     SemVer semver2(version2);
181     return Compare(semver1, semver2);
182 }
183 
Compare(const SemVer & semVer1,const SemVer & semVer2)184 int32_t RouterMapHelper::Compare(const SemVer &semVer1, const SemVer &semVer2)
185 {
186     if (semVer1.raw == semVer2.raw) {
187         return 0;
188     }
189     auto res = CompareMain(semVer1, semVer2);
190     return res ? res : ComparePre(semVer1, semVer2);
191 }
192 } // namespace AppExecFwk
193 } // namespace OHOS