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
82 actParam.TrimEnd();
83 if ( actParam.IsNotEmpty() ) {
84 // remove space before reference "&" and pointer "*"
85 integer actIdx= 0;
86 while ((actIdx= actParam.IndexOf('&', actIdx)) > 0) {
87 if (actParam.CharAt(actIdx-1) == ' ')
88 actParam.Delete(actIdx-1, 1);
89 ++actIdx;
90 }
91 actIdx= 0;
92 while ((actIdx= actParam.IndexOf('*', actIdx)) > 0) {
93 if (actParam.CharAt(actIdx-1) == ' ')
94 actParam.Delete(actIdx-1, 1);
95 ++actIdx;
96 }
97
98 actIdx= 0;
99 while ((actIdx= actParam.IndexOf("...", actIdx)) > 0) {
100 if (actParam.CharAt(actIdx-1) != ' ')
101 actParam.InsertAt(" ", actIdx);
102 actIdx+=3;
103 }
104
105 if ( lastChar == '=') {
106 // skip assignment
107 bool inLiteral= false;
108 bool escaped= false;
109 depth= 0;
110 for (;;) {
111 lastChar= parser.ConsumeChar();
112 if ( lastChar == '\0')
113 break;
114 bool isLitChar= lastChar=='\'' || lastChar == '"';
115 bool isEscChar= lastChar=='\\';
116 if ( inLiteral ) { if ( escaped ) { escaped = false; continue; }
117 if ( isEscChar) { escaped = true; continue; } }
118 if (isLitChar) { inLiteral= !inLiteral; continue; }
119 if (inLiteral) continue;
120 if (String8("({[<").IndexOf(lastChar) >= 0)
121 {++depth; continue;}
122 if (String8(">)}]").IndexOf(lastChar) >= 0)
123 {if (--depth < 0) break; continue;}
124
125 if ( depth==0 && (lastChar== ',' || lastChar==')'))
126 break;
127 }
128 }
129
130 // remove spaces before/after template braces
131 actParam.SearchAndReplace("< ", "<");
132 actParam.SearchAndReplace(" >", ">");
133
134 parsed[cntArgs++]= String(ma, actParam);
135 } // not empty
136
137 if ( lastChar==')')
138 break;
139
140 if (cntArgs==128)
141 return nullptr; // todo: notify caller
142 parser.TrimStart();
143 }
144
145 FunctionArguments* result= ma().Alloc<FunctionArguments>();
146 result->Count = cntArgs;
147 if ( cntArgs > 0) {
148 result->Arguments= ma().NewArray<String>(cntArgs);
149 for (int i= 0; i< cntArgs; ++i)
150 result->Arguments[i]= parsed[i];
151 }
152 return result;
153}
154
156 int cntArgs= 0;
157 String parsed[128];
158
159 if (!parser.ConsumeChar('<') ) {
160 ALIB_ERROR("DXL/TARGET", "Template brackets expected.")
161 return nullptr;
162 }
163
164 // find all
165 for (;;) {
166 // find end of actual
167 String256 actParam;
168 int depth= 0;
169 parser.TrimStart();
170 char lastChar;
171 for(;;) {
172 lastChar= parser.ConsumeChar();
173 if ( lastChar == '\0') {
174 break; // full syntax error
175 }
176 if ( String("<([{").IndexOf(lastChar) >= 0 ) ++depth;
177 if ( String( ")]}").IndexOf(lastChar) >= 0 ) --depth;
178 if ( lastChar == '>' && --depth< 0 ) break;
179 if ( lastChar == ',' && depth==0 ) break;
180
181 actParam._<NC>(lastChar);
182 }
183
184 // remove ',' or '>'
185 actParam.Trim();
186 if(actParam.IsNotEmpty()) // full syntax error, otherwise
187 parsed[cntArgs++]= String(ma, actParam);
188 if ( depth<0 || lastChar==0) {
189 break;
190 }
191
192 if (cntArgs>64) {
193 break; // todo: notify caller
194 }
195 parser.TrimStart();
196 }
197
198 TemplateArguments* result= ma().Alloc<TemplateArguments>();
199 result->Count = cntArgs;
200 if ( cntArgs > 0) {
201 result->Arguments= ma().NewArray<String>(cntArgs);
202 for (int i= 0; i< cntArgs; ++i)
203 result->Arguments[i]= parsed[i];
204 }
205 return result;
206}
207
209 // target has no args?
210 if (target==nullptr || target->Count == 0 ) {
211 if (linkArgs ==nullptr) return 2; // XLink has no arg spec given
212 if (linkArgs->Count==0) return 3; // XLink has 0 args given
213 return 0; // no match
214 }
215
216 // target has at least one argument
217 if (linkArgs ==nullptr || linkArgs->Count==0)
218 return 1;
219
220 // search parameters
221 int argNoLink= 0;
222 int argNoTarget= 0;
223 bool exactMatch = true;
224 for (;argNoLink<linkArgs->Count && argNoTarget<target->Count;) {
225 if ( target->Arguments[argNoTarget].StartsWith(linkArgs->Arguments[argNoLink]) ) {
226 if ( target->Arguments[argNoTarget].Length() != linkArgs->Arguments[argNoLink].Length())
227 exactMatch= false;
228 ++argNoLink;
229 }
230 ++argNoTarget;
231 }
232 if ( argNoLink < linkArgs->Count )
233 return 0;
234 if ( exactMatch && linkArgs->Count == target->Count )
235 return 4;
236 return 3;
237}
238
239#include "ALib.Lang.CIMethods.H"
240
242 int argNoSearch= 0;
243 int argNoTarget= 0;
244 bool exactMatch = true;
245 for (;argNoSearch < Count && argNoTarget < target.Count;) {
246 auto& tArg= target.Arguments[argNoTarget];
247 if ( tArg.StartsWith(Arguments[argNoSearch])
248 || (tArg.StartsWith("typename ") && tArg.Substring(9).StartsWith(Arguments[argNoSearch]) )
249 || (tArg.StartsWith("class ") && tArg.Substring(6).StartsWith(Arguments[argNoSearch]) )
250 ) {
251 if (tArg.Length() != Arguments[argNoSearch].Length())
252 exactMatch= false;
253 ++argNoSearch;
254 }
255 ++argNoTarget;
256 }
257 if ( argNoSearch < Count )
258 return 0;
259 if ( exactMatch && Count == target.Count )
260 return 2;
261 return 1;
262}
263
265 dest << '<';
266 for (int i= 0; i< Count; ++i) {
267 dest << Arguments[i];
268 if ( i < Count - 1)
269 dest << ", ";
270 }
271 dest << '>';
272}
273
274} //namespace [dxl]
275
#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:86
static int MATCH(FunctionArguments *linkArgs, FunctionArguments *targetArgs)
Definition target.cpp:208
int Count
The number of arguments.
Definition target.hpp:83
static FunctionArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:28
TemplateArguments()
Constructor.
Definition target.hpp:147
int Count
The number of arguments.
Definition target.hpp:141
static TemplateArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:155
int Match(TemplateArguments &target)
Definition target.cpp:241
void Print(alib::AString &dest)
Definition target.cpp:264
alib::String * Arguments
An array of length Count of strings.
Definition target.hpp:144