Skip to content

Commit

Permalink
Add bml parser and sha256 sum support.
Browse files Browse the repository at this point in the history
  • Loading branch information
bearoso committed Apr 24, 2018
1 parent 048ed08 commit 14c8ebb
Show file tree
Hide file tree
Showing 5 changed files with 562 additions and 1 deletion.
349 changes: 349 additions & 0 deletions bml.cpp
@@ -0,0 +1,349 @@
#include <ctype.h>
#include <vector>
#include <string.h>
#include <stdio.h>

#include "bml.h"

static inline bml_node *bml_node_new(void)
{
bml_node *node = new bml_node;

node->data = NULL;
node->name = NULL;
node->depth = -1;
}

static char *strndup_trim (char *str, int len)
{
int start;
int end;

for (start = 0; str[start] && start != len && isblank (str[start]); start++) {}
if (!str[start] || start >= len)
return strdup ("");

for (end = len - 1; isblank (str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}

return strndup (str + start, end - start + 1);
}

static inline int bml_valid (char c)
{
return (isalnum (c) || c == '-');
}

static inline int islf(char c)
{
return (c == '\r' || c == '\n');
}

static inline unsigned int bml_read_depth (char *data)
{
unsigned int depth;
for (depth = 0; isblank (data[depth]); depth++) {}
return depth;
}

static unsigned int bml_parse_depth (bml_node *node, char **data)
{
unsigned int depth = bml_read_depth (*data);
*data += depth;
node->depth = depth;
}

static char *bml_parse_name (bml_node *node, char **data)
{
int len;

for (len = 0; bml_valid(*(*data + len)); len++) {};

node->name = strndup_trim (*data, len);
*data += len;
}

static void bml_parse_data (bml_node *node, char **data)
{
char *p = *data;
int len;

if (p[0] == '=' && p[1] == '\"')
{
len = 2;
while (p[len] && !islf (p[len]))
len++;
if (p[len] != '\"')
return;

node->data = strndup (p + 2, len - 2);
*data += len + 1;
}
else if (*p == '=')
{
len = 1;
while (p[len] && !islf (p[len]) && p[len] != '"' && p[len] != ' ')
len++;
if (p[len] == '\"')
return;
node->data = strndup_trim (p + 1, len - 1);
*data += len;
}
else if (*p == ':')
{
len = 1;
while (p[len] && !islf (p[len]))
len++;
node->data = strndup_trim (p + 1, len - 1);
*data += len;
}

return;
}

static void bml_skip_empty (char **data)
{
char *p = *data;

while (*p)
{
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)
{
p++;
*data = p;
}
}
}

static char *bml_read_line (char **data)
{
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;
bml_node *n;
int len;

while (*p && !islf (*p))
{
if (*p != ' ')
return;

while (isblank (*p))
p++;
if (p[0] == '/' && p[1] == '/')
break;

n = bml_node_new ();
len = 0;
while (bml_valid (p[len]))
len++;
if (len == 0)
return;
n->name = strndup_trim (p, len);
p += len;
bml_parse_data (n, &p);
node->attr.push_back (n);
}

*data = p;
}

static int contains_space (char *str)
{
for (int i = 0; str[i]; i++)
{
if (isblank (str[i]))
return 1;
}

return 0;
}

static void bml_print_node (bml_node *node, int depth)
{
if (!node)
return;

for (int i = 0; i < depth * 2; i++)
{
printf (" ");
}

if (node->name)
printf ("%s", node->name);

if (node->data)
{
if (contains_space (node->data))
printf (": \"%s\"", node->data);
else
printf (": %s", node->data);
}

for (int i = 0; i < node->attr.size(); i++)
{
if (node->attr[i]->name)
{
printf (" %s", node->attr[i]->name);
if (node->attr[i]->data)
{
if (contains_space (node->attr[i]->data))
printf ("=\"%s\"", node->attr[i]->data);
else
printf ("=%s", node->attr[i]->data);
}
}
}

if (depth >= 0)
printf ("\n");

for (int i = 0; i < node->child.size(); i++)
{
bml_print_node (node->child[i], depth + 1);
}

if (depth == 0)
printf ("\n");
}

void bml_print_node (bml_node *node)
{
bml_print_node (node, -1);
}

static bml_node *bml_parse_node (char **doc)
{
char *line;
bml_node *node = NULL;

if ((line = bml_read_line (doc)))
{
node = bml_node_new ();

bml_parse_depth (node, &line);
bml_parse_name (node, &line);
bml_parse_data (node, &line);
bml_parse_attr (node, &line);
}
else
return NULL;

bml_skip_empty (doc);
while (*doc && bml_read_depth (*doc) > node->depth)
{
bml_node *child = bml_parse_node (doc);

if (child)
node->child.push_back (child);

bml_skip_empty (doc);
}

return node;
}

void bml_free_node (bml_node *node)
{
delete[] (node->name);
delete[] (node->data);

for (int i = 0; i < node->child.size(); i++)
{
bml_free_node (node->child[i]);
delete node->child[i];
}

for (int i = 0; i < node->attr.size(); i++)
{
bml_free_node (node->attr[i]);
delete node->attr[i];
}

return;
}

bml_node *bml_parse (char **doc)
{
bml_node *root = NULL;
bml_node *node = NULL;
char *ptr = *doc;

root = bml_node_new ();

while ((node = bml_parse_node (&ptr)))
{
root->child.push_back (node);
}

if (!root->child.size())
{
delete root;
root = NULL;
}

return root;
}

bml_node *bml_parse_file (char *filename)
{
FILE *file = NULL;
char *buffer = NULL;
int file_size = 0;
bml_node *node = NULL;

file = fopen (filename, "r");

if (!file)
return NULL;

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

node = bml_parse (&buffer);
delete[] buffer;

return node;
}
28 changes: 28 additions & 0 deletions bml.h
@@ -0,0 +1,28 @@
#ifndef __BML_H
#define __BML_H
#include <vector>

typedef struct bml_node
{
char *name;
char *data;

int depth;

std::vector<bml_node *> attr;
std::vector<bml_node *> child;

} bml_node;

bml_node *bml_parse_file (char *filename);

/* Parse character array into BML tree. Destructive to input. */
bml_node *bml_parse (char **buffer);

/* Recursively free bml_node and substructures */
void bml_free_node (bml_node *);

/* Print node structure to stdout */
void bml_print_node (bml_node *);

#endif
2 changes: 1 addition & 1 deletion gtk/configure.ac
Expand Up @@ -9,7 +9,7 @@ if test -z "$CXXFLAGS"; then
CXXFLAGS="$CFLAGS"
fi

EXTRA_FLAGS="-Wall -W -pedantic -Wno-unused-parameter -Wno-unused-but-set-variable"
EXTRA_FLAGS="-Wall -W -pedantic -Wno-unused-parameter"
CFLAGS="$CFLAGS $EXTRA_FLAGS"
CXXFLAGS="$CXXFLAGS $EXTRA_FLAGS"

Expand Down

0 comments on commit 14c8ebb

Please sign in to comment.