support duplicate names

This commit is contained in:
vrd
2023-03-02 21:57:54 +02:00
parent 81963b0663
commit c796f69331
4 changed files with 57 additions and 21 deletions
+7 -3
View File
@@ -4,7 +4,6 @@ tft can create and display family trees on the terminal.
HOW TO CREATE: HOW TO CREATE:
Trees are created using the tft file format, for example this tft file: Trees are created using the tft file format, for example this tft file:
# This is a comment # This is a comment
@@ -44,7 +43,6 @@ DEPENDENCIES:
ncursesw development library (libncursesw5-dev on Debian/Ubuntu) ncursesw development library (libncursesw5-dev on Debian/Ubuntu)
HOW TO INSTALL: HOW TO INSTALL:
Make sure you satisfy the dependencies and have permissons and execute: Make sure you satisfy the dependencies and have permissons and execute:
git clone https://gitlab.com/venelin98/tft.git git clone https://gitlab.com/venelin98/tft.git
cd tft cd tft
@@ -52,5 +50,11 @@ Make sure you satisfy the dependencies and have permissons and execute:
HOW TO USE: HOW TO USE:
tft ${MY_TFT_FILE} 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
+43 -12
View File
@@ -39,6 +39,11 @@ namespace /* internal */
/* result */ /* result */
Tree* cur_tree; Tree* cur_tree;
bool isNum(char c)
{
return c >= '0' && c <= '9';
}
void unexpected_char(char c) void unexpected_char(char c)
{ {
cerr << "Line " << line << ": Unexpected '" << c << "'\n"; cerr << "Line " << line << ": Unexpected '" << c << "'\n";
@@ -56,7 +61,8 @@ namespace /* internal */
{ {
while(it_data < end_data && while(it_data < end_data &&
*it_data != ',' && *it_data != ',' &&
*it_data != '\n') *it_data != '\n' &&
!isNum(*it_data))
{ {
if(*it_data == ':' /* && *it_data == '-' */) if(*it_data == ':' /* && *it_data == '-' */)
unexpected_char(*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 findSex(char*& it_data)
{ {
Sex res = M; Sex res = M;
@@ -137,6 +154,7 @@ namespace /* internal */
pair<person_id, person_id> processParents(char*& it_data) pair<person_id, person_id> processParents(char*& it_data)
{ {
pair<person_id, person_id> res(Nobody, Nobody); pair<person_id, person_id> res(Nobody, Nobody);
U32 same_name_index = 0;
string name; /* todo dont use string */ string name; /* todo dont use string */
for(; it_data < end_data; ++it_data) for(; it_data < end_data; ++it_data)
{ {
@@ -144,11 +162,12 @@ namespace /* internal */
{ {
case ',': case ',':
if(res.first == Nobody) 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) else if(res.second == Nobody)
res.second = cur_tree->findId(name.data()); res.second = cur_tree->findId(name.data())[same_name_index];
else else
/* todo */exit(1); /* todo */exit(1);
same_name_index = 0;
name.clear(); name.clear();
break; break;
case '-': case '-':
@@ -159,23 +178,27 @@ namespace /* internal */
case '\n': case '\n':
++line; ++line;
if(res.first == Nobody) if(res.first == Nobody)
res.first = cur_tree->findId(name.data()); res.first = cur_tree->findId(name.data())[same_name_index];
else else
res.second = cur_tree->findId(name.data()); res.second = cur_tree->findId(name.data())[same_name_index];
return prev_parents = res; return prev_parents = res;
case '_': case '_':
name.push_back(' '); name.push_back(' ');
break; break;
case '0' ... '9':
same_name_index = *it_data - '0';
break;
default: default:
name.push_back(*it_data); name.push_back(*it_data);
} }
} }
unexpected_end();
} }
vector<person_id> parseSpouses(char*& it_data) vector<person_id> parseSpouses(char*& it_data)
{ {
vector<person_id> res; vector<person_id> res;
U32 same_name_index = 0;
string name; string name;
for(; it_data < end_data; ++it_data) for(; it_data < end_data; ++it_data)
{ {
@@ -184,25 +207,29 @@ namespace /* internal */
case ',': case ',':
if(!name.empty()) if(!name.empty())
{ {
res.push_back( cur_tree->findId(name.data()) ); res.push_back( cur_tree->findId(name.data())[same_name_index] );
name.clear(); name.clear();
same_name_index = 0;
} }
else else
unexpected_char(','); unexpected_char(',');
break; break;
case '\n': case '\n':
++line; ++line;
res.push_back( cur_tree->findId(name.data()) ); res.push_back( cur_tree->findId(name.data())[same_name_index] );
return res; return res;
case '_': case '_':
name.push_back(' '); name.push_back(' ');
break; break;
case '0' ... '9':
same_name_index = *it_data - '0';
break;
default: default:
name.push_back(*it_data); name.push_back(*it_data);
} }
} }
if(!name.empty()) if(!name.empty())
res.push_back( cur_tree->findId(name.data()) ); res.push_back( cur_tree->findId(name.data())[same_name_index] );
return res; return res;
} }
@@ -235,15 +262,19 @@ namespace /* internal */
EventTime birth{}; EventTime birth{};
EventTime death{}; EventTime death{};
proceedToNameEnd(it_data); proceedToNameEnd(it_data); /* todo merge funcs */
/* string_view name(name_start, it_data); */
string name(name_start, it_data); string name(name_start, it_data);
U32 same_name_index = sameNamedIndex(it_data);
/* string_view name(name_start, it_data); */
for(char& c: name) for(char& c: name)
{ {
if(c == '_') if(c == '_')
c = ' '; c = ' ';
} }
Sex sex = findSex(it_data); Sex sex = findSex(it_data);
for(; it_data < end_data; ++it_data) for(; it_data < end_data; ++it_data)
@@ -332,7 +363,7 @@ namespace /* internal */
Tree parseTftFile(fd_t file) Tree parseTftFile(fd_t file)
{ {
Tree result("name"); Tree result("t");
cur_tree = &result; cur_tree = &result;
MappedFile mapedfile = mapfile(file); MappedFile mapedfile = mapfile(file);
+6 -5
View File
@@ -107,14 +107,15 @@ person_id Tree::last()
return people.size() - 1; return people.size() - 1;
} }
person_id Tree::findId(const char* name) const vector<person_id> Tree::findId(const char* name) const
{ {
vector<person_id> res;
for (person_id i = 0; i < people.size(); ++i) for (person_id i = 0; i < people.size(); ++i)
{ {
if (name == people[i].name) 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 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) 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) 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) 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) void Tree::removePerson(const person_id id)
+1 -1
View File
@@ -45,7 +45,7 @@ public:
void rename(const char* newName); void rename(const char* newName);
person_id last(); person_id last();
person_id findId(const char* name) const; std::vector<person_id> findId(const char* name) const;
person_id findId(const char* name, Sex) const; person_id findId(const char* name, Sex) const;
person_id findOldestAncestor(person_id, Sex) const;// person_id findOldestAncestor(person_id, Sex) const;//