Skip to content

Commit f8c1c09

Browse files
committed
Moved citation cross reference searching to a separate function
1 parent 710117b commit f8c1c09

File tree

2 files changed

+119
-86
lines changed

2 files changed

+119
-86
lines changed

src/cite.cpp

Lines changed: 116 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -108,107 +108,139 @@ const char *CitationManager::anchorPrefix() const
108108
return "CITEREF_";
109109
}
110110

111-
void CitationManager::generatePage()
111+
void CitationManager::insertCrossReferencesForBibFile(const QCString &bibFile)
112112
{
113-
//printf("** CitationManager::generatePage() count=%d\n",m_ordering.count());
113+
// sanity checks
114+
if (bibFile.isEmpty())
115+
{
116+
return;
117+
}
118+
QFileInfo fi(bibFile);
119+
if (!fi.exists())
120+
{
121+
err("bib file %s not found!\n",bibFile.data());
122+
return;
123+
}
124+
QFile f(bibFile);
125+
if (!f.open(IO_ReadOnly))
126+
{
127+
err("could not open file %s for reading\n",bibFile.data());
128+
return;
129+
}
114130

115-
// do not generate an empty citations page
116-
if (isEmpty()) return; // nothing to cite
131+
// convert file to string
132+
QCString doc;
133+
QCString input(fi.size()+1);
134+
f.readBlock(input.rawData(),fi.size());
135+
f.close();
136+
input.at(fi.size())='\0';
117137

118-
// 0. add cross references from the bib files to the cite dictionary
119-
QFile f;
120-
const StringVector &citeDataList = Config_getList(CITE_BIB_FILES);
121-
for (const auto &bibdata : citeDataList)
138+
int pos=0;
139+
int s;
140+
141+
// helper lambda function to get the next line of input and update pos accordingly
142+
auto get_next_line = [&input,&pos,&s]()
122143
{
123-
QCString bibFile = bibdata.c_str();
124-
if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
125-
QFileInfo fi(bibFile);
126-
if (fi.exists())
144+
uint prevPos = (uint)pos;
145+
pos=s+1;
146+
return input.mid(prevPos,(uint)(s-prevPos));
147+
};
148+
149+
// helper lambda function to return if the end of the input has reached
150+
auto end_of_input = [&s]()
151+
{
152+
return s==-1;
153+
};
154+
155+
// helper lambda function to proceed to the next line in the input, and update s
156+
// to point to the start of the line. Return true as long as there is a new line.
157+
auto has_next_line = [&input,&pos,&s]()
158+
{
159+
s=input.find('\n',pos);
160+
return s!=-1;
161+
};
162+
163+
// search for citation cross references
164+
QCString citeName;
165+
while (has_next_line())
166+
{
167+
QCString line = get_next_line();
168+
169+
int i;
170+
if (line.stripWhiteSpace().startsWith("@"))
127171
{
128-
if (!bibFile.isEmpty())
172+
// assumption entry like: "@book { name," or "@book { name" (spaces optional)
173+
int j = line.find('{');
174+
// when no {, go hunting for it
175+
while (j==-1 && has_next_line())
129176
{
130-
f.setName(bibFile);
131-
if (!f.open(IO_ReadOnly))
132-
{
133-
err("could not open file %s for reading\n",bibFile.data());
134-
}
135-
QCString doc;
136-
QCString input(fi.size()+1);
137-
f.readBlock(input.rawData(),fi.size());
138-
f.close();
139-
input.at(fi.size())='\0';
140-
int pos=0;
141-
int s;
142-
QCString citeName;
143-
while ((s=input.find('\n',pos))!=-1)
177+
line = get_next_line();
178+
j = line.find('{');
179+
}
180+
// search for the name
181+
citeName = "";
182+
if (!end_of_input() && j!=-1) // to prevent something like "@manual ," and no { found
183+
{
184+
int k = line.find(',',j);
185+
j++;
186+
// found a line "@....{.....,...." or "@.....{....."
187+
// ^=j ^=k ^=j k=-1
188+
while (!end_of_input() && citeName.isEmpty())
144189
{
145-
QCString line = input.mid((uint)pos,(uint)(s-pos));
146-
pos=s+1;
147-
148-
int i;
149-
if ((i = line.find("crossref")) != -1) /* assumption cross reference is on one line and the only item */
190+
if (k!=-1)
191+
{
192+
citeName = line.mid((uint)(j),(uint)(k-j));
193+
}
194+
else
150195
{
151-
int j=line.find("{",i);
152-
int k=line.find("}",i);
153-
if (j!=-1 && k!=-1)
154-
{
155-
QCString crossrefName = line.mid((uint)(j+1),(uint)(k-j-1));
156-
// check if the reference with the cross reference is used
157-
// insert cross refererence when cross reference has not yet been added.
158-
if ((p->entries.find(citeName.data())!=p->entries.end()) &&
159-
(p->entries.find(crossrefName.data())==p->entries.end())) // not found yet
160-
{
161-
insert(crossrefName);
162-
}
163-
}
196+
citeName = line.mid((uint)(j));
164197
}
165-
else if (line.stripWhiteSpace().startsWith("@"))
198+
citeName = citeName.stripWhiteSpace();
199+
j = 0;
200+
if (citeName.isEmpty() && has_next_line())
166201
{
167-
// assumption entry like: "@book { name," or "@book { name" (spaces optional)
168-
int j=line.find("{");
169-
// when no {, go hunting for it
170-
while (j==-1 && (s=input.find('\n',pos))!=-1)
171-
{
172-
line = input.mid((uint)pos,(uint)(s-pos));
173-
j=line.find("{");
174-
pos=s+1;
175-
}
176-
// search for the name
177-
citeName = "";
178-
if (s != -1 && j!= -1) // to prevent something like "@manual ," and no { found
179-
{
180-
int k=line.find(",",j);
181-
j++;
182-
while (s != -1 && citeName.isEmpty())
183-
{
184-
if (k != -1)
185-
{
186-
citeName = line.mid((uint)(j),(uint)(k-j));
187-
}
188-
else
189-
{
190-
citeName = line.mid((uint)(j));
191-
}
192-
citeName = citeName.stripWhiteSpace();
193-
j = 0;
194-
if (citeName.isEmpty() && (s=input.find('\n',pos))!=-1)
195-
{
196-
line = input.mid((uint)pos,(uint)(s-pos));
197-
pos=s+1;
198-
k=line.find(",");
199-
}
200-
}
201-
}
202-
//printf("citeName = #%s#\n",citeName.data());
202+
line = get_next_line();
203+
k = line.find(',');
203204
}
204205
}
205206
}
207+
//printf("citeName = #%s#\n",citeName.data());
206208
}
207-
else if (!fi.exists())
209+
else if ((i=line.find("crossref"))!=-1 && !citeName.isEmpty()) /* assumption cross reference is on one line and the only item */
208210
{
209-
err("bib file %s not found!\n",bibFile.data());
211+
int j = line.find('{',i);
212+
int k = line.find('}',i);
213+
if (j>i && k>j)
214+
{
215+
QCString crossrefName = line.mid((uint)(j+1),(uint)(k-j-1));
216+
// check if the reference with the cross reference is used
217+
// insert cross refererence when cross reference has not yet been added.
218+
if ((p->entries.find(citeName.data())!=p->entries.end()) &&
219+
(p->entries.find(crossrefName.data())==p->entries.end())) // not found yet
220+
{
221+
insert(crossrefName);
222+
}
223+
}
210224
}
211225
}
226+
}
227+
228+
void CitationManager::generatePage()
229+
{
230+
//printf("** CitationManager::generatePage() count=%d\n",m_ordering.count());
231+
232+
// do not generate an empty citations page
233+
if (isEmpty()) return; // nothing to cite
234+
235+
// 0. add cross references from the bib files to the cite dictionary
236+
QFile f;
237+
const StringVector &citeDataList = Config_getList(CITE_BIB_FILES);
238+
for (const auto &bibdata : citeDataList)
239+
{
240+
QCString bibFile = bibdata.c_str();
241+
if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
242+
insertCrossReferencesForBibFile(bibFile);
243+
}
212244

213245
// 1. generate file with markers and citations to OUTPUT_DIRECTORY
214246
QCString outputDir = Config_getString(OUTPUT_DIRECTORY);

src/cite.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* Based on a patch by David Munger
55
*
66
* Permission to use, copy, modify, and distribute this software and its
7-
* documentation under the terms of the GNU General Public License is hereby
8-
* granted. No representations are made about the suitability of this software
7+
* documentation under the terms of the GNU General Public License is hereby
8+
* granted. No representations are made about the suitability of this software
99
* for any purpose. It is provided "as is" without express or implied warranty.
1010
* See the GNU General Public License for more details.
1111
*
@@ -70,6 +70,7 @@ class CitationManager
7070
private:
7171
/** Create the database, with an expected maximum of \a size entries */
7272
CitationManager();
73+
void insertCrossReferencesForBibFile(const QCString &bibFile);
7374
struct Private;
7475
std::unique_ptr<Private> p;
7576
};

0 commit comments

Comments
 (0)