This repository has been archived by the owner on Apr 18, 2023. It is now read-only.
/
config_parser.h
182 lines (137 loc) · 5.04 KB
/
config_parser.h
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright 2009 Daniel Erat <dan@erat.org>
// All rights reserved.
#ifndef __XSETTINGSD_CONFIG_PARSER_H__
#define __XSETTINGSD_CONFIG_PARSER_H__
#include <map>
#include <stdint.h>
#include <string>
#ifdef __TESTING
#include <gtest/gtest_prod.h>
#endif
#include "common.h"
namespace xsettingsd {
class Setting;
class SettingsMap;
// Doing the parsing by hand like this for a line-based config format is
// pretty much the worst idea ever -- it would've been much easier to use
// libpcrecpp. :-( The tests all pass, though, for whatever that's worth.
class ConfigParser {
public:
class CharStream;
// The parser takes ownership of 'stream', which must be uninitialized
// (that is, its Init() method shouldn't have been called yet).
explicit ConfigParser(CharStream* stream);
~ConfigParser();
// Returns a formatted string describing a parse error. Can be called
// after Parse() returns false.
std::string FormatError() const;
// Reset the parser to read from a new stream.
void Reset(CharStream* stream);
// Parse the data in the stream into 'settings', using 'prev_settings'
// (pass the previous version if it exists or NULL otherwise) and
// 'serial' (the new serial number) to determine which serial number each
// setting should have. This method calls the stream's Init() method;
// don't do it beforehand.
bool Parse(SettingsMap* settings,
const SettingsMap* prev_settings,
uint32_t serial);
// Abstract base class for reading a stream of characters.
class CharStream {
public:
CharStream()
: initialized_(false),
have_buffered_char_(false),
buffered_char_(0),
at_line_end_(true),
prev_at_line_end_(false),
line_num_(0) {
}
virtual ~CharStream() {}
int line_num() const { return line_num_; }
// Must be called before using the stream.
// The stream is unusable if false is returned.
bool Init(std::string* error_out);
// Are we currently at the end of the stream?
bool AtEOF();
// Get the next character in the stream.
int GetChar();
// Push a previously-read character back onto the stream.
// At most one character can be buffered.
void UngetChar(int ch);
private:
virtual bool InitImpl(std::string* error_out) { return true; }
virtual bool AtEOFImpl() = 0;
virtual int GetCharImpl() = 0;
// Has Init() been called?
bool initialized_;
// Has a character been returned with UngetChar() but not yet re-read?
bool have_buffered_char_;
// The character returned by UngetChar().
int buffered_char_;
// Are we currently at the end of the line?
bool at_line_end_;
bool prev_at_line_end_;
// The line number of the last-fetched character.
int line_num_;
DISALLOW_COPY_AND_ASSIGN(CharStream);
};
// An implementation of CharStream that reads from a file.
class FileCharStream : public CharStream {
public:
FileCharStream(const std::string& filename);
~FileCharStream();
private:
bool InitImpl(std::string* error_out);
bool AtEOFImpl();
int GetCharImpl();
std::string filename_;
FILE* file_;
DISALLOW_COPY_AND_ASSIGN(FileCharStream);
};
// An implementation of CharStream that reads from an in-memory string.
class StringCharStream : public CharStream {
public:
StringCharStream(const std::string& data);
private:
bool AtEOFImpl();
int GetCharImpl();
std::string data_;
size_t pos_;
DISALLOW_COPY_AND_ASSIGN(StringCharStream);
};
private:
#ifdef __TESTING
friend class ConfigParserTest;
FRIEND_TEST(ConfigParserTest, ReadSettingName);
#endif
// Read a setting name starting at the current position in the stream.
// Returns false if the setting name is invalid.
bool ReadSettingName(std::string* name_out);
// Read the value starting at the current position in the stream.
// Its type is inferred from the first character. 'setting_ptr' is
// updated to point at a newly-allocated Setting object (which the caller
// is responsible for deleting).
bool ReadValue(Setting** setting_ptr);
// Read an integer starting at the current position in the stream.
bool ReadInteger(int32_t* int_out);
// Read a double-quoted string starting at the current position in the
// stream.
bool ReadString(std::string* str_out);
// Read a color of the form "(red, green, blue, alpha)" or "(red, green,
// blue)".
bool ReadColor(uint16_t* red_out, uint16_t* green_out,
uint16_t* blue_out, uint16_t* alpha_out);
// Record an error to 'error_str_', also saving the stream's current line
// number to 'error_line_num_'.
void SetErrorF(const char* format, ...);
// Stream from which the config is being parsed.
CharStream* stream_;
// If an error was encountered while parsing, the line number where
// it happened and a string describing it. Line 0 is used for errors
// occuring before making any progress into the file.
int error_line_num_;
std::string error_str_;
DISALLOW_COPY_AND_ASSIGN(ConfigParser);
};
} // namespace
#endif