File: bibtexparser.cpp

package info (click to toggle)
texstudio 2.11.2%2Bdebian-1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 41,292 kB
  • ctags: 12,405
  • sloc: cpp: 93,072; xml: 10,217; ansic: 4,153; sh: 145; makefile: 56
file content (93 lines) | stat: -rw-r--r-- 2,803 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "bibtexparser.h"

bool	BibTeXFileInfo::loadIfModified(const QFileInfo &fi)
{
	QDateTime fileLastModified = fi.lastModified();
	if (lastModified != fileLastModified) { //load BibTeX iff modified
		lastModified = fileLastModified;
		load(fi);
		return true;
	}
	return false;
}

void BibTeXFileInfo::load(const QFileInfo &fi)
{
	//lastModified=lastModified; see above
	QFile f(fi.absoluteFilePath());
	if (!f.open(QFile::ReadOnly)) return; //ups...
	QByteArray data = f.readAll().trimmed();
	parse(data);
}

void BibTeXFileInfo::parse(QByteArray &data)
{
	ids.clear();
	linksTo.clear();
	if (data.startsWith("link ")) {
		//handle obscure bib tex feature, a just line containing "link fileName"
		linksTo  = QString::fromLatin1(data.constData(), data.count()).mid(5).trimmed();
	} else {
		enum BibTeXState {BTS_IN_SPACE,  //searches the first @, ignore everything before it
		                  BTS_IN_TYPE,   //read until bracket ( or { e.g in @article{, reset if @comment
		                  BTS_IN_ID,     //read everything until bracket close or , and ignore whitespace, reset when = or "
		                  BTS_IN_DATA_KEY
		                 }; //read balanced bracket until all are closed, then reset
		enum BibTeXState state = BTS_IN_SPACE;
		const char *comment = "comment\0";
		const char *COMMENT = "COMMENT\0";
		int typeLen = 0;
		bool commentPossible = false;
		int bracketBalance = 0;
		char bracketOpen = 0;
		char bracketClose = 0;
		QByteArray curID;
		for (int j = 0; j < data.count(); j++) {
			char c = data.at(j);
			switch (state) {
			case BTS_IN_SPACE:
				if (c == '@') {
					state = BTS_IN_TYPE;
					commentPossible = true;
					typeLen = 0;
				}
				break;
			case BTS_IN_TYPE:
				if (c == '(' || c == '{') {
					bracketOpen = c;
					if (c == '(') bracketClose = ')';
					if (c == '{') bracketClose = '}';
					bracketBalance = 1;
					curID = "";
					state = BTS_IN_ID;
				} else if (commentPossible && (comment[typeLen] == c || COMMENT[typeLen] == c)) {
					if (comment[typeLen + 1] == '\0') state = BTS_IN_SPACE; //comment found
				} else commentPossible = false;
				typeLen++;
				break;
			case BTS_IN_ID:
				if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
					if (c == ',' || c == bracketClose) {
						if (!curID.isEmpty()) {
							if (codec)
								ids.insert(codec->toUnicode(curID)); //**found id**
							else
								ids.insert(curID);
						}
						state = BTS_IN_DATA_KEY;
					} else if (c == '=' || c == '"')
						state = BTS_IN_DATA_KEY; //@string or @preamble (don't cite that)
					else curID += c;
				}
				break;
			case BTS_IN_DATA_KEY:
				if (c == bracketOpen) bracketBalance++;
				else if (c == bracketClose) {
					bracketBalance--;
					if (bracketBalance <= 0) state = BTS_IN_SPACE;
				}
				break;
			}
		}
	}
}