3
A brief file description
5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
24
/***************************************************************************
28
***************************************************************************/
33
/*--- for stand-alone testing
34
#define xstrdup strdup
36
#define xmalloc malloc
38
#define ink_isspace isspace
41
/*-------------------------------------------------------------------------
43
-------------------------------------------------------------------------*/
45
InkXmlAttr::InkXmlAttr(char *tag, char *value)
48
m_value = xstrdup(value);
51
InkXmlAttr::~InkXmlAttr()
58
InkXmlAttr::display(FILE * fd)
60
fprintf(fd, " <%s,%s>\n", m_tag, m_value);
63
/*-------------------------------------------------------------------------
65
-------------------------------------------------------------------------*/
67
InkXmlObject::InkXmlObject(char *object_name, bool dup_attrs_allowed)
69
m_object_name = xstrdup(object_name);
70
m_dup_attrs_allowed = dup_attrs_allowed;
73
InkXmlObject::~InkXmlObject()
80
InkXmlObject::clear_tags()
83
while ((attr = m_tags.dequeue())) {
89
InkXmlObject::add_tag(char *tag, char *value)
91
ink_assert(tag != NULL);
92
ink_assert(value != NULL);
94
InkXmlAttr *attr = NEW(new InkXmlAttr(tag, value));
95
return add_attr(attr);
99
InkXmlObject::add_attr(InkXmlAttr * attr)
101
ink_assert(attr != NULL);
103
if (!m_dup_attrs_allowed) {
104
for (InkXmlAttr * a = first(); a; a = next(a)) {
105
if (!strcmp(a->tag(), attr->tag())) {
106
Debug("xml", "tag %s already exists & dups not allowed", attr->tag());
111
m_tags.enqueue(attr);
116
InkXmlObject::tag_value(char *tag_name)
118
ink_assert(tag_name != NULL);
120
for (InkXmlAttr * a = first(); a; a = next(a)) {
121
if (!strcmp(a->tag(), tag_name)) {
129
InkXmlObject::display(FILE * fd)
131
fprintf(fd, "<%s>\n", m_object_name);
132
for (InkXmlAttr * a = first(); a; a = next(a)) {
137
/*-------------------------------------------------------------------------
139
-------------------------------------------------------------------------*/
141
InkXmlConfigFile::InkXmlConfigFile(char *config_file):
145
m_config_file = xstrdup(config_file);
148
InkXmlConfigFile::~InkXmlConfigFile()
150
xfree(m_config_file);
155
InkXmlConfigFile::clear_objects()
158
while ((obj = m_objects.dequeue())) {
165
InkXmlConfigFile::parse(int fd)
168
Debug("log", "Parsing XML config info from memory..");
174
while ((obj = get_next_xml_object(fd)) != NULL) {
175
Debug("log", "Adding XML object <%s>", obj->object_name());
185
InkXmlConfigFile::parse()
187
ink_assert(m_config_file != NULL);
188
Debug("xml", "Parsing XML config file %s ...", m_config_file);
190
int fd =::open(m_config_file, O_RDONLY);
192
Debug("xml", "Error opening %s: %d, %s", m_config_file, fd, strerror(errno));
200
while ((obj = get_next_xml_object(fd)) != NULL) {
201
Debug("xml", "Adding XML object <%s>", obj->object_name());
210
InkXmlConfigFile::find_object(char *object_name)
212
for (InkXmlObject * obj = first(); obj; obj = next(obj)) {
213
if (!strcmp(object_name, obj->object_name())) {
221
InkXmlConfigFile::display(FILE * fd)
226
for (i = 0; i < strlen(m_config_file) + 13; i++)
228
fprintf(fd, "\nConfig File: %s\n", m_config_file);
229
for (i = 0; i < strlen(m_config_file) + 13; i++)
232
for (InkXmlObject * obj = first(); obj; obj = next(obj)) {
239
InkXmlConfigFile::add_object(InkXmlObject * object)
241
ink_assert(object != NULL);
242
m_objects.enqueue(object);
245
/*-------------------------------------------------------------------------
246
InkXmlConfigFile::get_next_xml_object()
248
This routine (and its friends) does the real work of parsing the given
249
open file for the next XML object.
250
-------------------------------------------------------------------------*/
253
InkXmlConfigFile::get_next_xml_object(int fd)
258
bool start_object = false;
260
while ((token = next_token(fd)) != EOF) {
269
return parse_error();
270
if ((token = scan_comment(fd)) == EOF) {
273
Debug("xml", "comment scanned");
274
start_object = false;
279
return parse_error();
280
return scan_object(fd, token);
287
InkXmlConfigFile::parse_error()
289
Debug("xml", "Invalid XML tag, line %u, col %u", m_line, m_col);
293
#define BAD_ATTR ((InkXmlAttr*)1)
296
InkXmlConfigFile::scan_object(int fd, char token)
298
// this routine is called just after the first '<' is read for a new
301
const int max_ident_len = 2048;
302
char ident[max_ident_len];
305
while (token != '>' && ident_len < max_ident_len) {
306
ident[ident_len++] = token;
307
token = next_token(fd);
309
return parse_error();
311
if (!ident_len || ident_len >= max_ident_len) {
312
return parse_error();
315
ident[ident_len] = 0;
316
InkXmlObject *obj = new InkXmlObject(ident);
317
ink_assert(obj != NULL);
320
while ((attr = scan_attr(fd, ident)) != NULL) {
321
if (attr == BAD_ATTR) {
322
return parse_error();
331
InkXmlConfigFile::scan_attr(int fd, char *id)
333
// this routine is called after the object identifier has been scannedm
334
// and should attempt to scan for the next attribute set. When we see
335
// the end of the object (closing identifier), we scan it and return
336
// NULL for the attribute, signalling that there are no more
339
char token, prev, next;
340
const int buf_size = 2048;
342
char value[buf_size];
343
char ident[buf_size];
344
char *write_to = NULL;
346
bool start_attr = false;
347
bool in_quotes = false;
348
InkXmlAttr *attr = NULL;
351
while ((token = next_token(fd, !in_quotes)) != EOF) {
354
if (in_quotes && write_to) {
355
if (write_len >= buf_size)
357
write_to[write_len++] = token;
366
if (in_quotes && write_to) {
367
if (write_len >= buf_size)
369
write_to[write_len++] = token;
374
write_to[write_len] = 0;
382
// escape the quote, just replace the backslash
384
write_to[write_len - 1] = token;
388
in_quotes = !in_quotes;
392
if (in_quotes && write_to) {
393
if (write_len >= buf_size)
395
write_to[write_len++] = token;
402
token = next_token(fd, !in_quotes);
403
while (token != '>' && write_len < buf_size) {
404
ident[write_len++] = token;
405
token = next_token(fd, !in_quotes);
409
if (!write_len || write_len >= buf_size) {
412
ident[write_len] = 0;
413
if (strcmp(ident, id) != 0)
418
next = next_token(fd, !in_quotes);
421
write_to[write_len] = 0;
422
attr = new InkXmlAttr(name, value);
423
ink_assert(attr != NULL);
427
if (in_quotes && write_to) {
428
if (write_len >= buf_size)
430
write_to[write_len++] = token;
433
// seen at this point, this is an error, probably becase
434
// the person forgot the trailing '/'.
440
if (write_len >= buf_size)
442
write_to[write_len++] = token;
451
InkXmlConfigFile::next_token(int fd, bool eat_whitespace)
454
while (read(fd, &ch, 1) == 1) {
461
if (eat_whitespace && ParseRules::is_space(ch))
469
InkXmlConfigFile::scan_comment(int fd)
471
// this routine is called when we're just past a "<!" in the file. we
472
// need to skip until we find the matching '>'.
474
int lt_stack = 1; // we've already seen one '<' character
476
while ((token = next_token(fd)) != EOF) {