1//
2// Namespace.cpp
3//
4// Library: CppParser
5// Package: SymbolTable
6// Module: Namespace
7//
8// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/CppParser/NameSpace.h"
16#include "Poco/Exception.h"
17#include <sstream>
18#include <cstddef>
19
20
21using Poco::ExistsException;
22using Poco::NotFoundException;
23
24
25namespace Poco {
26namespace CppParser {
27
28
29NameSpace::NameSpace()
30{
31}
32
33
34NameSpace::NameSpace(const std::string& name, NameSpace* pNameSpace):
35 Symbol(name, pNameSpace)
36{
37}
38
39
40NameSpace::~NameSpace()
41{
42 for (SymbolTable::iterator it = _symbols.begin(); it != _symbols.end(); ++it)
43 {
44 delete it->second;
45 }
46}
47
48
49void NameSpace::addSymbol(Symbol* pSymbol)
50{
51 poco_check_ptr (pSymbol);
52
53 _symbols.insert(SymbolTable::value_type(pSymbol->name(), pSymbol));
54}
55
56
57void NameSpace::importSymbol(const std::string& fullName)
58{
59 std::string localName;
60 std::string::size_type pos = fullName.find_last_of(':');
61 if (pos != std::string::npos && pos < fullName.size() - 1)
62 {
63 localName.assign(fullName, pos + 1, fullName.size() - pos - 1);
64 _importedSymbols[localName] = fullName;
65 }
66}
67
68
69void NameSpace::importNameSpace(const std::string& nameSpace)
70{
71 _importedNameSpaces.push_back(nameSpace);
72}
73
74
75NameSpace::Iterator NameSpace::begin() const
76{
77 return _symbols.begin();
78}
79
80
81NameSpace::Iterator NameSpace::end() const
82{
83 return _symbols.end();
84}
85
86
87Symbol* NameSpace::lookup(const std::string& name) const
88{
89 std::set<const NameSpace*> alreadyVisited;
90 return lookup(name, alreadyVisited);
91}
92
93
94Symbol* NameSpace::lookup(const std::string& name, std::set<const NameSpace*>& alreadyVisited) const
95{
96 Symbol* pSymbol = 0;
97
98 if (name.empty())
99 return pSymbol;
100
101 if (alreadyVisited.find(this) != alreadyVisited.end())
102 return pSymbol;
103 std::string head;
104 std::string tail;
105 splitName(name, head, tail);
106
107 alreadyVisited.insert(this);
108 bool currentNSInserted = true;
109
110
111 if (head.empty())
112 {
113 alreadyVisited.insert(this);
114 return root()->lookup(tail, alreadyVisited);
115 }
116 SymbolTable::const_iterator it = _symbols.find(head);
117 if (it != _symbols.end())
118 {
119 pSymbol = it->second;
120 if (!tail.empty())
121 {
122 alreadyVisited.insert(this);
123 NameSpace* pNS = dynamic_cast<NameSpace*>(pSymbol);
124 if (pNS)
125 pSymbol = static_cast<NameSpace*>(pSymbol)->lookup(tail, alreadyVisited);
126 else
127 pSymbol = 0;
128 }
129 }
130 else if (tail.empty())
131 {
132 AliasMap::const_iterator itAlias = _importedSymbols.find(head);
133 if (itAlias != _importedSymbols.end())
134 pSymbol = lookup(itAlias->second, alreadyVisited);
135 else
136 {
137 for (NameSpaceVec::const_iterator itns = _importedNameSpaces.begin(); !pSymbol && itns != _importedNameSpaces.end(); ++itns)
138 {
139 Symbol* pNS = lookup(*itns, alreadyVisited);
140 if (pNS && pNS->kind() == Symbol::SYM_NAMESPACE)
141 {
142 pSymbol = static_cast<NameSpace*>(pNS)->lookup(name, alreadyVisited);
143 }
144 }
145 }
146 }
147 NameSpace* pNS = nameSpace();
148 if (!pSymbol && pNS && (alreadyVisited.find(pNS) == alreadyVisited.end()))
149 {
150 // if we have to go up, never push the NS!
151 if (currentNSInserted)
152 alreadyVisited.erase(this);
153 pSymbol = nameSpace()->lookup(name, alreadyVisited);
154 }
155 return pSymbol;
156}
157
158
159void NameSpace::nameSpaces(SymbolTable& table) const
160{
161 extract(Symbol::SYM_NAMESPACE, table);
162}
163
164
165void NameSpace::typeDefs(SymbolTable& table) const
166{
167 extract(Symbol::SYM_TYPEDEF, table);
168}
169
170
171void NameSpace::enums(SymbolTable& table) const
172{
173 extract(Symbol::SYM_ENUM, table);
174}
175
176
177void NameSpace::classes(SymbolTable& table) const
178{
179 extract(Symbol::SYM_STRUCT, table);
180}
181
182
183void NameSpace::functions(SymbolTable& table) const
184{
185 extract(Symbol::SYM_FUNCTION, table);
186}
187
188
189void NameSpace::variables(SymbolTable& table) const
190{
191 extract(Symbol::SYM_VARIABLE, table);
192}
193
194
195Symbol::Kind NameSpace::kind() const
196{
197 return Symbol::SYM_NAMESPACE;
198}
199
200
201std::string NameSpace::toString() const
202{
203 std::ostringstream ostr;
204 ostr << "namespace " << name() << "\n{\n";
205 for (Iterator it = begin(); it != end(); ++it)
206 {
207 ostr << it->second->fullName() << "\n";
208 ostr << it->second->toString() << "\n";
209 }
210 ostr << "}\n";
211 return ostr.str();
212}
213
214
215void NameSpace::splitName(const std::string& name, std::string& head, std::string& tail)
216{
217 std::string::size_type pos = name.find(':');
218 if (pos != std::string::npos)
219 {
220 head.assign(name, 0, pos);
221 pos += 2;
222 poco_assert (pos < name.length());
223 tail.assign(name, pos, name.length() - pos);
224 }
225 else head = name;
226}
227
228
229NameSpace* NameSpace::root()
230{
231 static NameSpace root;
232 return &root;
233}
234
235
236void NameSpace::extract(Symbol::Kind kind, SymbolTable& table) const
237{
238 for (SymbolTable::const_iterator it = _symbols.begin(); it != _symbols.end(); ++it)
239 {
240 if (it->second->kind() == kind)
241 table.insert(*it);
242 }
243}
244
245
246} } // namespace Poco::CppParser
247