new tree file format
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
#include <iostream>
|
||||
/* #include <string_view> */
|
||||
#include <string>
|
||||
#include "tree.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
using std::cerr;
|
||||
using std::string_view;
|
||||
using std::string;
|
||||
|
||||
namespace /* internal */
|
||||
{
|
||||
char* data;
|
||||
char* data_end; /* past the end pointer */
|
||||
unsigned line = 1;
|
||||
|
||||
/* state */
|
||||
void (*state)(); /* current state */
|
||||
void state_neutral();
|
||||
void state_person();
|
||||
/* void state_person_attribute() */
|
||||
|
||||
/* result */
|
||||
Tree* cur_tree;
|
||||
|
||||
|
||||
void unexpected_char(char c)
|
||||
{
|
||||
cerr << "Line " << line << ": Unexpected '" << c << "'\n";
|
||||
exit(1);
|
||||
/* throw 0; */
|
||||
}
|
||||
|
||||
void unexpected_end()
|
||||
{
|
||||
cerr << "Unexpected end of file";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void proceedToNameEnd()
|
||||
{
|
||||
while(data < data_end &&
|
||||
*data != ',' &&
|
||||
*data != '\n')
|
||||
{
|
||||
if(*data == ':' /* && *data == '-' */)
|
||||
unexpected_char(*data);
|
||||
++data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Sex findSex()
|
||||
{
|
||||
Sex res = M;
|
||||
if(*data == ',')
|
||||
{
|
||||
++data;
|
||||
if(*data == 'M')
|
||||
res = M;
|
||||
else if(*data == 'F')
|
||||
res = F;
|
||||
else
|
||||
unexpected_char(*data);
|
||||
|
||||
++data;
|
||||
if(*data != '\n')
|
||||
unexpected_char(*data);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void processAtribute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void state_neutral()
|
||||
{
|
||||
for(; data < data_end; ++data)
|
||||
{
|
||||
switch(*data)
|
||||
{
|
||||
default:
|
||||
state_person();
|
||||
return;
|
||||
break;
|
||||
case '\n':
|
||||
++line;
|
||||
break;
|
||||
/* case '#': */
|
||||
/* state = state_comment; */
|
||||
/* return; */
|
||||
case ',':
|
||||
case '-':
|
||||
case 0 ... 9:
|
||||
case ':':
|
||||
unexpected_char(*data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void state_person()
|
||||
{
|
||||
char* name_start = data;
|
||||
person_id parent1;
|
||||
person_id parent2;
|
||||
EventTime birth;
|
||||
EventTime death;
|
||||
|
||||
proceedToNameEnd();
|
||||
/* string_view name(name_start, data); */
|
||||
string name(name_start, data);
|
||||
|
||||
Sex sex = findSex();
|
||||
|
||||
for(; data < data_end; ++data)
|
||||
{
|
||||
switch(*data)
|
||||
{
|
||||
case '\n':
|
||||
++line;
|
||||
if(data[1] == ':') /* todo */
|
||||
{
|
||||
processAtribute();
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_tree->addPerson(name.c_str(), sex/* , parent1, parent2, birth, death */);
|
||||
}
|
||||
break;
|
||||
/* case '#': */
|
||||
/* state = state_comment; */
|
||||
/* return; */
|
||||
/* case 0...9: */
|
||||
/* case ':': */
|
||||
/* unexpected_char(*data); */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tree parseTftFile(MappedFile file)
|
||||
{
|
||||
data = file.data;
|
||||
data_end = file.data + file.len;
|
||||
|
||||
Tree result("name");
|
||||
cur_tree = &result;
|
||||
|
||||
state_neutral();
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "tree.hpp"
|
||||
|
||||
Tree parseTftFile(MappedFile file);
|
||||
+6
-11
@@ -60,10 +60,10 @@ void EventTime::print() const
|
||||
}
|
||||
|
||||
|
||||
Person::Person(const char* name, EventTime birth, bool isMale, EventTime death)
|
||||
Person::Person(const char* name, EventTime birth, Sex sex, EventTime death)
|
||||
: name_(name)
|
||||
, birth_(birth)
|
||||
, isMale_(isMale)
|
||||
, sex(sex)
|
||||
, death_(death)
|
||||
{
|
||||
}
|
||||
@@ -71,7 +71,7 @@ Person::Person(const char* name, EventTime birth, bool isMale, EventTime death)
|
||||
|
||||
bool Person::operator==(const Person &other)const
|
||||
{
|
||||
return name_ == other.name_; //&& isMale_ == other.isMale_; //TODO && day == other.day || !day || !other.day) && (month == other.month || !month || !other.month) && (year == other.year || !year || !other.year);
|
||||
return name_ == other.name_; //&& sex == other.sex; //TODO && day == other.day || !day || !other.day) && (month == other.month || !month || !other.month) && (year == other.year || !year || !other.year);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ void Person::write(std::ofstream &file)const
|
||||
char nameLen = name_.size();
|
||||
file.write(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
|
||||
file.write(name_.data(), nameLen * sizeof(name_[0]));
|
||||
file.write(reinterpret_cast<const char*>(&isMale_), sizeof(isMale_));
|
||||
file.write(reinterpret_cast<const char*>(&sex), sizeof(sex));
|
||||
//file.write(reinterpret_cast<const char*>(&day), sizeof(day)); TODO
|
||||
//file.write(reinterpret_cast<const char*>(&month), sizeof(month));
|
||||
//file.write(reinterpret_cast<const char*>(&year), sizeof(year));
|
||||
@@ -97,7 +97,7 @@ void Person::read(std::ifstream &file)
|
||||
nameBuf[nameLen] = '\0';
|
||||
name_ = nameBuf;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&isMale_), sizeof(isMale_));
|
||||
file.read(reinterpret_cast<char*>(&sex), sizeof(sex));
|
||||
//file.read(reinterpret_cast<char*>(&day), sizeof(day)); TODO
|
||||
//file.read(reinterpret_cast<char*>(&month), sizeof(month));
|
||||
//file.read(reinterpret_cast<char*>(&year), sizeof(year));
|
||||
@@ -132,11 +132,6 @@ void Person::displayInfo()const
|
||||
}
|
||||
|
||||
|
||||
bool Person::isMale() const
|
||||
{
|
||||
return isMale_;
|
||||
}
|
||||
|
||||
static U16 strUtf8Symbols(const std::string& str)
|
||||
{
|
||||
U16 num = 0;
|
||||
@@ -172,7 +167,7 @@ void Person::draw(const I16 drawY, const I16 drawX, bool selected, bool hasSpous
|
||||
WINDOW* pad = newpad(BOX_HEIGHT, width);
|
||||
|
||||
auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED
|
||||
: (isMale_ ? COLOR_MALE : COLOR_FEMALE) );
|
||||
: (sex ? COLOR_MALE : COLOR_FEMALE) );
|
||||
|
||||
wbkgd(pad, color_pair);
|
||||
/* wattron(pad, color_pair); */
|
||||
|
||||
+5
-7
@@ -20,10 +20,10 @@ struct EventTime
|
||||
I8 minute; //0-59
|
||||
};
|
||||
|
||||
enum Genders: U8
|
||||
enum Sex: U8
|
||||
{
|
||||
FEMALE = 0,
|
||||
MALE
|
||||
M = 0,
|
||||
F
|
||||
};
|
||||
|
||||
enum BoxColors: U8 {
|
||||
@@ -41,7 +41,7 @@ class Person
|
||||
{
|
||||
public:
|
||||
Person() = default;
|
||||
Person(const char* name, EventTime birth={}, bool sex=true, EventTime death={});
|
||||
Person(const char* name, EventTime birth={}, Sex=M, EventTime death={});
|
||||
/* Person(Person&&) = default; */
|
||||
/* Person& operator=(Person&&) = default; */
|
||||
/* Person& operator=(const Person&) = default; */
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
|
||||
void displayInfo() const;
|
||||
|
||||
bool isMale() const;
|
||||
const EventTime& birth() const { return birth_; };
|
||||
U16 boxWidth() const;
|
||||
|
||||
@@ -63,9 +62,8 @@ public:
|
||||
returns the width of the box*/
|
||||
void draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasChildren=false) const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
EventTime birth_;
|
||||
bool isMale_;
|
||||
Sex sex;
|
||||
EventTime death_;
|
||||
};
|
||||
|
||||
+27
-23
@@ -2,6 +2,7 @@
|
||||
#include <iostream>
|
||||
#include "tree.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
|
||||
/* using std::cin; */
|
||||
@@ -10,27 +11,30 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
init();
|
||||
|
||||
auto f = mapfile("example_tree.tft");
|
||||
parseTftFile(f).display();
|
||||
|
||||
Tree test1("Dechkovi");
|
||||
test1.loadFromFile();
|
||||
|
||||
|
||||
/* test1.addPerson("Rumen", true, Nobody, Nobody, {1968, 8, 9}); */
|
||||
/* test1.addPerson("Nadejda", false, Nobody, Nobody, {1972, 12, 15}); */
|
||||
/* test1.addPerson("Rumen", M, Nobody, Nobody, {1968, 8, 9}); */
|
||||
/* test1.addPerson("Nadejda", F, Nobody, Nobody, {1972, 12, 15}); */
|
||||
/* test1.addRelation(0, Spouse, 1); */
|
||||
/* test1.addPerson("Venelin", true, 0, 1, {1998, 6, 9}); */
|
||||
/* test1.addPerson("Vasil", true, 0, 1, {2001, 1, 16}); */
|
||||
/* test1.addPerson("Venelin", M, 0, 1, {1998, 6, 9}); */
|
||||
/* test1.addPerson("Vasil", M, 0, 1, {2001, 1, 16}); */
|
||||
/* test1.saveToFile(); */
|
||||
|
||||
Tree test2("Karamanovi");
|
||||
test2.addPerson("Vasil Dimitrov", true, Nobody, Nobody, {1941, 5, 18});
|
||||
test2.addPerson("Maria", false);
|
||||
test2.addPerson("Vasil Dimitrov", M, Nobody, Nobody, {1941, 5, 18});
|
||||
test2.addPerson("Maria", F);
|
||||
test2.addRelation(0, Spouse, 1);
|
||||
test2.addPerson("Dimitar", true, 0, 1);
|
||||
test2.addPerson("Nadejda", false, 0, 1, {1972, 12, 15});
|
||||
test2.addPerson("Branimira", false);
|
||||
test2.addPerson("Dimitar", M, 0, 1);
|
||||
test2.addPerson("Nadejda", F, 0, 1, {1972, 12, 15});
|
||||
test2.addPerson("Branimira", F);
|
||||
test2.addRelation(2, Spouse, 4);
|
||||
test2.addPerson("Ioan", true, 2, 4);
|
||||
test2.addPerson("Rumiana", false, 2, 4);
|
||||
test2.addPerson("Ioan", M, 2, 4);
|
||||
test2.addPerson("Rumiana", F, 2, 4);
|
||||
|
||||
test1.display();
|
||||
test2.display();
|
||||
@@ -38,25 +42,25 @@ int main(int argc, char* argv[])
|
||||
(test2 + test1).display();
|
||||
|
||||
/* Tree firstTree("firstTree"); */
|
||||
/* firstTree.addPerson("Адам", true, Nobody, Nobody, {0, 1, 6}); */
|
||||
/* firstTree.addPerson("Ева", false, Nobody, Nobody, {0, 1, 6}); */
|
||||
/* firstTree.addPerson("Адам", M, Nobody, Nobody, {0, 1, 6}); */
|
||||
/* firstTree.addPerson("Ева", F, Nobody, Nobody, {0, 1, 6}); */
|
||||
/* firstTree.addRelation(0, Spouse, 1); */
|
||||
|
||||
/* firstTree.addPerson("Кайн", true, 0, 1); */
|
||||
/* firstTree.addPerson("Кайн", M, 0, 1); */
|
||||
|
||||
/* firstTree.addPerson("Авел", true, 0, 1); */
|
||||
/* firstTree.addPerson("Авел", M, 0, 1); */
|
||||
/* firstTree.addRelation(2, Sibling, 3); */
|
||||
|
||||
/* firstTree.addPerson("Сит", true, 0, 1, 230); */
|
||||
/* firstTree.addPerson("Сит", M, 0, 1, 230); */
|
||||
/* firstTree.addRelation(2, Sibling, 4); */
|
||||
/* firstTree.addPerson("Енос", true, 4, Nobody, 435); */
|
||||
/* firstTree.addPerson("Каинан", true, 5 , Nobody, 605); */
|
||||
/* firstTree.addPerson("Малелеил", true, 6, Nobody, 605); */
|
||||
/* firstTree.addPerson("Енос", M, 4, Nobody, 435); */
|
||||
/* firstTree.addPerson("Каинан", M, 5 , Nobody, 605); */
|
||||
/* firstTree.addPerson("Малелеил", M, 6, Nobody, 605); */
|
||||
|
||||
|
||||
/* firstTree.addPerson("Енох", true, 3 , Nobody); */
|
||||
/* firstTree.addPerson("Гаидад", true, 8 , Nobody); */
|
||||
/* firstTree.addPerson("Малелеил", true, 9, Nobody); */
|
||||
/* firstTree.addPerson("Енох", M, 3 , Nobody); */
|
||||
/* firstTree.addPerson("Гаидад", M, 8 , Nobody); */
|
||||
/* firstTree.addPerson("Малелеил", M, 9, Nobody); */
|
||||
|
||||
|
||||
/* firstTree.print(); */
|
||||
@@ -70,7 +74,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
/* std::vector<Tree> trees; */
|
||||
|
||||
/* bool quit = false; */
|
||||
/* bool quit = F; */
|
||||
/* char input[128]; */
|
||||
/* short i; //Number of the entered command */
|
||||
/* const short numCom = 24; */
|
||||
|
||||
+16
-16
@@ -102,9 +102,9 @@ void Tree::rename(const char* newName)
|
||||
treeName = newName;
|
||||
}
|
||||
|
||||
person_id Tree::findId(const char* name, bool m) const
|
||||
person_id Tree::findId(const char* name, Sex s) const
|
||||
{
|
||||
Person sought(name, {}, m);
|
||||
Person sought(name, {}, s);
|
||||
for (person_id i = 0; i < numPeople; ++i)
|
||||
{
|
||||
if (sought == people[i])
|
||||
@@ -113,12 +113,12 @@ person_id Tree::findId(const char* name, bool m) const
|
||||
return Nobody;
|
||||
}
|
||||
|
||||
person_id Tree::findOldestAncestor(person_id id, bool isMale) const
|
||||
person_id Tree::findOldestAncestor(person_id id, Sex sex) const
|
||||
{
|
||||
for (const Relation& rel: relations[id])
|
||||
{
|
||||
if (rel.type == Child && people[ rel.id ].isMale() == isMale)
|
||||
return findOldestAncestor(rel.id, isMale);
|
||||
if (rel.type == Child && people[ rel.id ].sex == sex)
|
||||
return findOldestAncestor(rel.id, sex);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -143,12 +143,12 @@ person_id Tree::findCommonAncestor(const unsigned first, const unsigned second)
|
||||
return oldest;
|
||||
}
|
||||
|
||||
person_id Tree::findParent(person_id child, bool isParentMale) const
|
||||
person_id Tree::findParent(person_id child, Sex parentSex) const
|
||||
{
|
||||
person_id parent = Nobody;
|
||||
for(const Relation& rel: relations[child])
|
||||
{
|
||||
if (rel.type == Child && people[rel.id].isMale() == isParentMale)
|
||||
if (rel.type == Child && people[rel.id].sex == parentSex)
|
||||
parent = rel.id;
|
||||
}
|
||||
return parent;
|
||||
@@ -253,9 +253,9 @@ bool Tree::loadFromFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tree::addPerson(const char* name, bool isMale, unsigned father, unsigned mother, EventTime birth, EventTime death)
|
||||
void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother, EventTime birth, EventTime death)
|
||||
{
|
||||
people.emplace_back(name, birth, isMale, death);
|
||||
people.emplace_back(name, birth, sex, death);
|
||||
|
||||
relations.emplace_back(); /* relations of the new person */
|
||||
++numPeople;
|
||||
@@ -464,8 +464,8 @@ void Tree::display()
|
||||
|
||||
void Tree::updateRels(person_id id)
|
||||
{
|
||||
person_id dad = findParent(id, true);
|
||||
person_id mom = findParent(id, false);
|
||||
person_id dad = findParent(id, M);
|
||||
person_id mom = findParent(id, F);
|
||||
|
||||
auto dad_children = findChildren(dad, id);
|
||||
auto mom_children = findChildren(mom, id);
|
||||
@@ -570,8 +570,8 @@ void Tree::printMember(const unsigned id)const
|
||||
|
||||
void Tree::printOldestAncestors(const unsigned id)const
|
||||
{
|
||||
people[findOldestAncestor(id)].displayInfo();
|
||||
people[findOldestAncestor(id, 1)].displayInfo();
|
||||
people[findOldestAncestor(id, M)].displayInfo();
|
||||
people[findOldestAncestor(id, F)].displayInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -749,7 +749,7 @@ void Tree::selectUp()
|
||||
{
|
||||
if (rel.type == Child)
|
||||
{
|
||||
if (people[rel.id].isMale())
|
||||
if (people[rel.id].sex == M)
|
||||
dad = rel.id;
|
||||
else
|
||||
mom = rel.id;
|
||||
@@ -801,7 +801,7 @@ void Tree::selectLeftSibSpouse(person_id person) /* todo: return a value and spl
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(person_id sel_par = findParent(person, true); sel_par != Nobody)
|
||||
else if(person_id sel_par = findParent(person, M); sel_par != Nobody)
|
||||
{
|
||||
auto siblings = findChildren(sel_par);
|
||||
for(auto it = siblings.begin()+1; it < siblings.end(); ++it)
|
||||
@@ -835,7 +835,7 @@ void Tree::selectRightSib(person_id person)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(person_id sel_par = findParent(person, true); sel_par != Nobody)
|
||||
else if(person_id sel_par = findParent(person, M); sel_par != Nobody)
|
||||
{
|
||||
auto siblings = findChildren(sel_par);
|
||||
for(auto it = siblings.begin(); it < siblings.end()-1; ++it)
|
||||
|
||||
+5
-4
@@ -44,12 +44,13 @@ public:
|
||||
|
||||
void rename(const char* newName);
|
||||
|
||||
person_id findId(const char* name, bool=true) const;
|
||||
person_id findOldestAncestor(person_id, bool sex = 0) const;//
|
||||
person_id findId(const char* name) const{return Nobody;} /* todo */
|
||||
person_id findId(const char* name, Sex) const;
|
||||
person_id findOldestAncestor(person_id, Sex) const;//
|
||||
//oldest common ancestor ID, a person is considerd an ancestor of himself
|
||||
person_id findCommonAncestor(person_id first, person_id second) const;
|
||||
RelType findRelation(person_id first, person_id second) const;
|
||||
person_id findParent(person_id child, bool isParentMale) const;
|
||||
person_id findParent(person_id child, Sex parentSex) const;
|
||||
person_id findSpouse(person_id person) const;
|
||||
std::vector<person_id> findChildren(person_id person) const;
|
||||
std::vector<person_id> findChildren(person_id person, person_id exclude) const;
|
||||
@@ -57,7 +58,7 @@ public:
|
||||
void saveToFile()const;//
|
||||
bool loadFromFile();
|
||||
|
||||
void addPerson(const char* name, bool isMale, person_id father=Nobody, person_id mother=Nobody, EventTime birth={}, EventTime death={});
|
||||
void addPerson(const char* name, Sex sex, person_id father=Nobody, person_id mother=Nobody, EventTime birth={}, EventTime death={});
|
||||
bool addRelation(const char* firstName, RelType, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
|
||||
bool addRelation(person_id first, RelType, person_id second, bool update=true); //0 - failure 1 - success
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "utils.hpp"
|
||||
#include "person.hpp"
|
||||
#include <clocale>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
void init()
|
||||
{
|
||||
@@ -22,6 +25,18 @@ void init()
|
||||
wnoutrefresh(stdscr); /* if not present the first real refresh is missed */
|
||||
}
|
||||
|
||||
MappedFile mapfile(const char* path)
|
||||
{
|
||||
int file = open(path, O_RDONLY);
|
||||
|
||||
MappedFile res;
|
||||
res.len = lseek(file, 0, SEEK_END);
|
||||
res.data = (char*)mmap(nullptr, res.len, PROT_READ, MAP_PRIVATE, file, 0);
|
||||
|
||||
close(file);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool willBeVisible(I16 drawY, I16 drawX, U16 height, U16 width)
|
||||
{
|
||||
return (drawY + height > 0) && (drawX + width > 0) &&
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
|
||||
void init();
|
||||
|
||||
struct MappedFile
|
||||
{
|
||||
char* data;
|
||||
unsigned len;
|
||||
};
|
||||
|
||||
MappedFile mapfile(const char* path);
|
||||
|
||||
template <class Vec>
|
||||
void remove(Vec& vec, size_t pos) /* Remove from vector by moving the last element in its place */
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user