Doxygen
Loading...
Searching...
No Matches
searchindex_js.cpp File Reference
#include <utility>
#include <algorithm>
#include <cassert>
#include "searchindex_js.h"
#include "doxygen.h"
#include "groupdef.h"
#include "pagedef.h"
#include "namespacedef.h"
#include "classdef.h"
#include "classlist.h"
#include "membername.h"
#include "filename.h"
#include "language.h"
#include "textstream.h"
#include "util.h"
#include "version.h"
#include "message.h"
#include "resourcemgr.h"
#include "indexlist.h"
#include "portable.h"
#include "threadpool.h"
#include "moduledef.h"
#include "section.h"
#include "htmldocvisitor.h"
#include "outputlist.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 QCString convertTitleToHtml (const Definition *scope, const QCString &fileName, int lineNr, const QCString &title)
static void splitSearchTokens (QCString &title, IntVector &indices)
static void addMemberToSearchIndex (const MemberDef *md)
void createJavaScriptSearchIndex ()
static void writeJavascriptSearchData (const QCString &searchDirName)
static void writeJavasScriptSearchDataPage (const QCString &baseName, const QCString &dataFileName, const SearchIndexList &list)
void writeJavaScriptSearchIndex ()
const std::array< SearchIndexInfo, NUM_SEARCH_INDICES > & getSearchIndices ()

Variables

static std::mutex g_titleCacheMutex
static std::unordered_map< std::string, QCStringg_titleCache
static std::array< SearchIndexInfo, NUM_SEARCH_INDICESg_searchIndexInfo

Macro Definition Documentation

◆ SEARCH_INDEX_ALL

#define SEARCH_INDEX_ALL   0

Definition at line 195 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex(), and createJavaScriptSearchIndex().

◆ SEARCH_INDEX_CLASSES

#define SEARCH_INDEX_CLASSES   1

Definition at line 196 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_CONCEPTS

#define SEARCH_INDEX_CONCEPTS   20

Definition at line 215 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_DEFINES

#define SEARCH_INDEX_DEFINES   17

Definition at line 212 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_DICTIONARIES

#define SEARCH_INDEX_DICTIONARIES   11

Definition at line 206 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_ENUMS

#define SEARCH_INDEX_ENUMS   12

Definition at line 207 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_ENUMVALUES

#define SEARCH_INDEX_ENUMVALUES   13

Definition at line 208 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_EVENTS

#define SEARCH_INDEX_EVENTS   15

Definition at line 210 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_EXCEPTIONS

#define SEARCH_INDEX_EXCEPTIONS   4

Definition at line 199 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_FILES

#define SEARCH_INDEX_FILES   6

Definition at line 201 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_FUNCTIONS

#define SEARCH_INDEX_FUNCTIONS   7

Definition at line 202 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_GROUPS

#define SEARCH_INDEX_GROUPS   18

Definition at line 213 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_INTERFACES

#define SEARCH_INDEX_INTERFACES   2

Definition at line 197 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_MODULES

#define SEARCH_INDEX_MODULES   21

Definition at line 216 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_NAMESPACES

#define SEARCH_INDEX_NAMESPACES   5

Definition at line 200 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_PAGES

#define SEARCH_INDEX_PAGES   19

Definition at line 214 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_PROPERTIES

#define SEARCH_INDEX_PROPERTIES   14

Definition at line 209 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_RELATED

#define SEARCH_INDEX_RELATED   16

Definition at line 211 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_SEQUENCES

#define SEARCH_INDEX_SEQUENCES   10

Definition at line 205 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_STRUCTS

#define SEARCH_INDEX_STRUCTS   3

Definition at line 198 of file searchindex_js.cpp.

Referenced by createJavaScriptSearchIndex().

◆ SEARCH_INDEX_TYPEDEFS

#define SEARCH_INDEX_TYPEDEFS   9

Definition at line 204 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

◆ SEARCH_INDEX_VARIABLES

#define SEARCH_INDEX_VARIABLES   8

Definition at line 203 of file searchindex_js.cpp.

Referenced by addMemberToSearchIndex().

Function Documentation

◆ addMemberToSearchIndex()

void addMemberToSearchIndex ( const MemberDef * md)
static

Definition at line 251 of file searchindex_js.cpp.

252{
253 bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
254 bool isLinkable = md->isLinkable();
255 const ClassDef *cd=nullptr;
256 const NamespaceDef *nd=nullptr;
257 const FileDef *fd=nullptr;
258 const GroupDef *gd=nullptr;
259 if (isLinkable &&
260 (
261 ((cd=md->getClassDef()) && cd->isLinkable() && !cd->isImplicitTemplateInstance()) ||
262 ((gd=md->getGroupDef()) && gd->isLinkable())
263 )
264 )
265 {
266 QCString n = md->name();
267 if (!n.isEmpty())
268 {
269 bool isFriendToHide = hideFriendCompounds &&
270 (QCString(md->typeString())=="friend class" ||
271 QCString(md->typeString())=="friend struct" ||
272 QCString(md->typeString())=="friend union");
273 if (!(md->isFriend() && isFriendToHide))
274 {
276 }
277 if (md->isFunction() || md->isSlot() || md->isSignal())
278 {
280 }
281 else if (md->isVariable())
282 {
284 }
285 else if (md->isSequence())
286 {
288 }
289 else if (md->isDictionary())
290 {
292 }
293 else if (md->isTypedef())
294 {
296 }
297 else if (md->isEnumerate())
298 {
300 }
301 else if (md->isEnumValue())
302 {
304 }
305 else if (md->isProperty())
306 {
308 }
309 else if (md->isEvent())
310 {
312 }
313 else if (md->isRelated() || md->isForeign() ||
314 (md->isFriend() && !isFriendToHide))
315 {
317 }
318 }
319 }
320 else if (isLinkable &&
321 (((nd=md->getNamespaceDef()) && nd->isLinkable()) ||
322 ((fd=md->getFileDef()) && fd->isLinkable())
323 )
324 )
325 {
326 QCString n = md->name();
327 if (!n.isEmpty())
328 {
330
331 if (md->isFunction())
332 {
334 }
335 else if (md->isVariable())
336 {
338 }
339 else if (md->isSequence())
340 {
342 }
343 else if (md->isDictionary())
344 {
346 }
347 else if (md->isTypedef())
348 {
350 }
351 else if (md->isEnumerate())
352 {
354 }
355 else if (md->isEnumValue())
356 {
358 }
359 else if (md->isDefine())
360 {
362 }
363 }
364 }
365}
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual bool isImplicitTemplateInstance() const =0
virtual bool isLinkable() const =0
virtual const QCString & name() const =0
A model of a file symbol.
Definition filedef.h:99
A model of a group of symbols.
Definition groupdef.h:52
virtual QCString typeString() const =0
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 bool isEnumValue() const =0
virtual bool isProperty() const =0
An abstract interface of a namespace symbol.
This is an alternative implementation of QCString.
Definition qcstring.h:101
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
#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.

References Config_getBool, g_searchIndexInfo, MemberDef::getClassDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), MemberDef::getNamespaceDef(), MemberDef::isDefine(), MemberDef::isDictionary(), QCString::isEmpty(), 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(), 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 addToIndices(), and createJavaScriptSearchIndex().

◆ convertTitleToHtml()

QCString convertTitleToHtml ( const Definition * scope,
const QCString & fileName,
int lineNr,
const QCString & title )
static

Definition at line 48 of file searchindex_js.cpp.

49{
50 std::lock_guard lock(g_titleCacheMutex);
51 auto it = g_titleCache.find(title.str());
52 if (it != g_titleCache.end())
53 {
54 //printf("Cache: [%s]->[%s]\n",qPrint(title),qPrint(it->second));
55 return it->second;
56 }
57 auto parser { createDocParser() };
58 auto ast { validatingParseDoc(*parser.get(),fileName,lineNr,scope,nullptr,title,false,false,
59 QCString(),true,false,Config_getBool(MARKDOWN_SUPPORT)) };
60 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
61 QCString result;
62 if (astImpl)
63 {
64 TextStream t;
65 OutputCodeList codeList;
66 codeList.add<HtmlCodeGenerator>(&t);
67 HtmlDocVisitor visitor(t,codeList,scope,fileName);
68 std::visit(visitor,astImpl->root);
69 result = t.str();
70 }
71 else // fallback, should not happen
72 {
73 result = filterTitle(title);
74 }
75 //printf("Conversion: [%s]->[%s]\n",qPrint(title),qPrint(result));
76 g_titleCache.insert(std::make_pair(title.str(),result));
77 return result;
78}
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1461
Generator for HTML code fragments.
Definition htmlgen.h:26
Concrete visitor implementation for HTML output.
Class representing a list of different code generators.
Definition outputlist.h:164
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:194
const std::string & str() const
Definition qcstring.h:537
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
static std::unordered_map< std::string, QCString > g_titleCache
static std::mutex g_titleCacheMutex
QCString filterTitle(const QCString &title)
Definition util.cpp:6093

References OutputCodeList::add(), Config_getBool, createDocParser(), filterTitle(), g_titleCache, g_titleCacheMutex, QCString::str(), TextStream::str(), and validatingParseDoc().

Referenced by SearchTerm::makeTitle(), and writeJavasScriptSearchDataPage().

◆ createJavaScriptSearchIndex()

void createJavaScriptSearchIndex ( )

Definition at line 369 of file searchindex_js.cpp.

370{
371 // index classes
372 for (const auto &cd : *Doxygen::classLinkedMap)
373 {
374 if (cd->isLinkable())
375 {
376 QCString n = cd->localName();
378 if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
379 {
380 if (cd->compoundType()==ClassDef::Interface)
381 {
383 }
384 else if (cd->compoundType()==ClassDef::Struct)
385 {
387 }
388 else if (cd->compoundType()==ClassDef::Exception)
389 {
391 }
392 else // cd->compoundType()==ClassDef::Class
393 {
395 }
396 }
397 else // non slice optimization: group all types under classes
398 {
400 }
401 }
402 }
403
404 // index namespaces
405 for (const auto &nd : *Doxygen::namespaceLinkedMap)
406 {
407 if (nd->isLinkable())
408 {
409 QCString n = nd->name();
412 }
413 }
414
415 // index concepts
416 for (const auto &cd : *Doxygen::conceptLinkedMap)
417 {
418 if (cd->isLinkable())
419 {
420 QCString n = cd->localName();
423 }
424 }
425
426 // index modules
427 for (const auto &mod : ModuleManager::instance().modules())
428 {
429 if (mod->isLinkable() && mod->isPrimaryInterface())
430 {
431 QCString n = mod->name();
434 }
435 }
436
437 // index files
438 for (const auto &fn : *Doxygen::inputNameLinkedMap)
439 {
440 for (const auto &fd : *fn)
441 {
442 QCString n = fd->name();
443 if (fd->isLinkable())
444 {
447 }
448 }
449 }
450
451 // index class members
452 {
453 // for each member name
454 for (const auto &mn : *Doxygen::memberNameLinkedMap)
455 {
456 // for each member definition
457 for (const auto &md : *mn)
458 {
459 addMemberToSearchIndex(md.get());
460 }
461 }
462 }
463
464 // index file/namespace members
465 {
466 // for each member name
467 for (const auto &mn : *Doxygen::functionNameLinkedMap)
468 {
469 // for each member definition
470 for (const auto &md : *mn)
471 {
472 addMemberToSearchIndex(md.get());
473 }
474 }
475 }
476
477 // index groups
478 for (const auto &gd : *Doxygen::groupLinkedMap)
479 {
480 if (gd->isLinkable())
481 {
482 QCString title(filterTitle(gd->groupTitle()).str());
483 IntVector tokenIndices;
484 splitSearchTokens(title,tokenIndices);
485 for (int index : tokenIndices)
486 {
487 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),gd.get()));
488 g_searchIndexInfo[SEARCH_INDEX_GROUPS].add(SearchTerm(title.mid(index),gd.get()));
489 }
490 }
491 }
492
493 // index pages
494 for (const auto &pd : *Doxygen::pageLinkedMap)
495 {
496 if (pd->isLinkable())
497 {
498 QCString title(filterTitle(pd->title()).str());
499 IntVector tokenIndices;
500 splitSearchTokens(title,tokenIndices);
501 for (int index : tokenIndices)
502 {
503 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),pd.get()));
504 g_searchIndexInfo[SEARCH_INDEX_PAGES].add(SearchTerm(title.mid(index),pd.get()));
505 }
506 }
507 }
508
509 // main page
511 {
512 QCString title(filterTitle(Doxygen::mainPage->title()).str());
513 IntVector tokenIndices;
514 splitSearchTokens(title,tokenIndices);
515 for (int index : tokenIndices)
516 {
519 }
520 }
521
522 // sections
523 const auto &sm = SectionManager::instance();
524 for (const auto &sectionInfo : sm)
525 {
526 if (sectionInfo->level()>0) // level 0 is for page titles
527 {
528 QCString title = filterTitle(sectionInfo->title());
529 IntVector tokenIndices;
530 splitSearchTokens(title,tokenIndices);
531 //printf("split(%s)=(%s) %zu\n",qPrint(sectionInfo->title()),qPrint(title),tokenIndices.size());
532 for (int index : tokenIndices)
533 {
534 g_searchIndexInfo[SEARCH_INDEX_ALL].add(SearchTerm(title.mid(index),sectionInfo.get()));
535 g_searchIndexInfo[SEARCH_INDEX_PAGES].add(SearchTerm(title.mid(index),sectionInfo.get()));
536 }
537 }
538 }
539
540 // sort all lists
541 for (auto &sii : g_searchIndexInfo) // for each index
542 {
543 for (auto &[name,symList] : sii.symbolMap) // for each symbol in the index
544 {
545 // sort the symbols (first on search term, and then on full name)
546 //
547 // `std::stable_sort` is used here due to reproducibility issues
548 // on key collisions
549 // https://github.com/doxygen/doxygen/issues/10445
550 std::stable_sort(symList.begin(),
551 symList.end(),
552 [](const auto &t1,const auto &t2)
553 {
554 int eq = qstricmp_sort(t1.word,t2.word); // search term first
555 return eq==0 ? qstricmp_sort(t1.title,t2.title)<0 : eq<0; // then full title
556 });
557 }
558 }
559}
@ Interface
Definition classdef.h:112
@ Exception
Definition classdef.h:115
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:98
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:101
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:96
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:112
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:100
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:111
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
static ModuleManager & instance()
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:175
std::vector< int > IntVector
Definition containers.h:38
static void addMemberToSearchIndex(const MemberDef *md)
#define SEARCH_INDEX_STRUCTS
static void splitSearchTokens(QCString &title, IntVector &indices)
#define SEARCH_INDEX_NAMESPACES
#define SEARCH_INDEX_CONCEPTS
#define SEARCH_INDEX_FILES
#define SEARCH_INDEX_PAGES
#define SEARCH_INDEX_GROUPS
#define SEARCH_INDEX_INTERFACES
#define SEARCH_INDEX_MODULES
#define SEARCH_INDEX_CLASSES
#define SEARCH_INDEX_EXCEPTIONS

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, QCString::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(), QCString::str(), and ClassDef::Struct.

Referenced by generateOutput().

◆ getSearchIndices()

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

Definition at line 903 of file searchindex_js.cpp.

904{
905 return g_searchIndexInfo;
906}

References g_searchIndexInfo.

◆ splitSearchTokens()

void splitSearchTokens ( QCString & title,
IntVector & 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 127 of file searchindex_js.cpp.

128{
129 if (title.isEmpty()) return;
130
131 // simplify title to contain only words with single space as separator
132 size_t di=0;
133 bool lastIsSpace=true;
134 for (size_t si=0; si<title.length(); si++)
135 {
136 char c = title.at(si);
137 if (c=='@' || c=='\\') // skip over special commands
138 {
139 title.at(di)=' ';
140 if (si<title.length()-1)
141 {
142 c = title.at(++si);
143 while (si<title.length() && (isId(c) || c==':')) c = title.at(++si);
144 --si;
145 }
146 }
147 else if (c=='<') // skip over html tags
148 {
149 if (si<title.length()-1)
150 {
151 for (size_t tsi = si; tsi<title.length(); ++tsi)
152 {
153 if (title.at(tsi)=='>')
154 {
155 si=tsi;
156 break;
157 }
158 }
159 }
160 }
161 else if (isId(c) || c==':') // add "word" character
162 {
163 title.at(di)=c;
164 di++;
165 lastIsSpace=false;
166 }
167 else if (!lastIsSpace) // add one separator as space
168 {
169 title.at(di)=' ';
170 di++;
171 lastIsSpace=true;
172 }
173 }
174 if (di>0 && title.at(di-1)==' ') di--; // strip trailing whitespace
175 title.resize(di);
176
177 // create a list of start positions within title for
178 // each unique word in order of appearance
179 int p=0,i=0;
180 while ((i=title.find(' ',p))!=-1)
181 {
182 std::string word = title.mid(p,i-p).str();
183 indices.push_back(p);
184 p = i+1;
185 }
186 if (p<static_cast<int>(title.length()))
187 {
188 std::string word = title.mid(p).str();
189 indices.push_back(p);
190 }
191}
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
void resize(size_t newlen)
Definition qcstring.h:167
std::string_view word
Definition util.cpp:980
bool isId(int c)
Definition util.h:208

References QCString::at(), QCString::find(), QCString::isEmpty(), isId(), QCString::length(), QCString::mid(), QCString::resize(), QCString::str(), and word.

Referenced by createJavaScriptSearchIndex().

◆ writeJavascriptSearchData()

void writeJavascriptSearchData ( const QCString & searchDirName)
static

Definition at line 561 of file searchindex_js.cpp.

562{
563 std::ofstream t = Portable::openOutputStream(searchDirName+"/searchdata.js");
564 if (t.is_open())
565 {
566 t << "var indexSectionsWithContent =\n";
567 t << "{\n";
568 int j=0;
569 for (const auto &sii : g_searchIndexInfo)
570 {
571 if (!sii.symbolMap.empty())
572 {
573 if (j>0) t << ",\n";
574 t << " " << j << ": \"";
575
576 std::string previous_letter; // start with value that does not exist in the map
577 for (const auto &[letter,list] : sii.symbolMap)
578 {
579 if (letter != previous_letter)
580 {
581 if ( letter == "\"" ) t << "\\"; // add escape for backslash
582 t << letter;
583 previous_letter = letter;
584 }
585 }
586 t << "\"";
587 j++;
588 }
589 }
590 if (j>0) t << "\n";
591 t << "};\n\n";
592 t << "var indexSectionNames =\n";
593 t << "{\n";
594 j=0;
595 for (const auto &sii : g_searchIndexInfo)
596 {
597 if (!sii.symbolMap.empty())
598 {
599 if (j>0) t << ",\n";
600 t << " " << j << ": \"" << sii.name << "\"";
601 j++;
602 }
603 }
604 if (j>0) t << "\n";
605 t << "};\n\n";
606 t << "var indexSectionLabels =\n";
607 t << "{\n";
608 j=0;
609 for (const auto &sii : g_searchIndexInfo)
610 {
611 if (!sii.symbolMap.empty())
612 {
613 if (j>0) t << ",\n";
614 t << " " << j << ": \"" << convertToXML(sii.getText()) << "\"";
615 j++;
616 }
617 }
618 if (j>0) t << "\n";
619 t << "};\n\n";
620 }
621}
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:4428

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

Referenced by writeJavaScriptSearchIndex().

◆ writeJavaScriptSearchIndex()

void writeJavaScriptSearchIndex ( )

Definition at line 832 of file searchindex_js.cpp.

833{
834 // write index files
835 QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search";
836
837 std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
838 if (numThreads>1) // multi threaded version
839 {
840 ThreadPool threadPool(numThreads);
841 std::vector< std::future<int> > results;
842 for (auto &sii : g_searchIndexInfo)
843 {
844 int p=0;
845 for (const auto &[letter,symList] : sii.symbolMap)
846 {
847 QCString baseName;
848 baseName.sprintf("%s_%x",sii.name.data(),p);
849 QCString dataFileName = searchDirName + "/"+baseName+".js";
850 auto &list = symList;
851 auto processFile = [p,baseName,dataFileName,&list]()
852 {
853 writeJavasScriptSearchDataPage(baseName,dataFileName,list);
854 return p;
855 };
856 results.emplace_back(threadPool.queue(processFile));
857 p++;
858 }
859 }
860 // wait for the results
861 for (auto &f : results) f.get();
862 }
863 else // single threaded version
864 {
865 for (auto &sii : g_searchIndexInfo)
866 {
867 int p=0;
868 for (const auto &[letter,symList] : sii.symbolMap)
869 {
870 QCString baseName;
871 baseName.sprintf("%s_%x",sii.name.data(),p);
872 QCString dataFileName = searchDirName + "/"+baseName+".js";
873 writeJavasScriptSearchDataPage(baseName,dataFileName,symList);
874 p++;
875 }
876 }
877 }
878
879 writeJavascriptSearchData(searchDirName);
880 auto &mgr = ResourceMgr::instance();
881 {
882 std::ofstream fn = Portable::openOutputStream(searchDirName+"/search.js");
883 if (fn.is_open())
884 {
885 TextStream t(&fn);
886 t << substitute(mgr.getAsString("search.js"),"$PROJECTID",getProjectId());
887 }
888 }
889
890 Doxygen::indexList->addStyleSheetFile("search/searchdata.js");
891 Doxygen::indexList->addStyleSheetFile("search/search.js");
892}
static IndexList * indexList
Definition doxygen.h:134
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
static ResourceMgr & instance()
Returns the one and only instance of this class.
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
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
static void writeJavasScriptSearchDataPage(const QCString &baseName, const QCString &dataFileName, const SearchIndexList &list)
static void writeJavascriptSearchData(const QCString &searchDirName)
QCString getProjectId()
Definition util.cpp:7288

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

Referenced by generateOutput().

◆ writeJavasScriptSearchDataPage()

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

Definition at line 623 of file searchindex_js.cpp.

624{
625 auto isDef = [](const SearchTerm::LinkInfo &info)
626 {
627 return std::holds_alternative<const Definition *>(info);
628 };
629 auto getDef = [&isDef](const SearchTerm::LinkInfo &info)
630 {
631 return isDef(info) ? std::get<const Definition *>(info) : nullptr;
632 };
633 auto isSection = [](const SearchTerm::LinkInfo &info)
634 {
635 return std::holds_alternative<const SectionInfo *>(info);
636 };
637 auto getSection = [&isSection](const SearchTerm::LinkInfo &info)
638 {
639 return isSection(info) ? std::get<const SectionInfo *>(info) : nullptr;
640 };
641
642 int cnt = 0;
643 std::ofstream ti = Portable::openOutputStream(dataFileName);
644 if (!ti.is_open())
645 {
646 err("Failed to open file '{}' for writing...\n",dataFileName);
647 return;
648 }
649
650 ti << "var searchData=\n";
651 // format
652 // searchData[] = array of items
653 // searchData[x][0] = id
654 // searchData[x][1] = [ name + child1 + child2 + .. ]
655 // searchData[x][1][0] = name as shown
656 // searchData[x][1][y+1] = info for child y
657 // searchData[x][1][y+1][0] = url
658 // searchData[x][1][y+1][1] = 1 => target="_parent"
659 // searchData[x][1][y+1][1] = 0 => target="_blank"
660 // searchData[x][1][y+1][2] = scope
661
662 ti << "[\n";
663 bool firstEntry=TRUE;
664
665 int childCount=0;
666 QCString lastWord;
667 const Definition *prevScope = nullptr;
668 for (auto it = list.begin(); it!=list.end();)
669 {
670 const SearchTerm &term = *it;
671 const SearchTerm::LinkInfo info = term.info;
672 const Definition *d = getDef(info);
673 const SectionInfo *si = getSection(info);
674 assert(d || si); // either d or si should be valid
675 QCString word = term.word;
676 QCString id = term.termEncoded();
677 ++it;
678 const Definition *scope = d ? d->getOuterScope() : nullptr;
679 const SearchTerm::LinkInfo next = it!=list.end() ? it->info : SearchTerm::LinkInfo();
680 const Definition *nextScope = isDef(next) ? getDef(next)->getOuterScope() : nullptr;
681 const MemberDef *md = toMemberDef(d);
682 QCString anchor = d ? d->anchor() : si ? si->label() : QCString();
683
684 if (word!=lastWord) // this item has a different search word
685 {
686 if (!firstEntry)
687 {
688 ti << "]]]";
689 ti << ",\n";
690 }
691 firstEntry=FALSE;
692 ti << " ['" << id << "_" << cnt++ << "',['";
693 if (next==SearchTerm::LinkInfo() || it->word!=word) // unique result, show title
694 {
695 ti << convertToXML(term.title);
696 }
697 else // multiple results, show matching word only, expanded list will show title
698 {
699 ti << convertToXML(term.word);
700 }
701 ti << "',[";
702 childCount=0;
703 prevScope=nullptr;
704 }
705
706 if (childCount>0)
707 {
708 ti << "],[";
709 }
710 QCString fn = d ? d->getOutputFileBase() : si ? si->fileName() : QCString();
711 QCString ref = d ? d->getReference() : si ? si->ref() : QCString();
713 ti << "'" << externalRef("../",ref,TRUE) << fn;
714 if (!anchor.isEmpty())
715 {
716 ti << "#" << anchor;
717 }
718 ti << "',";
719
720 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
721 if (!extLinksInWindow || ref.isEmpty())
722 {
723 ti << "1,";
724 }
725 else
726 {
727 ti << "0,";
728 }
729
730 if (lastWord!=word && (next==SearchTerm::LinkInfo() || it->word!=word)) // unique search result
731 {
732 if (d && d->getOuterScope()!=Doxygen::globalScope)
733 {
734 ti << "'" << convertToXML(d->getOuterScope()->name()) << "'";
735 }
736 else if (md)
737 {
738 const FileDef *fd = md->getBodyDef();
739 if (fd==nullptr) fd = md->getFileDef();
740 if (fd)
741 {
742 ti << "'" << convertToXML(fd->localName()) << "'";
743 }
744 }
745 else
746 {
747 ti << "''";
748 }
749 }
750 else // multiple entries with the same name
751 {
752 bool found=FALSE;
753 bool overloadedFunction = ((prevScope!=nullptr && scope==prevScope) || (scope && scope==nextScope)) &&
754 md && md->isCallable();
756 if (md) prefix=convertToXML(md->localName());
757 if (overloadedFunction) // overloaded member function
758 {
760 // show argument list to disambiguate overloaded functions
761 }
762 else if (md && md->isCallable()) // unique member function
763 {
764 prefix+="()"; // only to show it is a callable symbol
765 }
766 QCString name;
767 if (d)
768 {
769 switch (d->definitionType())
770 {
771 case Definition::TypeClass: name = convertToXML((toClassDef(d))->displayName()); found=true; break;
772 case Definition::TypeNamespace: name = convertToXML((toNamespaceDef(d))->displayName()); found=true; break;
773 case Definition::TypeModule: name = convertToXML(d->name()+" "+theTranslator->trModule(false,true)); found=true; break;
774 case Definition::TypePage: name = convertToXML(filterTitle(toPageDef(d)->title())); found=true; break;
775 case Definition::TypeGroup: name = convertToXML(filterTitle(toGroupDef(d)->groupTitle())); found=true; break;
776 default:
777 if (scope==nullptr || scope==Doxygen::globalScope) // in global scope
778 {
779 if (md)
780 {
781 const FileDef *fd = md->getBodyDef();
782 if (fd==nullptr) fd = md->resolveAlias()->getFileDef();
783 if (fd)
784 {
785 if (!prefix.isEmpty()) prefix+=":&#160;";
786 name = prefix + convertToXML(fd->localName());
787 found = true;
788 }
789 }
790 }
791 else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef()))
792 // member in class or namespace scope
793 {
794 SrcLangExt lang = md->getLanguage();
796 found = true;
797 }
798 else if (scope) // some thing else? -> show scope
799 {
800 name = prefix + convertToXML(scope->name());
801 found = true;
802 }
803 break;
804 }
805 }
806 else if (si)
807 {
808 name = convertTitleToHtml(si->definition(),si->fileName(),si->lineNr(),si->title());
809 found = true;
810 }
811 if (!found) // fallback
812 {
813 name = prefix + "("+theTranslator->trGlobalNamespace()+")";
814 }
815
816 ti << "'" << name << "'";
817
818 prevScope = scope;
819 childCount++;
820 }
821 lastWord = word;
822 }
823 if (!firstEntry)
824 {
825 ti << "]]]\n";
826 }
827 ti << "];\n";
828 Doxygen::indexList->addStyleSheetFile(("search/"+baseName+".js").data());
829}
constexpr auto prefix
Definition anchor.cpp:44
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual const QCString & localName() const =0
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual DefType definitionType() const =0
virtual QCString anchor() const =0
virtual const FileDef * getBodyDef() const =0
virtual QCString getReference() const =0
virtual QCString qualifiedName() const =0
virtual QCString getOutputFileBase() const =0
virtual Definition * getOuterScope() const =0
static NamespaceDefMutable * globalScope
Definition doxygen.h:121
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual MemberDef * resolveAlias()=0
virtual QCString argsString() const =0
virtual bool isCallable() const =0
class that provide information about a section.
Definition section.h:57
QCString label() const
Definition section.h:68
Definition * definition() const
Definition section.h:76
QCString ref() const
Definition section.h:71
QCString fileName() const
Definition section.h:73
int lineNr() const
Definition section.h:72
QCString title() const
Definition section.h:69
ClassDef * toClassDef(Definition *d)
GroupDef * toGroupDef(Definition *d)
Translator * theTranslator
Definition language.cpp:71
MemberDef * toMemberDef(Definition *d)
#define err(fmt,...)
Definition message.h:127
#define term(fmt,...)
Definition message.h:137
NamespaceDef * toNamespaceDef(Definition *d)
PageDef * toPageDef(Definition *d)
Definition pagedef.cpp:487
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
static QCString convertTitleToHtml(const Definition *scope, const QCString &fileName, int lineNr, const QCString &title)
std::variant< std::monostate, const Definition *, const SectionInfo * > LinkInfo
SrcLangExt
Definition types.h:207
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:6232
bool found
Definition util.cpp:984
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:6376
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5415

References addHtmlExtensionIfMissing(), Definition::anchor(), MemberDef::argsString(), Config_getBool, convertTitleToHtml(), convertToXML(), SectionInfo::definition(), Definition::definitionType(), err, externalRef(), FALSE, SectionInfo::fileName(), filterTitle(), found, Definition::getBodyDef(), MemberDef::getClassDef(), MemberDef::getFileDef(), Definition::getLanguage(), getLanguageSpecificSeparator(), MemberDef::getNamespaceDef(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), Doxygen::globalScope, Doxygen::indexList, MemberDef::isCallable(), QCString::isEmpty(), SectionInfo::label(), SectionInfo::lineNr(), Definition::localName(), Definition::name(), Portable::openOutputStream(), prefix, Definition::qualifiedName(), SectionInfo::ref(), MemberDef::resolveAlias(), term, theTranslator, SectionInfo::title(), toClassDef(), toGroupDef(), toMemberDef(), toNamespaceDef(), toPageDef(), TRUE, Definition::TypeClass, Definition::TypeGroup, Definition::TypeModule, Definition::TypeNamespace, Definition::TypePage, and word.

Referenced by writeJavaScriptSearchIndex().

Variable Documentation

◆ g_searchIndexInfo

std::array<SearchIndexInfo,NUM_SEARCH_INDICES> g_searchIndexInfo
static

Definition at line 218 of file searchindex_js.cpp.

219{ {
220 // index name getText symbolList
221 { /* SEARCH_INDEX_ALL */ "all" , []() { return theTranslator->trAll(); }, {} },
222 { /* SEARCH_INDEX_CLASSES */ "classes" , []() { return theTranslator->trClasses(); }, {} },
223 { /* SEARCH_INDEX_INTERFACES */ "interfaces" , []() { return theTranslator->trSliceInterfaces(); }, {} },
224 { /* SEARCH_INDEX_STRUCTS */ "structs" , []() { return theTranslator->trStructs(); }, {} },
225 { /* SEARCH_INDEX_EXCEPTIONS */ "exceptions" , []() { return theTranslator->trExceptions(); }, {} },
226 { /* SEARCH_INDEX_NAMESPACES */ "namespaces" , []() { return Config_getBool(OPTIMIZE_OUTPUT_SLICE) ?
227 theTranslator->trModules() :
228 theTranslator->trNamespace(TRUE,FALSE); }, {} },
229 { /* SEARCH_INDEX_FILES */ "files" , []() { return theTranslator->trFile(TRUE,FALSE); }, {} },
230 { /* SEARCH_INDEX_FUNCTIONS */ "functions" , []() { return Config_getBool(OPTIMIZE_OUTPUT_SLICE) ?
231 theTranslator->trOperations() :
232 theTranslator->trFunctions(); }, {} },
233 { /* SEARCH_INDEX_VARIABLES */ "variables" , []() { return Config_getBool(OPTIMIZE_OUTPUT_SLICE) ?
234 theTranslator->trConstants() :
235 theTranslator->trVariables(); }, {} },
236 { /* SEARCH_INDEX_TYPEDEFS */ "typedefs" , []() { return theTranslator->trTypedefs(); }, {} },
237 { /* SEARCH_INDEX_SEQUENCES */ "sequences" , []() { return theTranslator->trSequences(); }, {} },
238 { /* SEARCH_INDEX_DICTIONARIES */ "dictionaries", []() { return theTranslator->trDictionaries(); }, {} },
239 { /* SEARCH_INDEX_ENUMS */ "enums" , []() { return theTranslator->trEnumerations(); }, {} },
240 { /* SEARCH_INDEX_ENUMVALUES */ "enumvalues" , []() { return theTranslator->trEnumerationValues(); }, {} },
241 { /* SEARCH_INDEX_PROPERTIES */ "properties" , []() { return theTranslator->trProperties(); }, {} },
242 { /* SEARCH_INDEX_EVENTS */ "events" , []() { return theTranslator->trEvents(); }, {} },
243 { /* SEARCH_INDEX_RELATED */ "related" , []() { return theTranslator->trFriends(); }, {} },
244 { /* SEARCH_INDEX_DEFINES */ "defines" , []() { return theTranslator->trDefines(); }, {} },
245 { /* SEARCH_INDEX_GROUPS */ "groups" , []() { return theTranslator->trGroup(TRUE,FALSE); }, {} },
246 { /* SEARCH_INDEX_PAGES */ "pages" , []() { return theTranslator->trPage(TRUE,FALSE); }, {} },
247 { /* SEARCH_INDEX_CONCEPTS */ "concepts" , []() { return theTranslator->trConcept(true,false); }, {} },
248 { /* SEARCH_INDEX_MODULES */ "modules" , []() { return theTranslator->trModule(true,false); }, {} }
249} };

Referenced by addMemberToSearchIndex(), createJavaScriptSearchIndex(), getSearchIndices(), writeJavascriptSearchData(), and writeJavaScriptSearchIndex().

◆ g_titleCache

std::unordered_map<std::string,QCString> g_titleCache
static

Definition at line 46 of file searchindex_js.cpp.

Referenced by convertTitleToHtml().

◆ g_titleCacheMutex

std::mutex g_titleCacheMutex
static

Definition at line 45 of file searchindex_js.cpp.

Referenced by convertTitleToHtml().