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" #include "utils.hpp"
using std::cerr; using std::cerr;
using std::string_view; /* using std::string_view; */
using std::string; using std::string;
using std::vector;
using std::pair;
namespace /* internal */ namespace /* internal */
{ {
char* data; struct alloced
char* data_end; /* past the end pointer */ {
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; unsigned line = 1;
/* state */ /* state */
@@ -39,13 +56,13 @@ namespace /* internal */
void proceedToNameEnd() void proceedToNameEnd()
{ {
while(data < data_end && while(it_data < end_data &&
*data != ',' && *it_data != ',' &&
*data != '\n') *it_data != '\n')
{ {
if(*data == ':' /* && *data == '-' */) if(*it_data == ':' /* && *it_data == '-' */)
unexpected_char(*data); unexpected_char(*it_data);
++data; ++it_data;
} }
} }
@@ -53,80 +70,196 @@ namespace /* internal */
Sex findSex() Sex findSex()
{ {
Sex res = M; Sex res = M;
if(*data == ',') if(*it_data == ',')
{ {
++data; ++it_data;
if(*data == 'M') if(*it_data == 'M')
res = M; res = M;
else if(*data == 'F') else if(*it_data == 'F')
res = F; res = F;
else else
unexpected_char(*data); unexpected_char(*it_data);
++data; ++it_data;
if(*data != '\n') if(*it_data != '\n')
unexpected_char(*data); unexpected_char(*it_data);
} }
return res; 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() void state_neutral()
{ {
for(; data < data_end; ++data) for(; it_data < end_data; ++it_data)
{ {
switch(*data) switch(*it_data)
{ {
default: default:
state_person(); state_person();
return;
break; break;
case '\n': case '\n':
++line; ++line;
break; break;
/* case '#': */
/* state = state_comment; */
/* return; */
case ',': case ',':
case '-': case '-':
case 0 ... 9: case 0 ... 9:
case ':': case ':':
unexpected_char(*data); unexpected_char(*it_data);
} }
} }
} }
void state_person() void state_person()
{ {
char* name_start = data; char* name_start = it_data;
person_id parent1; pair<person_id, person_id> parents;
person_id parent2; person_id spouse;
EventTime birth; EventTime birth{};
EventTime death; EventTime death{};
proceedToNameEnd(); proceedToNameEnd();
/* string_view name(name_start, data); */ /* string_view name(name_start, it_data); */
string name(name_start, data); string name(name_start, it_data);
Sex sex = findSex(); Sex sex = findSex();
for(; data < data_end; ++data) for(; it_data < end_data; ++it_data)
{ {
switch(*data) switch(*it_data)
{ {
case '\n': case '\n':
++line; ++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 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; break;
/* case '#': */ /* case '#': */
@@ -134,23 +267,51 @@ namespace /* internal */
/* return; */ /* return; */
/* case 0...9: */ /* case 0...9: */
/* case ':': */ /* case ':': */
/* unexpected_char(*data); */ /* unexpected_char(*it_data); */
default: default:
break; 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) Tree parseTftFile(MappedFile file)
{ {
data = file.data;
data_end = file.data + file.len;
Tree result("name"); Tree result("name");
cur_tree = &result; cur_tree = &result;
alloced preprocessed = preprocess(file);
it_data = preprocessed.data;
end_data = preprocessed.end;
state_neutral(); state_neutral();
return result; return result;