~ubuntu-branches/ubuntu/vivid/debtags/vivid-proposed

« back to all changes in this revision

Viewing changes to libapt-front/apt-front/utils/debdbparser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Enrico Zini
  • Date: 2006-03-18 20:31:47 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20060318203147-d9uzdeong5f5nk14
Tags: 1.5.5
* Added dumpavail command.
* Don't rebuild the database on install: apt-index-watcher does it instead.
  Closes: #357103.
* Compiles with g++ 4.1.  Closes: #357360.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Parser for debian database files
3
 
 *
4
 
 * Copyright (C) 2003  Enrico Zini <enrico@debian.org>
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2.1 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19
 
 */
20
 
 
21
 
#include "debdbparser.h"
22
 
 
23
 
#include <iostream>
24
 
#include <ctype.h>
25
 
 
26
 
using namespace std;
27
 
using namespace Tagcoll;
28
 
using namespace aptFront;
29
 
using namespace utils;
30
 
 
31
 
// Eat spaces and empty lines
32
 
// Returns the number of '\n' encountered
33
 
int DebDBParser::eatSpacesAndEmptyLines() throw (ParserException)
34
 
{
35
 
        int res = 0;
36
 
        int c;
37
 
        while ((c = in.nextChar()) != ParserInput::Eof && (isblank(c) || c == '\n'))
38
 
                if (c == '\n')
39
 
                {
40
 
                        isBOL = true;
41
 
                        //line++;
42
 
                        res++;
43
 
                } else
44
 
                        isBOL = false;
45
 
        
46
 
        if (c == ParserInput::Eof)
47
 
                isEOF = true;
48
 
        else
49
 
                in.pushChar(c);
50
 
 
51
 
        return res;
52
 
}
53
 
 
54
 
// Get the ^([A-Za-z0-9]+) field name
55
 
std::string DebDBParser::getFieldName() throw (ParserException)
56
 
{
57
 
        if (! isBOL)
58
 
                throw ParserException(in, "field must start at the beginning of the line");
59
 
 
60
 
        string res;
61
 
 
62
 
        int c;
63
 
        while ((c = in.nextChar()) != ParserInput::Eof && (isalnum(c) || c == '-'))
64
 
                res += c;
65
 
 
66
 
        if (c == ParserInput::Eof)
67
 
        {
68
 
                isEOF = true;
69
 
                if (!res.empty())
70
 
                        throw ParserException(in, "field is truncated at end of file.  Last line begins with: \"" + res + "\n");
71
 
        } else
72
 
                in.pushChar(c);
73
 
 
74
 
        return res;
75
 
}
76
 
 
77
 
// Eat the \s*: characters that divide the field name and the field
78
 
// data
79
 
void DebDBParser::eatFieldSep() throw (ParserException)
80
 
{
81
 
        int c;
82
 
 
83
 
        while ((c = in.nextChar()) != ParserInput::Eof && isblank(c))
84
 
                ;
85
 
 
86
 
        if (c != ':')
87
 
        {
88
 
                if (c == ParserInput::Eof)
89
 
                {
90
 
                        isEOF = true;
91
 
                        throw ParserException(in, "field is truncated at end of file");
92
 
                } else {
93
 
                        throw ParserException(in, string("invalid character `") + (char)c + "' expecting `:'");
94
 
                }
95
 
        }
96
 
}
97
 
 
98
 
// Get the \s*(.+?)\s*\n of a body line
99
 
void DebDBParser::appendFieldBody(string& body) throw (ParserException)
100
 
{
101
 
        int c;
102
 
 
103
 
        // Skip leading spaces
104
 
        while ((c = in.nextChar()) != ParserInput::Eof && isblank(c))
105
 
                ;
106
 
 
107
 
        // Get the body part
108
 
        for ( ; c != ParserInput::Eof && c != '\n'; c = in.nextChar())
109
 
                body += c;
110
 
 
111
 
        // Delete trailing spaces
112
 
        unsigned int end = body.find_last_not_of(" \t");
113
 
        if (end != string::npos)
114
 
                body.resize(end + 1);
115
 
 
116
 
        if (c == ParserInput::Eof)
117
 
                isEOF = true;
118
 
        else
119
 
        {
120
 
                //line++;
121
 
                isBOL = true;
122
 
        }
123
 
}
124
 
 
125
 
 
126
 
DebDBParser::DebDBParser(ParserInput& input) throw (ParserException) :
127
 
    in(input), isBOL(true), isEOF(false)
128
 
{
129
 
        // Go at the start of the next record
130
 
        eatSpacesAndEmptyLines();
131
 
}
132
 
 
133
 
 
134
 
// Read a record and positions itself at the start of the next one
135
 
// Returns false when there are no more records available
136
 
bool DebDBParser::nextRecord(Record& rec) throw (ParserException)
137
 
{
138
 
        if (isEOF)
139
 
                return false;
140
 
 
141
 
        rec.clear();
142
 
 
143
 
        int n;
144
 
        do {
145
 
                // Read the field name
146
 
                string field = getFieldName();
147
 
                string body;
148
 
 
149
 
                //fprintf(stderr, "Got field: %.*s\n", field.size(), field.data());
150
 
 
151
 
                // Read the colon
152
 
                eatFieldSep();
153
 
 
154
 
                // Read the first line of the field body
155
 
                appendFieldBody(body);
156
 
                //fprintf(stderr, "Got body: %.*s\n", body.size(), body.data());
157
 
 
158
 
                // Read the continuation lines of field body
159
 
                while ((n = eatSpacesAndEmptyLines()) == 0 && ! isBOL)
160
 
                {
161
 
                        body += '\n';
162
 
 
163
 
                        size_t start_size = body.size();
164
 
 
165
 
                        appendFieldBody(body);
166
 
 
167
 
                        // Check for dot-only lines to be changed to empty lines
168
 
                        if (body.size() - start_size == 1 && body[body.size() - 1] == '.')
169
 
                                body.resize(body.size() - 1);
170
 
        
171
 
                        //fprintf(stderr, "Appended body: %.*s\n", body.size(), body.data());
172
 
                }
173
 
                //fprintf(stderr, "Trailing newlines: %d\n", n);
174
 
 
175
 
                
176
 
                rec.insert(pair<string,string>(field, body));
177
 
        } while (!isEOF && !n);
178
 
 
179
 
        return true;
180
 
}
181
 
 
182
 
/*
183
 
void State::read(const char* file)
184
 
{
185
 
        parser p;
186
 
        if (p.open(file))
187
 
        {
188
 
                record rec;
189
 
                int rnum = 1;
190
 
                while (p.nextRecord(rec))
191
 
                {
192
 
                        //fprintf(stderr, "Got record:\n");
193
 
                        //for (record::const_iterator i = rec.begin(); i != rec.end(); i++)
194
 
                                //fprintf(stderr, "\t%.*s: %.*s\n", i->first.size(), i->first.data(), i->second.size(), i->second.data());
195
 
 
196
 
                        // Get record values
197
 
                        
198
 
                        // Variable name
199
 
                        record::const_iterator i = rec.find("Name");
200
 
                        if (i == rec.end())
201
 
                                throw ParserException(file, p.getLine(),
202
 
                                                "No Name: field found in record %d", rnum);
203
 
                        if (find(i->second) != end())
204
 
                                throw ParserException(file, p.getLine(),
205
 
                                                "Duplicate record %d for variable %.*s", rnum,
206
 
                                                (int)i->second.size(), i->second.data());
207
 
                        const string& name = i->second;
208
 
 
209
 
                        // Variable description
210
 
                        i = rec.find("Description");
211
 
                        if (i == rec.end())
212
 
                                throw ParserException(file, p.getLine(),
213
 
                                                "No Description: field found in record %d for %.*s",
214
 
                                                rnum, (int)name.size(), name.data());
215
 
                        const string& desc = i->second;
216
 
 
217
 
                        // Variable type (bool if omitted)
218
 
                        Variable::Type type = Variable::vBOOL;
219
 
                        i = rec.find("Type");
220
 
                        if (i != rec.end())
221
 
                                if (i->second == "enum")
222
 
                                        type = Variable::vENUM;
223
 
                                else if (i->second != "bool")
224
 
                                        throw ParserException(file, p.getLine(),
225
 
                                                        "Invalid type %.*s for variable %.*s",
226
 
                                                        (int)i->second.size(), i->second.data(),
227
 
                                                        (int)name.size(), name.data());
228
 
                        
229
 
                        Variable* var = 0;
230
 
                        switch (type)
231
 
                        {
232
 
                                case Variable::vBOOL:
233
 
                                {
234
 
                                        // Default value (defaults to 'false')
235
 
                                        i = rec.find("Default");
236
 
                                        bool val = false;
237
 
                                        if (i != rec.end())
238
 
                                                if (i->second == "true")
239
 
                                                        val = true;
240
 
                                                else if (i->second == "false")
241
 
                                                        val = false;
242
 
                                                else
243
 
                                                        throw ParserException(file, p.getLine(),
244
 
                                                                "Invalid value `%.*s' for Default: field in"
245
 
                                                                " record %d for variable %.*s",
246
 
                                                                        (int)i->second.size(), i->second.data(), rnum,
247
 
                                                                        (int)name.size(), name.data());
248
 
                                        var = new BoolVariable(name, desc, val);
249
 
                                        break;
250
 
                                }
251
 
                                case Variable::vENUM:
252
 
                                {
253
 
                                        // Domain for the enum: comma-separated list of
254
 
                                        // [^ ,]+ or "<string with \<char> escapes"
255
 
                                        record::iterator i = rec.find("Domain");
256
 
                                        if (i == rec.end())
257
 
                                                throw ParserException(file, p.getLine(),
258
 
                                                                "No Domain: field found for enum `%.*s'"
259
 
                                                                " in record %d", (int)name.size(), name.data(),
260
 
                                                                rnum);
261
 
                                        string& domainstr = i->second;
262
 
                                        EnumDomain domain;
263
 
 
264
 
                                        // Parse the domain enumeration
265
 
                                        parse_enum_domain(domainstr, domain, file, p.getLine());
266
 
 
267
 
                                        // Default value (mandatory for enums)
268
 
                                        i = rec.find("Default");
269
 
                                        if (i == rec.end())
270
 
                                                throw ParserException(file, p.getLine(),
271
 
                                                                "No Default: field found in record %d for enum `%.*s'",
272
 
                                                                rnum, (int)name.size(), name.data());
273
 
                                        const string& val = i->second;
274
 
 
275
 
                                        var = new EnumVariable(name, desc, val, domain);
276
 
                                        break;
277
 
                                }
278
 
                        }
279
 
 
280
 
                        insert(pair<string, Variable*>(name, var));
281
 
                        rec.clear();
282
 
                        rnum++;
283
 
                }
284
 
        }
285
 
        p.close();
286
 
}
287
 
*/
288
 
 
289
 
// vim:set ts=4 sw=4: