• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 "plugins/ets/runtime/ani/ani_mangle.h"
17 #include "plugins/ets/runtime/ets_panda_file_items.h"
18 
19 namespace ark::ets::ani {
20 
21 static size_t ParseArrayBody(const std::string_view data, PandaStringStream &ss);
22 
23 /*static*/
ConvertDescriptor(const std::string_view descriptor,bool allowArray)24 PandaString Mangle::ConvertDescriptor(const std::string_view descriptor, bool allowArray)
25 {
26     if (descriptor.empty() || descriptor.back() == ';' || descriptor.find('/') != std::string::npos) {
27         // The 'descriptor' does not have a new format, so no conversion is required.
28         return PandaString(descriptor);
29     }
30 
31     PandaStringStream ss;
32     if (allowArray) {
33         // NOLINTNEXTLINE(readability-magic-numbers)
34         if (descriptor.size() >= 2U && descriptor[0] == 'A' && descriptor[1] == '{') {
35             auto bodySize = ParseArrayBody(descriptor.substr(1), ss);
36             if (bodySize == std::string_view::npos) {
37                 // The 'descriptor' has wrong format, so can't be convert
38                 return PandaString("");
39             }
40             return ss.str();
41         }
42     }
43 
44     ss << 'L';
45     ss << descriptor;
46     ss << ';';
47     PandaString oldDescriptor = ss.str();
48     std::replace(oldDescriptor.begin(), oldDescriptor.end(), '.', '/');
49 
50     return oldDescriptor;
51 }
52 
53 static constexpr size_t MIN_BODY_SIZE = sizeof('{') + 1 + sizeof('}');
54 
55 static size_t ParseType(char type, const std::string_view data, PandaStringStream &ss);
56 
ParseArrayBody(const std::string_view data,PandaStringStream & ss)57 static size_t ParseArrayBody(const std::string_view data, PandaStringStream &ss)
58 {
59     if (data.size() < MIN_BODY_SIZE || data[0] != '{') {
60         return std::string_view::npos;
61     }
62     ss << '[';
63 
64     char type = data[1];
65     const std::string_view typeData = data.substr(1);
66     size_t size = ParseType(type, typeData, ss);
67     if (size == std::string_view::npos || size >= typeData.size() || typeData[size] != '}') {
68         return std::string_view::npos;
69     }
70     return sizeof('{') + size + sizeof('}');
71 }
72 
ParseBody(char type,const std::string_view data,PandaStringStream & ss)73 static size_t ParseBody(char type, const std::string_view data, PandaStringStream &ss)
74 {
75     ASSERT(type != 'A');
76 
77     if (data.size() < MIN_BODY_SIZE || data[0] != '{') {
78         return std::string_view::npos;
79     }
80     for (size_t pos = 1; pos < data.size(); ++pos) {
81         if (data[pos] != '}') {
82             continue;
83         }
84         PandaString oldName(data.substr(1, pos - 1));
85         std::replace(oldName.begin(), oldName.end(), '.', '/');
86         ss << 'L';
87         ss << oldName;
88         ss << (type == 'P' ? "$partial;" : ";");
89         return pos + 1;
90     }
91     return std::string_view::npos;
92 }
93 
ParseType(char type,const std::string_view data,PandaStringStream & ss)94 static size_t ParseType(char type, const std::string_view data, PandaStringStream &ss)
95 {
96     size_t bodySize = std::string_view::npos;
97     // clang-format off
98     switch (type) {
99         case 'z': ss << 'Z'; return 1;
100         case 'c': ss << 'C'; return 1;
101         case 'b': ss << 'B'; return 1;
102         case 's': ss << 'S'; return 1;
103         case 'i': ss << 'I'; return 1;
104         case 'l': ss << 'J'; return 1;
105         case 'f': ss << 'F'; return 1;
106         case 'd': ss << 'D'; return 1;
107         case 'N': ss << panda_file_items::class_descriptors::OBJECT; return 1;
108         case 'U': ss << panda_file_items::class_descriptors::OBJECT; return 1;
109         case 'A': bodySize = ParseArrayBody(data.substr(1), ss); break;
110         case 'C':
111         case 'E':
112         case 'P': bodySize = ParseBody(type, data.substr(1), ss); break;
113         default:
114             // The 'descriptor' does not have a new format, so no conversion is required.
115             return std::string_view::npos;
116     }
117     // clang-format on
118 
119     if (bodySize == std::string_view::npos) {
120         return std::string_view::npos;
121     }
122     return 1 + bodySize;
123 }
124 
125 /*static*/
ConvertSignature(const std::string_view descriptor)126 PandaString Mangle::ConvertSignature(const std::string_view descriptor)
127 {
128     PandaStringStream ss;
129     int nr = -1;
130     int k = -1;
131     for (size_t i = 0; i < descriptor.size(); ++i) {
132         char type = descriptor[i];
133         if (type == ':') {
134             ss << ':';
135             nr = 0;
136             k = 1;
137             continue;
138         }
139         size_t sz = ParseType(type, descriptor.substr(i), ss);
140         if (sz == std::string_view::npos) {
141             // The 'descriptor' does not have a new format, so no conversion is required.
142             return PandaString(descriptor);
143         }
144         i += sz - 1;
145         nr += k;
146     }
147     if (k == -1) {
148         // The 'descriptor' does not have a ':' symbol
149         return PandaString(descriptor);
150     }
151     if (nr == 0) {
152         ss << 'V';
153     }
154     return ss.str();
155 }
156 
157 }  // namespace ark::ets::ani
158