Doxygen XLinks
by
V: 2511R0
Website: doxygen
Loading...
Searching...
No Matches
target.cpp
1//==================================================================================================
2// This implementation-file is part of DoxygenXLinks - A doxygen post-processor that allows to
3// define smarter <b>Doxygen</b>-links.
4//
5// \emoji :copyright: 2025-2026 A-Worx GmbH, Germany.
6// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#include "target.hpp"
9
10using namespace alib;
11using namespace std;
12
13namespace dxl {
14
16
18 dest << '(';
19 for (int i= 0; i< Count; ++i) {
20 dest << Arguments[i];
21 if ( i < Count - 1)
22 dest << ", ";
23 }
24 dest << ')';
25}
26
29 int cntArgs= 0;
30 String parsed[128];
31
32 if (!parser.ConsumeChar('('))
33 return nullptr;
34
35 // find all
36 for (;;) {
37 String256 actParam;
38 int depth= 0;
39
40 // find end of actual
41 char lastChar;
42 for(;;) {
43 lastChar= parser.ConsumeChar();
44 if ( lastChar == '\0')
45 return nullptr;
46 actParam._<NC>(lastChar);
47 if ( depth == 0 && String("=,)").IndexOf(lastChar) >= 0 )
48 break;
49
50 if ( String("<([{").IndexOf(lastChar) >= 0 ) { depth++; continue; }
51 if ( String(">)]}").IndexOf(lastChar) >= 0 ) { depth--; continue; }
52 }
53
54 // remove '=', ',' or ')'
55 actParam.ShortenBy(1);
56 // strip parameter name
57 {
58 // search the last "identifier"
59 integer paramNameStart= actParam.Length()-1;
60 for ( ; paramNameStart>=0
61 && String(" &*").IndexOf(actParam[paramNameStart]) < 0
62 && ( isalnum(actParam[paramNameStart])
63 || '_' == actParam[paramNameStart] )
64 ; --paramNameStart) ;
65 paramNameStart++;
66
67 // now we trim further from there and check if the remaining last word is a
68 // C++ keyword. If so, the identifier is a type and NOT a parameter name
69 Substring remainder= actParam.Substring(0, paramNameStart);
70 remainder.TrimEnd();
71 if ( remainder.EndsWith("const")
72 || remainder.EndsWith("volatile")
73 || remainder.EndsWith("::") )
74 paramNameStart= -1;
75
76 if ( paramNameStart>0 && paramNameStart < actParam.Length() ) {
77 actParam.ShortenTo(paramNameStart);
78 actParam.TrimEnd();
79 } }
80
81 actParam.TrimEnd();
82 if ( actParam.IsNotEmpty() ) {
83 // remove space before reference "&" and pointer "*"
84 integer actIdx= 0;
85 while ((actIdx= actParam.IndexOf('&', actIdx)) > 0) {
86 if (actParam.CharAt(actIdx-1) == ' ')
87 actParam.Delete(actIdx-1, 1);
88 ++actIdx;
89 }
90 actIdx= 0;
91 while ((actIdx= actParam.IndexOf('*', actIdx)) > 0) {
92 if (actParam.CharAt(actIdx-1) == ' ')
93 actParam.Delete(actIdx-1, 1);
94 ++actIdx;
95 }
96
97 actIdx= 0;
98 while ((actIdx= actParam.IndexOf("...", actIdx)) > 0) {
99 if (actParam.CharAt(actIdx-1) != ' ')
100 actParam.InsertAt(" ", actIdx);
101 actIdx+=3;
102 }
103
104 if ( lastChar == '=') {
105 // skip assignment
106 bool inLiteral= false;
107 bool escaped= false;
108 depth= 0;
109 for (;;) {
110 lastChar= parser.ConsumeChar();
111 if ( lastChar == '\0')
112 break;
113 bool isLitChar= lastChar=='\'' || lastChar == '"';
114 bool isEscChar= lastChar=='\\';
115 if ( inLiteral ) { if ( escaped ) { escaped = false; continue; }
116 if ( isEscChar) { escaped = true; continue; } }
117 if (isLitChar) { inLiteral= !inLiteral; continue; }
118 if (inLiteral) continue;
119 if (String8("({[<").IndexOf(lastChar) >= 0)
120 {++depth; continue;}
121 if (String8(">)}]").IndexOf(lastChar) >= 0)
122 {if (--depth < 0) break; continue;}
123
124 if ( depth==0 && (lastChar== ',' || lastChar==')'))
125 break;
126 } }
127
128 // remove spaces before/after template braces
129 actParam.SearchAndReplace("< ", "<");
130 actParam.SearchAndReplace(" >", ">");
131
132 parsed[cntArgs++]= String(ma, actParam);
133 } // not empty
134
135 if ( lastChar==')')
136 break;
137
138 if (cntArgs==128)
139 return nullptr; // todo: notify caller
140 parser.TrimStart();
141 }
142
143 FunctionArguments* result= ma().Alloc<FunctionArguments>();
144 result->Count = cntArgs;
145 if ( cntArgs > 0) {
146 result->Arguments= ma().NewArray<String>(cntArgs);
147 for (int i= 0; i< cntArgs; ++i)
148 result->Arguments[i]= parsed[i];
149 }
150 return result;
151}
152
154 int cntArgs= 0;
155 String parsed[128];
156
157 if (!parser.ConsumeChar('<') ) {
158 ALIB_ERROR("DXL/TARGET", "Template brackets expected.")
159 return nullptr;
160 }
161
162 // find all
163 for (;;) {
164 // find end of actual
165 String256 actParam;
166 int depth= 0;
167 parser.TrimStart();
168 char lastChar;
169 for(;;) {
170 lastChar= parser.ConsumeChar();
171 if ( lastChar == '\0') {
172 break; // full syntax error
173 }
174 if ( String("<([{").IndexOf(lastChar) >= 0 ) ++depth;
175 if ( String( ")]}").IndexOf(lastChar) >= 0 ) --depth;
176 if ( lastChar == '>' && --depth< 0 ) break;
177 if ( lastChar == ',' && depth==0 ) break;
178
179 actParam._<NC>(lastChar);
180 }
181
182 // remove ',' or '>'
183 actParam.Trim();
184 if(actParam.IsNotEmpty()) // full syntax error, otherwise
185 parsed[cntArgs++]= String(ma, actParam);
186 if ( depth<0 || lastChar==0) {
187 break;
188 }
189
190 if (cntArgs>64) {
191 break; // todo: notify caller
192 }
193 parser.TrimStart();
194 }
195
196 TemplateArguments* result= ma().Alloc<TemplateArguments>();
197 result->Count = cntArgs;
198 if ( cntArgs > 0) {
199 result->Arguments= ma().NewArray<String>(cntArgs);
200 for (int i= 0; i< cntArgs; ++i)
201 result->Arguments[i]= parsed[i];
202 }
203 return result;
204}
205
207 // target has no args?
208 if (target==nullptr || target->Count == 0 ) {
209 if (linkArgs ==nullptr) return 2; // XLink has no arg spec given
210 if (linkArgs->Count==0) return 3; // XLink has 0 args given
211 return 0; // no match
212 }
213
214 // target has at least one argument
215 if (linkArgs ==nullptr || linkArgs->Count==0)
216 return 1;
217
218 // search parameters
219 int argNoLink= 0;
220 int argNoTarget= 0;
221 bool exactMatch = true;
222 for (;argNoLink<linkArgs->Count && argNoTarget<target->Count;) {
223 if ( target->Arguments[argNoTarget].StartsWith(linkArgs->Arguments[argNoLink]) ) {
224 if ( target->Arguments[argNoTarget].Length() != linkArgs->Arguments[argNoLink].Length())
225 exactMatch= false;
226 ++argNoLink;
227 }
228 ++argNoTarget;
229 }
230 if ( argNoLink < linkArgs->Count )
231 return 0;
232 if ( exactMatch && linkArgs->Count == target->Count )
233 return 4;
234 return 3;
235}
236
237#include "ALib.Lang.CIMethods.H"
238
240 int argNoSearch= 0;
241 int argNoTarget= 0;
242 bool exactMatch = true;
243 for (;argNoSearch < Count && argNoTarget < target.Count;) {
244 auto& tArg= target.Arguments[argNoTarget];
245 if ( tArg.StartsWith(Arguments[argNoSearch])
246 || (tArg.StartsWith("typename ") && tArg.Substring(9).StartsWith(Arguments[argNoSearch]) )
247 || (tArg.StartsWith("class ") && tArg.Substring(6).StartsWith(Arguments[argNoSearch]) )
248 ) {
249 if (tArg.Length() != Arguments[argNoSearch].Length())
250 exactMatch= false;
251 ++argNoSearch;
252 }
253 ++argNoTarget;
254 }
255 if ( argNoSearch < Count )
256 return 0;
257 if ( exactMatch && Count == target.Count )
258 return 2;
259 return 1;
260}
261
263 dest << '<';
264 for (int i= 0; i< Count; ++i) {
265 dest << Arguments[i];
266 if ( i < Count - 1)
267 dest << ", ";
268 }
269 dest << '>';
270}
271
272} //namespace [dxl]
#define ALIB_ERROR(domain,...)
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
TAString & InsertAt(const TString< TChar > &src, integer pos)
integer SearchAndReplace(const TString< TChar > &needle, const TString< TChar > &replacement, integer startIdx=0, integer maxReplacements=strings::MAX_LEN, lang::Case sensitivity=lang::Case::Sensitive, integer endIdx=strings::MAX_LEN)
TAString & ShortenTo(integer newLength)
TAString & ShortenBy(integer charsToRemove)
TAString & Trim(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TAString & TrimEnd(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
constexpr integer Length() const
bool EndsWith(const TString &needle) const
TChar CharAt(integer idx) const
constexpr bool IsNotEmpty() const
integer IndexOf(const TString &needle, integer startIdx=0, integer endIdx=strings::MAX_LEN) const
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
bool StartsWith(const TString &needle) const
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
static size_t MAX_TEMPLATE_ARGS
Definition target.hpp:26
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
LocalString< 8 > String8
lang::integer integer
strings::TString< character > String
strings::TSubstring< character > Substring
LocalString< 256 > String256
strings::TAString< character, lang::HeapAllocator > AString
todox
Definition doxyfile.cpp:20
FunctionArguments()=default
Constructor.
void Print(alib::AString &dest)
Definition target.cpp:17
alib::String * Arguments
An array of length Count of strings.
Definition target.hpp:87
static int MATCH(FunctionArguments *linkArgs, FunctionArguments *targetArgs)
Definition target.cpp:206
int Count
The number of arguments.
Definition target.hpp:84
static FunctionArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:28
TemplateArguments()
Constructor.
Definition target.hpp:148
int Count
The number of arguments.
Definition target.hpp:142
static TemplateArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:153
int Match(TemplateArguments &target)
Definition target.cpp:239
void Print(alib::AString &dest)
Definition target.cpp:262
alib::String * Arguments
An array of length Count of strings.
Definition target.hpp:145