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 "ast/ast.h"
17
18#include <cstdlib>
19
20#include "util/string_builder.h"
21
22namespace OHOS {
23namespace Idl {
24AST::TypeStringMap AST::basicTypes_ = {
25    {"void",           new ASTVoidType()     },
26    {"boolean",        new ASTBooleanType()     },
27    {"byte",           new ASTByteType()        },
28    {"short",          new ASTShortType()       },
29    {"int",            new ASTIntegerType()     },
30    {"long",           new ASTLongType()        },
31    {"float",          new ASTFloatType()       },
32    {"double",         new ASTDoubleType()      },
33    {"String",         new ASTStringType()      },
34    {"String16",       new ASTString16Type()    },
35    {"char",           new ASTCharType()        },
36    {"unsigned char",  new ASTUcharType()       },
37    {"unsigned short", new ASTUshortType()      },
38    {"unsigned int",   new ASTUintType()        },
39    {"unsigned long",  new ASTUlongType()       },
40    {"FileDescriptor", new ASTFdType()          },
41    {"Ashmem",         new ASTAshmemType()      },
42    {"NativeBuffer",   new ASTNativeBufferType()},
43    {"Pointer",        new ASTPointerType()     },
44};
45
46void AST::SetIdlFile(const std::string &idlFile)
47{
48    idlFilePath_ = idlFile;
49#ifdef __MINGW32__
50    size_t index = idlFilePath_.rfind('\\');
51#else
52    size_t index = idlFilePath_.rfind('/');
53#endif
54
55    size_t end = idlFilePath_.rfind(".idl");
56    if (end == std::string::npos) {
57        end = idlFile.size();
58    }
59
60    name_ = StringHelper::SubStr(idlFilePath_, (index == std::string::npos) ? 0 : (index + 1), end);
61}
62
63void AST::SetFullName(const std::string &fullName)
64{
65    std::string name = fullName;
66    size_t start = fullName.rfind("..");
67    if (start != std::string::npos) {
68        name = StringHelper::SubStr(fullName, start + strlen(".."));
69    }
70    size_t index = name.rfind('.');
71    if (index != std::string::npos) {
72        packageName_ = StringHelper::SubStr(name, 0, index);
73        name_ = StringHelper::SubStr(name, index + 1);
74    } else {
75        packageName_ = "";
76        name_ = name;
77    }
78}
79
80void AST::SetPackageName(const std::string &packageName)
81{
82    packageName_ = packageName;
83    ParseNamespace(packageName_);
84}
85
86AutoPtr<ASTNamespace> AST::ParseNamespace(const std::string &nspaceStr)
87{
88    AutoPtr<ASTNamespace> currNspace;
89    size_t begin = 0;
90    size_t index = 0;
91    while ((index = nspaceStr.find('.', begin)) != std::string::npos) {
92        std::string ns = StringHelper::SubStr(nspaceStr, begin, index);
93        AutoPtr<ASTNamespace> nspace;
94        if (currNspace == nullptr) {
95            nspace = NewNameSpace(ns);
96        } else {
97            nspace = currNspace->FindNamespace(ns);
98            if (nspace == nullptr) {
99                nspace = new ASTNamespace(ns);
100                currNspace->AddNamespace(nspace);
101            }
102        }
103        currNspace = nspace;
104        begin = index + 1;
105    }
106    if (currNspace == nullptr) {
107        currNspace = NewNameSpace("");
108    }
109    return currNspace;
110}
111
112AutoPtr<ASTNamespace> AST::NewNameSpace(std::string nameSpace)
113{
114    AutoPtr<ASTNamespace> currNspace = FindNamespace(nameSpace);
115    if (currNspace == nullptr) {
116        currNspace = new ASTNamespace(nameSpace);
117        AddNamespace(currNspace);
118    }
119    return currNspace;
120}
121
122void AST::AddNamespace(const AutoPtr<ASTNamespace> &nspace)
123{
124    if (nspace == nullptr) {
125        return;
126    }
127    namespaces_.push_back(nspace);
128}
129
130AutoPtr<ASTNamespace> AST::FindNamespace(const std::string &nspaceStr)
131{
132    for (auto nspace : namespaces_) {
133        if (nspace->ToShortString() == nspaceStr) {
134            return nspace;
135        }
136    }
137    return nullptr;
138}
139
140AutoPtr<ASTNamespace> AST::GetNamespace(size_t index)
141{
142    if (index >= namespaces_.size()) {
143        return nullptr;
144    }
145
146    return namespaces_[index];
147}
148
149void AST::AddInterfaceDef(const AutoPtr<ASTInterfaceType> &interface)
150{
151    if (interface == nullptr) {
152        return;
153    }
154
155    interfaceDefs_.push_back(interface);
156    AddType(interface.Get());
157}
158
159AutoPtr<ASTInterfaceType> AST::GetInterfaceDef(size_t index)
160{
161    if (index >= interfaceDefs_.size()) {
162        return nullptr;
163    }
164
165    return interfaceDefs_[index];
166}
167
168AutoPtr<ASTSequenceableType> AST::GetSequenceableDef(size_t index)
169{
170    if (index >= sequenceableDefs_.size()) {
171        return nullptr;
172    }
173
174    return sequenceableDefs_[index];
175}
176
177void AST::AddSequenceableDef(const AutoPtr<ASTSequenceableType> &sequenceable)
178{
179    if (sequenceable == nullptr) {
180        return;
181    }
182
183    sequenceableDefs_.push_back(sequenceable);
184    AddType(sequenceable.Get());
185}
186
187int AST::IndexOf(ASTInterfaceType* interface)
188{
189    for (size_t i = 0; i < interfaceDefs_.size(); i++) {
190        if (interfaceDefs_[i] == interface) {
191            return i;
192        }
193    }
194    return -1;
195}
196
197int AST::IndexOf(ASTSequenceableType* sequenceable)
198{
199    for (size_t i = 0; i < sequenceableDefs_.size(); i++) {
200        if (sequenceableDefs_[i] == sequenceable) {
201            return i;
202        }
203    }
204    return -1;
205}
206
207int AST::IndexOf(ASTType* type)
208{
209    int i = 0;
210    for (auto it = types_.begin(); it != types_.end(); ++it, ++i) {
211        if (it->second == type) {
212            return i;
213        }
214    }
215    return -1;
216}
217
218void AST::AddType(const AutoPtr<ASTType> &type)
219{
220    if (type == nullptr) {
221        return;
222    }
223
224    types_[type->ToString()] = type;
225}
226
227AutoPtr<ASTType> AST::FindType(const std::string &typeName, bool lookImports)
228{
229    if (typeName.empty()) {
230        return nullptr;
231    }
232
233    for (const auto &type : types_) {
234        if ((typeName.find('.') == std::string::npos && type.second->GetName() == typeName) ||
235            type.first == typeName) {
236            return type.second;
237        }
238    }
239
240    auto basicTypePair = basicTypes_.find(typeName);
241    if (basicTypePair != basicTypes_.end()) {
242        return basicTypePair->second;
243    }
244
245    if (!lookImports) {
246        return nullptr;
247    }
248
249    AutoPtr<ASTType> type = nullptr;
250    for (const auto &importPair : imports_) {
251        type = importPair.second->FindType(typeName, false);
252        if (type != nullptr) {
253            break;
254        }
255    }
256    return type;
257}
258
259void AST::AddTypeDefinition(const AutoPtr<ASTType> &type)
260{
261    if (type == nullptr) {
262        return;
263    }
264
265    AddType(type);
266    typeDefinitions_.push_back(type);
267}
268
269AutoPtr<ASTType> AST::GetTypeDefintion(size_t index)
270{
271    if (index >= typeDefinitions_.size()) {
272        return nullptr;
273    }
274    return typeDefinitions_[index];
275}
276
277std::string AST::Dump(const std::string &prefix)
278{
279    StringBuilder sb;
280
281    sb.Append(prefix);
282    if (Options::GetInstance().GetInterfaceType() == InterfaceType::SA) {
283        sb.Append("Module[");
284    } else {
285        sb.Append("AST[");
286    }
287    sb.Append("name: ").Append(name_).Append(" ");
288    sb.Append("file: ").Append(idlFilePath_);
289    sb.Append("]\n");
290
291    if (!packageName_.empty()) {
292        sb.Append("package ").Append(packageName_).Append(";");
293        sb.Append('\n');
294        sb.Append('\n');
295    }
296
297    if (imports_.size() > 0) {
298        std::string Keyword = "import";
299        if (Options::GetInstance().GetInterfaceType() == InterfaceType::SA) {
300            Keyword = "sequenceable";
301        }
302        for (const auto &import : imports_) {
303            sb.AppendFormat("%s %s;\n", Keyword.c_str(), import.first.c_str());
304        }
305        sb.Append("\n");
306    }
307
308    if (typeDefinitions_.size() > 0) {
309        for (auto type : typeDefinitions_) {
310            std::string info = type->Dump("");
311            sb.Append(info).Append("\n");
312        }
313    }
314
315    if (interfaceDefs_.size() > 0) {
316        for (auto type : interfaceDefs_) {
317            if (type->IsExternal()) {
318                std::string info = type->Dump("");
319                sb.Append(info).Append("\n");
320            }
321        }
322
323        for (auto type : interfaceDefs_) {
324            if (!type->IsExternal()) {
325                std::string info = type->Dump("");
326                sb.Append(info).Append("\n");
327            }
328        }
329    }
330
331    return sb.ToString();
332}
333
334bool AST::AddImport(const AutoPtr<AST> &importAst)
335{
336    if (imports_.find(importAst->GetFullName()) != imports_.end()) {
337        return false;
338    }
339
340    imports_[importAst->GetFullName()] = importAst;
341
342    return true;
343}
344
345void AST::SetVersion(size_t &majorVer, size_t &minorVer)
346{
347    majorVersion_ = majorVer;
348    minorVersion_ = minorVer;
349}
350
351bool AST::IsValid()
352{
353    if (name_.empty()) {
354        return false;
355    }
356
357    return interfaceDefs_.size() > 0;
358}
359
360} // namespace Idl
361} // namespace OHOS