diff --git a/source/snes9x/bml.cpp b/source/snes9x/bml.cpp index 9bfe800..df2531e 100644 --- a/source/snes9x/bml.cpp +++ b/source/snes9x/bml.cpp @@ -1,5 +1,7 @@ #include -#include +#include +#include +#include #include #include "port.h" @@ -7,6 +9,7 @@ bml_node::bml_node() { + type = CHILD; depth = -1; } @@ -20,6 +23,11 @@ static inline int isblank(char c) return (c == ' ' || c == '\t'); } +static inline int isblankorlf(char c) +{ + return (islf(c) || isblank(c)); +} + static inline int isalnum(char c) { return ((c >= 'a' && c <= 'z') || @@ -27,172 +35,151 @@ static inline int isalnum(char c) (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) { int start; 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()) 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); } -static inline unsigned int bml_read_depth(char *data) +static std::string trimcomments(std::string str) { - unsigned int depth; - for (depth = 0; isblank(data[depth]); depth++) {} - return depth; + int end = str.length(); + size_t comment = str.find("//"); + 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); - *data += depth; + size_t 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; } -static void bml_parse_name(bml_node &node, char **data) +static void bml_parse_name(bml_node &node, std::string &line) { 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)); - *data += len; + node.name = trim(line.substr(0, 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; - if (p[0] == '=' && p[1] == '\"') + if (line[0] == '=' && line[1] == '\"') { len = 2; - while (p[len] && p[len] != '\"' && !islf(p[len])) + while (line[len] && line[len] != '\"' && !islf(line[len])) len++; - if (p[len] != '\"') + if (line[len] != '\"') return; - node.data = std::string(p + 2, len - 2); - *data += len + 1; + node.data = line.substr(2, len - 2); + line.erase(0, len + 1); } - else if (*p == '=') + else if (line[0] == '=') { len = 1; - while (p[len] && !islf(p[len]) && p[len] != '"' && p[len] != ' ') + while (line[len] && !islf(line[len]) && line[len] != '"' && line[len] != ' ') len++; - if (p[len] == '\"') + if (line[len] == '\"') return; - node.data = std::string(p + 1, len - 1); - *data += len; + node.data = line.substr(1, len - 1); + line.erase(0, len); } - else if (*p == ':') + else if (line[0] == ':') { len = 1; - while (p[len] && !islf(p[len])) + while (line[len] && !islf(line[len])) len++; - node.data = std::string(p + 1, len - 1); - *data += len; + node.data = line.substr(1, len - 1); + line.erase(0, len); } 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++) {} - - if (!islf(p[0]) && (p[0] != '/' && p[1] != '/')) - return; - - /* Skip comment data */ - while (*p && *p != '\r' && *p != '\n') - p++; - - /* If we found new-line, try to skip more */ - if (*p) + std::getline(fd, line); + line = trimcomments(line); + if (!line.empty()) { - p++; - *data = p; + return line; } } + + 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; - while (*p && !islf(*p)) + while (line.length() > 0) { - if (*p != ' ') + if (!isblank(line[0])) return; - while (isblank(*p)) - p++; - if (p[0] == '/' && p[1] == '/') - break; + while (isblank(line[0])) + line.erase(0, 1); bml_node n; len = 0; - while (bml_valid(p[len])) + while (bml_valid(line[len])) len++; if (len == 0) return; - n.name = trim(std::string(p, len)); - p += len; - bml_parse_data(n, &p); - n.depth = bml_attr_type; + n.name = trim(line.substr(0, len)); + line.erase(0, len); + bml_parse_data(n, line); + n.depth = node.depth + 1; + n.type = bml_node::ATTRIBUTE; 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++) { - if (isblank (str[i])) + if (isblank(str[i])) return 1; } @@ -205,44 +192,44 @@ static void bml_print_node(bml_node &node, int depth) for (i = 0; i < depth * 2; i++) { - printf (" "); + printf(" "); } if (!node.name.empty()) - printf ("%s", node.name.c_str()); + printf("%s", node.name.c_str()); if (!node.data.empty()) { if (contains_space(node.data.c_str())) - printf ("=\"%s\"", node.data.c_str()); + printf("=\"%s\"", node.data.c_str()); else - printf (": %s", node.data.c_str()); + printf(": %s", node.data.c_str()); } - for (i = 0; i < (int) node.child.size () && node.child[i].depth == bml_attr_type; i++) + for (i = 0; i < (int)node.child.size() && node.child[i].type == bml_node::ATTRIBUTE; i++) { 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 (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 - printf ("=%s", node.child[i].data.c_str()); + printf("=%s", node.child[i].data.c_str()); } } } 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) - printf ("\n"); + printf("\n"); } void bml_node::print() @@ -250,53 +237,39 @@ void bml_node::print() bml_print_node(*this, -1); } -static bml_node bml_parse_node(char **doc) +void bml_node::parse(std::ifstream &fd) { - char *line; - bml_node node; + std::stack nodestack; + nodestack.push(this); - if ((line = bml_read_line(doc))) + while (fd) { - bml_parse_depth(node, &line); - bml_parse_name(node, &line); - bml_parse_data(node, &line); - bml_parse_attr(node, &line); - } - else - return node; + bml_node newnode; + std::string line = bml_read_line(fd); + if (line.empty()) + return; - bml_skip_empty(doc); - while (*doc && (int)bml_read_depth(*doc) > node.depth) - { - bml_node child = bml_parse_node(doc); + int line_depth = bml_read_depth(line); + while (line_depth <= nodestack.top()->depth && nodestack.size() > 1) + nodestack.pop(); - if (child.depth != -1) - node.child.push_back(child); + bml_parse_depth(newnode, line); + bml_parse_name(newnode, line); + bml_parse_data(newnode, line); + bml_parse_attr(newnode, line); - bml_skip_empty(doc); - } - - 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); + nodestack.top()->child.push_back(newnode); + nodestack.push(&nodestack.top()->child.back()); } return; } -bml_node *bml_node::find_subnode (std::string name) +bml_node *bml_node::find_subnode(std::string name) { unsigned int i; - for (i = 0; i < child.size (); i++) + for (i = 0; i < child.size(); i++) { if (name.compare(child[i].name) == 0) return &child[i]; @@ -305,28 +278,14 @@ bml_node *bml_node::find_subnode (std::string name) return NULL; } -bool bml_node::parse_file(const char *filename) +bool bml_node::parse_file(std::string filename) { - FILE *file = NULL; - char *buffer = NULL; - int file_size = 0; - - file = fopen(filename, "rb"); + std::ifstream file(filename.c_str(), std::ios_base::binary); if (!file) return false; - fseek(file, 0, SEEK_END); - 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; + parse(file); return true; } diff --git a/source/snes9x/bml.h b/source/snes9x/bml.h index d1dd5c3..56b6006 100644 --- a/source/snes9x/bml.h +++ b/source/snes9x/bml.h @@ -2,22 +2,26 @@ #define __BML_H #include #include - -const int bml_attr_type = -2; +#include struct bml_node { + enum node_type { + CHILD, + ATTRIBUTE + }; + bml_node(); - bool parse_file(const char *filename); - void parse(char *buffer); + bool parse_file(std::string filename); + void parse(std::ifstream &fd); bml_node *find_subnode(std::string name); void print(); - static const int bml_attr_type = -2; std::string name; std::string data; int depth; std::vector child; + node_type type; }; #endif