assert names are valid identifier with little exceptions only (closes #1302)
This commit is contained in:
+43
-7
@@ -191,6 +191,34 @@ string AttributedItem::getAttribute(const string& name) const {
|
||||
}
|
||||
|
||||
|
||||
bool isValidIdentifierChar(char ch, bool first, bool allowFirstDigit) {
|
||||
return ((ch >= '0' && ch <= '9') && (!first || allowFirstDigit))
|
||||
|| (ch >= 'a' && ch <= 'z')
|
||||
|| (ch >= 'A' && ch <= 'Z')
|
||||
|| ch == '_' || ch == '$'
|
||||
// todo '.' is the only excuse for now and should be removed some day
|
||||
|| (ch == '.' && !first);
|
||||
}
|
||||
|
||||
bool DataField::checkIdentifier(const string& name, bool allowFirstDigit) {
|
||||
for (size_t i = 0; i < name.size(); i++) {
|
||||
char ch = name[i];
|
||||
if (!isValidIdentifierChar(ch, i==0, allowFirstDigit)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataField::normalizeIdentifier(string& name, bool allowFirstDigit) {
|
||||
for (size_t i = 0; i < name.size(); i++) {
|
||||
char ch = name[i];
|
||||
if (!isValidIdentifierChar(ch, i==0, allowFirstDigit)) {
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result_t DataField::create(bool isWriteMessage, bool isTemplate, bool isBroadcastOrMasterDestination,
|
||||
size_t maxFieldLength, const DataFieldTemplates* templates, vector< map<string, string> >* rows,
|
||||
string* errorDescription, const DataField** returnField) {
|
||||
@@ -345,6 +373,9 @@ result_t DataField::create(bool isWriteMessage, bool isTemplate, bool isBroadcas
|
||||
if (!dataType) {
|
||||
result = RESULT_ERR_NOTFOUND;
|
||||
*errorDescription = "field type "+typeName+" in field "+formatInt(fieldIndex);
|
||||
} else if (firstType && !name.empty() && !DataField::checkIdentifier(name)) {
|
||||
*errorDescription = "field name "+name;
|
||||
result = RESULT_ERR_INVALID_ARG;
|
||||
} else {
|
||||
SingleDataField* add = nullptr;
|
||||
result = SingleDataField::create(firstType ? name : "", row, dataType, partType, length, divisor,
|
||||
@@ -370,14 +401,19 @@ result_t DataField::create(bool isWriteMessage, bool isTemplate, bool isBroadcas
|
||||
} else {
|
||||
fieldName = (firstType && lastType) ? name : "";
|
||||
}
|
||||
if (lastType) {
|
||||
result = templ->derive(fieldName, partType, divisor, values, &row, &fields);
|
||||
if (!fieldName.empty() && !DataField::checkIdentifier(fieldName)) {
|
||||
*errorDescription = "field name "+fieldName;
|
||||
result = RESULT_ERR_INVALID_ARG;
|
||||
} else {
|
||||
map<string, string> attrs = row; // don't let DataField::derive() consume the row
|
||||
result = templ->derive(fieldName, partType, divisor, values, &attrs, &fields);
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
*errorDescription = "derive field "+fieldName+" in field "+formatInt(fieldIndex);
|
||||
if (lastType) {
|
||||
result = templ->derive(fieldName, partType, divisor, values, &row, &fields);
|
||||
} else {
|
||||
map<string, string> attrs = row; // don't let DataField::derive() consume the row
|
||||
result = templ->derive(fieldName, partType, divisor, values, &attrs, &fields);
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
*errorDescription = "derive field "+fieldName+" in field "+formatInt(fieldIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstType && !lastType) {
|
||||
|
||||
@@ -215,6 +215,22 @@ class DataField : public AttributedItem {
|
||||
*/
|
||||
virtual bool isList() const { return false; }
|
||||
|
||||
/**
|
||||
* Check if the given name is a valid identifier.
|
||||
* @param name the name to check (and optionally normalize).
|
||||
* @param allowFirstDigit whether to additionally allow the name to start with a digit.
|
||||
* @param normalize whether to replace invalid characters with an underscore.
|
||||
* @return true if the name is valid (or was normalized), false if invalid.
|
||||
*/
|
||||
static bool checkIdentifier(const string& name, bool allowFirstDigit = false);
|
||||
|
||||
/**
|
||||
* Normalize the given name to be a valid identifier.
|
||||
* @param name the name to check and normalize.
|
||||
* @param allowFirstDigit whether to additionally allow the name to start with a digit.
|
||||
*/
|
||||
static void normalizeIdentifier(string& name, bool allowFirstDigit = false);
|
||||
|
||||
/**
|
||||
* Factory method for creating new instances.
|
||||
* @param isWriteMessage whether the field is part of a write message (default false).
|
||||
|
||||
@@ -301,11 +301,19 @@ result_t Message::create(const string& filename, const DataFieldTemplates* templ
|
||||
*errorDescription = "circuit";
|
||||
return RESULT_ERR_MISSING_ARG; // empty circuit
|
||||
}
|
||||
if (!DataField::checkIdentifier(circuit, true)) {
|
||||
*errorDescription = "circuit name "+circuit;
|
||||
return RESULT_ERR_INVALID_ARG; // invalid circuit name
|
||||
}
|
||||
string name = getDefault(pluck("name", row), defaults, "name", true, true); // name
|
||||
if (name.empty()) {
|
||||
*errorDescription = "name";
|
||||
return RESULT_ERR_MISSING_ARG; // empty name
|
||||
}
|
||||
if (!DataField::checkIdentifier(name)) {
|
||||
*errorDescription = "name "+name;
|
||||
return RESULT_ERR_INVALID_ARG; // invalid message name
|
||||
}
|
||||
string comment = getDefault(pluck("comment", row), defaults, "comment", true); // [comment]
|
||||
if (!comment.empty()) {
|
||||
(*row)["comment"] = comment;
|
||||
|
||||
Reference in New Issue
Block a user