diff --git a/example_tree.hpp b/example_tree.hpp index 09bcfab..8e6fe8f 100644 --- a/example_tree.hpp +++ b/example_tree.hpp @@ -1,30 +1,53 @@ void create_tree() { // Declare your tree - Tree tree("first_tree"); + Tree t("first_tree"); - // Add member Adam with parents Nobody, Born: y, m, d - tree.addPerson("Адам", true, Nobody, Nobody, {0, 1, 6}); // ID 0 - tree.addPerson("Ева", false, Nobody, Nobody, {0, 1, 6}); // ID 1 + // Add member Adam with parents Nobody + t.addPerson("Адам", M, // ID 0 + Nobody, Nobody, + {0, 1, 6}); // Born: y, m, d + + t.addPerson("Ева", F, // ID 1 + Nobody, Nobody, + {0, 1, 6}); // Adam (0) is a Spouse of Eve (1) - tree.addRelation(0, Spouse, 1); + t.addRelation(0, Spouse, 1); // Add Cain with parents Adam (0) and Eve - tree.addPerson("Кайн", true, 0, 1); + t.addPerson("Кайн", M, + 0, 1); - tree.addPerson("Авел", true, 0, 1); + t.addPerson("Авел", M, + 0, 1); - tree.addPerson("Сит", true, 0, 1, 230); - tree.addPerson("Енос", true, 4, Nobody, 435); - tree.addPerson("Каинан", true, 5 , Nobody, 605); - tree.addPerson("Малелеил", true, 6, Nobody, 605); + t.addPerson("Сит", M, + 0, 1, + 230); + + t.addPerson("Енос", M, + 4, Nobody, + 435); + + t.addPerson("Каинан", M, + 5, Nobody, + 605); + + t.addPerson("Малелеил", M, + 6, Nobody, + 605); - tree.addPerson("Енох", true, 3 , Nobody); - tree.addPerson("Гаидад", true, 8 , Nobody); - tree.addPerson("Малелеил", true, 9, Nobody); + t.addPerson("Енох", M, + 3, Nobody); - tree.saveToFile(); - tree.display(); + t.addPerson("Гаидад", M, + 8, Nobody); + + t.addPerson("Малелеил", M, + 9, Nobody); + + /* t.saveToFile(); */ + t.display(); } diff --git a/src/parser.cpp b/src/parser.cpp new file mode 100644 index 0000000..04ccbd7 --- /dev/null +++ b/src/parser.cpp @@ -0,0 +1,157 @@ +#include +/* #include */ +#include +#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; +} diff --git a/src/parser.hpp b/src/parser.hpp new file mode 100644 index 0000000..7ce9e19 --- /dev/null +++ b/src/parser.hpp @@ -0,0 +1,3 @@ +#include "tree.hpp" + +Tree parseTftFile(MappedFile file); diff --git a/src/person.cpp b/src/person.cpp index d91ec3f..78cb751 100644 --- a/src/person.cpp +++ b/src/person.cpp @@ -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(&nameLen), sizeof(nameLen)); file.write(name_.data(), nameLen * sizeof(name_[0])); - file.write(reinterpret_cast(&isMale_), sizeof(isMale_)); + file.write(reinterpret_cast(&sex), sizeof(sex)); //file.write(reinterpret_cast(&day), sizeof(day)); TODO //file.write(reinterpret_cast(&month), sizeof(month)); //file.write(reinterpret_cast(&year), sizeof(year)); @@ -97,7 +97,7 @@ void Person::read(std::ifstream &file) nameBuf[nameLen] = '\0'; name_ = nameBuf; - file.read(reinterpret_cast(&isMale_), sizeof(isMale_)); + file.read(reinterpret_cast(&sex), sizeof(sex)); //file.read(reinterpret_cast(&day), sizeof(day)); TODO //file.read(reinterpret_cast(&month), sizeof(month)); //file.read(reinterpret_cast(&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); */ diff --git a/src/person.hpp b/src/person.hpp index d9c8bb0..a440dd6 100644 --- a/src/person.hpp +++ b/src/person.hpp @@ -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_; }; diff --git a/src/tft.cpp b/src/tft.cpp index b5f602a..c68929b 100644 --- a/src/tft.cpp +++ b/src/tft.cpp @@ -2,6 +2,7 @@ #include #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 trees; */ - /* bool quit = false; */ + /* bool quit = F; */ /* char input[128]; */ /* short i; //Number of the entered command */ /* const short numCom = 24; */ diff --git a/src/tree.cpp b/src/tree.cpp index 84bc4a9..dd9159f 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -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) diff --git a/src/tree.hpp b/src/tree.hpp index 09b0074..3f45633 100644 --- a/src/tree.hpp +++ b/src/tree.hpp @@ -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 findChildren(person_id person) const; std::vector 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 diff --git a/src/utils.cpp b/src/utils.cpp index a503e3c..9317196 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,6 +1,9 @@ #include "utils.hpp" #include "person.hpp" #include +#include +#include +#include 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) && diff --git a/src/utils.hpp b/src/utils.hpp index 5a9a402..be8785c 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -25,6 +25,14 @@ void init(); +struct MappedFile +{ + char* data; + unsigned len; +}; + +MappedFile mapfile(const char* path); + template void remove(Vec& vec, size_t pos) /* Remove from vector by moving the last element in its place */ { diff --git a/todo.txt b/todo.txt index aea56bc..58badee 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,8 @@ +open tree + +Parser: +- clean wh + --help findRelative