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
17 #include "app_log_wrapper.h"
18 #include "router_item_compare.h"
19
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 const std::regex ALNUM_REGEX("^[a-zA-Z0-9]*$");
24 const std::regex NUM_REGEX("^[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
CompareIdentifiers(const std::string & a,const std::string & b)85 int32_t RouterMapHelper::CompareIdentifiers(const std::string& a, const std::string& b)
86 {
87 if (!std::regex_match(a, ALNUM_REGEX) || !std::regex_match(b, ALNUM_REGEX)) {
88 return 1;
89 }
90 bool anum = std::regex_match(a, NUM_REGEX);
91 bool bnum = std::regex_match(b, NUM_REGEX);
92 if (anum && bnum) {
93 auto diff = std::stoi(a) - std::stoi(b);
94 if (diff) {
95 return diff > 0 ? 1 : -1;
96 }
97 return 0;
98 }
99
100 if (anum && !bnum) {
101 return -1;
102 }
103 if (bnum && !anum) {
104 return 1;
105 }
106 if (a < b) {
107 return -1;
108 }
109 if (a > b) {
110 return 1;
111 }
112 return 0;
113 }
114
CompareMain(const SemVer & semVer1,const SemVer & semVer2)115 int32_t RouterMapHelper::CompareMain(const SemVer &semVer1, const SemVer &semVer2)
116 {
117 auto res = CompareIdentifiers(semVer1.major, semVer2.major);
118 if (res) {
119 return res;
120 }
121 res = CompareIdentifiers(semVer1.minor, semVer2.minor);
122 if (res) {
123 return res;
124 }
125 return CompareIdentifiers(semVer1.patch, semVer2.patch);
126 }
127
ComparePre(const SemVer & semVer1,const SemVer & semVer2)128 int32_t RouterMapHelper::ComparePre(const SemVer &semVer1, const SemVer &semVer2)
129 {
130 // NOT having a prerelease is > having one
131 if (!semVer1.prerelease.empty() && semVer2.prerelease.empty()) {
132 return -1;
133 } else if (semVer1.prerelease.empty() && !semVer2.prerelease.empty()) {
134 return 1;
135 } else if (semVer1.prerelease.empty() && semVer2.prerelease.empty()) {
136 return 0;
137 }
138 size_t i = 0;
139 do {
140 if ((i >= semVer1.prerelease.size()) && (i >= semVer2.prerelease.size())) {
141 return 0;
142 } else if (i >= semVer2.prerelease.size()) {
143 return 1;
144 } else if (i >= semVer1.prerelease.size()) {
145 return -1;
146 }
147 std::string a = semVer1.prerelease[i];
148 std::string b = semVer2.prerelease[i];
149 if (a == b || !CompareIdentifiers(a, b)) {
150 continue;
151 }
152 return CompareIdentifiers(a, b);
153 } while (++i);
154 return 0;
155 }
156
Compare(const std::string & version1,const std::string & version2)157 int32_t RouterMapHelper::Compare(const std::string &version1, const std::string &version2)
158 {
159 SemVer semver1(version1);
160 SemVer semver2(version2);
161 return Compare(semver1, semver2);
162 }
163
Compare(const SemVer & semVer1,const SemVer & semVer2)164 int32_t RouterMapHelper::Compare(const SemVer &semVer1, const SemVer &semVer2)
165 {
166 if (semVer1.raw == semVer2.raw) {
167 return 0;
168 }
169 auto res = CompareMain(semVer1, semVer2);
170 return res ? res : ComparePre(semVer1, semVer2);
171 }
172 } // namespace AppExecFwk
173 } // namespace OHOS