Doxygen
Loading...
Searching...
No Matches
anchor.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2023 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <mutex>
17#include <algorithm>
18#include <string>
19#include <unordered_map>
20
21#include "anchor.h"
22#include "containers.h"
23#include "utf8.h"
24#include "config.h"
25
27{
30 std::mutex mutex;
31 std::unordered_map<std::string,int> idCount;
32};
33
34AnchorGenerator::AnchorGenerator() : p(std::make_unique<Private>()) {}
35
37
39{
40 static AnchorGenerator am;
41 return am;
42}
43
44constexpr auto prefix = "autotoc_md";
45
46std::string AnchorGenerator::addPrefixIfNeeded(const std::string &anchor)
47{
48 if (Config_getEnum(MARKDOWN_ID_STYLE)==MARKDOWN_ID_STYLE_t::GITHUB &&
49 (anchor.empty() || anchor.front() == '-' || std::isdigit(anchor.front())))
50 {
51 return prefix+anchor;
52 }
53 else
54 {
55 return anchor;
56 }
57}
58
59std::string AnchorGenerator::generate(const std::string &label)
60{
61 std::lock_guard lock(p->mutex);
62
63 std::string result;
64
65 auto createDoxygenStyleAnchor = [&]()
66 {
67 // overwrite result with the doxygen style anchor
68 result = prefix+std::to_string(p->anchorCount++);
69 };
70
71 auto createGitHubStyleAnchor = [&]()
72 {
73 result.clear();
74 size_t pos=0;
75 while (pos<label.length())
76 {
77 uint8_t bytes = getUTF8CharNumBytes(label[pos]);
78 std::string charStr = getUTF8CharAt(label,pos);
79 uint32_t cUnicode = getUnicodeForUTF8CharAt(label,pos);
80 char c = charStr[0];
81 if (qisspace(c) || c=='-')
82 {
83 result+='-';
84 }
85 else if (c!='_' && isUTF8PunctuationCharacter(cUnicode))
86 {
87 // skip punctuation characters
88 }
89 else // normal UTF8 character
90 {
91 result+=convertUTF8ToLower(charStr);
92 }
93 pos+=bytes;
94 }
95 //printf("label='%s' result='%s'\n",qPrint(label),qPrint(result));
96 if (result.empty()) // fallback use doxygen style anchor
97 {
98 createDoxygenStyleAnchor();
99 }
100 else
101 {
102 result = addPrefixIfNeeded(result);
103 int &count = p->idCount[result];
104 // Add end digits if an identical header already exists
105 if (count>0)
106 {
107 result+="-"+std::to_string(count);
108 }
109 count++;
110 }
111 };
112
113 switch (Config_getEnum(MARKDOWN_ID_STYLE))
114 {
115 case MARKDOWN_ID_STYLE_t::DOXYGEN:
116 createDoxygenStyleAnchor();
117 break;
118 case MARKDOWN_ID_STYLE_t::GITHUB:
119 createGitHubStyleAnchor();
120 break;
121 }
122
123 p->anchorsUsed.insert(result);
124
125 return result;
126}
127
128bool AnchorGenerator::isGenerated(const std::string &anchor) const
129{
130 std::lock_guard lock(p->mutex);
131 return p->anchorsUsed.find(anchor)!=p->anchorsUsed.end();
132}
133
134int AnchorGenerator::reserve(const std::string &anchor)
135{
136 std::lock_guard lock(p->mutex);
137 return p->idCount[anchor]++;
138}
139
140bool AnchorGenerator::looksGenerated(const std::string &anchor)
141{
142 return Config_getEnum(MARKDOWN_ID_STYLE)==MARKDOWN_ID_STYLE_t::DOXYGEN &&
143 QCString(anchor).startsWith("autotoc_md");
144}
145
constexpr auto prefix
Definition anchor.cpp:44
bool isGenerated(const std::string &anchor) const
Returns true iff anchor is one of the generated anchors.
Definition anchor.cpp:128
static AnchorGenerator & instance()
Returns the singleton instance.
Definition anchor.cpp:38
static std::string addPrefixIfNeeded(const std::string &anchor)
Definition anchor.cpp:46
std::string generate(const std::string &title)
generates an anchor for a section with title.
Definition anchor.cpp:59
int reserve(const std::string &anchor)
Reserves a non-generated anchor.
Definition anchor.cpp:134
static bool looksGenerated(const std::string &anchor)
Returns true if anchor is a potentially generated anchor.
Definition anchor.cpp:140
std::unique_ptr< Private > p
Definition anchor.h:54
This is an alternative implementation of QCString.
Definition qcstring.h:101
bool startsWith(const char *s) const
Definition qcstring.h:492
#define Config_getEnum(name)
Definition config.h:35
std::unordered_set< std::string > StringUnorderedSet
Definition containers.h:29
bool qisspace(char c)
Definition qcstring.h:81
StringUnorderedSet anchorsUsed
Definition anchor.cpp:28
std::unordered_map< std::string, int > idCount
Definition anchor.cpp:31
bool isUTF8PunctuationCharacter(uint32_t unicode)
Check if the given Unicode character represents a punctuation character.
Definition utf8.cpp:234
uint32_t getUnicodeForUTF8CharAt(const std::string &input, size_t pos)
Returns the 32bit Unicode value matching character at byte position pos in the UTF8 encoded input.
Definition utf8.cpp:135
std::string convertUTF8ToLower(const std::string &input)
Converts the input string into a lower case version, also taking into account non-ASCII characters th...
Definition utf8.cpp:187
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Definition utf8.cpp:23
std::string getUTF8CharAt(const std::string &input, size_t pos)
Returns the UTF8 character found at byte position pos in the input string.
Definition utf8.cpp:127
Various UTF8 related helper functions.