simplified too complex CSV header line interpretation

This commit is contained in:
john30
2017-05-07 15:31:09 +02:00
parent 0a57962791
commit 340f862026
2 changed files with 85 additions and 104 deletions
+43 -44
View File
@@ -184,8 +184,8 @@ string AttributedItem::getAttribute(const string& name) const {
result_t DataField::create(bool isWriteMessage, bool isTemplate, bool isBroadcastOrMasterDestination, result_t DataField::create(bool isWriteMessage, bool isTemplate, bool isBroadcastOrMasterDestination,
size_t maxFieldLength, const DataFieldTemplates* templates, vector< map<string, string> >* rows, size_t maxFieldLength, const DataFieldTemplates* templates, vector< map<string, string> >* rows,
string* errorDescription, const DataField** returnField) { string* errorDescription, const DataField** returnField) {
// template: name,[,part]basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]] // template: name[,part]basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
// std: name,part,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]] // std: name[,part],basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
vector<const SingleDataField*> fields; vector<const SingleDataField*> fields;
string firstName; string firstName;
result_t result = RESULT_OK; result_t result = RESULT_OK;
@@ -1130,21 +1130,41 @@ result_t DataFieldTemplates::getFieldMap(const string& preferLanguage, vector<st
string lowerName = name; string lowerName = name;
tolower(&lowerName); tolower(&lowerName);
trim(&lowerName); trim(&lowerName);
bool toDataFields;
if (!lowerName.empty() && lowerName[0] == '*') {
lowerName.erase(0, 1);
toDataFields = true;
} else {
toDataFields = false;
}
if (lowerName.empty()) { if (lowerName.empty()) {
*errorDescription = "missing name in column " + AttributedItem::formatInt(col); *errorDescription = "missing name in column " + AttributedItem::formatInt(col);
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
bool supportsLang = false; if (toDataFields) {
string useName = getDataFieldName(lowerName, &supportsLang); if (inDataFields) {
bool unknown = useName.empty(); if (seen.find("type") == seen.end()) {
size_t langPos = supportsLang ? lowerName.find_last_of('.') : string::npos; *errorDescription = "missing field type";
map<string, size_t>::iterator previous; return RESULT_ERR_EOF; // require at least name and type
if (langPos == lowerName.length()-3) {
string lang = lowerName.substr(langPos+1);
if (unknown) {
useName = lowerName.substr(0, langPos);
} }
previous = seen.find(useName); } else {
if (seen.find("name") == seen.end()) {
*errorDescription = "missing template name";
return RESULT_ERR_EOF; // require at least name
}
if (seen.size() > 1) {
*errorDescription = "extra template columns";
return RESULT_ERR_INVALID_ARG;
}
inDataFields = true;
}
seen.clear();
}
size_t langPos = lowerName.find_last_of('.');
if (langPos != string::npos && langPos > 0 && langPos == lowerName.length()-3) {
string lang = lowerName.substr(langPos+1);
lowerName.erase(langPos);
map<string, size_t>::iterator previous = seen.find(lowerName);
if (previous != seen.end()) { if (previous != seen.end()) {
if (lang != preferLanguage) { if (lang != preferLanguage) {
// skip this column // skip this column
@@ -1153,45 +1173,21 @@ result_t DataFieldTemplates::getFieldMap(const string& preferLanguage, vector<st
} }
// replace previous // replace previous
(*row)[previous->second] = SKIP_COLUMN; (*row)[previous->second] = SKIP_COLUMN;
seen.erase(useName); seen.erase(lowerName);
previous = seen.end();
} }
} else { } else {
if (unknown) { map<string, size_t>::iterator previous = seen.find(lowerName);
useName = lowerName; if (seen.find(lowerName) != seen.end()) {
}
previous = seen.find(useName);
}
if (inDataFields) { if (inDataFields) {
if (!unknown && previous != seen.end()) { *errorDescription = "duplicate field " + name;
if (seen.find("type") == seen.end()) {
*errorDescription = "missing field type";
return RESULT_ERR_EOF; // require at least type
}
seen.clear();
}
} else { } else {
if (!unknown && useName == "name" && seen.find("name") == seen.end()) { *errorDescription = "duplicate template " + name;
// keep first name for template
} else if (!unknown) {
if (seen.find("name") == seen.end()) {
*errorDescription = "missing template name";
return RESULT_ERR_EOF; // require at least name
} }
inDataFields = true;
seen.clear();
}
if (!inDataFields && seen.find(useName) != seen.end()) {
*errorDescription = "duplicate template " + useName;
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
} }
if (seen.empty() && inDataFields) { name = toDataFields ? "*"+lowerName : lowerName;
name = "*" + useName; // data field repetition seen[lowerName] = col;
} else {
name = useName;
}
seen[useName] = col;
} }
if (!inDataFields) { if (!inDataFields) {
*errorDescription = "missing template fields"; *errorDescription = "missing template fields";
@@ -1216,9 +1212,12 @@ result_t DataFieldTemplates::addFromFile(const string& filename, unsigned int li
name = name.substr(0, colon); name = name.substr(0, colon);
} }
const DataField* field = NULL; const DataField* field = NULL;
if (!subRows->empty() && (*subRows)[0].find("name") == (*subRows)[0].end()) { if (!subRows->empty()) {
map<string, string>::iterator it = (*subRows)[0].find("name");
if (it == (*subRows)[0].end() || it->second.empty()) {
(*subRows)[0]["name"] = firstFieldName; (*subRows)[0]["name"] = firstFieldName;
} }
}
result_t result = DataField::create(false, true, false, MAX_POS, this, subRows, errorDescription, &field); result_t result = DataField::create(false, true, false, MAX_POS, this, subRows, errorDescription, &field);
if (result != RESULT_OK) { if (result != RESULT_OK) {
return result; return result;
+35 -53
View File
@@ -1772,9 +1772,8 @@ result_t MessageMap::add(bool storeByName, Message* message) {
} }
result_t MessageMap::getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const { result_t MessageMap::getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const {
// type (r[1-9];w;u),circuit,name,[comment],[QQ],ZZ,PBSB,[ID],field1,part (m/s),datatypes/templates,divider/values, // type,circuit,name,[comment],[QQ],ZZ,PBSB,[ID],*name,[part],type,divisor/values,unit,comment
// unit,comment // minimum: type,name,PBSB,*type
// minimum: type,name,PBSB,field,datatype
if (row->empty()) { if (row->empty()) {
for (const auto& col : defaultMessageFieldMap) { for (const auto& col : defaultMessageFieldMap) {
row->push_back(col); row->push_back(col);
@@ -1788,30 +1787,37 @@ result_t MessageMap::getFieldMap(const string& preferLanguage, vector<string>* r
string lowerName = name; string lowerName = name;
tolower(&lowerName); tolower(&lowerName);
trim(&lowerName); trim(&lowerName);
bool toDataFields;
if (!lowerName.empty() && lowerName[0] == '*') {
lowerName.erase(0, 1);
toDataFields = true;
} else {
toDataFields = false;
}
if (lowerName.empty()) { if (lowerName.empty()) {
*errorDescription = "missing name in column " + AttributedItem::formatInt(col); *errorDescription = "missing name in column " + AttributedItem::formatInt(col);
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
bool supportsLang = false, toDataFields = false; if (toDataFields) {
string useName;
if (inDataFields) { if (inDataFields) {
useName = getDataFieldName(lowerName, &supportsLang); if (seen.find("type") == seen.end()) {
*errorDescription = "missing field type";
return RESULT_ERR_EOF; // require at least name and type
}
} else { } else {
useName = getMessageFieldName(lowerName, &supportsLang); if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
if (useName.empty()) { *errorDescription = "missing message type/name/pbsb";
useName = getDataFieldName(lowerName, &supportsLang); return RESULT_ERR_EOF; // require at least type, name, and pbsb
toDataFields = !useName.empty();
} }
inDataFields = true;
} }
bool unknown = useName.empty(); seen.clear();
size_t langPos = supportsLang ? lowerName.find_last_of('.') : string::npos; }
map<string, size_t>::iterator previous; size_t langPos = lowerName.find_last_of('.');
if (langPos == lowerName.length()-3) { if (langPos != string::npos && langPos > 0 && langPos == lowerName.length()-3) {
string lang = lowerName.substr(langPos+1); string lang = lowerName.substr(langPos+1);
if (unknown) { lowerName.erase(langPos);
useName = lowerName.substr(0, langPos); map<string, size_t>::iterator previous = seen.find(lowerName);
}
previous = seen.find(useName);
if (previous != seen.end()) { if (previous != seen.end()) {
if (lang != preferLanguage) { if (lang != preferLanguage) {
// skip this column // skip this column
@@ -1820,54 +1826,30 @@ result_t MessageMap::getFieldMap(const string& preferLanguage, vector<string>* r
} }
// replace previous // replace previous
(*row)[previous->second] = SKIP_COLUMN; (*row)[previous->second] = SKIP_COLUMN;
seen.erase(useName); seen.erase(lowerName);
previous = seen.end();
} }
} else { } else {
if (unknown) { map<string, size_t>::iterator previous = seen.find(lowerName);
useName = lowerName; if (seen.find(lowerName) != seen.end()) {
}
previous = seen.find(useName);
}
if (inDataFields) { if (inDataFields) {
if (!unknown && previous != seen.end()) { *errorDescription = "duplicate field " + name;
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
*errorDescription = "missing field name/type as of already seen "+useName;
return RESULT_ERR_EOF; // require at least name and type
}
seen.clear();
}
} else { } else {
/*if (!unknown && (useName != "name" || seen.find("name") == seen.end())) { *errorDescription = "duplicate message " + name;
// keep first name for message
} else {*/
if (toDataFields) {
if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
*errorDescription = "missing message name/type/pbsb";
return RESULT_ERR_EOF; // require at least type, name, and pbsb
} }
inDataFields = true;
seen.clear();
}
if (!inDataFields && seen.find(useName) != seen.end()) {
*errorDescription = "duplicate message " + useName;
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
} }
if (seen.empty() && inDataFields) { //std::cout<<(inDataFields?"data:":"msg:")<<lowerName<<"\n";
name = "*" + useName; // data field repetition name = toDataFields ? "*"+lowerName : lowerName;
} else { seen[lowerName] = col;
name = useName;
}
seen[useName] = col;
} }
if (inDataFields) { if (inDataFields) {
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) { if (seen.find("type") == seen.end()) {
*errorDescription = "missing field name/type"; *errorDescription = "missing field type";
return RESULT_ERR_EOF; // require at least name and type return RESULT_ERR_EOF; // require at least name and type
} }
} else if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) { } else if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
*errorDescription = "missing message name/type/pbsb"; *errorDescription = "missing message type/name/pbsb";
return RESULT_ERR_EOF; // require at least type, name, and pbsb return RESULT_ERR_EOF; // require at least type, name, and pbsb
} }
return RESULT_OK; return RESULT_OK;