C++ification of bml parser.
This commit is contained in:
parent
abed48e2d0
commit
124323f614
267
bml.cpp
267
bml.cpp
@ -1,5 +1,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string.h>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stack>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
@ -21,6 +23,11 @@ static inline int isblank(char c)
|
|||||||
return (c == ' ' || c == '\t');
|
return (c == ' ' || c == '\t');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int isblankorlf(char c)
|
||||||
|
{
|
||||||
|
return (islf(c) || isblank(c));
|
||||||
|
}
|
||||||
|
|
||||||
static inline int isalnum(char c)
|
static inline int isalnum(char c)
|
||||||
{
|
{
|
||||||
return ((c >= 'a' && c <= 'z') ||
|
return ((c >= 'a' && c <= 'z') ||
|
||||||
@ -28,173 +35,151 @@ static inline int isalnum(char c)
|
|||||||
(c >= '0' && c <= '9'));
|
(c >= '0' && c <= '9'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int bml_valid (char c)
|
static inline int bml_valid(char c)
|
||||||
{
|
{
|
||||||
return (isalnum (c) || c == '-');
|
return (isalnum(c) || c == '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string trim(std::string str)
|
static std::string trim(std::string str)
|
||||||
{
|
{
|
||||||
int start;
|
int start;
|
||||||
int end;
|
int end;
|
||||||
for (start = 0; str[start] && start != (int)str.length() && isblank (str[start]); start++) {}
|
for (start = 0; str[start] && start != (int)str.length() && isblank(str[start]); start++) {}
|
||||||
if (start >= (int)str.length())
|
if (start >= (int)str.length())
|
||||||
return std::string("");
|
return std::string("");
|
||||||
for (end = str.length() - 1; isblank (str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}
|
for (end = str.length() - 1; isblank(str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}
|
||||||
return str.substr(start, end - start + 1);
|
return str.substr(start, end - start + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int bml_read_depth(char *data)
|
static std::string trimcomments(std::string str)
|
||||||
{
|
{
|
||||||
unsigned int depth;
|
int end = str.length();
|
||||||
for (depth = 0; isblank(data[depth]); depth++) {}
|
size_t comment = str.find("//");
|
||||||
return depth;
|
if (comment != std::string::npos)
|
||||||
|
end = comment;
|
||||||
|
|
||||||
|
for (int i = end - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (!isblankorlf(str[i]))
|
||||||
|
{
|
||||||
|
end = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.substr(0, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bml_parse_depth(bml_node &node, char **data)
|
static inline int bml_read_depth(std::string &data)
|
||||||
{
|
{
|
||||||
unsigned int depth = bml_read_depth(*data);
|
size_t depth;
|
||||||
*data += depth;
|
for (depth = 0; isblank(data[depth]) && depth < data.length(); depth++) {}
|
||||||
|
return depth == data.length() ? -1 : depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bml_parse_depth(bml_node &node, std::string &line)
|
||||||
|
{
|
||||||
|
unsigned int depth = bml_read_depth(line);
|
||||||
|
line.erase(0, depth);
|
||||||
node.depth = depth;
|
node.depth = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bml_parse_name(bml_node &node, char **data)
|
static void bml_parse_name(bml_node &node, std::string &line)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (len = 0; bml_valid(*(*data + len)); len++) {};
|
for (len = 0; bml_valid(line[len]); len++) {};
|
||||||
|
|
||||||
node.name = trim(std::string(*data, len));
|
node.name = trim(line.substr(0, len));
|
||||||
*data += len;
|
line.erase(0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bml_parse_data(bml_node &node, char **data)
|
static void bml_parse_data(bml_node &node, std::string &line)
|
||||||
{
|
{
|
||||||
char *p = *data;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (p[0] == '=' && p[1] == '\"')
|
if (line[0] == '=' && line[1] == '\"')
|
||||||
{
|
{
|
||||||
len = 2;
|
len = 2;
|
||||||
while (p[len] && p[len] != '\"' && !islf(p[len]))
|
while (line[len] && line[len] != '\"' && !islf(line[len]))
|
||||||
len++;
|
len++;
|
||||||
if (p[len] != '\"')
|
if (line[len] != '\"')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
node.data = std::string(p + 2, len - 2);
|
node.data = line.substr(2, len - 2);
|
||||||
*data += len + 1;
|
line.erase(0, len + 1);
|
||||||
}
|
}
|
||||||
else if (*p == '=')
|
else if (line[0] == '=')
|
||||||
{
|
{
|
||||||
len = 1;
|
len = 1;
|
||||||
while (p[len] && !islf(p[len]) && p[len] != '"' && p[len] != ' ')
|
while (line[len] && !islf(line[len]) && line[len] != '"' && line[len] != ' ')
|
||||||
len++;
|
len++;
|
||||||
if (p[len] == '\"')
|
if (line[len] == '\"')
|
||||||
return;
|
return;
|
||||||
node.data = std::string(p + 1, len - 1);
|
node.data = line.substr(1, len - 1);
|
||||||
*data += len;
|
line.erase(0, len);
|
||||||
}
|
}
|
||||||
else if (*p == ':')
|
else if (line[0] == ':')
|
||||||
{
|
{
|
||||||
len = 1;
|
len = 1;
|
||||||
while (p[len] && !islf(p[len]))
|
while (line[len] && !islf(line[len]))
|
||||||
len++;
|
len++;
|
||||||
node.data = std::string(p + 1, len - 1);
|
node.data = line.substr(1, len - 1);
|
||||||
*data += len;
|
line.erase(0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bml_skip_empty(char **data)
|
static std::string bml_read_line(std::ifstream &fd)
|
||||||
{
|
{
|
||||||
char *p = *data;
|
std::string line;
|
||||||
|
|
||||||
while (*p)
|
while (fd)
|
||||||
{
|
{
|
||||||
for (; *p && isblank (*p) ; p++) {}
|
std::getline(fd, line);
|
||||||
|
line = trimcomments(line);
|
||||||
if (!islf(p[0]) && (p[0] != '/' && p[1] != '/'))
|
if (!line.empty())
|
||||||
return;
|
|
||||||
|
|
||||||
/* Skip comment data */
|
|
||||||
while (*p && *p != '\r' && *p != '\n')
|
|
||||||
p++;
|
|
||||||
|
|
||||||
/* If we found new-line, try to skip more */
|
|
||||||
if (*p)
|
|
||||||
{
|
{
|
||||||
p++;
|
return line;
|
||||||
*data = p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::string("");
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *bml_read_line (char **data)
|
static void bml_parse_attr(bml_node &node, std::string &line)
|
||||||
{
|
{
|
||||||
char *line;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
bml_skip_empty (data);
|
|
||||||
|
|
||||||
line = *data;
|
|
||||||
|
|
||||||
if (line == NULL || *line == '\0')
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
p = strpbrk (line, "\r\n\0");
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (islf (*p))
|
|
||||||
{
|
|
||||||
*p = '\0';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*data = p;
|
|
||||||
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bml_parse_attr(bml_node &node, char **data)
|
|
||||||
{
|
|
||||||
char *p = *data;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
while (*p && !islf(*p))
|
while (line.length() > 0)
|
||||||
{
|
{
|
||||||
if (*p != ' ')
|
if (!isblank(line[0]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (isblank(*p))
|
while (isblank(line[0]))
|
||||||
p++;
|
line.erase(0, 1);
|
||||||
if (p[0] == '/' && p[1] == '/')
|
|
||||||
break;
|
|
||||||
|
|
||||||
bml_node n;
|
bml_node n;
|
||||||
len = 0;
|
len = 0;
|
||||||
while (bml_valid(p[len]))
|
while (bml_valid(line[len]))
|
||||||
len++;
|
len++;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return;
|
return;
|
||||||
n.name = trim(std::string(p, len));
|
n.name = trim(line.substr(0, len));
|
||||||
p += len;
|
line.erase(0, len);
|
||||||
bml_parse_data(n, &p);
|
bml_parse_data(n, line);
|
||||||
n.depth = node.depth + 1;
|
n.depth = node.depth + 1;
|
||||||
n.type = bml_node::CHILD;
|
n.type = bml_node::ATTRIBUTE;
|
||||||
node.child.push_back(n);
|
node.child.push_back(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int contains_space (const char *str)
|
static int contains_space(const char *str)
|
||||||
{
|
{
|
||||||
for (int i = 0; str[i]; i++)
|
for (int i = 0; str[i]; i++)
|
||||||
{
|
{
|
||||||
if (isblank (str[i]))
|
if (isblank(str[i]))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,44 +192,44 @@ static void bml_print_node(bml_node &node, int depth)
|
|||||||
|
|
||||||
for (i = 0; i < depth * 2; i++)
|
for (i = 0; i < depth * 2; i++)
|
||||||
{
|
{
|
||||||
printf (" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.name.empty())
|
if (!node.name.empty())
|
||||||
printf ("%s", node.name.c_str());
|
printf("%s", node.name.c_str());
|
||||||
|
|
||||||
if (!node.data.empty())
|
if (!node.data.empty())
|
||||||
{
|
{
|
||||||
if (contains_space(node.data.c_str()))
|
if (contains_space(node.data.c_str()))
|
||||||
printf ("=\"%s\"", node.data.c_str());
|
printf("=\"%s\"", node.data.c_str());
|
||||||
else
|
else
|
||||||
printf (": %s", node.data.c_str());
|
printf(": %s", node.data.c_str());
|
||||||
}
|
}
|
||||||
for (i = 0; i < (int) node.child.size () && node.child[i].type == bml_node::CHILD; i++)
|
for (i = 0; i < (int)node.child.size() && node.child[i].type == bml_node::ATTRIBUTE; i++)
|
||||||
{
|
{
|
||||||
if (!node.child[i].name.empty())
|
if (!node.child[i].name.empty())
|
||||||
{
|
{
|
||||||
printf (" %s", node.child[i].name.c_str());
|
printf(" %s", node.child[i].name.c_str());
|
||||||
if (!node.child[i].data.empty())
|
if (!node.child[i].data.empty())
|
||||||
{
|
{
|
||||||
if (contains_space(node.child[i].data.c_str()))
|
if (contains_space(node.child[i].data.c_str()))
|
||||||
printf ("=\"%s\"", node.child[i].data.c_str());
|
printf("=\"%s\"", node.child[i].data.c_str());
|
||||||
else
|
else
|
||||||
printf ("=%s", node.child[i].data.c_str());
|
printf("=%s", node.child[i].data.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth >= 0)
|
if (depth >= 0)
|
||||||
printf ("\n");
|
printf("\n");
|
||||||
|
|
||||||
for (; i < (int) node.child.size(); i++)
|
for (; i < (int)node.child.size(); i++)
|
||||||
{
|
{
|
||||||
bml_print_node (node.child[i], depth + 1);
|
bml_print_node(node.child[i], depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
printf ("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void bml_node::print()
|
void bml_node::print()
|
||||||
@ -252,53 +237,39 @@ void bml_node::print()
|
|||||||
bml_print_node(*this, -1);
|
bml_print_node(*this, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bml_node bml_parse_node(char **doc)
|
void bml_node::parse(std::ifstream &fd)
|
||||||
{
|
{
|
||||||
char *line;
|
std::stack<bml_node *> nodestack;
|
||||||
bml_node node;
|
nodestack.push(this);
|
||||||
|
|
||||||
if ((line = bml_read_line(doc)))
|
while (fd)
|
||||||
{
|
{
|
||||||
bml_parse_depth(node, &line);
|
bml_node newnode;
|
||||||
bml_parse_name(node, &line);
|
std::string line = bml_read_line(fd);
|
||||||
bml_parse_data(node, &line);
|
if (line.empty())
|
||||||
bml_parse_attr(node, &line);
|
return;
|
||||||
}
|
|
||||||
else
|
|
||||||
return node;
|
|
||||||
|
|
||||||
bml_skip_empty(doc);
|
int line_depth = bml_read_depth(line);
|
||||||
while (*doc && (int)bml_read_depth(*doc) > node.depth)
|
while (line_depth <= nodestack.top()->depth && nodestack.size() > 1)
|
||||||
{
|
nodestack.pop();
|
||||||
bml_node child = bml_parse_node(doc);
|
|
||||||
|
|
||||||
if (child.depth != -1)
|
bml_parse_depth(newnode, line);
|
||||||
node.child.push_back(child);
|
bml_parse_name(newnode, line);
|
||||||
|
bml_parse_data(newnode, line);
|
||||||
|
bml_parse_attr(newnode, line);
|
||||||
|
|
||||||
bml_skip_empty(doc);
|
nodestack.top()->child.push_back(newnode);
|
||||||
}
|
nodestack.push(&nodestack.top()->child.back());
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bml_node::parse(char *doc)
|
|
||||||
{
|
|
||||||
bml_node node;
|
|
||||||
char *ptr = doc;
|
|
||||||
|
|
||||||
while ((node = bml_parse_node (&ptr)).depth != -1)
|
|
||||||
{
|
|
||||||
child.push_back(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bml_node *bml_node::find_subnode (std::string name)
|
bml_node *bml_node::find_subnode(std::string name)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < child.size (); i++)
|
for (i = 0; i < child.size(); i++)
|
||||||
{
|
{
|
||||||
if (name.compare(child[i].name) == 0)
|
if (name.compare(child[i].name) == 0)
|
||||||
return &child[i];
|
return &child[i];
|
||||||
@ -307,28 +278,14 @@ bml_node *bml_node::find_subnode (std::string name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bml_node::parse_file(const char *filename)
|
bool bml_node::parse_file(std::string filename)
|
||||||
{
|
{
|
||||||
FILE *file = NULL;
|
std::ifstream file(filename, std::ios_base::binary);
|
||||||
char *buffer = NULL;
|
|
||||||
int file_size = 0;
|
|
||||||
|
|
||||||
file = fopen(filename, "rb");
|
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
parse(file);
|
||||||
file_size = ftell(file);
|
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
|
|
||||||
buffer = new char[file_size + 1];
|
|
||||||
fread(buffer, file_size, 1, file);
|
|
||||||
buffer[file_size] = '\0';
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
parse(buffer);
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
5
bml.h
5
bml.h
@ -2,6 +2,7 @@
|
|||||||
#define __BML_H
|
#define __BML_H
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
struct bml_node
|
struct bml_node
|
||||||
{
|
{
|
||||||
@ -11,8 +12,8 @@ struct bml_node
|
|||||||
};
|
};
|
||||||
|
|
||||||
bml_node();
|
bml_node();
|
||||||
bool parse_file(const char *filename);
|
bool parse_file(std::string filename);
|
||||||
void parse(char *buffer);
|
void parse(std::ifstream &fd);
|
||||||
bml_node *find_subnode(std::string name);
|
bml_node *find_subnode(std::string name);
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user