/* * blogc: A blog compiler. * Copyright (C) 2015 Rafael G. Martins * * This program can be distributed under the terms of the BSD License. * See the file COPYING. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include #include "utils/utils.h" #include "source-parser.h" #include "output.h" typedef enum { SOURCE_START = 1, SOURCE_CONFIG_KEY, SOURCE_CONFIG_VALUE_START, SOURCE_CONFIG_VALUE, SOURCE_SEPARATOR, SOURCE_CONTENT_START, SOURCE_CONTENT, } blogc_source_parser_state_t; blogc_source_t* blogc_source_parse(const char *src, size_t src_len) { size_t current = 0; size_t start = 0; bool error = false; char *key = NULL; char *tmp = NULL; b_trie_t *config = b_trie_new(free); char *content = NULL; blogc_source_parser_state_t state = SOURCE_START; while (current < src_len) { char c = src[current]; switch (state) { case SOURCE_START: if (c == ' ' || c == '\t' || c == '\n' || c == '\r') break; if (c >= 'A' && c <= 'Z') { state = SOURCE_CONFIG_KEY; start = current; break; } if (c == '-') { state = SOURCE_SEPARATOR; break; } error = true; break; case SOURCE_CONFIG_KEY: if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') break; if (c == ':') { key = b_strndup(src + start, current - start); state = SOURCE_CONFIG_VALUE_START; break; } error = true; break; case SOURCE_CONFIG_VALUE_START: if (c != '\n' && c != '\r') { state = SOURCE_CONFIG_VALUE; start = current; break; } error = true; break; case SOURCE_CONFIG_VALUE: if (c == '\n' || c == '\r') { tmp = b_strndup(src + start, current - start); b_trie_insert(config, key, b_strdup(b_str_strip(tmp))); free(tmp); free(key); key = NULL; state = SOURCE_START; } break; case SOURCE_SEPARATOR: if (c == '-') break; if (c == '\n' || c == '\r') { state = SOURCE_CONTENT_START; break; } error = true; break; case SOURCE_CONTENT_START: start = current; state = SOURCE_CONTENT; break; case SOURCE_CONTENT: if (current == (src_len - 1)) content = b_strndup(src + start, src_len - start); break; } if (error) break; current++; } if (error) { free(key); free(content); b_trie_free(config); blogc_parser_syntax_error("source", src, src_len, current); return NULL; } blogc_source_t *rv = malloc(sizeof(blogc_source_t)); rv->config = config; rv->content = content; return rv; } void blogc_source_free(blogc_source_t *source) { if (source == NULL) return; free(source->content); b_trie_free(source->config); free(source); }