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 
20 #include "util/helpers.h"
21 
22 namespace panda::es2panda::util {
23 
Split(const std::string &str, const char delimiter)24 std::vector<std::string> Split(const std::string &str, const char delimiter)
25 {
26     std::string normalizedImport {};
27     std::string pkgName {};
28     std::vector<std::string> items;
29 
30     size_t start = 0;
31     size_t pos = str.find(delimiter);
32     while (pos != std::string::npos) {
33         std::string item = str.substr(start, pos - start);
34         items.emplace_back(item);
35         start = pos + 1;
36         pos = str.find(delimiter, start);
37     }
38     std::string tail = str.substr(start);
39     items.emplace_back(tail);
40 
41     return items;
42 }
43 
GetPkgNameFromNormalizedImport(const std::string &normalizedImport)44 std::string GetPkgNameFromNormalizedImport(const std::string &normalizedImport)
45 {
46     std::string pkgName {};
47     size_t pos = normalizedImport.find(SLASH_TAG);
48     if (pos != std::string::npos) {
49         pkgName = normalizedImport.substr(0, pos);
50     }
51     if (normalizedImport[0] == NORMALIZED_OHMURL_PREFIX) {
52         pos = normalizedImport.find(SLASH_TAG, pos + 1);
53         if (pos != std::string::npos) {
54             pkgName = normalizedImport.substr(0, pos);
55         }
56     }
57     return pkgName;
58 }
59 
GetPkgNameFromNormalizedOhmurl(const std::string &ohmurl)60 std::string GetPkgNameFromNormalizedOhmurl(const std::string &ohmurl)
61 {
62     std::string normalizedImport {};
63     std::string pkgName {};
64     auto items = Split(ohmurl, NORMALIZED_OHMURL_SEPARATOR);
65     if (items.size() <= NORMALIZED_IMPORT_POS) {
66         return pkgName;
67     }
68     normalizedImport = items[NORMALIZED_IMPORT_POS];
69     return GetPkgNameFromNormalizedImport(normalizedImport);
70 }
71 
GetRecordNameFromNormalizedOhmurl(const std::string &ohmurl)72 std::string GetRecordNameFromNormalizedOhmurl(const std::string &ohmurl)
73 {
74     // format of recordName: "<bundleName>&normalizedImport&<version>"
75     std::string recordName {};
76     auto items = Split(ohmurl, NORMALIZED_OHMURL_SEPARATOR);
77 
78     recordName += items[BUNDLE_NAME_POS] + NORMALIZED_OHMURL_SEPARATOR + items[NORMALIZED_IMPORT_POS] +
79         NORMALIZED_OHMURL_SEPARATOR + items[VERSION_POS];
80     return recordName;
81 }
82 
IsExternalPkgNames(const std::string &ohmurl, const std::set<std::string> &externalPkgNames)83 bool IsExternalPkgNames(const std::string &ohmurl, const std::set<std::string> &externalPkgNames)
84 {
85     auto pkgName = GetPkgNameFromNormalizedOhmurl(ohmurl);
86     if (std::find(externalPkgNames.begin(), externalPkgNames.end(), pkgName) != externalPkgNames.end()) {
87         return true;
88     }
89     return false;
90 }
91 
UpdatePackageVersionIfNeeded(const std::string &ohmurl, const std::unordered_map<std::string, PkgInfo> &pkgContextInfo)92 std::string UpdatePackageVersionIfNeeded(const std::string &ohmurl,
93                                          const std::unordered_map<std::string, PkgInfo> &pkgContextInfo)
94 {
95     // Input ohmurl format:
96     // @normalized:{N|Y}&[module name]&[bundle name]&{<package name>|<@package/name>}/{import_path}&[version]
97     // Update the version for ohmurls and return the updated ohmurl when:
98     // 1. The package name and version are specified in the CompileContextInfo file.
99     // 2. The ohmurl is an imported non-native ohmurl (starts with @normalized:N).
100     // 3. The version in the ohmurl differs from the version in the CompileContextInfo file.
101     // Return the original ohmurl otherwise.
102     if (ohmurl.find(util::NORMALIZED_OHMURL_NOT_SO) != 0) {
103         return ohmurl;
104     }
105     std::string packageName = util::GetPkgNameFromNormalizedOhmurl(ohmurl);
106     // Incorrect ohmurl format: no package name, skip version update
107     if (packageName.empty()) {
108         return ohmurl;
109     }
110     auto iter = pkgContextInfo.find(packageName);
111     if (iter == pkgContextInfo.end()) {
112         return ohmurl;
113     }
114     auto versionStart = ohmurl.rfind(util::NORMALIZED_OHMURL_SEPARATOR);
115     // Incorrect ohmurl format: no version, skip version update
116     if (versionStart == std::string::npos) {
117         return ohmurl;
118     }
119     return ohmurl.substr(0, versionStart + 1) + iter->second.version;
120 }
121 
RecordNotGeneratedFromBytecode(std::string recordName)122 bool RecordNotGeneratedFromBytecode(std::string recordName)
123 {
124     return recordName.find(util::CHAR_VERTICAL_LINE) == std::string::npos;
125 }
126 
127 } // namespace panda::es2panda::util