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 return (Config_getEnum(MARKDOWN_ID_STYLE) == MARKDOWN_ID_STYLE_t::GITHUB &&
49 (anchor.empty() || anchor.front() == '-' || std::isdigit(anchor.front())))
50 ? prefix + anchor : anchor;
51}
52
53std::string AnchorGenerator::generate(const std::string &label)
54{
55 std::lock_guard lock(p->mutex);
56
57 std::string result;
58
59 auto createDoxygenStyleAnchor = [&]()
60 {
61 // overwrite result with the doxygen style anchor
62 result = prefix+std::to_string(p->anchorCount++);
63 };
64
65 auto createGitHubStyleAnchor = [&]()
66 {
67 result.clear();
68 size_t pos=0;
69 while (pos<label.length())
70 {
71 uint8_t bytes = getUTF8CharNumBytes(label[pos]);
72 std::string charStr = getUTF8CharAt(label,pos);
73 uint32_t cUnicode = getUnicodeForUTF8CharAt(label,pos);
74 char c = charStr[0];
75 if (qisspace(c) || c=='-')
76 {
77 result+='-';
78 }
79 else if (c!='_' && isUTF8PunctuationCharacter(cUnicode))
80 {
81 // skip punctuation characters
82 }
83 else // normal UTF8 character
84 {
85 result+=convertUTF8ToLower(charStr);
86 }
87 pos+=bytes;
88 }
89 //printf("label='%s' result='%s'\n",qPrint(label),qPrint(result));
90 if (result.empty()) // fallback use doxygen style anchor
91 {
92 createDoxygenStyleAnchor();
93 }
94 else
95 {
96 result = addPrefixIfNeeded(result);
97 int &count = p->idCount[result];
98 // Add end digits if an identical header already exists
99 if (count>0)
100 {
101 result+="-"+std::to_string(count);
102 }
103 count++;
104 }
105 };
106
107 switch (Config_getEnum(MARKDOWN_ID_STYLE))
108 {
109 case MARKDOWN_ID_STYLE_t::DOXYGEN:
110 createDoxygenStyleAnchor();
111 break;
112 case MARKDOWN_ID_STYLE_t::GITHUB:
113 createGitHubStyleAnchor();
114 break;
115 }
116
117 p->anchorsUsed.insert(result);
118
119 return result;
120}
121
122bool AnchorGenerator::isGenerated(const std::string &anchor) const
123{
124 std::lock_guard lock(p->mutex);
125 return p->anchorsUsed.find(anchor)!=p->anchorsUsed.end();
126}
127
128int AnchorGenerator::reserve(const std::string &anchor)
129{
130 std::lock_guard lock(p->mutex);
131 return p->idCount[anchor]++;
132}
133
134bool AnchorGenerator::looksGenerated(const std::string &anchor)
135{
136 return Config_getEnum(MARKDOWN_ID_STYLE)==MARKDOWN_ID_STYLE_t::DOXYGEN &&
137 QCString(anchor).startsWith(prefix);
138}
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:122
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:53
int reserve(const std::string &anchor)
Reserves a non-generated anchor.
Definition anchor.cpp:128
static bool looksGenerated(const std::string &anchor)
Returns true if anchor is a potentially generated anchor.
Definition anchor.cpp:134
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:507
#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.