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