Doxygen
Loading...
Searching...
No Matches
searchindex_js.cpp File Reference
#include "searchindex_js.h"
#include <algorithm>
#include <utility>
#include "classdef.h"
#include "classlist.h"
#include "conceptdef.h"
#include "docparser.h"
#include "doxygen.h"
#include "filename.h"
#include "groupdef.h"
#include "indexlist.h"
#include "language.h"
#include "membername.h"
#include "message.h"
#include "moduledef.h"
#include "namespacedef.h"
#include "pagedef.h"
#include "portable.h"
#include "resourcemgr.h"
#include "section.h"
#include "textstream.h"
#include "threadpool.h"
#include "util.h"
Include dependency graph for searchindex_js.cpp:

Go to the source code of this file.

Macros

#define SEARCH_INDEX_ALL   0
#define SEARCH_INDEX_CLASSES   1
#define SEARCH_INDEX_INTERFACES   2
#define SEARCH_INDEX_STRUCTS   3
#define SEARCH_INDEX_EXCEPTIONS   4
#define SEARCH_INDEX_NAMESPACES   5
#define SEARCH_INDEX_FILES   6
#define SEARCH_INDEX_FUNCTIONS   7
#define SEARCH_INDEX_VARIABLES   8
#define SEARCH_INDEX_TYPEDEFS   9
#define SEARCH_INDEX_SEQUENCES   10
#define SEARCH_INDEX_DICTIONARIES   11
#define SEARCH_INDEX_ENUMS   12
#define SEARCH_INDEX_ENUMVALUES   13
#define SEARCH_INDEX_PROPERTIES   14
#define SEARCH_INDEX_EVENTS   15
#define SEARCH_INDEX_RELATED   16
#define SEARCH_INDEX_DEFINES   17
#define SEARCH_INDEX_GROUPS   18
#define SEARCH_INDEX_PAGES   19
#define SEARCH_INDEX_CONCEPTS   20
#define SEARCH_INDEX_MODULES   21

Functions

static void splitSearchTokens (DString &title, SizeVector &indices)
static void addMemberToSearchIndex (const MemberDef *md)
void createJavaScriptSearchIndex ()
static void writeJavascriptSearchData (const DString &searchDirName)
static void writeJavasScriptSearchDataPage (const DString &baseName, const DString &dataFileName, const SearchIndexList &list)
void writeJavaScriptSearchIndex ()
const std::array< SearchIndexInfo, NUM_SEARCH_INDICES > & getSearchIndices ()

Variables

static std::array< SearchIndexInfo, NUM_SEARCH_INDICESg_searchIndexInfo

Macro Definition Documentation

◆ SEARCH_INDEX_ALL

#define SEARCH_INDEX_ALL   0

Definition at line 162 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex(), and createJavaScriptSearchIndex().

◆ SEARCH_INDEX_CLASSES

#define SEARCH_INDEX_CLASSES   1

Definition at line 163 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_CONCEPTS

#define SEARCH_INDEX_CONCEPTS   20

Definition at line 182 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_DEFINES

#define SEARCH_INDEX_DEFINES   17

Definition at line 179 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_DICTIONARIES

#define SEARCH_INDEX_DICTIONARIES   11

Definition at line 173 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_ENUMS

#define SEARCH_INDEX_ENUMS   12

Definition at line 174 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_ENUMVALUES

#define SEARCH_INDEX_ENUMVALUES   13

Definition at line 175 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_EVENTS

#define SEARCH_INDEX_EVENTS   15

Definition at line 177 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_EXCEPTIONS

#define SEARCH_INDEX_EXCEPTIONS   4

Definition at line 166 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_FILES

#define SEARCH_INDEX_FILES   6

Definition at line 168 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_FUNCTIONS

#define SEARCH_INDEX_FUNCTIONS   7

Definition at line 169 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_GROUPS

#define SEARCH_INDEX_GROUPS   18

Definition at line 180 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_INTERFACES

#define SEARCH_INDEX_INTERFACES   2

Definition at line 164 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_MODULES

#define SEARCH_INDEX_MODULES   21

Definition at line 183 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_NAMESPACES

#define SEARCH_INDEX_NAMESPACES   5

Definition at line 167 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_PAGES

#define SEARCH_INDEX_PAGES   19

Definition at line 181 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_PROPERTIES

#define SEARCH_INDEX_PROPERTIES   14

Definition at line 176 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_RELATED

#define SEARCH_INDEX_RELATED   16

Definition at line 178 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_SEQUENCES

#define SEARCH_INDEX_SEQUENCES   10

Definition at line 172 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_STRUCTS

#define SEARCH_INDEX_STRUCTS   3

Definition at line 165 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_TYPEDEFS

#define SEARCH_INDEX_TYPEDEFS   9

Definition at line 171 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_VARIABLES

#define SEARCH_INDEX_VARIABLES   8

Definition at line 170 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

Function Documentation

◆ addMemberToSearchIndex()

void addMemberToSearchIndex ( const MemberDef * md)
static

Definition at line 218 of file searchindex_js.cpp.

219{
220 bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
221 bool isLinkable = md->isLinkable();
222 const ClassDef *cd=nullptr;
223 const NamespaceDef *nd=nullptr;
224 const FileDef *fd=nullptr;
225 const GroupDef *gd=nullptr;
226 if (isLinkable &&
227 (
228 ((cd=md->getClassDef()) && cd->isLinkable() && !cd->isImplicitTemplateInstance()) ||
229 ((gd=md->getGroupDef()) && gd->isLinkable())
230 )
231 )
232 {
233 const DString &n = md->name();
234 if (!n.empty())
235 {
236 bool isFriendToHide = hideFriendCompounds && isTypeAClassFriend(md->typeString());
237 if (!(md->isFriend() && isFriendToHide))
238 {
240 }
241 if (md->isFunction() || md->isSlot() || md->isSignal())
242 {
244 }
245 else if (md->isVariable())
246 {
248 }
249 else if (md->isSequence())
250 {
252 }
253 else if (md->isDictionary())
254 {
256 }
257 else if (md->isTypedef())
258 {
260 }
261 else if (md->isEnumerate())
262 {
264 }
265 else if (md->isEnumValue())
266 {
268 }
269 else if (md->isProperty())
270 {
272 }
273 else if (md->isEvent())
274 {
276 }
277 else if (md->isRelated() || md->isForeign() ||
278 (md->isFriend() && !isFriendToHide))
279 {
281 }
282 }
283 }
284 else if (isLinkable &&
285 (((nd=md->getNamespaceDef()) && nd->isLinkable()) ||
286 ((fd=md->getFileDef()) && fd->isLinkable())
287 )
288 )
289 {
290 const DString &n = md->name();
291 if (!n.empty())
292 {
294
295 if (md->isFunction())
296 {
298 }
299 else if (md->isVariable())
300 {
302 }
303 else if (md->isSequence())
304 {
306 }
307 else if (md->isDictionary())
308 {
310 }
311 else if (md->isTypedef())
312 {
314 }
315 else if (md->isEnumerate())
316 {
318 }
319 else if (md->isEnumValue())
320 {
322 }
323 else if (md->isDefine())
324 {
326 }
327 }
328 }
329}
A abstract class representing of a compound symbol.
Definition classdef.h:100
virtual bool isImplicitTemplateInstance() const =0
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
virtual bool isLinkable() const =0
virtual const DString & name() const =0
A model of a file symbol.
Definition filedef.h:97
A model of a group of symbols.
Definition groupdef.h:48
virtual bool isSignal() const =0
virtual bool isFriend() const =0
virtual bool isForeign() const =0
virtual bool isRelated() const =0
virtual bool isSequence() const =0
virtual const ClassDef * getClassDef() const =0
virtual GroupDef * getGroupDef()=0
virtual bool isTypedef() const =0
virtual bool isSlot() const =0
virtual const FileDef * getFileDef() const =0
virtual bool isEvent() const =0
virtual bool isFunction() const =0
virtual bool isDictionary() const =0
virtual bool isDefine() const =0
virtual const NamespaceDef * getNamespaceDef() const =0
virtual bool isEnumerate() const =0
virtual bool isVariable() const =0
virtual DString typeString() const =0
virtual bool isEnumValue() const =0
virtual bool isProperty() const =0
An abstract interface of a namespace symbol.
#define Config_getBool(name)
Definition config.h:33
#define SEARCH_INDEX_TYPEDEFS
#define SEARCH_INDEX_EVENTS
static std::array< SearchIndexInfo, NUM_SEARCH_INDICES > g_searchIndexInfo
#define SEARCH_INDEX_DEFINES
#define SEARCH_INDEX_ENUMS
#define SEARCH_INDEX_DICTIONARIES
#define SEARCH_INDEX_ALL
#define SEARCH_INDEX_SEQUENCES
#define SEARCH_INDEX_PROPERTIES
#define SEARCH_INDEX_ENUMVALUES
#define SEARCH_INDEX_FUNCTIONS
#define SEARCH_INDEX_VARIABLES
#define SEARCH_INDEX_RELATED
Searchable term.
bool isTypeAClassFriend(const DString &type)
Definition types.h:920

References Config_getBool, DString::empty(), g_searchIndexInfo, MemberDef::getClassDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), MemberDef::getNamespaceDef(), MemberDef::isDefine(), MemberDef::isDictionary(), MemberDef::isEnumerate(), MemberDef::isEnumValue(), MemberDef::isEvent(), MemberDef::isForeign(), MemberDef::isFriend(), MemberDef::isFunction(), ClassDef::isImplicitTemplateInstance(), Definition::isLinkable(), MemberDef::isProperty(), MemberDef::isRelated(), MemberDef::isSequence(), MemberDef::isSignal(), MemberDef::isSlot(), isTypeAClassFriend(), MemberDef::isTypedef(), MemberDef::isVariable(), Definition::name(), SEARCH_INDEX_ALL, SEARCH_INDEX_DEFINES, SEARCH_INDEX_DICTIONARIES, SEARCH_INDEX_ENUMS, SEARCH_INDEX_ENUMVALUES, SEARCH_INDEX_EVENTS, SEARCH_INDEX_FUNCTIONS, SEARCH_INDEX_PROPERTIES, SEARCH_INDEX_RELATED, SEARCH_INDEX_SEQUENCES, SEARCH_INDEX_TYPEDEFS, SEARCH_INDEX_VARIABLES, and MemberDef::typeString().

Referenced by createJavaScriptSearchIndex().

◆ createJavaScriptSearchIndex()

void createJavaScriptSearchIndex ( )

Definition at line 333 of file searchindex_js.cpp.

334{
335 // index classes
336 for (const auto &cd : *Doxygen::classLinkedMap)
337 {
338 if (cd->isLinkable())
339 {
340 DString n = cd->localName();
342 if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
343 {
344 if (cd->compoundType()==ClassDef::Interface)
345 {
347 }
348 else if (cd->compoundType()==ClassDef::Struct)
349 {
351 }
352 else if (cd->compoundType()==ClassDef::Exception)
353 {
355 }
356 else // cd->compoundType()==ClassDef::Class
357 {
359 }
360 }
361 else // non slice optimization: group all types under classes
362 {
364 }
365 }
366 }
367
368 // index namespaces
369 for (const auto &nd : *Doxygen::namespaceLinkedMap)
370 {
371 if (nd->isLinkable())
372 {
373 DString n = nd->name();
376 }
377 }
378
379 // index concepts
380 for (const auto &cd : *Doxygen::conceptLinkedMap)
381 {
382 if (cd->isLinkable())
383 {
384 DString n = cd->localName();
387 }
388 }
389
390 // index modules
391 for (const auto &mod : ModuleManager::instance().modules())
392 {
393 if (mod->isLinkable() && mod->isPrimaryInterface())
394 {
395 DString n = mod->name();
398 }
399 }
400
401 // index files
402 for (const auto &fn : *Doxygen::inputNameLinkedMap)
403 {
404 for (const auto &fd : *fn)
405 {
406 DString n = fd->name();
407 if (fd->isLinkable())
408 {
411 }
412 }
413 }
414
415 // index class members
416 {
417 // for each member name
418 for (const auto &mn : *Doxygen::memberNameLinkedMap)
419 {
420 // for each member definition
421 for (const auto &md : *mn)
422 {
423 addMemberToSearchIndex(md.get());
424 }
425 }
426 }
427
428 // index file/namespace members
429 {
430 // for each member name
431 for (const auto &mn : *Doxygen::functionNameLinkedMap)
432 {
433 // for each member definition
434 for (const auto &md : *mn)
435 {
436 addMemberToSearchIndex(md.get());
437 }
438 }
439 }
440
441 // index groups
442 for (const auto &gd : *Doxygen::groupLinkedMap)
443 {
444 if (gd->isLinkable())
445 {
446 DString title(filterTitle(gd->groupTitle()).str());
447 SizeVector tokenIndices;
448 splitSearchTokens(title,tokenIndices);
449 for (size_t index : tokenIndices)
450 {
451 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),gd.get()));
452 g_searchIndexInfo[SEARCH_INDEX_GROUPS].add(SearchTerm(title.mid(index),gd.get()));
453 }
454 }
455 }
456
457 // index pages
458 for (const auto &pd : *Doxygen::pageLinkedMap)
459 {
460 if (pd->isLinkable())
461 {
462 DString title(filterTitle(pd->title()).str());
463 SizeVector tokenIndices;
464 splitSearchTokens(title,tokenIndices);
465 for (size_t index : tokenIndices)
466 {
467 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),pd.get()));
468 g_searchIndexInfo[SEARCH_INDEX_PAGES].add(SearchTerm(title.mid(index),pd.get()));
469 }
470 }
471 }
472
473 // main page
475 {
476 DString title(filterTitle(Doxygen::mainPage->title()).str());
477 SizeVector tokenIndices;
478 splitSearchTokens(title,tokenIndices);
479 for (size_t index : tokenIndices)
480 {
483 }
484 }
485
486 // sections
487 const auto &sm = SectionManager::instance();
488 for (const auto &sectionInfo : sm)
489 {
490 if (sectionInfo->level()>0) // level 0 is for page titles
491 {
492 DString title = filterTitle(sectionInfo->title());
493 SizeVector tokenIndices;
494 splitSearchTokens(title,tokenIndices);
495 //printf("split(%s)=(%s) %zu\n",qPrint(sectionInfo->title()),qPrint(title),tokenIndices.size());
496 for (size_t index : tokenIndices)
497 {
498 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),sectionInfo.get()));
499 g_searchIndexInfo[SEARCH_INDEX_PAGES].add(SearchTerm(title.mid(index),sectionInfo.get()));
500 }
501 }
502 }
503
504 // sort all lists
505 for (auto &sii : g_searchIndexInfo) // for each index
506 {
507 for (auto &[name,symList] : sii.symbolMap) // for each symbol in the index
508 {
509 // sort the symbols (first on search term, and then on full name)
510 //
511 // `std::stable_sort` is used here due to reproducibility issues
512 // on key collisions
513 // https://github.com/doxygen/doxygen/issues/10445
514 std::stable_sort(symList.begin(),
515 symList.end(),
516 [](const auto &t1,const auto &t2)
517 {
518 int eq = dstricmp_sort(t1.word,t2.word); // search term first
519 return eq==0 ? dstricmp_sort(t1.title,t2.title)<0 : eq<0; // then full title
520 });
521 }
522 }
523}
@ Interface
Definition classdef.h:108
@ Exception
Definition classdef.h:111
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
const std::string & str() const
Definition dstring.h:645
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:108
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:90
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:93
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:97
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:88
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:105
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:92
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:104
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:107
static ModuleManager & instance()
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
std::vector< size_t > SizeVector
Definition containers.h:39
static void addMemberToSearchIndex(const MemberDef *md)
#define SEARCH_INDEX_STRUCTS
#define SEARCH_INDEX_NAMESPACES
#define SEARCH_INDEX_CONCEPTS
#define SEARCH_INDEX_FILES
#define SEARCH_INDEX_PAGES
#define SEARCH_INDEX_GROUPS
#define SEARCH_INDEX_INTERFACES
static void splitSearchTokens(DString &title, SizeVector &indices)
#define SEARCH_INDEX_MODULES
#define SEARCH_INDEX_CLASSES
#define SEARCH_INDEX_EXCEPTIONS
DString filterTitle(const DString &title)
Definition util.cpp:4454

References addMemberToSearchIndex(), Doxygen::classLinkedMap, Doxygen::conceptLinkedMap, Config_getBool, ClassDef::Exception, filterTitle(), Doxygen::functionNameLinkedMap, g_searchIndexInfo, Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), SectionManager::instance(), ClassDef::Interface, Doxygen::mainPage, Doxygen::memberNameLinkedMap, DString::mid(), Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, SEARCH_INDEX_ALL, SEARCH_INDEX_CLASSES, SEARCH_INDEX_CONCEPTS, SEARCH_INDEX_EXCEPTIONS, SEARCH_INDEX_FILES, SEARCH_INDEX_GROUPS, SEARCH_INDEX_INTERFACES, SEARCH_INDEX_MODULES, SEARCH_INDEX_NAMESPACES, SEARCH_INDEX_PAGES, SEARCH_INDEX_STRUCTS, splitSearchTokens(), DString::str(), and ClassDef::Struct.

Referenced by generateOutput().

◆ getSearchIndices()

const std::array< SearchIndexInfo, NUM_SEARCH_INDICES > & getSearchIndices ( )

Definition at line 869 of file searchindex_js.cpp.

870{
871 return g_searchIndexInfo;
872}

References g_searchIndexInfo.

◆ splitSearchTokens()

void splitSearchTokens ( DString & title,
SizeVector & indices )
static

helper function to simplify the given title string, and fill a list of start positions for the start of each word in the simplified title string.

Definition at line 94 of file searchindex_js.cpp.

95{
96 if (title.empty()) return;
97
98 // simplify title to contain only words with single space as separator
99 size_t di=0;
100 bool lastIsSpace=true;
101 for (size_t si=0; si<title.length(); si++)
102 {
103 char c = title.at(si);
104 if (c=='@' || c=='\\') // skip over special commands
105 {
106 title.at(di)=' ';
107 if (si<title.length()-1)
108 {
109 c = title.at(++si);
110 while (si<title.length() && (isId(c) || c==':')) c = title.at(++si);
111 --si;
112 }
113 }
114 else if (c=='<') // skip over html tags
115 {
116 if (si<title.length()-1)
117 {
118 for (size_t tsi = si; tsi<title.length(); ++tsi)
119 {
120 if (title.at(tsi)=='>')
121 {
122 si=tsi;
123 break;
124 }
125 }
126 }
127 }
128 else if (isId(c) || c==':') // add "word" character
129 {
130 title.at(di)=c;
131 di++;
132 lastIsSpace=false;
133 }
134 else if (!lastIsSpace) // add one separator as space
135 {
136 title.at(di)=' ';
137 di++;
138 lastIsSpace=true;
139 }
140 }
141 if (di>0 && title.at(di-1)==' ') di--; // strip trailing whitespace
142 title.resize(di);
143
144 // create a list of start positions within title for
145 // each unique word in order of appearance
146 size_t p=0,i=0;
147 while ((i=title.find(' ',p))!=DString::npos)
148 {
149 std::string word = title.mid(p,i-p).str();
150 indices.push_back(p);
151 p = i+1;
152 }
153 if (p<title.length())
154 {
155 std::string word = title.mid(p).str();
156 indices.push_back(p);
157 }
158}
void resize(size_t newlen)
Definition dstring.h:209
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
bool isId(char c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:895

References DString::at(), DString::empty(), DString::find(), isId(), DString::length(), DString::mid(), DString::npos, DString::resize(), and DString::str().

Referenced by createJavaScriptSearchIndex().

◆ writeJavascriptSearchData()

void writeJavascriptSearchData ( const DString & searchDirName)
static

Definition at line 525 of file searchindex_js.cpp.

526{
527 std::ofstream t = Portable::openOutputStream(searchDirName+"/searchdata.js");
528 if (t.is_open())
529 {
530 t << "var indexSectionsWithContent =\n";
531 t << "{\n";
532 int j=0;
533 for (const auto &sii : g_searchIndexInfo)
534 {
535 if (!sii.symbolMap.empty())
536 {
537 if (j>0) t << ",\n";
538 t << " " << j << ": \"";
539
540 std::string previous_letter; // start with value that does not exist in the map
541 for (const auto &[letter,list] : sii.symbolMap)
542 {
543 if (letter != previous_letter)
544 {
545 if ( letter == "\"" ) t << "\\"; // add escape for backslash
546 t << letter;
547 previous_letter = letter;
548 }
549 }
550 t << "\"";
551 j++;
552 }
553 }
554 if (j>0) t << "\n";
555 t << "};\n\n";
556 t << "var indexSectionNames =\n";
557 t << "{\n";
558 j=0;
559 for (const auto &sii : g_searchIndexInfo)
560 {
561 if (!sii.symbolMap.empty())
562 {
563 if (j>0) t << ",\n";
564 t << " " << j << ": \"" << convertToJSString(sii.name,true,false) << "\"";
565 j++;
566 }
567 }
568 if (j>0) t << "\n";
569 t << "};\n\n";
570 t << "var indexSectionLabels =\n";
571 t << "{\n";
572 j=0;
573 for (const auto &sii : g_searchIndexInfo)
574 {
575 if (!sii.symbolMap.empty())
576 {
577 if (j>0) t << ",\n";
578 t << " " << j << ": \"" << convertToJSString(convertToXML(sii.getText()),true,false) << "\"";
579 j++;
580 }
581 }
582 if (j>0) t << "\n";
583 t << "};\n\n";
584 }
585}
std::ofstream openOutputStream(const DString &name, bool append=false)
Definition portable.cpp:681
DString convertToJSString(const DString &s, bool keepEntities, bool singleQuotes)
Definition util.cpp:3351
DString convertToXML(const DString &s, bool keepEntities, const bool citeEntry)
Definition util.cpp:3232

References convertToJSString(), convertToXML(), g_searchIndexInfo, and Portable::openOutputStream().

Referenced by writeJavaScriptSearchIndex().

◆ writeJavaScriptSearchIndex()

void writeJavaScriptSearchIndex ( )

Definition at line 798 of file searchindex_js.cpp.

799{
800 // write index files
801 DString searchDirName = Config_getString(HTML_OUTPUT)+"/search";
802
803 std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
804 if (numThreads>1) // multi threaded version
805 {
806 ThreadPool threadPool(numThreads);
807 std::vector< std::future<int> > results;
808 for (auto &sii : g_searchIndexInfo)
809 {
810 int p=0;
811 for (const auto &[letter,symList] : sii.symbolMap)
812 {
813 DString baseName;
814 baseName.sprintf("%s_%x",sii.name.data(),p);
815 DString dataFileName = searchDirName + "/"+baseName+".js";
816 auto &list = symList;
817 auto processFile = [p,baseName,dataFileName,&list]()
818 {
819 writeJavasScriptSearchDataPage(baseName,dataFileName,list);
820 return p;
821 };
822 results.emplace_back(threadPool.queue(processFile));
823 p++;
824 }
825 }
826 // wait for the results
827 for (auto &f : results) f.get();
828 }
829 else // single threaded version
830 {
831 for (auto &sii : g_searchIndexInfo)
832 {
833 int p=0;
834 for (const auto &[letter,symList] : sii.symbolMap)
835 {
836 DString baseName;
837 baseName.sprintf("%s_%x",sii.name.data(),p);
838 DString dataFileName = searchDirName + "/"+baseName+".js";
839 writeJavasScriptSearchDataPage(baseName,dataFileName,symList);
840 p++;
841 }
842 }
843 }
844
845 writeJavascriptSearchData(searchDirName);
846 auto &mgr = ResourceMgr::instance();
847 {
848 std::ofstream fn = Portable::openOutputStream(searchDirName+"/search.js");
849 if (fn.is_open())
850 {
851 TextStream t(&fn);
852 t << substitute(mgr.getAsString("search.js"),"$PROJECTID",getProjectId());
853 }
854 }
855
856 Doxygen::indexList->addStyleSheetFile("search/searchdata.js");
857 Doxygen::indexList->addStyleSheetFile("search/search.js");
858}
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
static IndexList * indexList
Definition doxygen.h:125
void addStyleSheetFile(const DString &name)
Definition indexlist.h:127
static ResourceMgr & instance()
Returns the one and only instance of this class.
Text streaming class that buffers data.
Definition textstream.h:36
Class managing a pool of worker threads.
Definition threadpool.h:48
#define Config_getInt(name)
Definition config.h:34
#define Config_getString(name)
Definition config.h:32
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:485
static void writeJavascriptSearchData(const DString &searchDirName)
static void writeJavasScriptSearchDataPage(const DString &baseName, const DString &dataFileName, const SearchIndexList &list)
DString getProjectId()
Definition util.cpp:5270

References IndexList::addStyleSheetFile(), Config_getInt, Config_getString, g_searchIndexInfo, getProjectId(), Doxygen::indexList, ResourceMgr::instance(), Portable::openOutputStream(), ThreadPool::queue(), DString::sprintf(), substitute(), writeJavascriptSearchData(), and writeJavasScriptSearchDataPage().

Referenced by generateOutput().

◆ writeJavasScriptSearchDataPage()

void writeJavasScriptSearchDataPage ( const DString & baseName,
const DString & dataFileName,
const SearchIndexList & list )
static

Definition at line 587 of file searchindex_js.cpp.

588{
589 auto isDef = [](const SearchTerm::LinkInfo &info)
590 {
591 return std::holds_alternative<const Definition *>(info);
592 };
593 auto getDef = [&isDef](const SearchTerm::LinkInfo &info)
594 {
595 return isDef(info) ? std::get<const Definition *>(info) : nullptr;
596 };
597 auto isSection = [](const SearchTerm::LinkInfo &info)
598 {
599 return std::holds_alternative<const SectionInfo *>(info);
600 };
601 auto getSection = [&isSection](const SearchTerm::LinkInfo &info)
602 {
603 return isSection(info) ? std::get<const SectionInfo *>(info) : nullptr;
604 };
605
606 int cnt = 0;
607 std::ofstream ti = Portable::openOutputStream(dataFileName);
608 if (!ti.is_open())
609 {
610 err("Failed to open file '{}' for writing...\n",dataFileName);
611 return;
612 }
613
614 ti << "var searchData=\n";
615 // format
616 // searchData[] = array of items
617 // searchData[x][0] = id
618 // searchData[x][1] = [ name + child1 + child2 + .. ]
619 // searchData[x][1][0] = name as shown
620 // searchData[x][1][y+1] = info for child y
621 // searchData[x][1][y+1][0] = url
622 // searchData[x][1][y+1][1] = 1 => target="_parent"
623 // searchData[x][1][y+1][1] = 0 => target="_blank"
624 // searchData[x][1][y+1][2] = scope
625
626 ti << "[\n";
627 bool firstEntry=true;
628
629 int childCount=0;
630 DString lastWord;
631 const Definition *prevScope = nullptr;
632 for (auto it = list.begin(); it!=list.end();)
633 {
634 const SearchTerm &term = *it;
635 const SearchTerm::LinkInfo info = term.info;
636 const Definition *d = getDef(info);
637 const SectionInfo *si = getSection(info);
638 ASSERT(d || si); // either d or si should be valid
639 DString word = term.word;
640 DString id = term.termEncoded();
641 ++it;
642 const Definition *scope = d ? d->getOuterScope() : nullptr;
643 const SearchTerm::LinkInfo next = it!=list.end() ? it->info : SearchTerm::LinkInfo();
644 const Definition *nextScope = isDef(next) ? getDef(next)->getOuterScope() : nullptr;
645 const MemberDef *md = toMemberDef(d);
646 DString anchor = d ? d->anchor() : si ? si->label() : DString();
647
648 if (word!=lastWord) // this item has a different search word
649 {
650 if (!firstEntry)
651 {
652 ti << "]]]";
653 ti << ",\n";
654 }
655 firstEntry=false;
656 ti << " ['" << id << "_" << cnt++ << "',['";
657 if (next==SearchTerm::LinkInfo() || it->word!=word) // unique result, show title
658 {
659 ti << convertToJSString(convertToXML(term.title),true,true);
660 }
661 else // multiple results, show matching word only, expanded list will show title
662 {
663 ti << convertToJSString(convertToXML(term.word),true,true);
664 }
665 ti << "',[";
666 childCount=0;
667 prevScope=nullptr;
668 }
669
670 if (childCount>0)
671 {
672 ti << "],[";
673 }
674 DString fn = d ? d->getOutputFileBase() : si ? si->fileName() : DString();
675 DString ref = d ? d->getReference() : si ? si->ref() : DString();
677 DString extRef = externalRef("../",ref)+fn;
678 if (!anchor.empty())
679 {
680 extRef+="#"+anchor;
681 }
682 ti << "'" << convertToJSString(extRef,true,true) << "',";
683
684 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
685 if (!extLinksInWindow || ref.empty())
686 {
687 ti << "1,";
688 }
689 else
690 {
691 ti << "0,";
692 }
693
694 if (lastWord!=word && (next==SearchTerm::LinkInfo() || it->word!=word)) // unique search result
695 {
696 if (d && d->getOuterScope()!=Doxygen::globalScope)
697 {
698 ti << "'" << convertToJSString(convertToXML(d->getOuterScope()->name()),true,true) << "'";
699 }
700 else if (md)
701 {
702 const FileDef *fd = md->getBodyDef();
703 if (fd==nullptr) fd = md->getFileDef();
704 if (fd)
705 {
706 ti << "'" << convertToJSString(convertToXML(fd->localName()),true,true) << "'";
707 }
708 }
709 else
710 {
711 ti << "''";
712 }
713 }
714 else // multiple entries with the same name
715 {
716 bool found=false;
717 bool overloadedFunction = ((prevScope!=nullptr && scope==prevScope) || (scope && scope==nextScope)) &&
718 md && md->isCallable();
720 if (md) prefix=convertToXML(md->localName());
721 if (overloadedFunction) // overloaded member function
722 {
724 // show argument list to disambiguate overloaded functions
725 }
726 else if (md && md->isCallable()) // unique member function
727 {
728 prefix+="()"; // only to show it is a callable symbol
729 }
730 DString name;
731 if (d)
732 {
733 switch (d->definitionType())
734 {
735 case Definition::TypeClass: name = convertToXML((toClassDef(d))->displayName()); found=true; break;
736 case Definition::TypeNamespace: name = convertToXML((toNamespaceDef(d))->displayName()); found=true; break;
737 case Definition::TypeModule: name = convertToXML(d->name()+" "+theTranslator->trModule(false,true)); found=true; break;
738 case Definition::TypePage: name = convertToXML(filterTitle(toPageDef(d)->title())); found=true; break;
739 case Definition::TypeGroup: name = convertToXML(filterTitle(toGroupDef(d)->groupTitle())); found=true; break;
740 default:
741 if (scope==nullptr || scope==Doxygen::globalScope) // in global scope
742 {
743 if (md)
744 {
745 const FileDef *fd = md->getBodyDef();
746 if (fd==nullptr) fd = md->resolveAlias()->getFileDef();
747 if (fd)
748 {
749 if (!prefix.empty()) prefix+=":&#160;";
750 name = prefix + convertToXML(fd->localName());
751 found = true;
752 }
753 }
754 }
755 else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef()))
756 // member in class or namespace scope
757 {
758 SrcLangExt lang = md->getLanguage();
760 name = convertToXML(d->getOuterScope()->qualifiedName()) + sep + prefix;
761 found = true;
762 }
763 else if (scope) // some thing else? -> show scope
764 {
765 name = prefix + convertToXML(scope->name());
766 found = true;
767 }
768 break;
769 }
770 }
771 else if (si)
772 {
773 name = parseCommentAsHtml(si->definition(),nullptr,si->title(),si->fileName(),si->lineNr());
774 name = convertToXML(name);
775 found = true;
776 }
777 if (!found) // fallback
778 {
779 name = prefix + "("+theTranslator->trGlobalNamespace()+")";
780 }
781
782 ti << "'" << convertToJSString(name,true,true) << "'";
783
784 prevScope = scope;
785 childCount++;
786 }
787 lastWord = word;
788 }
789 if (!firstEntry)
790 {
791 ti << "]]]\n";
792 }
793 ti << "];\n";
794 Doxygen::indexList->addStyleSheetFile(("search/"+baseName+".js").data());
795}
constexpr auto prefix
Definition anchor.cpp:47
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual DefType definitionType() const =0
virtual const DString & localName() const =0
virtual const FileDef * getBodyDef() const =0
virtual DString qualifiedName() const =0
virtual DString anchor() const =0
virtual DString getReference() const =0
virtual Definition * getOuterScope() const =0
virtual DString getOutputFileBase() const =0
static NamespaceDefMutable * globalScope
Definition doxygen.h:114
A model of a class/file/namespace member symbol.
Definition memberdef.h:45
virtual DString argsString() const =0
virtual MemberDef * resolveAlias()=0
virtual bool isCallable() const =0
class that provide information about a section.
Definition section.h:58
DString fileName() const
Definition section.h:74
Definition * definition() const
Definition section.h:77
int lineNr() const
Definition section.h:73
DString title() const
Definition section.h:70
DString ref() const
Definition section.h:72
DString label() const
Definition section.h:69
virtual DString trGlobalNamespace()=0
virtual DString trModule(bool first_capital, bool singular)=0
ClassDef * toClassDef(Definition *d)
DString parseCommentAsHtml(const Definition *scope, const MemberDef *member, const DString &doc, const DString &fileName, int lineNr)
GroupDef * toGroupDef(Definition *d)
Translator * theTranslator
Definition language.cpp:76
MemberDef * toMemberDef(Definition *d)
#define err(fmt,...)
Definition message.h:127
#define ASSERT(x)
Definition message.h:142
#define term(fmt,...)
Definition message.h:137
NamespaceDef * toNamespaceDef(Definition *d)
PageDef * toPageDef(Definition *d)
Definition pagedef.cpp:656
std::variant< std::monostate, const Definition *, const SectionInfo * > LinkInfo
SrcLangExt
Definition types.h:207
void addHtmlExtensionIfMissing(DString &fName)
Definition util.cpp:3931
DString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition util.cpp:4629
DString externalRef(const DString &relPath, const DString &ref)
Definition util.cpp:4538

References addHtmlExtensionIfMissing(), IndexList::addStyleSheetFile(), Definition::anchor(), MemberDef::argsString(), ASSERT, Config_getBool, convertToJSString(), convertToXML(), SectionInfo::definition(), Definition::definitionType(), DString::empty(), err, externalRef(), SectionInfo::fileName(), filterTitle(), Definition::getBodyDef(), MemberDef::getClassDef(), MemberDef::getFileDef(), Definition::getLanguage(), getLanguageSpecificSeparator(), MemberDef::getNamespaceDef(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), Doxygen::globalScope, Doxygen::indexList, MemberDef::isCallable(), SectionInfo::label(), SectionInfo::lineNr(), Definition::localName(), Definition::name(), Portable::openOutputStream(), parseCommentAsHtml(), prefix, Definition::qualifiedName(), SectionInfo::ref(), MemberDef::resolveAlias(), term, theTranslator, SectionInfo::title(), toClassDef(), toGroupDef(), toMemberDef(), toNamespaceDef(), toPageDef(), Translator::trGlobalNamespace(), Translator::trModule(), Definition::TypeClass, Definition::TypeGroup, Definition::TypeModule, Definition::TypeNamespace, and Definition::TypePage.

Referenced by writeJavaScriptSearchIndex().

Variable Documentation

◆ g_searchIndexInfo