]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | // | |
3 | // Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | // Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. | |
5 | // Use, modification and distribution is subject to the Boost Software License, | |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // | |
10 | #ifndef DOXYGEN_XML_PARSER_HPP | |
11 | #define DOXYGEN_XML_PARSER_HPP | |
12 | ||
13 | ||
14 | #include <string> | |
15 | #include <vector> | |
16 | ||
17 | #include <boost/algorithm/string.hpp> | |
18 | ||
19 | #include <rapidxml_util.hpp> | |
20 | #include <doxygen_elements.hpp> | |
21 | #include <parameter_predicates.hpp> | |
22 | #include <configuration.hpp> | |
23 | ||
24 | ||
25 | inline std::string keep_after(std::string const& input, std::string const& sig) | |
26 | { | |
27 | std::size_t pos = input.rfind(sig); | |
28 | if (pos != std::string::npos) | |
29 | { | |
30 | std::string copy = input.substr(pos + sig.length()); | |
31 | return copy; | |
32 | } | |
33 | return input; | |
34 | } | |
35 | ||
36 | ||
37 | static inline void add_or_set(std::vector<parameter>& parameters, parameter const& p) | |
38 | { | |
39 | std::vector<parameter>::iterator it = std::find_if(parameters.begin(), parameters.end(), par_by_name(p.name)); | |
40 | if (it != parameters.end()) | |
41 | { | |
42 | if (it->brief_description.empty()) it->brief_description = p.brief_description; | |
43 | if (it->type.empty()) it->type = p.type; | |
44 | if (it->fulltype.empty()) it->fulltype = p.fulltype; | |
45 | if (it->default_value.empty()) it->default_value = p.default_value; | |
46 | } | |
47 | else | |
48 | { | |
49 | parameters.push_back(p); | |
50 | } | |
51 | } | |
52 | ||
53 | ||
54 | ||
55 | ||
56 | /// Parses a "para" element | |
57 | /* | |
58 | This is used for different purposes within Doxygen. | |
59 | - Either a detailed description, possibly containing several sections (para's) | |
60 | -> so parse next siblings | |
61 | - Or a detailed description also containing qbk records | |
62 | ||
63 | So we have to list explicitly either where to recurse, or where not to... | |
64 | ||
65 | */ | |
66 | ||
67 | // Type used to store parsing state. It indicates if QBK formatting block was opened - [*...], [^...], etc. | |
68 | enum text_block | |
69 | { | |
70 | not_in_block, | |
71 | in_code_block, | |
72 | in_block | |
73 | }; | |
74 | ||
75 | static void parse_para(rapidxml::xml_node<>* node, configuration const& config, std::string& contents, bool& skip, bool first = true, text_block tb = not_in_block) | |
76 | { | |
77 | if (node != NULL) | |
78 | { | |
79 | if (node->type() == rapidxml::node_element) | |
80 | { | |
81 | //std::cout << "ELEMENT: " << node->name() << "=" << node->value() << std::endl; | |
82 | std::string name = node->name(); | |
83 | if ( boost::equals(name, "itemizedlist") ) | |
84 | { | |
85 | contents += "\n\n"; | |
86 | parse_para(node->first_node(), config, contents, skip, true, tb); | |
87 | contents += "\n"; | |
88 | parse_para(node->next_sibling(), config, contents, skip, true, tb); | |
89 | return; | |
90 | } | |
91 | else if ( boost::equals(name, "listitem") ) | |
92 | { | |
93 | contents += "* "; | |
94 | parse_para(node->first_node(), config, contents, skip, true, tb); | |
95 | contents += "\n"; | |
96 | parse_para(node->next_sibling(), config, contents, skip, true, tb); | |
97 | return; | |
98 | } | |
99 | else if ( boost::equals(name, "verbatim") ) | |
100 | { | |
101 | contents += "\n``\n"; | |
102 | parse_para(node->first_node(), config, contents, skip, false, tb); | |
103 | contents += "``\n"; | |
104 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
105 | return; | |
106 | } | |
107 | else if ( boost::equals(name, "bold") ) | |
108 | { | |
109 | contents += "[*"; | |
110 | parse_para(node->first_node(), config, contents, skip, false, in_block); | |
111 | contents += "]"; | |
112 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
113 | return; | |
114 | } | |
115 | else if ( boost::equals(name, "emphasis") ) | |
116 | { | |
117 | contents += "['"; | |
118 | parse_para(node->first_node(), config, contents, skip, false, in_block); | |
119 | contents += "]"; | |
120 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
121 | return; | |
122 | } | |
123 | else if ( boost::equals(name, "computeroutput") ) | |
124 | { | |
125 | contents += "[^"; | |
126 | parse_para(node->first_node(), config, contents, skip, false, tb == in_block ? in_block : in_code_block); | |
127 | contents += "]"; | |
128 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
129 | return; | |
130 | } | |
131 | else if ( boost::equals(name, "ref") ) | |
132 | { | |
133 | // If alternative output is used - insert links | |
134 | if ( configuration::alt == config.output_style ) | |
135 | { | |
136 | std::string refid = node->first_attribute("refid")->value(); | |
137 | if ( !refid.empty() ) | |
138 | { | |
139 | contents += std::string("[link ") + refid + " "; | |
140 | parse_para(node->first_node(), config, contents, skip, false, in_block); | |
141 | contents += "]"; | |
142 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
143 | return; | |
144 | } | |
145 | } | |
146 | } | |
147 | else if (! ( | |
148 | (boost::equals(name, "para") && first) | |
149 | || boost::equals(name, "defval") | |
150 | || boost::equals(name, "linebreak") | |
151 | )) | |
152 | { | |
153 | return; | |
154 | } | |
155 | } | |
156 | else if (node->type() == rapidxml::node_data) | |
157 | { | |
158 | std::string str = node->value(); | |
159 | if ( tb == in_block ) | |
160 | { | |
161 | boost::replace_all(str, "\\", "\\\\"); | |
162 | boost::replace_all(str, "[", "\\["); | |
163 | boost::replace_all(str, "]", "\\]"); | |
164 | } | |
165 | else if ( tb == in_code_block ) | |
166 | { | |
167 | if ( str.find('`') == std::string::npos ) | |
168 | str = std::string("`") + str + "`"; | |
169 | } | |
170 | contents += str; | |
171 | //std::cout << "DATA: " << node->name() << "=" << node->value() << std::endl; | |
172 | } | |
173 | else | |
174 | { | |
175 | //std::cout << "OTHER: " << node->name() << "=" << node->value() << std::endl; | |
176 | } | |
177 | ||
178 | parse_para(node->first_node(), config, contents, skip, false, tb); | |
179 | parse_para(node->next_sibling(), config, contents, skip, false, tb); | |
180 | } | |
181 | } | |
182 | ||
183 | ||
184 | static void parse_parameter(rapidxml::xml_node<>* node, configuration const& config, parameter& p) | |
185 | { | |
186 | // #define: <param><defname>Point</defname></param> | |
187 | // template: <param><type>typename</type><declname>CoordinateType</declname><defname>CoordinateType</defname></param> | |
188 | // template with default: <param><type>typename</type><declname>CoordinateSystem</declname><defname>CoordinateSystem</defname><defval><ref ....>cs::cartesian</ref></defval></param> | |
189 | // with enum: <type><ref refid="group__enum_1ga7d33eca9a5389952bdf719972eb802b6" kindref="member">closure_selector</ref></type> | |
190 | if (node != NULL) | |
191 | { | |
192 | std::string name = node->name(); | |
193 | if (name == "type") | |
194 | { | |
195 | get_contents(node->first_node(), p.fulltype); | |
196 | p.type = p.fulltype; | |
197 | boost::replace_all(p.type, " const", ""); | |
198 | boost::trim(p.type); | |
199 | boost::replace_all(p.type, "&", ""); | |
200 | boost::replace_all(p.type, "*", ""); | |
201 | boost::trim(p.type); | |
202 | ||
203 | // If alt output is used retrieve type with QBK links | |
204 | if ( configuration::alt == config.output_style ) | |
205 | { | |
206 | p.fulltype_without_links = p.fulltype; | |
207 | p.fulltype.clear(); | |
208 | parse_para(node->first_node(), config, p.fulltype, p.skip); | |
209 | } | |
210 | } | |
211 | else if (name == "declname") p.name = node->value(); | |
212 | else if (name == "parametername") p.name = node->value(); | |
213 | else if (name == "defname") p.name = node->value(); | |
214 | else if (name == "defval") | |
215 | { | |
216 | parse_para(node, config, p.default_value, p.skip); | |
217 | } | |
218 | else if (name == "para") | |
219 | { | |
220 | parse_para(node, config, p.brief_description, p.skip); | |
221 | } | |
222 | ||
223 | parse_parameter(node->first_node(), config, p); | |
224 | parse_parameter(node->next_sibling(), config, p); | |
225 | } | |
226 | } | |
227 | ||
228 | static void parse_enumeration_value(rapidxml::xml_node<>* node, configuration const& config, enumeration_value& value) | |
229 | { | |
230 | // <enumvalue><name>green</name><initializer> 2</initializer> | |
231 | // <briefdescription><para>...</para></briefdescription> | |
232 | // <detaileddescription><para>...</para></detaileddescription> | |
233 | // </enumvalue> | |
234 | if (node != NULL) | |
235 | { | |
236 | std::string node_name = node->name(); | |
237 | ||
238 | if (node_name == "name") value.name = node->value(); | |
239 | else if (node_name == "para") | |
240 | { | |
241 | // Parses both brief AND detailed into this description | |
242 | parse_para(node, config, value.brief_description, value.skip); | |
243 | } | |
244 | else if (node_name == "initializer") | |
245 | { | |
246 | value.initializer = node->value(); | |
247 | } | |
248 | ||
249 | parse_enumeration_value(node->first_node(), config, value); | |
250 | parse_enumeration_value(node->next_sibling(), config, value); | |
251 | } | |
252 | } | |
253 | ||
254 | // Definition is a function or a class/struct | |
255 | template <typename Parameters> | |
256 | static void parse_parameter_list(rapidxml::xml_node<>* node, configuration const& config, Parameters& parameters) | |
257 | { | |
258 | if (node != NULL) | |
259 | { | |
260 | std::string name = node->name(); | |
261 | ||
262 | if (name == "parameteritem") | |
263 | { | |
264 | parameter p; | |
265 | parse_parameter(node->first_node(), config, p); | |
266 | if (! p.name.empty()) | |
267 | { | |
268 | // Copy its description | |
269 | std::vector<parameter>::iterator it = std::find_if(parameters.begin(), | |
270 | parameters.end(), par_by_name(p.name)); | |
271 | if (it != parameters.end()) | |
272 | { | |
273 | it->brief_description = p.brief_description; | |
274 | } | |
275 | else | |
276 | { | |
277 | parameters.push_back(p); | |
278 | } | |
279 | } | |
280 | } | |
281 | else if (name == "param") | |
282 | { | |
283 | // Element of 'templateparamlist.param (.type,.declname,.defname)' | |
284 | parameter p; | |
285 | parse_parameter(node->first_node(), config, p); | |
286 | ||
287 | // Doxygen handles templateparamlist param's differently: | |
288 | // | |
289 | // Case 1: | |
290 | // <param><type>typename T</type></param> | |
291 | // -> no name, assign type to name, replace typename | |
292 | // | |
293 | // Case 2: | |
294 | // <type>typename</type><declname>T</declname><defname>T</defname> | |
295 | // -> set full type | |
296 | if (p.name.empty()) | |
297 | { | |
298 | // Case 1 | |
299 | p.name = p.type; | |
300 | boost::replace_all(p.name, "typename", ""); | |
301 | boost::trim(p.name); | |
302 | } | |
303 | else | |
304 | { | |
305 | // Case 2 | |
306 | p.fulltype = p.type + " " + p.name; | |
307 | } | |
308 | ||
309 | add_or_set(parameters, p); | |
310 | } | |
311 | ||
312 | parse_parameter_list(node->first_node(), config, parameters); | |
313 | parse_parameter_list(node->next_sibling(), config, parameters); | |
314 | } | |
315 | } | |
316 | ||
317 | static void copy_string_property(std::string const& source, std::string& target) | |
318 | { | |
319 | if (target.empty()) | |
320 | { | |
321 | target = source; | |
322 | } | |
323 | } | |
324 | ||
325 | ||
326 | template <typename Parameters> | |
327 | static void copy_parameter_properties(parameter const& source, Parameters& target) | |
328 | { | |
329 | BOOST_FOREACH(parameter& t, target) | |
330 | { | |
331 | if (source.name == t.name) | |
332 | { | |
333 | t.skip = source.skip; | |
334 | copy_string_property(source.brief_description, t.brief_description); | |
335 | copy_string_property(source.type, t.type); | |
336 | copy_string_property(source.default_value, t.default_value); | |
337 | copy_string_property(source.fulltype, t.fulltype); | |
338 | ||
339 | return; | |
340 | } | |
341 | } | |
342 | // If not found, write a warning | |
343 | std::cerr << "Parameter not found: " << source.name << std::endl; | |
344 | } | |
345 | ||
346 | ||
347 | template <typename Parameters> | |
348 | static void copy_parameters_properties(Parameters const& source, Parameters& target) | |
349 | { | |
350 | BOOST_FOREACH(parameter const& s, source) | |
351 | { | |
352 | copy_parameter_properties(s, target); | |
353 | } | |
354 | } | |
355 | ||
356 | ||
357 | ||
358 | template <typename Element> | |
359 | static void parse_element(rapidxml::xml_node<>* node, configuration const& config, std::string const& parent, Element& el) | |
360 | { | |
361 | if (node != NULL) | |
362 | { | |
363 | std::string name = node->name(); | |
364 | std::string full = parent + "." + name; | |
365 | ||
366 | if (full == ".briefdescription.para") | |
367 | { | |
368 | parse_para(node, config, el.brief_description, el.skip); | |
369 | } | |
370 | else if (full == ".detaileddescription.para") | |
371 | { | |
372 | std::string para; | |
373 | parse_para(node, config, para, el.skip); | |
374 | if (!para.empty() && !el.detailed_description.empty()) | |
375 | { | |
376 | el.detailed_description += "\n\n"; | |
377 | } | |
378 | el.detailed_description += para; | |
379 | } | |
380 | else if (full == ".location") | |
381 | { | |
382 | std::string loc = get_attribute(node, "file"); | |
383 | // Location of (header)file. It is a FULL path, so find the start | |
384 | // and strip the rest | |
385 | std::size_t pos = loc.rfind(config.start_include); | |
386 | if (pos != std::string::npos) | |
387 | { | |
388 | loc = loc.substr(pos); | |
389 | } | |
390 | el.location = loc; | |
391 | el.line = atol(get_attribute(node, "line").c_str()); | |
392 | } | |
393 | else if (full == ".detaileddescription.para.qbk") | |
394 | { | |
395 | el.qbk_markup.push_back(markup(node->value())); | |
396 | } | |
397 | else if (full == ".detaileddescription.para.qbk.after.synopsis") | |
398 | { | |
399 | el.qbk_markup.push_back(markup(markup_after, markup_synopsis, node->value())); | |
400 | } | |
401 | else if (full == ".detaileddescription.para.qbk.before.synopsis") | |
402 | { | |
403 | el.qbk_markup.push_back(markup(markup_before, markup_synopsis, node->value())); | |
404 | } | |
405 | else if (full == ".detaileddescription.para.qbk.distinguish") | |
406 | { | |
407 | el.additional_description = node->value(); | |
408 | boost::trim(el.additional_description); | |
409 | } | |
410 | else if (full == ".templateparamlist") | |
411 | { | |
412 | parse_parameter_list(node->first_node(), config, el.template_parameters); | |
413 | } | |
414 | else if (full == ".detaileddescription.para.parameterlist") | |
415 | { | |
416 | std::string kind = get_attribute(node, "kind"); | |
417 | if (kind == "param") | |
418 | { | |
419 | // Parse parameters and their descriptions. | |
420 | // NOTE: they are listed here, but the order might not be the order in the function call | |
421 | std::vector<parameter> parameters; | |
422 | parse_parameter_list(node->first_node(), config, parameters); | |
423 | copy_parameters_properties(parameters, el.parameters); | |
424 | } | |
425 | else if (kind == "templateparam") | |
426 | { | |
427 | parse_parameter_list(node->first_node(), config, el.template_parameters); | |
428 | } | |
429 | } | |
430 | else if (full == ".detaileddescription.para.simplesect") | |
431 | { | |
432 | std::string kind = get_attribute(node, "kind"); | |
433 | if (kind == "par") | |
434 | { | |
435 | paragraph p; | |
436 | ||
437 | rapidxml::xml_node<> * title_node = node->first_node("title"); | |
438 | if ( title_node ) | |
439 | p.title = title_node->value(); | |
440 | ||
441 | parse_para(node->first_node("para"), config, p.text, el.skip); | |
442 | ||
443 | el.paragraphs.push_back(p); | |
444 | } | |
445 | else if (kind == "warning") | |
446 | { | |
447 | parse_para(node->first_node("para"), config, el.warning, el.skip); | |
448 | } | |
449 | else if (kind == "note") | |
450 | { | |
451 | parse_para(node->first_node("para"), config, el.note, el.skip); | |
452 | } | |
453 | } | |
454 | else if (full == ".param") | |
455 | { | |
456 | // Parse one parameter, and add it to el.parameters | |
457 | parameter p; | |
458 | parse_parameter(node->first_node(), config, p); | |
459 | el.parameters.push_back(p); | |
460 | } | |
461 | ||
462 | ||
463 | parse_element(node->first_node(), config, full, el); | |
464 | parse_element(node->next_sibling(), config, parent, el); | |
465 | } | |
466 | } | |
467 | ||
468 | static void parse_function(rapidxml::xml_node<>* node, configuration const& config, std::string const& parent, function& f) | |
469 | { | |
470 | if (node != NULL) | |
471 | { | |
472 | std::string name = node->name(); | |
473 | std::string full = parent + "." + name; | |
474 | ||
475 | if (full == ".name") f.name = node->value(); | |
476 | else if (full == ".argsstring") f.argsstring = node->value(); | |
477 | else if (full == ".definition") | |
478 | { | |
479 | f.definition = node->value(); | |
480 | if (! config.skip_namespace.empty()) | |
481 | { | |
482 | boost::replace_all(f.definition, config.skip_namespace, ""); | |
483 | } | |
484 | } | |
485 | else if (full == ".param") | |
486 | { | |
487 | parameter p; | |
488 | parse_parameter(node->first_node(), config, p); | |
489 | add_or_set(f.parameters, p); | |
490 | } | |
491 | else if (full == ".type") | |
492 | { | |
493 | get_contents(node->first_node(), f.return_type); | |
494 | ||
495 | // If alt output is used, retrieve return type with links | |
496 | if ( configuration::alt == config.output_style ) | |
497 | { | |
498 | f.return_type_without_links = f.return_type; | |
499 | bool dummy_skip; | |
500 | f.return_type.clear(); | |
501 | parse_para(node->first_node(), config, f.return_type, dummy_skip); | |
502 | } | |
503 | } | |
504 | else if (full == ".detaileddescription.para.simplesect") | |
505 | { | |
506 | std::string kind = get_attribute(node, "kind"); | |
507 | if (kind == "return") | |
508 | { | |
509 | parse_para(node->first_node(), config, f.return_description, f.skip); | |
510 | } | |
511 | /*else if (kind == "param") | |
512 | { | |
513 | get_contents(node->first_node(), f.paragraphs); | |
514 | }*/ | |
515 | else if (kind == "pre") | |
516 | { | |
517 | parse_para(node->first_node(), config, f.precondition, f.skip); | |
518 | } | |
519 | } | |
520 | else if (full == ".detaileddescription.para.image") | |
521 | { | |
522 | } | |
523 | ||
524 | parse_function(node->first_node(), config, full, f); | |
525 | parse_function(node->next_sibling(), config, parent, f); | |
526 | } | |
527 | } | |
528 | ||
529 | static void parse_enumeration(rapidxml::xml_node<>* node, configuration const& config, std::string const& parent, enumeration& e) | |
530 | { | |
531 | if (node != NULL) | |
532 | { | |
533 | std::string name = node->name(); | |
534 | std::string full = parent + "." + name; | |
535 | ||
536 | if (full == ".name") e.name = node->value(); | |
537 | else if (full == ".enumvalue") | |
538 | { | |
539 | enumeration_value value; | |
540 | parse_enumeration_value(node->first_node(), config, value); | |
541 | e.enumeration_values.push_back(value); | |
542 | } | |
543 | ||
544 | parse_enumeration(node->first_node(), config, full, e); | |
545 | parse_enumeration(node->next_sibling(), config, parent, e); | |
546 | } | |
547 | } | |
548 | ||
549 | ||
550 | static std::string parse_named_node(rapidxml::xml_node<>* node, std::string const& look_for_name) | |
551 | { | |
552 | if (node != NULL) | |
553 | { | |
554 | std::string node_name = node->name(); | |
555 | std::string contents; | |
556 | ||
557 | if (boost::equals(node_name, look_for_name)) | |
558 | { | |
559 | contents = node->value(); | |
560 | } | |
561 | ||
562 | return contents | |
563 | + parse_named_node(node->first_node(), look_for_name) | |
564 | + parse_named_node(node->next_sibling(), look_for_name); | |
565 | } | |
566 | return ""; | |
567 | } | |
568 | ||
569 | ||
570 | ||
571 | ||
572 | static void parse(rapidxml::xml_node<>* node, configuration const& config, documentation& doc, bool member = false) | |
573 | { | |
574 | if (node != NULL) | |
575 | { | |
576 | bool recurse = false; | |
577 | bool is_member = member; | |
578 | ||
579 | std::string nodename = node->name(); | |
580 | ||
581 | if (nodename == "doxygen") | |
582 | { | |
583 | recurse = true; | |
584 | } | |
585 | else if (nodename == "sectiondef") | |
586 | { | |
587 | std::string kind = get_attribute(node, "kind"); | |
588 | ||
589 | if (kind == "func" | |
590 | || kind == "define" | |
591 | || kind == "enum" | |
592 | ) | |
593 | { | |
594 | recurse = true; | |
595 | } | |
596 | else if (boost::starts_with(kind, "public")) | |
597 | { | |
598 | recurse = true; | |
599 | is_member = true; | |
600 | } | |
601 | } | |
602 | else if (nodename == "compounddef") | |
603 | { | |
604 | std::string kind = get_attribute(node, "kind"); | |
605 | std::string id = get_attribute(node, "id"); | |
606 | if (kind == "group") | |
607 | { | |
608 | recurse = true; | |
609 | doc.group_id = id; | |
610 | rapidxml::xml_node<> * n = node->first_node("title"); | |
611 | if ( n ) | |
612 | doc.group_title = n->value(); | |
613 | } | |
614 | else if (kind == "struct") | |
615 | { | |
616 | recurse = true; | |
617 | doc.cos.is_class = false; | |
618 | doc.cos.id = id; | |
619 | parse_element(node->first_node(), config, "", doc.cos); | |
620 | } | |
621 | else if (kind == "class") | |
622 | { | |
623 | recurse = true; | |
624 | doc.cos.is_class = true; | |
625 | doc.cos.id = id; | |
626 | parse_element(node->first_node(), config, "", doc.cos); | |
627 | } | |
628 | } | |
629 | else if (nodename == "memberdef") | |
630 | { | |
631 | std::string kind = get_attribute(node, "kind"); | |
632 | std::string id = get_attribute(node, "id"); | |
633 | ||
634 | if (kind == "function") | |
635 | { | |
636 | function f; | |
637 | f.id = id; | |
638 | f.is_static = get_attribute(node, "static") == "yes" ? true : false; | |
639 | f.is_const = get_attribute(node, "const") == "yes" ? true : false; | |
640 | f.is_explicit = get_attribute(node, "explicit") == "yes" ? true : false; | |
641 | f.is_virtual = get_attribute(node, "virt") == "virtual" ? true : false; | |
642 | ||
643 | parse_element(node->first_node(), config, "", f); | |
644 | parse_function(node->first_node(), config, "", f); | |
645 | ||
646 | if (member) | |
647 | { | |
648 | bool c_or_d = boost::equals(f.name, doc.cos.name) || | |
649 | boost::equals(f.name, std::string("~") + doc.cos.name); | |
650 | ||
651 | f.type = c_or_d | |
652 | ? function_constructor_destructor | |
653 | : function_member; | |
654 | doc.cos.functions.push_back(f); | |
655 | } | |
656 | else | |
657 | { | |
658 | f.type = function_free; | |
659 | doc.functions.push_back(f); | |
660 | } | |
661 | } | |
662 | else if (kind == "define") | |
663 | { | |
664 | function f; | |
665 | f.id = id; | |
666 | f.type = function_define; | |
667 | parse_element(node->first_node(), config, "", f); | |
668 | parse_function(node->first_node(), config, "", f); | |
669 | doc.defines.push_back(f); | |
670 | } | |
671 | else if (kind == "enum") | |
672 | { | |
673 | enumeration e; | |
674 | e.id = id; | |
675 | parse_element(node->first_node(), config, "", e); | |
676 | parse_enumeration(node->first_node(), config, "", e); | |
677 | doc.enumerations.push_back(e); | |
678 | } | |
679 | else if (kind == "typedef") | |
680 | { | |
681 | if (boost::equals(get_attribute(node, "prot"), "public")) | |
682 | { | |
683 | std::string name = parse_named_node(node->first_node(), "name"); | |
684 | doc.cos.typedefs.push_back(base_element(name)); | |
685 | doc.cos.typedefs.back().id = id; | |
686 | ||
687 | element dummy; | |
688 | parse_element(node->first_node(), config, "", dummy); | |
689 | doc.cos.typedefs.back().brief_description = dummy.brief_description; | |
690 | } | |
691 | } | |
692 | else if (kind == "variable") | |
693 | { | |
694 | if (boost::equals(get_attribute(node, "prot"), "public")) | |
695 | { | |
696 | parameter p; | |
697 | p.id = id; | |
698 | for(rapidxml::xml_node<>* var_node = node->first_node(); var_node; var_node=var_node->next_sibling()) | |
699 | { | |
700 | if(boost::equals(var_node->name(), "name")) | |
701 | { | |
702 | p.name = var_node->value(); | |
703 | } | |
704 | else if(boost::equals(var_node->name(), "type")) | |
705 | { | |
706 | get_contents(var_node->first_node(), p.fulltype); | |
707 | p.type = p.fulltype; | |
708 | //boost::replace_all(p.type, " const", ""); | |
709 | //boost::trim(p.type); | |
710 | //boost::replace_all(p.type, "&", ""); | |
711 | //boost::replace_all(p.type, "*", ""); | |
712 | boost::trim(p.type); | |
713 | ||
714 | // If alt output is used retrieve type with QBK links | |
715 | if ( configuration::alt == config.output_style ) | |
716 | { | |
717 | p.fulltype_without_links = p.fulltype; | |
718 | p.fulltype.clear(); | |
719 | parse_para(var_node->first_node(), config, p.fulltype, p.skip); | |
720 | } | |
721 | } | |
722 | else if(boost::equals(var_node->name(), "briefdescription")) | |
723 | { | |
724 | parse_para(var_node->first_node(), config, p.brief_description, p.skip); | |
725 | } | |
726 | else if(p.brief_description.empty() && boost::equals(var_node->name(), "detaileddescription")) | |
727 | { | |
728 | parse_para(var_node->first_node(), config, p.brief_description, p.skip); | |
729 | } | |
730 | } | |
731 | doc.cos.variables.push_back(p); | |
732 | } | |
733 | } | |
734 | ||
735 | } | |
736 | else if (nodename == "compoundname") | |
737 | { | |
738 | std::string name = node->value(); | |
739 | if (name.find("::") != std::string::npos) | |
740 | { | |
741 | doc.cos.fullname = name; | |
742 | ||
743 | // For a class, it should have "boost::something::" before | |
744 | // set its name without namespace | |
745 | doc.cos.name = keep_after(name, "::"); | |
746 | } | |
747 | } | |
748 | else if (nodename == "basecompoundref") | |
749 | { | |
750 | base_class bc; | |
751 | bc.name = node->value(); | |
752 | bc.derivation = get_attribute(node, "prot"); | |
753 | bc.virtuality = get_attribute(node, "virt"); | |
754 | doc.cos.base_classes.push_back(bc); | |
755 | } | |
756 | else | |
757 | { | |
758 | //std::cout << nodename << " ignored." << std::endl; | |
759 | } | |
760 | ||
761 | ||
762 | if (recurse) | |
763 | { | |
764 | // First recurse into childnodes, then handle next siblings | |
765 | parse(node->first_node(), config, doc, is_member); | |
766 | } | |
767 | parse(node->next_sibling(), config, doc, is_member); | |
768 | } | |
769 | } | |
770 | ||
771 | #endif // DOXYGEN_XML_PARSER_HPP |