preprocess tft files

This commit is contained in:
vrd
2023-02-22 22:36:12 +02:00
parent 78408bd223
commit 864d40cb81
+201 -40
View File
@@ -5,13 +5,30 @@
#include "utils.hpp"
using std::cerr;
using std::string_view;
/* using std::string_view; */
using std::string;
using std::vector;
using std::pair;
namespace /* internal */
{
char* data;
char* data_end; /* past the end pointer */
struct alloced
{
char* const data;
char* const end;
alloced(U32 len)
: data(new char[len])
, end(data + len)
{
}
~alloced()
{
delete[] data;
}
};
char* it_data;
char* end_data; /* past the end pointer */
unsigned line = 1;
/* state */
@@ -39,13 +56,13 @@ namespace /* internal */
void proceedToNameEnd()
{
while(data < data_end &&
*data != ',' &&
*data != '\n')
while(it_data < end_data &&
*it_data != ',' &&
*it_data != '\n')
{
if(*data == ':' /* && *data == '-' */)
unexpected_char(*data);
++data;
if(*it_data == ':' /* && *it_data == '-' */)
unexpected_char(*it_data);
++it_data;
}
}
@@ -53,80 +70,196 @@ namespace /* internal */
Sex findSex()
{
Sex res = M;
if(*data == ',')
if(*it_data == ',')
{
++data;
if(*data == 'M')
++it_data;
if(*it_data == 'M')
res = M;
else if(*data == 'F')
else if(*it_data == 'F')
res = F;
else
unexpected_char(*data);
unexpected_char(*it_data);
++data;
if(*data != '\n')
unexpected_char(*data);
++it_data;
if(*it_data != '\n')
unexpected_char(*it_data);
}
return res;
}
void processAtribute()
I32 processDatePart()
{
I32 sign = 1;
I32 val = 0;
for(; it_data < end_data; ++it_data)
{
switch(*it_data)
{
case '-':
sign = -1;
break;
case '0' ... '9':
val = val*10 + *it_data;
break;
case '.':
if(val == 0)
unexpected_char('.');
else
return sign * val;
break;
case '\n':
++line;
return sign * val;
/* case '?': todo */
default:
unexpected_char(*it_data);
}
}
unexpected_end();
}
EventTime processDate() /* todo validate */
{
EventTime date;
date.year = processDatePart();
if(*it_data == '.')
{
++it_data;
date.month = processDatePart();
if(*it_data == '.')
{
++it_data;
date.day = processDatePart();
}
}
return date;
}
pair<person_id, person_id> processParents()
{
pair<person_id, person_id> res(Nobody, Nobody);
string name; /* todo dont use string */
for(; it_data < end_data; ++it_data)
{
switch(*it_data)
{
/* case '-':todo */
case ',':
if(res.first == Nobody)
res.first = cur_tree->findId(name.data());
else if(res.second == Nobody)
res.second = cur_tree->findId(name.data());
else
/* todo */exit(1);
name.clear();
break;
case '\n':
++line;
if(res.first == Nobody)
res.first = cur_tree->findId(name.data());
else
res.second = cur_tree->findId(name.data());
return res;
default:
name.push_back(*it_data);
}
}
}
vector<person_id> parseSpouses()
{
vector<person_id> res;
string name;
for(; it_data < end_data; ++it_data)
{
switch(*it_data)
{
case ',':
res.push_back( cur_tree->findId(name.data()) );
name.clear();
break;
case '\n':
++line;
res.push_back( cur_tree->findId(name.data()) );
return res;
default:
name.push_back(*it_data);
}
}
/* return res;todo */
}
void state_neutral()
{
for(; data < data_end; ++data)
for(; it_data < end_data; ++it_data)
{
switch(*data)
switch(*it_data)
{
default:
state_person();
return;
break;
case '\n':
++line;
break;
/* case '#': */
/* state = state_comment; */
/* return; */
case ',':
case '-':
case 0 ... 9:
case ':':
unexpected_char(*data);
unexpected_char(*it_data);
}
}
}
void state_person()
{
char* name_start = data;
person_id parent1;
person_id parent2;
EventTime birth;
EventTime death;
char* name_start = it_data;
pair<person_id, person_id> parents;
person_id spouse;
EventTime birth{};
EventTime death{};
proceedToNameEnd();
/* string_view name(name_start, data); */
string name(name_start, data);
/* string_view name(name_start, it_data); */
string name(name_start, it_data);
Sex sex = findSex();
for(; data < data_end; ++data)
for(; it_data < end_data; ++it_data)
{
switch(*data)
switch(*it_data)
{
case '\n':
++line;
if(data[1] == ':') /* todo */
++it_data;
if(it_data[1] == ':') /* todo */
{
processAtribute();
switch(*it_data)
{
case 'b':
it_data += 2;
birth = processDate();
break;
case 'd':
it_data += 2;
death = processDate();
break;
case 'p':
it_data += 2;
processParents();
case 's':
it_data += 2;
parseSpouses();
default:
unexpected_char(it_data[-1]);
}
}
else
{
cur_tree->addPerson(name.c_str(), sex/* , parent1, parent2, birth, death */);
cur_tree->addPerson(name.c_str(), sex, parents.first, parents.second, birth, death);
return;
}
break;
/* case '#': */
@@ -134,23 +267,51 @@ namespace /* internal */
/* return; */
/* case 0...9: */
/* case ':': */
/* unexpected_char(*data); */
/* unexpected_char(*it_data); */
default:
break;
}
}
}
alloced preprocess(MappedFile file) /* remove whitespace and comments */
{
alloced res(file.len);
char* end = file.data + file.len;
for(char* it = file.data, * itres = res.data; it < end; ++it)
{
switch(*it)
{
case '#':
while(++it != end && *it != '\n'); /* skip comment */
*itres++ = '\n'; /* add \n */
break;
case ' ':
case '\t':
case '\r':
break;
default:
*itres = *it;
++itres;
}
}
return res;
}
}
Tree parseTftFile(MappedFile file)
{
data = file.data;
data_end = file.data + file.len;
Tree result("name");
cur_tree = &result;
alloced preprocessed = preprocess(file);
it_data = preprocessed.data;
end_data = preprocessed.end;
state_neutral();
return result;