C++ification of bml parser.

This commit is contained in:
Brandon Wright 2019-06-02 19:09:52 -05:00
parent abed48e2d0
commit 124323f614
2 changed files with 115 additions and 157 deletions

267
bml.cpp
View File

@ -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
View File

@ -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();