diff --git a/readme.txt b/readme.txt index fd2795c..b65a056 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,6 @@ tft can create and display family trees on the terminal. HOW TO CREATE: - Trees are created using the tft file format, for example this tft file: # This is a comment @@ -44,7 +43,6 @@ DEPENDENCIES: ncursesw development library (libncursesw5-dev on Debian/Ubuntu) HOW TO INSTALL: - Make sure you satisfy the dependencies and have permissons and execute: git clone https://gitlab.com/venelin98/tft.git cd tft @@ -52,5 +50,11 @@ Make sure you satisfy the dependencies and have permissons and execute: HOW TO USE: - tft ${MY_TFT_FILE} + +TFT FORMAT: + - All spaces are ignored e.g.: Adam 0 and Adam0 are equivalent + - '_' in names is converted to ' ' + - Number at the end of a name is used to disambiguate when multiple people have identical names e.g.: + Adam0 is the first added Adam, Adam1 is the second added Adam + - Must end with a newline diff --git a/src/parser.cpp b/src/parser.cpp index 9fe5d17..7a3ee58 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -39,6 +39,11 @@ namespace /* internal */ /* result */ Tree* cur_tree; + bool isNum(char c) + { + return c >= '0' && c <= '9'; + } + void unexpected_char(char c) { cerr << "Line " << line << ": Unexpected '" << c << "'\n"; @@ -56,7 +61,8 @@ namespace /* internal */ { while(it_data < end_data && *it_data != ',' && - *it_data != '\n') + *it_data != '\n' && + !isNum(*it_data)) { if(*it_data == ':' /* && *it_data == '-' */) unexpected_char(*it_data); @@ -65,6 +71,17 @@ namespace /* internal */ } + U32 sameNamedIndex(char*& it_data) + { + U32 res = 0; + if(isNum(*it_data)) + { + res = *it_data - '0'; /* todo many digits */ + ++it_data; + } + return res; + } + Sex findSex(char*& it_data) { Sex res = M; @@ -137,6 +154,7 @@ namespace /* internal */ pair processParents(char*& it_data) { pair res(Nobody, Nobody); + U32 same_name_index = 0; string name; /* todo dont use string */ for(; it_data < end_data; ++it_data) { @@ -144,11 +162,12 @@ namespace /* internal */ { case ',': if(res.first == Nobody) - res.first = cur_tree->findId(name.data()); + res.first = cur_tree->findId(name.data())[same_name_index]; /* todo validate index */ else if(res.second == Nobody) - res.second = cur_tree->findId(name.data()); + res.second = cur_tree->findId(name.data())[same_name_index]; else /* todo */exit(1); + same_name_index = 0; name.clear(); break; case '-': @@ -159,23 +178,27 @@ namespace /* internal */ case '\n': ++line; if(res.first == Nobody) - res.first = cur_tree->findId(name.data()); + res.first = cur_tree->findId(name.data())[same_name_index]; else - res.second = cur_tree->findId(name.data()); + res.second = cur_tree->findId(name.data())[same_name_index]; return prev_parents = res; case '_': name.push_back(' '); break; + case '0' ... '9': + same_name_index = *it_data - '0'; + break; default: name.push_back(*it_data); } } - + unexpected_end(); } vector parseSpouses(char*& it_data) { vector res; + U32 same_name_index = 0; string name; for(; it_data < end_data; ++it_data) { @@ -184,25 +207,29 @@ namespace /* internal */ case ',': if(!name.empty()) { - res.push_back( cur_tree->findId(name.data()) ); + res.push_back( cur_tree->findId(name.data())[same_name_index] ); name.clear(); + same_name_index = 0; } else unexpected_char(','); break; case '\n': ++line; - res.push_back( cur_tree->findId(name.data()) ); + res.push_back( cur_tree->findId(name.data())[same_name_index] ); return res; case '_': name.push_back(' '); break; + case '0' ... '9': + same_name_index = *it_data - '0'; + break; default: name.push_back(*it_data); } } if(!name.empty()) - res.push_back( cur_tree->findId(name.data()) ); + res.push_back( cur_tree->findId(name.data())[same_name_index] ); return res; } @@ -235,15 +262,19 @@ namespace /* internal */ EventTime birth{}; EventTime death{}; - proceedToNameEnd(it_data); - /* string_view name(name_start, it_data); */ + proceedToNameEnd(it_data); /* todo merge funcs */ string name(name_start, it_data); + + U32 same_name_index = sameNamedIndex(it_data); + /* string_view name(name_start, it_data); */ for(char& c: name) { if(c == '_') c = ' '; } + + Sex sex = findSex(it_data); for(; it_data < end_data; ++it_data) @@ -332,7 +363,7 @@ namespace /* internal */ Tree parseTftFile(fd_t file) { - Tree result("name"); + Tree result("t"); cur_tree = &result; MappedFile mapedfile = mapfile(file); diff --git a/src/tree.cpp b/src/tree.cpp index dc2036a..44b1d37 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -107,14 +107,15 @@ person_id Tree::last() return people.size() - 1; } -person_id Tree::findId(const char* name) const +vector Tree::findId(const char* name) const { + vector res; for (person_id i = 0; i < people.size(); ++i) { if (name == people[i].name) - return i; + res.push_back(i); } - return Nobody; + return res; } person_id Tree::findId(const char* name, Sex s) const @@ -286,7 +287,7 @@ void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother bool Tree::addRelation(const char* firstName, const RelType type, const char* secondName) { - return addRelation(findId(firstName), type, findId(secondName)); + return addRelation(findId(firstName)[0], type, findId(secondName)[0]); } bool Tree::addRelation(const unsigned first, const RelType type, const unsigned second, bool update) @@ -341,7 +342,7 @@ void Tree::addRelOneSide(person_id first, RelType type, person_id second) void Tree::removeRelation(const char* firstName, const char* secondName) { - removeRelation(findId(firstName), findId(secondName)); + removeRelation(findId(firstName)[0], findId(secondName)[0]); } void Tree::removePerson(const person_id id) diff --git a/src/tree.hpp b/src/tree.hpp index 0c8f059..a02943a 100644 --- a/src/tree.hpp +++ b/src/tree.hpp @@ -45,7 +45,7 @@ public: void rename(const char* newName); person_id last(); - person_id findId(const char* name) const; + std::vector findId(const char* name) const; person_id findId(const char* name, Sex) const; person_id findOldestAncestor(person_id, Sex) const;//