blob: a6c5ca9cf2efc94a188c76a4fe02839669f06ce7 [file] [log] [blame]
#ifndef ODIN_BUFFER_HPP
#define ODIN_BUFFER_HPP
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include "vtr_memory.h"
#define CHUNK_SIZE 128
/* General Utility methods ------------------------------------------------- */
class dynamic_buffer_t
{
private:
char *str = NULL;
size_t len = 0;
public:
void push(char in)
{
if(this->len % CHUNK_SIZE == 0)
{
this->str = (char*) vtr::realloc(this->str, sizeof(char) * (this->len + CHUNK_SIZE));
memset(&this->str[this->len], 0, CHUNK_SIZE);
}
this->str[this->len] = in;
this->len += 1;
}
char *dump_str()
{
char *temp = str;
str = NULL;
return temp;
}
};
class buffered_reader_t
{
private:
FILE *source = NULL;
bool eof = false;
bool multiline_comment = false;
const char *one_line_comment = "";
size_t one_line_comment_len = 0;
const char *n_line_comment_ST = "";
size_t n_line_comment_ST_len = 0;
const char *n_line_comment_END = "";
size_t n_line_comment_END_len = 0;
size_t buffer_size = 2;
static bool is_eof(int in)
{
return (EOF == in);
}
static bool is_nl(int in)
{
return is_eof(in) || ('\n' == (char)in || '\r' == (char)in);
}
static bool is_whitespace(int in)
{
return is_nl(in) || ( ' ' == (char)in || '\t' == (char)in);
}
bool is_one_line_comment(const char *in)
{
return (one_line_comment_len && strncmp (in, one_line_comment, one_line_comment_len) == 0);
}
bool is_n_line_comment_ST(const char *in)
{
return (n_line_comment_ST_len && strncmp (in, n_line_comment_ST, n_line_comment_ST_len) == 0);
}
bool is_n_line_comment_END(const char *in)
{
return (n_line_comment_END_len && strncmp (in, n_line_comment_END, n_line_comment_END_len) == 0);
}
buffered_reader_t(){}
public:
buffered_reader_t(FILE *_source, const char *_one_line_comment, const char *_n_line_comment_ST, const char *_n_line_comment_END)
{
this->source = _source;
if(_one_line_comment)
{
this->one_line_comment = _one_line_comment;
this->one_line_comment_len = strlen(_one_line_comment);
}
if(_n_line_comment_ST && _n_line_comment_END)
{
this->n_line_comment_ST = _n_line_comment_ST;
this->n_line_comment_END = _n_line_comment_END;
this->n_line_comment_ST_len = strlen(_n_line_comment_ST);
this->n_line_comment_END_len = strlen(_n_line_comment_END);
}
this->buffer_size = (
std::max((size_t)2, // for whitespace duplicate
std::max(one_line_comment_len,
std::max(n_line_comment_ST_len,
n_line_comment_END_len)))
);
}
/*
* Reads a line from a file stream character-by-character
* to dynamically build a string.
* strip duplicate whitespace
* skip comments
*/
char* get_line()
{
char *line = NULL;
if(!(eof))
{
dynamic_buffer_t my_line;
char *buffer = (char*) vtr::calloc(this->buffer_size, sizeof(char));
bool single_line_comment = false;
size_t skip_count = this->buffer_size-1;
bool eol = false;
bool first_write = true;
// trim head and compress
while( !is_nl(buffer[0]) )
{
int c = '\n';
if(!eol && !(eof))
c = fgetc(source);
for(int i = 1; i < this->buffer_size; i++)
{
buffer[i-1] = buffer[i];
}
buffer[this->buffer_size-1] = (char)c;
eof = (eof || is_eof(c));
eol = (eol || is_nl(c));
if(skip_count)
{
skip_count--;
}
else if( multiline_comment )
{
if(is_n_line_comment_END(buffer))
{
multiline_comment = false;
skip_count = strlen(n_line_comment_END);
}
}
else if( single_line_comment )
{
// read until the end
}
else if(is_one_line_comment(buffer))
{
single_line_comment = true;
}
else if(is_n_line_comment_ST(buffer))
{
multiline_comment = true;
}
else if( ! is_whitespace(buffer[0]) )
{
first_write = false;
my_line.push(buffer[0]);
}
else if( ! is_whitespace(buffer[1]) )
{
if( ! first_write )
my_line.push(' ');
}
}
vtr::free(buffer);
my_line.push('\0');
line = my_line.dump_str();
}
return line;
}
};
#endif //ODIN_BUFFER_HPP