• 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 
16 #include "commonUtil.h"
17 
18 #include <algorithm>
19 #include <sstream>
20 
21 #include "util/helpers.h"
22 
23 namespace panda::es2panda::util {
24 
Split(const std::string & str,const char delimiter)25 std::vector<std::string> Split(const std::string &str, const char delimiter)
26 {
27     std::string normalizedImport {};
28     std::string pkgName {};
29     std::vector<std::string> items;
30 
31     size_t start = 0;
32     size_t pos = str.find(delimiter);
33     while (pos != std::string::npos) {
34         std::string item = str.substr(start, pos - start);
35         items.emplace_back(item);
36         start = pos + 1;
37         pos = str.find(delimiter, start);
38     }
39     std::string tail = str.substr(start);
40     items.emplace_back(tail);
41 
42     return items;
43 }
44 
GetStringByVectorElementsWithDelimiter(const std::vector<std::string> & vec,const char delimiter)45 std::string GetStringByVectorElementsWithDelimiter(const std::vector<std::string> &vec, const char delimiter)
46 {
47     std::ostringstream oss;
48     auto it = vec.begin();
49     if (it != vec.end()) {
50         oss << *it;
51         ++it;
52     }
53     for (; it != vec.end(); ++it) {
54         oss << delimiter << *it;
55     }
56     return oss.str();
57 }
58 
GetPkgNameFromNormalizedImport(const std::string & normalizedImport)59 std::string GetPkgNameFromNormalizedImport(const std::string &normalizedImport)
60 {
61     std::string pkgName {};
62     size_t pos = normalizedImport.find(SLASH_TAG);
63     if (pos != std::string::npos) {
64         pkgName = normalizedImport.substr(0, pos);
65     }
66     if (normalizedImport[0] == NORMALIZED_OHMURL_PREFIX) {
67         pos = normalizedImport.find(SLASH_TAG, pos + 1);
68         if (pos != std::string::npos) {
69             pkgName = normalizedImport.substr(0, pos);
70         }
71     }
72     return pkgName;
73 }
74 
GetPkgNameFromNormalizedOhmurl(const std::string & ohmurl)75 std::string GetPkgNameFromNormalizedOhmurl(const std::string &ohmurl)
76 {
77     std::string normalizedImport {};
78     std::string pkgName {};
79     auto items = Split(ohmurl, NORMALIZED_OHMURL_SEPARATOR);
80     if (items.size() <= NORMALIZED_IMPORT_POS) {
81         return pkgName;
82     }
83     normalizedImport = items[NORMALIZED_IMPORT_POS];
84     return GetPkgNameFromNormalizedImport(normalizedImport);
85 }
86 
GetRecordNameFromNormalizedOhmurl(const std::string & ohmurl)87 std::string GetRecordNameFromNormalizedOhmurl(const std::string &ohmurl)
88 {
89     // format of recordName: "<bundleName>&normalizedImport&<version>"
90     std::string recordName {};
91     auto items = Split(ohmurl, NORMALIZED_OHMURL_SEPARATOR);
92 
93     recordName += items[BUNDLE_NAME_POS] + NORMALIZED_OHMURL_SEPARATOR + items[NORMALIZED_IMPORT_POS] +
94         NORMALIZED_OHMURL_SEPARATOR + items[VERSION_POS];
95     return recordName;
96 }
97 
IsExternalPkgNames(const std::string & ohmurl,const std::set<std::string> & externalPkgNames)98 bool IsExternalPkgNames(const std::string &ohmurl, const std::set<std::string> &externalPkgNames)
99 {
100     auto pkgName = GetPkgNameFromNormalizedOhmurl(ohmurl);
101     if (std::find(externalPkgNames.begin(), externalPkgNames.end(), pkgName) != externalPkgNames.end()) {
102         return true;
103     }
104     return false;
105 }
106 
UpdatePackageVersionIfNeeded(const std::string & ohmurl,const std::unordered_map<std::string,PkgInfo> & pkgContextInfo)107 std::string UpdatePackageVersionIfNeeded(const std::string &ohmurl,
108                                          const std::unordered_map<std::string, PkgInfo> &pkgContextInfo)
109 {
110     // Input ohmurl format:
111     // @normalized:{N|Y}&[module name]&[bundle name]&{<package name>|<@package/name>}/{import_path}&[version]
112     // Update the version for ohmurls and return the updated ohmurl when:
113     // 1. The package name and version are specified in the CompileContextInfo file.
114     // 2. The ohmurl is an imported non-native ohmurl (starts with @normalized:N).
115     // 3. The version in the ohmurl differs from the version in the CompileContextInfo file.
116     // Return the original ohmurl otherwise.
117     if (ohmurl.find(util::NORMALIZED_OHMURL_NOT_SO) != 0) {
118         return ohmurl;
119     }
120     std::string packageName = util::GetPkgNameFromNormalizedOhmurl(ohmurl);
121     // Incorrect ohmurl format: no package name, skip version update
122     if (packageName.empty()) {
123         return ohmurl;
124     }
125     auto iter = pkgContextInfo.find(packageName);
126     if (iter == pkgContextInfo.end()) {
127         return ohmurl;
128     }
129     auto versionStart = ohmurl.rfind(util::NORMALIZED_OHMURL_SEPARATOR);
130     // Incorrect ohmurl format: no version, skip version update
131     if (versionStart == std::string::npos) {
132         return ohmurl;
133     }
134     return ohmurl.substr(0, versionStart + 1) + iter->second.version;
135 }
136 
137 /**
138  * If a Har package is dependent of a cross-app Hsp, its ohmurl need to contain the bundleName of this cross-app Hsp.
139  * Since Har's ohmurl doesn't contain bundleName during its own compilation, the bundleName need to be added during
140  * the compilation of cross-app Hsp.
141  */
UpdateBundleNameIfNeeded(std::string & ohmurl,const std::string & bundleName,const std::set<std::string> & externalPkgNames)142 std::string UpdateBundleNameIfNeeded(std::string &ohmurl, const std::string &bundleName,
143                                      const std::set<std::string> &externalPkgNames)
144 {
145     // Input ohmurl format:
146     // @normalized:{N|Y}&[module name]&[bundle name]&{<package name>|<@package/name>}/{import_path}&[version]
147     if (ohmurl.find(util::NORMALIZED) != 0) {
148         return ohmurl;
149     }
150 
151     std::vector<std::string> items = Split(ohmurl, NORMALIZED_OHMURL_SEPARATOR);
152     // Incorrect ohmurl format: The quantity of '&' is incorrect
153     if (items.size() <= VERSION_POS) {
154         return ohmurl;
155     }
156     /**
157      * If an ohmurl already contains [bundle name], it means its not from a Har, so there's no need to updated its
158      * [bundle name].
159      */
160     if (!items[BUNDLE_NAME_POS].empty()) {
161         return ohmurl;
162     }
163     /**
164      * The hsp package don't compile into the current abc file.
165      * Ohmurl of both Har and in-app Hsp don't contain [bundle name], need to further screen out Hsp.
166      */
167     if (IsExternalPkgNames(ohmurl, externalPkgNames)) {
168         return ohmurl;
169     }
170 
171     items[BUNDLE_NAME_POS] = bundleName;
172     return GetStringByVectorElementsWithDelimiter(items, NORMALIZED_OHMURL_SEPARATOR);
173 }
174 
RecordNotGeneratedFromBytecode(std::string recordName)175 bool RecordNotGeneratedFromBytecode(std::string recordName)
176 {
177     return recordName.find(util::CHAR_VERTICAL_LINE) == std::string::npos;
178 }
179 
180 } // namespace panda::es2panda::util