• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_METHOD_SIGNATURE_H_
17 #define PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_METHOD_SIGNATURE_H_
18 
19 #include "libpandabase/utils/logger.h"
20 #include "runtime/include/method.h"
21 #include "plugins/ets/runtime/types/ets_value.h"
22 #include "plugins/ets/runtime/ani/ani_mangle.h"
23 
24 namespace ark::ets {
25 
26 // Arguments type separated from return type by ":". Object names bounded by 'L' and ';'
27 class EtsMethodSignature {
28 public:
29     explicit EtsMethodSignature(const std::string_view sign, bool isANIFormat = false)
30     {
31         const PandaString signature = isANIFormat ? ani::Mangle::ConvertSignature(sign) : PandaString(sign);
32 
33         size_t dots = signature.find(':');
34         // Return if ':' wasn't founded or was founded at the end
35         if (dots == PandaString::npos || dots == signature.size() - 1) {
36             return;
37         }
38         // Process return type after ':'
39         if (ProcessParameter(signature, dots + 1) != signature.size() - 1) {
40             return;
41         }
42         // Process arguments
43         size_t i;
44         for (i = 0; i < dots; i++) {
45             i = ProcessParameter(signature, i);
46             if (i == PandaString::npos) {
47                 return;
48             }
49         }
50         isValid_ = true;
51         for (auto &paramType : paramTypes_) {
52             pandaProto_.GetRefTypes().push_back(paramType);
53         }
54     }
55 
IsValid()56     bool IsValid()
57     {
58         return isValid_;
59     }
60 
GetProto()61     Method::Proto &GetProto()
62     {
63         return pandaProto_;
64     }
65 
66 private:
ProcessParameter(const PandaString & signature,size_t i)67     size_t ProcessParameter(const PandaString &signature, size_t i)
68     {
69         EtsType paramType = GetTypeByFirstChar(signature[i]);
70         // Check that type is valid and return type is not void
71         if (paramType == EtsType::UNKNOWN || (paramType == EtsType::VOID && (i != signature.size() - 1))) {
72             return PandaString::npos;
73         }
74         pandaProto_.GetShorty().push_back(ets::ConvertEtsTypeToPandaType(paramType));
75 
76         if (paramType != EtsType::OBJECT) {
77             return i;
78         }
79         size_t nameStart = i;
80         i = ProcessObjectParameter(signature, i);
81         if (i == PandaString::npos) {
82             return i;
83         }
84         paramTypes_.push_back(signature.substr(nameStart, i + 1 - nameStart));
85         return i;
86     }
87 
88     PandaSmallVector<PandaString> paramTypes_;
89     Method::Proto pandaProto_;
90     bool isValid_ {false};
91 
ProcessObjectParameter(const PandaString & signature,size_t i)92     size_t ProcessObjectParameter(const PandaString &signature, size_t i)
93     {
94         while (signature[i] == '[') {
95             ++i;
96             if (i >= signature.size()) {
97                 return PandaString::npos;
98             }
99         }
100         if (GetTypeByFirstChar(signature[i]) == EtsType::UNKNOWN) {
101             return PandaString::npos;
102         }
103 
104         if (signature[i] == 'L') {
105             // Get object name bounded by 'L' and ';'
106             size_t prevI = i;
107             i = signature.find(';', i);
108             if (i == PandaString::npos || i == (prevI + 1)) {
109                 return PandaString::npos;
110             }
111         }
112         return i;
113     }
GetTypeByFirstChar(char c)114     EtsType GetTypeByFirstChar(char c)
115     {
116         switch (c) {
117             case 'L':
118             case '[':
119                 return EtsType::OBJECT;
120             case 'Z':
121                 return EtsType::BOOLEAN;
122             case 'B':
123                 return EtsType::BYTE;
124             case 'C':
125                 return EtsType::CHAR;
126             case 'S':
127                 return EtsType::SHORT;
128             case 'I':
129                 return EtsType::INT;
130             case 'J':
131                 return EtsType::LONG;
132             case 'F':
133                 return EtsType::FLOAT;
134             case 'D':
135                 return EtsType::DOUBLE;
136             case 'V':
137                 return EtsType::VOID;
138             default:
139                 return EtsType::UNKNOWN;
140         }
141     }
142 };
143 
144 }  // namespace ark::ets
145 
146 #endif  // PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_METHOD_SIGNATURE_H_
147