added conditional messages to find command with "-a" option and include condition prefix for CSV format

also allow passing scan messages with --checkconfig and --scanconfig (without --inject)
be more verbose on errors in configuration files
improved code style
This commit is contained in:
john30
2017-05-01 15:31:09 +02:00
parent 3d4d876d5e
commit 7b11a540b6
32 changed files with 1946 additions and 1949 deletions
+19 -22
View File
@@ -39,7 +39,7 @@ void contrib_tem_register() {
DataTypeList::getInstance()->add(new TemParamDataType("TEM_P"));
}
result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberDataType** derived) const {
if (divisor == 0) {
divisor = 1;
}
@@ -47,27 +47,26 @@ result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberData
bitCount = m_bitCount;
}
if (divisor == 1 && bitCount == 16) {
derived = this;
*derived = this;
return RESULT_OK;
}
return RESULT_ERR_INVALID_ARG;
}
result_t TemParamDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const {
result_t TemParamDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const {
unsigned int value = 0;
result_t result = readRawValue(input, offset, length, value);
result_t result = readRawValue(offset, length, input, &value);
if (result != RESULT_OK) {
return result;
}
if (value == m_replacement) {
if (outputFormat & OF_JSON) {
output << "null";
*output << "null";
} else {
output << NULL_VALUE;
*output << NULL_VALUE;
}
return RESULT_OK;
}
@@ -80,31 +79,29 @@ result_t TemParamDataType::readSymbols(const SymbolString& input,
num = (value & 0x7f); // num in bits 0...6
}
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
output << setfill('0') << setw(2) << dec << static_cast<int>(grp) << '-' << setw(3) << static_cast<int>(num);
*output << setfill('0') << setw(2) << dec << static_cast<int>(grp) << '-' << setw(3) << static_cast<int>(num);
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
output << setfill(' ') << setw(0); // reset
*output << setfill(' ') << setw(0); // reset
return RESULT_OK;
}
result_t TemParamDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const {
result_t TemParamDataType::writeSymbols(const size_t offset, const size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const {
unsigned int value;
int grp, num;
string token;
const char* str = input.str().c_str();
if (strcmp(str, NULL_VALUE) == 0) {
if (input->str() == NULL_VALUE) {
value = m_replacement; // replacement value
} else {
if (input.eof() || !getline(input, token, '-')) {
string token;
if (input->eof() || !getline(*input, token, '-')) {
return RESULT_ERR_EOF; // incomplete
}
str = token.c_str();
const char* str = token.c_str();
if (str == NULL || *str == 0) {
return RESULT_ERR_EOF; // input too short
}
@@ -113,7 +110,7 @@ result_t TemParamDataType::writeSymbols(istringstream& input,
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
return RESULT_ERR_INVALID_NUM; // invalid value
}
if (input.eof() || !getline(input, token, '-')) {
if (input->eof() || !getline(*input, token, '-')) {
return RESULT_ERR_EOF; // incomplete
}
str = token.c_str();
@@ -128,7 +125,7 @@ result_t TemParamDataType::writeSymbols(istringstream& input,
if (grp < 0 || grp > 0x1f || num < 0 || num > 0x7f) {
return RESULT_ERR_OUT_OF_RANGE; // value out of range
}
if (output.isMaster()) {
if (output->isMaster()) {
value = grp | (num << 8); // grp in bits 0...5, num in bits 8...13
} else {
value = (grp << 7) | num; // grp in bits 7...11, num in bits 0...6
+6 -8
View File
@@ -46,21 +46,19 @@ class TemParamDataType : public NumberDataType {
* Constructs a new instance.
* @param id the type identifier.
*/
explicit TemParamDataType(const string id)
explicit TemParamDataType(const string& id)
: NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0, NULL) {}
// @copydoc
result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const override;
result_t derive(int divisor, size_t bitCount, const NumberDataType** derived) const override;
// @copydoc
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
const OutputFormat outputFormat, ostream* output) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
};
/**
+28 -28
View File
@@ -54,31 +54,31 @@ class TestReader : public MappedFileReader {
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
m_fields(NULL) {}
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
if (row.empty()) {
row.push_back("*name");
row.push_back("part");
row.push_back("type");
row.push_back("divisor/values");
row.push_back("unit");
row.push_back("comment");
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
if (row->empty()) {
row->push_back("*name");
row->push_back("part");
row->push_back("type");
row->push_back("divisor/values");
row->push_back("unit");
row->push_back("comment");
return RESULT_OK;
}
if (row[0][0] != '*') {
if ((*row)[0][0] != '*') {
return RESULT_ERR_INVALID_ARG;
}
return RESULT_OK; // leave it to DataField::create
}
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override {
if (!row.empty() || subRows.empty()) {
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override {
if (!row->empty() || subRows->empty()) {
cout << "read line " << static_cast<unsigned>(lineNo) << ": read error: got "
<< static_cast<unsigned>(row.size()) << "/0 main, " << static_cast<unsigned>(subRows.size())
<< static_cast<unsigned>(row->size()) << "/0 main, " << static_cast<unsigned>(subRows->size())
<< "/>=3 sub" << endl;
return RESULT_ERR_EOF;
}
cout << "read line " << static_cast<unsigned>(lineNo) << ": read OK" << endl;
return DataField::create(subRows, errorDescription, m_templates, m_fields, m_isSet, false, m_isMasterDest);
return DataField::create(m_isSet, false, m_isMasterDest, MAX_POS, m_templates, subRows, errorDescription, &m_fields);
}
private:
DataFieldTemplates* m_templates;
@@ -118,7 +118,7 @@ int main() {
istringstream dummystr("#");
string errorDescription;
vector<string> row;
templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
templates->readLineFromStream("inline", false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
const DataField* fields = NULL;
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i];
@@ -156,7 +156,7 @@ int main() {
lineNo = 0;
dummystr.clear();
dummystr.str("#");
result = reader.readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
result = reader.readLineFromStream("inline", false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": reader header error: " << getResultCode(result) << ", " << errorDescription
<< endl;
@@ -164,7 +164,7 @@ int main() {
continue;
}
lineNo = baseLine + i;
result = reader.readLineFromStream(isstr, errorDescription, "", lineNo, row);
result = reader.readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
fields = reader.m_fields;
if (result != RESULT_OK) {
@@ -178,7 +178,7 @@ int main() {
continue;
}
cout << "\"" << check[0] << "\"=\"";
fields->dump(cout);
fields->dump(&cout);
cout << "\": create OK" << endl;
ostringstream output;
@@ -194,21 +194,21 @@ int main() {
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
error = true;
}
result = fields->read(mstr, 0, output, 0, -1, false);
result = fields->read(mstr, 0, false, NULL, -1, 0, -1, &output);
if (result >= RESULT_OK) {
result = fields->read(sstr, 0, output, 0, -1, !output.str().empty());
result = fields->read(sstr, 0, !output.str().empty(), NULL, -1, 0, -1, &output);
}
if (failedRead) {
if (result >= RESULT_OK) {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< error: unexpectedly succeeded" << endl;
error = true;
} else {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< OK" << endl;
}
} else if (result < RESULT_OK) {
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< error: " << getResultCode(result) << endl;
error = true;
} else {
@@ -217,21 +217,21 @@ int main() {
}
istringstream input(expectStr);
result = fields->write(input, writeMstr, 0);
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeMstr, NULL);
if (result >= RESULT_OK) {
result = fields->write(input, writeSstr, 0);
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeSstr, NULL);
}
if (failedWrite) {
if (result >= RESULT_OK) {
cout << " failed write " << fields->getName() << " >"
cout << " failed write " << fields->getName(-1) << " >"
<< expectStr << "< error: unexpectedly succeeded" << endl;
error = true;
} else {
cout << " failed write " << fields->getName() << " >"
cout << " failed write " << fields->getName(-1) << " >"
<< expectStr << "< OK" << endl;
}
} else if (result < RESULT_OK) {
cout << " write " << fields->getName() << " >" << expectStr
cout << " write " << fields->getName(-1) << " >" << expectStr
<< "< error: " << getResultCode(result) << endl;
error = true;
} else {
+244 -262
View File
File diff suppressed because it is too large Load Diff
+126 -124
View File
@@ -56,7 +56,7 @@ namespace ebusd {
* @param supportsLanguage set to true when the field supports multiple language.
* @return the normalized data field name, or empty if unknown.
*/
string getDataFieldName(const string name, bool& supportsLanguage);
string getDataFieldName(const string& name, bool* supportsLanguage);
class DataFieldTemplates;
class SingleDataField;
@@ -71,14 +71,14 @@ class AttributedItem {
* @param name the item name.
* @param attributes the additional named attributes.
*/
AttributedItem(const string name, const map<string, string>& attributes)
AttributedItem(const string& name, const map<string, string>& attributes)
: m_name(name), m_attributes(attributes) {}
/**
* Constructs a new instance (without additional attributes).
* @param name the field name.
*/
explicit AttributedItem(const string name)
explicit AttributedItem(const string& name)
: m_name(name) {}
/**
@@ -92,69 +92,69 @@ class AttributedItem {
* @param value the int value.
* @return the formatted string.
*/
static const string formatInt(size_t value);
static string formatInt(size_t value);
/**
* Remove and return a certain value from a map.
* @param row the map to remove the value from.
* @param key the name of the value to remove.
* @param row the map to remove the value from.
* @return the named value from the map, or empty if not available.
*/
static const string pluck(map<string, string>& row, const string key);
static string pluck(const string& key, map<string, string>* row);
/**
* Dump the @a string optionally embedded in @a TEXT_SEPARATOR to the output.
* @param output the @a ostream to dump to.
* @param str the @a string to dump.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
* @param str the @a string to dump.
* @param output the @a ostream to dump to.
*/
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator = true);
static void dumpString(bool prependFieldSeparator, const string& str, ostream* output);
/**
* Append a named attribute as JSON to the output.
* @param output the @a ostream to append to.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
* @param name the name of the attribute.
* @param value the value of the attribute.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
* @param asString true to force writing as string, false to detect the type from the value.
* @param output the @a ostream to append to.
*/
static void appendJson(ostream& output, const string name, const string value,
const bool prependFieldSeparator = true, bool asString = false);
static void appendJson(bool prependFieldSeparator, const string& name, const string& value,
bool asString, ostream* output);
/**
* Merge this instance's additional named attributes into the specified attributes.
* @param attributes the additional named attributes to merge in this instance's additional named attributes.
*/
void mergeAttributes(map<string, string>& attributes) const;
void mergeAttributes(map<string, string>* attributes) const;
/**
* Dump the attribute optionally embedded in @a TEXT_SEPARATOR to the output.
* @param output the @a ostream to dump to.
* @param name the name of the attribute to dump.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
* @param name the name of the attribute to dump.
* @param output the @a ostream to dump to.
*/
void dumpAttribute(ostream& output, const string name, const bool prependFieldSeparator = true) const;
void dumpAttribute(bool prependFieldSeparator, const string& name, ostream* output) const;
/**
* Append the attribute value to the output.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* @param name the name of the attribute to append.
* @param onlyIfNonEmpty true to append only if the value is not empty.
* @param prefix optional prefix to use (only for non-JSON output).
* @param suffix optional suffix to use (only for non-JSON output).
* @param output the @a ostream to append the formatted value to.
* @return true if data was added, false otherwise.
*/
bool appendAttribute(ostringstream& output, OutputFormat outputFormat, const string name,
const bool onlyIfNonEmpty = true, const string prefix = "", const string suffix = "") const;
bool appendAttribute(OutputFormat outputFormat, const string& name, bool onlyIfNonEmpty,
const string& prefix, const string& suffix, ostream* output) const;
/**
* Append the attributes to the output.
* @param output the @a ostringstream to append the formatted values to.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostream to append the formatted values to.
* @return true if data was added, false otherwise.
*/
bool appendAttributes(ostringstream& output, OutputFormat outputFormat) const;
bool appendAttributes(OutputFormat outputFormat, ostream* output) const;
/**
* Get the item name.
@@ -167,7 +167,7 @@ class AttributedItem {
* @param name the name of the attribute.
* @return the named attribute value, or empty.
*/
string getAttribute(const string name) const;
string getAttribute(const string& name) const;
protected:
@@ -178,6 +178,7 @@ class AttributedItem {
const map<string, string> m_attributes;
};
/**
* Base class for all kinds of data fields.
*/
@@ -188,14 +189,14 @@ class DataField : public AttributedItem {
* @param name the field name.
* @param attributes the additional named attributes.
*/
DataField(const string name, const map<string, string>& attributes)
DataField(const string& name, const map<string, string>& attributes)
: AttributedItem(name, attributes) {}
/**
* Constructs a new instance (without additional attributes).
* @param name the field name.
*/
explicit DataField(const string name)
explicit DataField(const string& name)
: AttributedItem(name) {}
/**
@@ -211,63 +212,62 @@ class DataField : public AttributedItem {
/**
* Factory method for creating new instances.
* @param rows the mapped field definition rows.
* @param errorDescription a string in which to store the error description in case of error.
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
* @param returnField the variable in which to store the created instance.
* @param isWriteMessage whether the field is part of a write message (default false).
* @param isTemplate true for creating a template @a DataField.
* @param isBroadcastOrMasterDestination true if the destination bus address is @a BRODCAST or a master address.
* @param maxFieldLength the maximum allowed length of a single field (default @a MAX_POS).
* @param maxFieldLength the maximum allowed length of a single field (e.g. @a MAX_POS).
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
* @param rows the mapped field definition rows (may be modified).
* @param errorDescription a string in which to store the error description in case of error.
* @param returnField the variable in which to store the created instance.
* @return @a RESULT_OK on success, or an error code.
* Note: the caller needs to free the created instance.
*/
static result_t create(vector< map<string, string> >& rows, string& errorDescription,
DataFieldTemplates* templates, const DataField*& returnField,
const bool isWriteMessage,
const bool isTemplate, const bool isBroadcastOrMasterDestination,
const size_t maxFieldLength = MAX_POS);
static result_t create(bool isWriteMessage, bool isTemplate, bool isBroadcastOrMasterDestination,
size_t maxFieldLength, const DataFieldTemplates* templates, vector< map<string, string> >* rows,
string* errorDescription, const DataField** returnField);
/**
* Return the name of the specified day.
* @param day the day (between 0 and 6).
* @return the name of the specified day.
*/
static string getDayName(int day);
static const char* getDayName(int day);
/**
* Returns the length of this field (or contained fields) in bytes.
* @param partType the message part of the contained fields to limit the length calculation to.
* @param maxLength the maximum length for calculating remainder of input.
* @param maxLength the maximum length for calculating remainder of input (e.g. @a MAX_LEN).
* @return the length of this field (or contained fields) in bytes.
*/
virtual size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const = 0;
virtual size_t getLength(PartType partType, size_t maxLength) const = 0;
/**
* Derive a new @a DataField from this field.
* @param name the field name, or empty to use this fields name.
* @param attributes the additional named attributes to override.
* @param partType the message part in which the field is stored.
* @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable).
* @param attributes the additional named attributes to override (may be modified).
* @param values the value=text assignments, or empty to use this fields assignments (if applicable).
* @param fields the @a vector to which created @a SingleDataField instances shall be added.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const = 0;
virtual result_t derive(const string& name, PartType partType, int divisor,
const map<unsigned int, string>& values, map<string, string>* attributes,
vector<const SingleDataField*>* fields) const = 0;
/**
* Get the specified field name.
* @param fieldIndex the index of the field, or -1 for this.
* @return the field name, or the index as string if not unique or not available.
*/
virtual string getName(const ssize_t fieldIndex = -1) const { return m_name; }
virtual string getName(ssize_t fieldIndex) const { return m_name; }
/**
* Dump the field settings to the output.
* @param output the @a ostream to dump to.
*/
virtual void dump(ostream& output) const = 0;
virtual void dump(ostream* output) const = 0;
/**
* Return whether the field is available.
@@ -281,46 +281,46 @@ class DataField : public AttributedItem {
* Reads the numeric value from the @a SymbolString.
* @param data the data @a SymbolString for reading binary data.
* @param offset the additional offset to add for reading binary data.
* @param output the variable in which to store the numeric value.
* @param fieldName the name of the field to read, or NULL for the first field.
* @param fieldIndex the optional index of the named field, or -1.
* @param output the variable in which to store the numeric value.
* @return @a RESULT_OK on success,
* or @a RESULT_EMPTY if the field was skipped (either if the partType does
* not match or ignored, or due to @a fieldName or @a fieldIndex),
* or an error code.
*/
virtual result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const = 0;
/**
* Reads the value from the @a SymbolString.
* @param data the data @a SymbolString for reading binary data.
* @param offset the additional offset to add for reading binary data.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* @param outputIndex the optional index of the field when using an indexed output format, or -1.
* @param leadingSeparator whether to prepend a separator before the formatted value.
* @param fieldName the optional name of a field to limit the output to.
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
* @param outputFormat the @a OutputFormat options to use.
* @param outputIndex the optional index of the field when using an indexed output format, or -1.
* @param output the @a ostream to append the formatted value to.
* @return @a RESULT_OK on success (or if the partType does not match),
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex),
* or an error code.
*/
virtual result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const = 0;
/**
* Writes the value to the master or slave @a SymbolString.
* @param input the @a istringstream to parse the formatted value from.
* @param data the unescaped data @a SymbolString for writing binary data.
* @param offset the additional offset to add for writing binary data.
* @param separator the separator character between multiple fields.
* @param length the variable in which to store the used length in bytes, or NULL.
* @param offset the additional offset to add for writing binary data.
* @param data the data @a SymbolString to write binary data to.
* @param usedLength the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const = 0;
virtual result_t write(char separator, size_t offset, istringstream* input,
SymbolString* data, size_t* usedLength) const = 0;
};
@@ -337,8 +337,8 @@ class SingleDataField : public DataField {
* @param partType the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored.
*/
SingleDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length)
SingleDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
PartType partType, size_t length)
: DataField(name, attributes),
m_partType(partType), m_dataType(dataType), m_length(length) {}
@@ -365,9 +365,9 @@ class SingleDataField : public DataField {
* @return @a RESULT_OK on success, or an error code.
* Note: the caller needs to free the created instance.
*/
static result_t create(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, int divisor, map<unsigned int, string> values,
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
static result_t create(const string& name, const map<string, string>& attributes, const DataType* dataType,
PartType partType, size_t length, int divisor, const string& constantValue,
bool verifyValue, map<unsigned int, string>* values, SingleDataField** returnField);
/**
* Get whether this field is ignored.
@@ -382,11 +382,12 @@ class SingleDataField : public DataField {
PartType getPartType() const { return m_partType; }
// @copydoc
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
size_t getLength(PartType partType, size_t maxLength) const override;
// @copydoc
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
result_t derive(const string& name, PartType partType, int divisor,
const map<unsigned int, string>& values, map<string, string>* attributes,
vector<const SingleDataField*>* fields) const override;
/**
* Get whether this field uses a full byte offset.
@@ -396,24 +397,36 @@ class SingleDataField : public DataField {
*/
bool hasFullByteOffset(bool after) const;
/**
* Dump the common prefix field settings to the output (name and part type).
* @param output the @a ostream to dump to.
*/
void dumpPrefix(ostream* output) const;
/**
* Dump the common suffix field settings to the output (optiona unit and comment).
* @param output the @a ostream to dump to.
*/
void dumpSuffix(ostream* output) const;
// @copydoc
void dump(ostream& output) const override;
void dump(ostream* output) const override;
// @copydoc
bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc
result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const override;
// @copydoc
result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const override;
// @copydoc
result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
result_t write(char separator, size_t offset, istringstream* input,
SymbolString* data, size_t* usedLength) const override;
protected:
@@ -421,13 +434,12 @@ class SingleDataField : public DataField {
* Internal method for reading the field from a @a SymbolString.
* @param input the @a SymbolString to read the binary value from.
* @param offset the offset in the @a SymbolString.
* @param output the ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* @param output the ostream to append the formatted value to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readSymbols(const SymbolString& input,
const size_t offset,
ostringstream& output, OutputFormat outputFormat) const;
virtual result_t readSymbols(const SymbolString& input, size_t offset,
OutputFormat outputFormat, ostream* output) const;
/**
* Internal method for writing the field to a @a SymbolString.
@@ -437,9 +449,8 @@ class SingleDataField : public DataField {
* @param usedLength the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t writeSymbols(istringstream& input,
const size_t offset,
SymbolString& output, size_t* usedLength) const;
virtual result_t writeSymbols(size_t offset, istringstream* input,
SymbolString* output, size_t* usedLength) const;
/** the message part in which the field is stored. */
const PartType m_partType;
@@ -466,8 +477,8 @@ class ValueListDataField : public SingleDataField {
* @param length the number of symbols in the message part in which the field is stored.
* @param values the value=text assignments.
*/
ValueListDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, const map<unsigned int, string> values)
ValueListDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
PartType partType, size_t length, const map<unsigned int, string>& values)
: SingleDataField(name, attributes, dataType, partType, length),
m_values(values) {}
@@ -480,21 +491,22 @@ class ValueListDataField : public SingleDataField {
const ValueListDataField* clone() const override;
// @copydoc
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
result_t derive(const string& name, PartType partType, int divisor,
const map<unsigned int, string>& values, map<string, string>* attributes,
vector<const SingleDataField*>* fields) const override;
// @copydoc
void dump(ostream& output) const override;
void dump(ostream* output) const override;
protected:
// @copydoc
result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(const SymbolString& input, size_t offset,
const OutputFormat outputFormat, ostream* output) const override;
// @copydoc
result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(size_t offset, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
private:
@@ -518,8 +530,8 @@ class ConstantDataField : public SingleDataField {
* @param value the constant value.
* @param verify whether to verify the read value against the constant value.
*/
ConstantDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, const string value, const bool verify)
ConstantDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
PartType partType, size_t length, const string& value, bool verify)
: SingleDataField(name, attributes, dataType, partType, length),
m_value(value), m_verify(verify) {}
@@ -532,21 +544,22 @@ class ConstantDataField : public SingleDataField {
const ConstantDataField* clone() const override;
// @copydoc
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
result_t derive(const string& name, PartType partType, int divisor,
const map<unsigned int, string>& values, map<string, string>* attributes,
vector<const SingleDataField*>* fields) const override;
// @copydoc
void dump(ostream& output) const override;
void dump(ostream* output) const override;
protected:
// @copydoc
result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(const SymbolString& input, size_t offset,
const OutputFormat outputFormat, ostream* output) const override;
// @copydoc
result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(size_t offset, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
private:
@@ -580,7 +593,7 @@ class DataFieldSet : public DataField {
* @param name the field name.
* @param fields the @a vector of @a SingleDataField instances part of this set.
*/
DataFieldSet(const string name, const vector<const SingleDataField*> fields)
DataFieldSet(const string& name, const vector<const SingleDataField*> fields)
: DataField(name), m_fields(fields) {
bool uniqueNames = true;
map<string, string> names;
@@ -588,7 +601,7 @@ class DataFieldSet : public DataField {
if (field->isIgnored()) {
continue;
}
string name = field->getName();
string name = field->getName(-1);
if (name.empty() || names.find(name) != names.end()) {
uniqueNames = false;
break;
@@ -607,33 +620,22 @@ class DataFieldSet : public DataField {
const DataFieldSet* clone() const override;
// @copydoc
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
size_t getLength(PartType partType, size_t maxLength) const override;
// @copydoc
string getName(const ssize_t fieldIndex = -1) const override;
string getName(ssize_t fieldIndex) const override;
// @copydoc
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
result_t derive(const string& name, PartType partType, int divisor,
const map<unsigned int, string>& values, map<string, string>* attributes,
vector<const SingleDataField*>* fields) const override;
/**
* Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL.
*/
/*SingleDataField* operator[](const size_t index) {
if (index >= m_fields.size()) {
return NULL;
}
return m_fields[index];
}*/
/**
* Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL.
*/
const SingleDataField* operator[](const size_t index) const {
const SingleDataField* operator[](size_t index) const {
if (index >= m_fields.size()) {
return NULL;
}
@@ -650,20 +652,20 @@ class DataFieldSet : public DataField {
bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc
void dump(ostream& output) const override;
void dump(ostream* output) const override;
// @copydoc
result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const override;
// @copydoc
result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const override;
// @copydoc
result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
result_t write(char separator, size_t offset, istringstream* input,
SymbolString* data, size_t* usedLength) const override;
private:
@@ -692,7 +694,7 @@ class DataFieldTemplates : public MappedFileReader {
* Constructs a new copied instance.
* @param other the @a DataFieldTemplates to copy from.
*/
DataFieldTemplates(DataFieldTemplates& other);
DataFieldTemplates(const DataFieldTemplates& other);
/**
* Destructor.
@@ -717,11 +719,11 @@ class DataFieldTemplates : public MappedFileReader {
result_t add(const DataField* field, string name = "", bool replace = false);
// @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override;
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override;
// @copydoc
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override;
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override;
/**
* Gets the template @a DataField instance with the specified name.
@@ -729,7 +731,7 @@ class DataFieldTemplates : public MappedFileReader {
* @return the template @a DataField instance, or NULL.
* Note: the caller may not free the returned instance.
*/
const DataField* get(string name) const;
const DataField* get(const string& name) const;
private:
+117 -126
View File
@@ -42,30 +42,29 @@ using std::setw;
using std::endl;
bool DataType::dump(ostream& output, const size_t length, const bool appendSeparatorDivisor) const {
output << m_id;
bool DataType::dump(size_t length, bool appendSeparatorDivisor, ostream* output) const {
*output << m_id;
if (isAdjustableLength()) {
if (length == REMAIN_LEN) {
output << ":*";
*output << ":*";
} else {
output << ":" << static_cast<unsigned>(length);
*output << ":" << static_cast<unsigned>(length);
}
}
if (appendSeparatorDivisor) {
output << FIELD_SEPARATOR;
*output << FIELD_SEPARATOR;
}
return false;
}
result_t StringDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) const {
result_t StringDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const {
return RESULT_EMPTY;
}
result_t StringDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const {
result_t StringDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol;
@@ -81,16 +80,16 @@ result_t StringDataType::readSymbols(const SymbolString& input,
}
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
output << setfill('0') << (m_isHex ? hex : dec);
*output << setfill('0') << (m_isHex ? hex : dec);
for (size_t index = start, i = 0; i < count; index += incr, i++) {
symbol = input.dataAt(offset + index);
if (m_isHex) {
if (i > 0) {
output << ' ';
*output << ' ';
}
output << setw(2) << static_cast<unsigned>(symbol);
*output << setw(2) << static_cast<unsigned>(symbol);
} else {
if (symbol == 0x00) {
terminated = true;
@@ -101,22 +100,21 @@ result_t StringDataType::readSymbols(const SymbolString& input,
symbol = '?';
} else if (outputFormat & OF_JSON) {
if (symbol == '"' || symbol == '\\') {
output << '\\'; // escape
*output << '\\'; // escape
}
}
output << static_cast<char>(symbol);
*output << static_cast<char>(symbol);
}
}
}
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
return RESULT_OK;
}
result_t StringDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const {
result_t StringDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const {
size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1;
@@ -132,7 +130,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
count = 1;
}
for (size_t index = start, i = 0; i < count; index += incr, i++) {
output.dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
output->dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
}
if (usedLength != NULL) {
*usedLength = count;
@@ -143,39 +141,39 @@ result_t StringDataType::writeSymbols(istringstream& input,
size_t i = 0, index;
for (index = start; i < count; index += incr, i++) {
if (m_isHex) {
while (!input.eof() && input.peek() == ' ') {
input.get();
while (!input->eof() && input->peek() == ' ') {
input->get();
}
if (input.eof()) { // no more digits
if (input->eof()) { // no more digits
value = m_replacement; // fill up with replacement
} else {
token.clear();
token.push_back((symbol_t)input.get());
if (input.eof()) {
token.push_back((symbol_t)input->get());
if (input->eof()) {
return RESULT_ERR_INVALID_NUM; // too short hex value
}
token.push_back((symbol_t)input.get());
if (input.eof()) {
token.push_back((symbol_t)input->get());
if (input->eof()) {
return RESULT_ERR_INVALID_NUM; // too short hex value
}
value = parseInt(token.c_str(), 16, 0, 0xff, result);
value = parseInt(token.c_str(), 16, 0, 0xff, &result);
if (result != RESULT_OK) {
return result; // invalid hex value
}
}
} else {
if (input.eof()) {
if (input->eof()) {
value = m_replacement;
} else {
value = input.get();
if (input.eof() || value < 0x20) {
value = input->get();
if (input->eof() || value < 0x20) {
value = m_replacement;
}
}
}
if (remainder && input.eof() && i > 0) {
if (remainder && input->eof() && i > 0) {
if (value == 0x00 && !m_isHex) {
output.dataAt(offset + index) = 0;
output->dataAt(offset + index) = 0;
index += incr;
}
break;
@@ -183,7 +181,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
if (value > 0xff) {
return RESULT_ERR_OUT_OF_RANGE; // value out of range
}
output.dataAt(offset + index) = (symbol_t)value;
output->dataAt(offset + index) = (symbol_t)value;
}
if (!remainder && i < count) {
@@ -196,14 +194,13 @@ result_t StringDataType::writeSymbols(istringstream& input,
}
result_t DateTimeDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) const {
result_t DateTimeDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const {
return RESULT_EMPTY;
}
result_t DateTimeDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const {
result_t DateTimeDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol, last = 0, hour = 0;
@@ -218,7 +215,7 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
}
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
int type = (m_hasDate?2:0) | (m_hasTime?1:0);
for (size_t index = start, i = 0; i < count; index += incr, i++) {
@@ -236,13 +233,13 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
case 2: // date only
if (!hasFlag(REQ) && symbol == m_replacement) {
if (i + 1 != length) {
output << NULL_VALUE << ".";
*output << NULL_VALUE << ".";
break;
} else if (last == m_replacement) {
if (length == 2) { // number of days since 01.01.1900
output << NULL_VALUE << ".";
*output << NULL_VALUE << ".";
}
output << NULL_VALUE;
*output << NULL_VALUE;
break;
}
}
@@ -259,29 +256,29 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
y++;
m -= 12;
}
output << dec << setfill('0') << setw(2) << static_cast<unsigned>(d) << "."
<< setw(2) << static_cast<unsigned>(m) << "." << static_cast<unsigned>(y + 1900);
*output << dec << setfill('0') << setw(2) << static_cast<unsigned>(d) << "."
<< setw(2) << static_cast<unsigned>(m) << "." << static_cast<unsigned>(y + 1900);
break;
}
if (i + 1 == length) {
output << (2000 + symbol);
*output << (2000 + symbol);
} else if (symbol < 1 || (i == 0 && symbol > 31) || (i == 1 && symbol > 12)) {
return RESULT_ERR_OUT_OF_RANGE; // invalid date
} else {
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol) << ".";
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol) << ".";
}
break;
case 1: // time only
if (!hasFlag(REQ) && symbol == m_replacement) {
if (length == 1) { // truncated time
output << NULL_VALUE << ":" << NULL_VALUE;
*output << NULL_VALUE << ":" << NULL_VALUE;
break;
}
if (i > 0) {
output << ":";
*output << ":";
}
output << NULL_VALUE;
*output << NULL_VALUE;
break;
}
if (hasFlag(SPE)) { // minutes since midnight
@@ -297,7 +294,7 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
if (hour > 24) {
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
}
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(hour);
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(hour);
symbol = (symbol_t)(minutes % 60);
} else if (length == 1) { // truncated time
if (m_bitCount < 8) {
@@ -320,22 +317,21 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
return RESULT_ERR_OUT_OF_RANGE; // invalid time
}
if (i > 0) {
output << ":";
*output << ":";
}
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol);
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol);
break;
}
last = symbol;
}
if (outputFormat & OF_JSON) {
output << '"';
*output << '"';
}
return RESULT_OK;
}
result_t DateTimeDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const {
result_t DateTimeDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const {
size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1;
@@ -351,7 +347,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
count = 1;
}
for (size_t index = start, i = 0; i < count; index += incr, i++) {
output.dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
output->dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
}
if (usedLength != NULL) {
*usedLength = count;
@@ -369,14 +365,14 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
if (length == 4 && i == 2) {
continue; // skip weekday in between
}
if (input.eof() || !getline(input, token, '.')) {
if (input->eof() || !getline(*input, token, '.')) {
return RESULT_ERR_EOF; // incomplete
}
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
if (!hasFlag(REQ) && token == NULL_VALUE) {
value = m_replacement;
break;
}
value = parseInt(token.c_str(), 10, 0, 2099, result);
value = parseInt(token.c_str(), 10, 0, 2099, &result);
if (result != RESULT_OK) {
return result; // invalid date part
}
@@ -389,7 +385,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
int l = last <= 2 ? 1 : 0;
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
value = mjd - 15020; // 01.01.1900
output.dataAt(offset + index) = (symbol_t)(value&0xff);
output->dataAt(offset + index) = (symbol_t)(value&0xff);
value >>= 8;
index += incr;
skip = false;
@@ -404,10 +400,10 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
int daysSinceSunday = (mjd+3) % 7; // Sun=0
if (hasFlag(BCD)) {
output.dataAt(offset + index - incr) = (symbol_t)((6+daysSinceSunday) % 7); // Sun=0x06
output->dataAt(offset + index - incr) = (symbol_t)((6+daysSinceSunday) % 7); // Sun=0x06
} else {
// Sun=0x07
output.dataAt(offset + index - incr) = (symbol_t)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
output->dataAt(offset + index - incr) = (symbol_t)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
}
}
if (value >= 2000) {
@@ -422,10 +418,10 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
break;
case 1: // time only
if (input.eof() || !getline(input, token, LENGTH_SEPARATOR)) {
if (input->eof() || !getline(*input, token, LENGTH_SEPARATOR)) {
return RESULT_ERR_EOF; // incomplete
}
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
if (!hasFlag(REQ) && token == NULL_VALUE) {
value = m_replacement;
if (length == 1) { // truncated time
if (i == 0) {
@@ -439,7 +435,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
}
break;
}
value = parseInt(token.c_str(), 10, 0, 59, result);
value = parseInt(token.c_str(), 10, 0, 59, &result);
if (result != RESULT_OK) {
return result; // invalid time part
}
@@ -452,7 +448,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
break;
}
value += last*60;
output.dataAt(offset + index) = (symbol_t)(value&0xff);
output->dataAt(offset + index) = (symbol_t)(value&0xff);
value >>= 8;
index += incr;
} else if (length == 1) { // truncated time
@@ -480,7 +476,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
if (value > 0xff) {
return RESULT_ERR_OUT_OF_RANGE; // value out of range
}
output.dataAt(offset + index) = (symbol_t)value;
output->dataAt(offset + index) = (symbol_t)value;
}
}
@@ -494,7 +490,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
}
size_t NumberDataType::calcPrecision(const int divisor) {
size_t NumberDataType::calcPrecision(int divisor) {
size_t precision = 0;
if (divisor > 1) {
for (unsigned int exp = 1; exp < MAX_DIVISOR; exp *= 10, precision++) {
@@ -506,28 +502,28 @@ size_t NumberDataType::calcPrecision(const int divisor) {
return precision;
}
bool NumberDataType::dump(ostream& output, size_t length, const bool appendSeparatorDivisor) const {
bool NumberDataType::dump(size_t length, bool appendSeparatorDivisor, ostream* output) const {
if (m_bitCount < 8) {
DataType::dump(output, m_bitCount, appendSeparatorDivisor);
DataType::dump(m_bitCount, appendSeparatorDivisor, output);
} else {
DataType::dump(output, length, appendSeparatorDivisor);
DataType::dump(length, appendSeparatorDivisor, output);
}
if (!appendSeparatorDivisor) {
return false;
}
if (m_baseType) {
if (m_baseType->m_divisor != m_divisor) {
output << static_cast<int>(m_divisor / m_baseType->m_divisor);
*output << static_cast<int>(m_divisor / m_baseType->m_divisor);
return true;
}
} else if (m_divisor != 1) {
output << static_cast<int>(m_divisor);
*output << static_cast<int>(m_divisor);
return true;
}
return false;
}
result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType** derived) const {
if (divisor == 0) {
divisor = 1;
}
@@ -549,7 +545,7 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataTy
}
}
if (divisor == m_divisor && bitCount == m_bitCount) {
derived = this;
*derived = this;
return RESULT_OK;
}
if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR) {
@@ -569,19 +565,18 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataTy
return RESULT_ERR_INVALID_ARG;
}
if (m_bitCount < 8) {
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
*derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
m_firstBit, divisor, m_baseType ? m_baseType : this);
} else {
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
*derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
m_minValue, m_maxValue, divisor, m_baseType ? m_baseType : this);
}
DataTypeList::getInstance()->addCleanup(derived);
DataTypeList::getInstance()->addCleanup(*derived);
return RESULT_OK;
}
result_t NumberDataType::readRawValue(const SymbolString& input,
size_t offset, const size_t length,
unsigned int& value) const {
result_t NumberDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol;
@@ -594,13 +589,13 @@ result_t NumberDataType::readRawValue(const SymbolString& input,
incr = -1;
}
value = 0;
*value = 0;
unsigned int exp = 1;
for (size_t index = start, i = 0; i < count; index += incr, i++) {
symbol = input.dataAt(offset + index);
if (hasFlag(BCD)) {
if (!hasFlag(REQ) && symbol == (m_replacement & 0xff)) {
value = m_replacement;
*value = m_replacement;
return RESULT_OK;
}
if (!hasFlag(HCD)) {
@@ -611,40 +606,39 @@ result_t NumberDataType::readRawValue(const SymbolString& input,
} else if (symbol > 0x63) {
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
}
value += symbol * exp;
*value += symbol * exp;
exp *= 100;
} else {
value |= symbol * exp;
*value |= symbol * exp;
exp <<= 8;
}
}
if (m_firstBit > 0) {
value >>= m_firstBit;
*value >>= m_firstBit;
}
if (m_bitCount < 8) {
value &= (1 << m_bitCount) - 1;
*value &= (1 << m_bitCount) - 1;
}
return RESULT_OK;
}
result_t NumberDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const {
result_t NumberDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const {
unsigned int value = 0;
int signedValue;
result_t result = readRawValue(input, offset, length, value);
result_t result = readRawValue(offset, length, input, &value);
if (result != RESULT_OK) {
return result;
}
output << setw(0) << dec; // initialize output
*output << setw(0) << dec; // initialize output
if (!hasFlag(REQ) && value == m_replacement) {
if (outputFormat & OF_JSON) {
output << "null";
*output << "null";
} else {
output << NULL_VALUE;
*output << NULL_VALUE;
}
return RESULT_OK;
}
@@ -694,21 +688,21 @@ result_t NumberDataType::readSymbols(const SymbolString& input,
}
}
if (m_precision != 0) {
output << fixed << setprecision(static_cast<int>(m_precision+6));
*output << fixed << setprecision(static_cast<int>(m_precision+6));
} else if (val == 0) {
output << fixed << setprecision(1);
*output << fixed << setprecision(1);
}
output << static_cast<double>(val);
*output << static_cast<double>(val);
return RESULT_OK;
}
if (!negative) {
if (m_divisor < 0) {
output << (static_cast<float>(value) * static_cast<float>(-m_divisor));
*output << (static_cast<float>(value) * static_cast<float>(-m_divisor));
} else if (m_divisor <= 1) {
output << static_cast<unsigned>(value);
*output << static_cast<unsigned>(value);
} else {
output << setprecision(static_cast<int>(m_precision))
<< fixed << (static_cast<float>(value) / static_cast<float>(m_divisor));
*output << setprecision(static_cast<int>(m_precision))
<< fixed << (static_cast<float>(value) / static_cast<float>(m_divisor));
}
return RESULT_OK;
}
@@ -719,30 +713,27 @@ result_t NumberDataType::readSymbols(const SymbolString& input,
signedValue = static_cast<int>(value);
}
if (m_divisor < 0) {
output << fixed << setprecision(0)
*output << fixed << setprecision(0)
<< (static_cast<float>(signedValue) * static_cast<float>(-m_divisor));
} else if (m_divisor <= 1) {
if (hasFlag(FIX) && hasFlag(BCD)) {
if (outputFormat & OF_JSON) {
output << '"';
output << setw(static_cast<int>(length * 2)) << setfill('0');
output << static_cast<signed>(signedValue) << setw(0);
output << '"';
*output << '"' << setw(static_cast<int>(length * 2))
<< setfill('0') << static_cast<signed>(signedValue) << setw(0) << '"';
return RESULT_OK;
}
output << setw(static_cast<int>(length * 2)) << setfill('0');
*output << setw(static_cast<int>(length * 2)) << setfill('0');
}
output << static_cast<signed>(signedValue) << setw(0);
*output << static_cast<signed>(signedValue) << setw(0);
} else {
output << setprecision(static_cast<int>(m_precision))
<< fixed << (static_cast<float>(signedValue) / static_cast<float>(m_divisor));
*output << setprecision(static_cast<int>(m_precision))
<< fixed << (static_cast<float>(signedValue) / static_cast<float>(m_divisor));
}
return RESULT_OK;
}
result_t NumberDataType::writeRawValue(unsigned int value,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const {
result_t NumberDataType::writeRawValue(unsigned int value, size_t offset, size_t length,
SymbolString* output, size_t* usedLength) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol;
@@ -774,10 +765,10 @@ result_t NumberDataType::writeRawValue(unsigned int value,
symbol = (value / exp) & 0xff;
exp <<= 8;
}
if (index == start && (m_bitCount % 8) != 0 && offset + index < output.getDataSize()) {
output.dataAt(offset + index) |= symbol;
if (index == start && (m_bitCount % 8) != 0 && offset + index < output->getDataSize()) {
output->dataAt(offset + index) |= symbol;
} else {
output.dataAt(offset + index) = symbol;
output->dataAt(offset + index) = symbol;
}
}
if (usedLength != NULL) {
@@ -786,17 +777,16 @@ result_t NumberDataType::writeRawValue(unsigned int value,
return RESULT_OK;
}
result_t NumberDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const {
result_t NumberDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const {
unsigned int value;
const char* str = input.str().c_str();
if (!hasFlag(REQ) && (isIgnored() || strcmp(str, NULL_VALUE) == 0)) {
if (!hasFlag(REQ) && (isIgnored() || input->str() == NULL_VALUE)) {
value = m_replacement; // replacement value
} else if (str == NULL || *str == 0) {
} else if (input->str().empty()) {
return RESULT_ERR_EOF; // input too short
} else if (hasFlag(EXP)) { // IEEE 754 binary32
const char* str = input->str().c_str();
char* strEnd = NULL;
double dvalue = strtod(str, &strEnd);
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
@@ -835,6 +825,7 @@ result_t NumberDataType::writeSymbols(istringstream& input,
}
#endif
} else {
const char* str = input->str().c_str();
char* strEnd = NULL;
if (m_divisor == 1) {
if (hasFlag(SIG)) {
@@ -1038,7 +1029,7 @@ result_t DataTypeList::add(const DataType* dataType) {
return RESULT_OK;
}
const DataType* DataTypeList::get(const string id, const size_t length) const {
const DataType* DataTypeList::get(const string& id, size_t length) const {
if (length > 0) {
ostringstream str;
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
+46 -59
View File
@@ -167,7 +167,7 @@ class DataType {
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to
* @a NumberDataType#minValue).
*/
DataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement)
DataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement)
: m_id(id), m_bitCount(bitCount), m_flags(flags), m_replacement(replacement) {}
/**
@@ -190,7 +190,7 @@ class DataType {
* @param flag the flag to check (like #BCD).
* @return whether the flag is set.
*/
bool hasFlag(const unsigned int flag) const { return (m_flags & flag) != 0; }
bool hasFlag(unsigned int flag) const { return (m_flags & flag) != 0; }
/**
* @return whether this type is ignored.
@@ -216,50 +216,47 @@ class DataType {
/**
* Dump the type identifier with the specified length and optionally the
* divisor to the output.
* @param output the @a ostream to dump to.
* @param length the number of symbols to read/write.
* @param appendSeparatorDivisor whether to append a @a FIELD_SEPARATOR followed by the divisor (if available).
* @param output the @a ostream to dump to.
* @return true when a non-default divisor was written to the output.
*/
virtual bool dump(ostream& output, const size_t length, const bool appendSeparatorDivisor = true) const;
virtual bool dump(size_t length, bool appendSeparatorDivisor, ostream* output) const;
/**
* Internal method for reading the numeric raw value from a @a SymbolString.
* @param input the @a SymbolString to read the binary value from.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to read.
* @param input the @a SymbolString to read the binary value from.
* @param value the variable in which to store the numeric raw value.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) const = 0;
virtual result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const = 0;
/**
* Internal method for reading the field from a @a SymbolString.
* @param input the @a SymbolString to read the binary value from.
* @param offset the offset in the data of the @a SymbolString.
* @param length the number of symbols to read.
* @param output the ostringstream to append the formatted value to.
* @param input the @a SymbolString to read the binary value from.
* @param outputFormat the @a OutputFormat options to use.
* @param output the ostream to append the formatted value to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const = 0;
virtual result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const = 0;
/**
* Internal method for writing the field to a @a SymbolString.
* @param input the @a istringstream to parse the formatted value from.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to write, or @a REMAIN_LEN.
* @param input the @a istringstream to parse the formatted value from.
* @param output the @a SymbolString to write the binary value to.
* @param usedLength the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const = 0;
virtual result_t writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const = 0;
protected:
@@ -291,8 +288,8 @@ class StringDataType : public DataType {
* @param replacement the replacement value (fill-up value).
* @param isHex true for hex digits instead of characters.
*/
StringDataType(const string id, const size_t bitCount, const uint16_t flags,
const unsigned int replacement, bool isHex = false)
StringDataType(const string& id, size_t bitCount, uint16_t flags,
unsigned int replacement, bool isHex = false)
: DataType(id, bitCount, flags, replacement), m_isHex(isHex) {}
/**
@@ -301,19 +298,16 @@ class StringDataType : public DataType {
virtual ~StringDataType() {}
// @copydoc
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) const override;
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const override;
// @copydoc
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
private:
@@ -337,8 +331,8 @@ class DateTimeDataType : public DataType {
* @param hasTime true if time part is present.
* @param resolution the the resolution in minutes for time types, or 1.
*/
DateTimeDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
const bool hasDate, const bool hasTime, const int16_t resolution)
DateTimeDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
bool hasDate, bool hasTime, int16_t resolution)
: DataType(id, bitCount, flags, replacement), m_hasDate(hasDate), m_hasTime(hasTime),
m_resolution(resolution == 0 ? 1 : resolution) {}
@@ -363,19 +357,16 @@ class DateTimeDataType : public DataType {
int16_t getResolution() const { return m_resolution; }
// @copydoc
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) const override;
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const override;
// @copydoc
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
OutputFormat outputFormat, ostream* output) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(const size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
private:
@@ -406,8 +397,8 @@ class NumberDataType : public DataType {
* @param divisor the divisor (negative for reciprocal).
* @param baseType the base @a NumberDataType for derived instances, or NULL.
*/
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
const unsigned int minValue, const unsigned int maxValue, const int divisor,
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
unsigned int minValue, unsigned int maxValue, int divisor,
const NumberDataType* baseType)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor),
m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(baseType) {}
@@ -422,8 +413,8 @@ class NumberDataType : public DataType {
* @param divisor the divisor (negative for reciprocal).
* @param baseType the base @a NumberDataType for derived instances, or NULL.
*/
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
const int16_t firstBit, const int divisor, const NumberDataType* baseType = NULL)
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
int16_t firstBit, int divisor, const NumberDataType* baseType = NULL)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor),
m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
@@ -438,10 +429,10 @@ class NumberDataType : public DataType {
* @param divisor the divisor (negative for reciprocal).
* @return the precision for formatting the value.
*/
static size_t calcPrecision(const int divisor);
static size_t calcPrecision(int divisor);
// @copydoc
bool dump(ostream& output, const size_t length, const bool appendSeparatorDivisor = true) const override;
bool dump(size_t length, bool appendSeparatorDivisor, ostream* output) const override;
/**
* Derive a new @a NumberDataType from this.
@@ -453,7 +444,7 @@ class NumberDataType : public DataType {
* not necessary.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const;
virtual result_t derive(int divisor, size_t bitCount, const NumberDataType** derived) const;
/**
* @return the minimum raw value.
@@ -481,14 +472,12 @@ class NumberDataType : public DataType {
int16_t getFirstBit() const { return m_firstBit; }
// @copydoc
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) const override;
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const override;
// @copydoc
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) const override;
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
const OutputFormat outputFormat, ostream* output) const override;
/**
* Internal method for writing the numeric raw value to a @a SymbolString.
@@ -500,14 +489,12 @@ class NumberDataType : public DataType {
* or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
result_t writeRawValue(unsigned int value,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength = NULL) const;
result_t writeRawValue(unsigned int value, size_t offset, size_t length,
SymbolString* output, size_t* usedLength) const;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) const override;
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
SymbolString* output, size_t* usedLength) const override;
private:
@@ -580,7 +567,7 @@ class DataTypeList {
* @return the @a DataType instance, or NULL if not available.
* Note: the caller may not free the instance.
*/
const DataType* get(const string id, const size_t length = 0) const;
const DataType* get(const string& id, size_t length = 0) const;
/**
* Returns an iterator pointing to the first ID/@a DataType pair.
+9 -9
View File
@@ -42,7 +42,7 @@ Device::~Device() {
close();
}
Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend) {
Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool initialSend) {
if (strchr(name, '/') == NULL && strchr(name, ':') != NULL) {
char* in = strdup(name);
bool udp = false;
@@ -57,7 +57,7 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
return NULL; // invalid protocol or missing port
}
result_t result = RESULT_OK;
unsigned int port = parseInt(portpos+1, 10, 1, 65535, result);
unsigned int port = parseInt(portpos+1, 10, 1, 65535, &result);
if (result != RESULT_OK) {
free(in);
return NULL; // invalid port
@@ -98,7 +98,7 @@ bool Device::isValid() {
return m_fd != -1;
}
result_t Device::send(const symbol_t value) {
result_t Device::send(symbol_t value) {
if (!isValid()) {
return RESULT_ERR_DEVICE;
}
@@ -111,7 +111,7 @@ result_t Device::send(const symbol_t value) {
return RESULT_OK;
}
result_t Device::recv(const unsigned int timeout, symbol_t& value) {
result_t Device::recv(unsigned int timeout, symbol_t* value) {
if (!isValid()) {
return RESULT_ERR_DEVICE;
}
@@ -162,7 +162,7 @@ result_t Device::recv(const unsigned int timeout, symbol_t& value) {
return RESULT_ERR_DEVICE;
}
if (m_listener != NULL) {
m_listener->notifyDeviceData(value, true);
m_listener->notifyDeviceData(*value, true);
}
return RESULT_OK;
}
@@ -299,14 +299,14 @@ bool NetworkDevice::available() {
return m_buffer && m_bufLen > 0;
}
ssize_t NetworkDevice::write(const symbol_t value) {
ssize_t NetworkDevice::write(symbol_t value) {
m_bufLen = 0; // flush read buffer
return Device::write(value);
}
ssize_t NetworkDevice::read(symbol_t& value) {
ssize_t NetworkDevice::read(symbol_t* value) {
if (available()) {
value = m_buffer[m_bufPos];
*value = m_buffer[m_bufPos];
m_bufPos = (m_bufPos+1)%m_bufSize;
m_bufLen--;
return 1;
@@ -316,7 +316,7 @@ ssize_t NetworkDevice::read(symbol_t& value) {
if (size <= 0) {
return size;
}
value = m_buffer[0];
*value = m_buffer[0];
m_bufPos = 1;
m_bufLen = size-1;
return size;
+13 -13
View File
@@ -54,7 +54,7 @@ class DeviceListener {
* @param symbol the received/sent symbol.
* @param received @a true on reception, @a false on sending.
*/
virtual void notifyDeviceData(const symbol_t symbol, bool received) = 0; // abstract
virtual void notifyDeviceData(symbol_t symbol, bool received) = 0; // abstract
};
@@ -70,7 +70,7 @@ class Device {
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
*/
Device(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend)
Device(const char* name, bool checkDevice, bool readOnly, bool initialSend)
: m_name(name), m_checkDevice(checkDevice), m_readOnly(readOnly), m_initialSend(initialSend), m_fd(-1),
m_listener(NULL) {}
@@ -88,8 +88,8 @@ class Device {
* @return the new @a Device, or NULL on error.
* Note: the caller needs to free the created instance.
*/
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false,
const bool initialSend = false);
static Device* create(const char* name, bool checkDevice = true, bool readOnly = false,
bool initialSend = false);
/**
* Get the transfer latency of this device.
@@ -113,7 +113,7 @@ class Device {
* @param value the byte value to write.
* @return the @a result_t code.
*/
result_t send(const symbol_t value);
result_t send(symbol_t value);
/**
* Read a single byte from the device.
@@ -121,7 +121,7 @@ class Device {
* @param value the reference in which the received byte value is stored.
* @return the result_t code.
*/
result_t recv(const unsigned int timeout, symbol_t& value);
result_t recv(unsigned int timeout, symbol_t* value);
/**
* Return the device name.
@@ -165,14 +165,14 @@ class Device {
* @param value the byte value to write.
* @return the number of bytes written, or -1 on error.
*/
virtual ssize_t write(const symbol_t value) { return ::write(m_fd, &value, 1); }
virtual ssize_t write(symbol_t value) { return ::write(m_fd, &value, 1); }
/**
* Read a single byte.
* @param value the reference in which the read byte value is stored.
* @return the number of bytes read, or -1 on error.
*/
virtual ssize_t read(symbol_t& value) { return ::read(m_fd, &value, 1); }
virtual ssize_t read(symbol_t* value) { return ::read(m_fd, value, 1); }
/** the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). */
const char* m_name;
@@ -207,7 +207,7 @@ class SerialDevice : public Device {
* @param readOnly whether to allow read access to the device only.
* @param initialSend whether to send an initial @a ESC symbol in @a open().
*/
SerialDevice(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend)
SerialDevice(const char* name, bool checkDevice, bool readOnly, bool initialSend)
: Device(name, checkDevice, readOnly, initialSend) {}
// @copydoc
@@ -240,8 +240,8 @@ class NetworkDevice : public Device {
* @param initialSend whether to send an initial @a ESC symbol in @a open().
* @param udp true for UDP, false to TCP.
*/
NetworkDevice(const char* name, const struct sockaddr_in address, const bool readOnly, const bool initialSend,
const bool udp)
NetworkDevice(const char* name, const struct sockaddr_in& address, bool readOnly, bool initialSend,
bool udp)
: Device(name, true, readOnly, initialSend), m_address(address), m_udp(udp),
m_buffer(NULL), m_bufSize(0), m_bufLen(0), m_bufPos(0) {}
@@ -269,10 +269,10 @@ class NetworkDevice : public Device {
bool available() override;
// @copydoc
ssize_t write(const symbol_t value) override;
ssize_t write(symbol_t value) override;
// @copydoc
ssize_t read(symbol_t& value) override;
ssize_t read(symbol_t* value) override;
private:
+88 -77
View File
@@ -36,21 +36,21 @@ using std::setw;
using std::dec;
result_t FileReader::readFromFile(const string filename, string& errorDescription, bool verbose,
map<string, string>* defaults, size_t* hash, size_t* size, time_t* time) {
result_t FileReader::readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
string* errorDescription, size_t* hash, size_t* size, time_t* time) {
struct stat st;
if (stat(filename.c_str(), &st) != 0) {
errorDescription = filename;
*errorDescription = filename;
return RESULT_ERR_NOTFOUND;
}
if (S_ISDIR(st.st_mode)) {
errorDescription = filename+" is a directory";
*errorDescription = filename+" is a directory";
return RESULT_ERR_NOTFOUND;
}
ifstream ifs;
ifs.open(filename.c_str(), ifstream::in);
if (!ifs.is_open()) {
errorDescription = filename;
ifstream stream;
stream.open(filename.c_str(), ifstream::in);
if (!stream.is_open()) {
*errorDescription = filename;
return RESULT_ERR_NOTFOUND;
}
if (hash) {
@@ -65,60 +65,56 @@ result_t FileReader::readFromFile(const string filename, string& errorDescriptio
unsigned int lineNo = 0;
vector<string> row;
result_t result = RESULT_OK;
while (ifs.peek() != EOF && result == RESULT_OK) {
result = readLineFromStream(ifs, errorDescription, filename, lineNo, row, verbose, hash, size);
while (stream.peek() != EOF && result == RESULT_OK) {
result = readLineFromStream(filename, verbose, &stream, &lineNo, &row, errorDescription, hash, size);
}
ifs.close();
stream.close();
return result;
}
result_t FileReader::readLineFromStream(istream& stream, string& errorDescription,
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose,
size_t* hash, size_t* size) {
result_t FileReader::readLineFromStream(const string& filename, bool verbose, istream* stream,
unsigned int* lineNo, vector<string>* row, string* errorDescription, size_t* hash, size_t* size) {
result_t result;
if (!splitFields(stream, row, lineNo, hash, size)) {
errorDescription = "blank line";
*errorDescription = "blank line";
result = RESULT_ERR_EOF;
} else {
errorDescription = "";
result = addFromFile(row, errorDescription, filename, lineNo);
*errorDescription = "";
result = addFromFile(filename, *lineNo, row, errorDescription);
}
if (result != RESULT_OK) {
if (!verbose) {
ostringstream error;
error << filename << ":" << lineNo;
if (errorDescription.length() > 0) {
error << ": " << errorDescription;
if (!errorDescription->empty()) {
string error;
formatError(filename, *lineNo, result, *errorDescription, &error);
*errorDescription = error;
if (verbose) {
cout << error << endl;
}
errorDescription = error.str();
return result;
}
if (!errorDescription.empty()) {
cout << "error reading " << filename << ":" << lineNo << ": " << getResultCode(result) << ", "
<< errorDescription << endl;
} else if (!verbose) {
return formatError(filename, *lineNo, result, "", errorDescription);
}
} else if (!verbose) {
errorDescription = "";
*errorDescription = "";
}
return result;
}
void FileReader::trim(string& str) {
size_t pos = str.find_first_not_of(" \t");
void FileReader::trim(string* str) {
size_t pos = str->find_first_not_of(" \t");
if (pos != string::npos) {
str.erase(0, pos);
str->erase(0, pos);
}
pos = str.find_last_not_of(" \t");
pos = str->find_last_not_of(" \t");
if (pos != string::npos) {
str.erase(pos+1);
str->erase(pos+1);
}
}
void FileReader::tolower(string& str) {
transform(str.begin(), str.end(), str.begin(), ::tolower);
void FileReader::tolower(string* str) {
transform(str->begin(), str->end(), str->begin(), ::tolower);
}
static size_t hashFunction(const string str) {
static size_t hashFunction(const string& str) {
size_t hash = 0;
for (char c : str) {
hash = (31 * hash) ^ c;
@@ -126,27 +122,27 @@ static size_t hashFunction(const string str) {
return hash;
}
bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& lineNo,
bool FileReader::splitFields(istream* stream, vector<string>* row, unsigned int* lineNo,
size_t* hash, size_t* size) {
row.clear();
row->clear();
string line;
bool quotedText = false, wasQuoted = false;
ostringstream field;
char prev = FIELD_SEPARATOR;
bool empty = true, read = false;
while (getline(ifs, line)) {
while (getline(*stream, line)) {
read = true;
lineNo++;
trim(line);
++(*lineNo);
trim(&line);
size_t length = line.size();
if (size) {
*size += length + 1; // normalized with trailing endl
}
if (hash) {
*hash ^= (hashFunction(line) ^ (length << (7 * (lineNo % 5)))) & 0xffffffff;
*hash ^= (hashFunction(line) ^ (length << (7 * (*lineNo % 5)))) & 0xffffffff;
}
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
if (lineNo == 1) {
if (*lineNo == 1) {
break; // keep empty first line for applying default header
}
continue; // skip empty lines and comments
@@ -159,9 +155,9 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
field << ch;
} else {
string str = field.str();
trim(str);
trim(&str);
empty &= str.empty();
row.push_back(str);
row->push_back(str);
field.str("");
wasQuoted = false;
}
@@ -197,37 +193,52 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
}
}
string str = field.str();
trim(str);
trim(&str);
if (empty && str.empty()) {
row.clear();
row->clear();
return read;
}
row.push_back(str);
row->push_back(str);
return true;
}
result_t FileReader::formatError(const string& filename, unsigned int lineNo, result_t result,
const string& error, string* errorDescription) {
ostringstream str;
if (!errorDescription->empty()) {
str << *errorDescription << ", ";
}
str << filename << ":" << static_cast<unsigned>(lineNo) << ": " << getResultCode(result);
if (!error.empty()) {
str << ", " << error;
}
*errorDescription = str.str();
return result;
}
string MappedFileReader::normalizeLanguage(string lang) {
tolower(lang);
if (lang.size() > 2) {
size_t pos = lang.find('.');
const string MappedFileReader::normalizeLanguage(const string& lang) {
string normLang = lang;
tolower(&normLang);
if (normLang.size() > 2) {
size_t pos = normLang.find('.');
if (pos == string::npos) {
pos = lang.size();
pos = normLang.size();
}
size_t strip = lang.find('_');
size_t strip = normLang.find('_');
if (strip == string::npos || strip > pos) {
strip = pos;
}
if (strip > 2) {
strip = 2;
}
lang = lang.substr(0, strip);
return normLang.substr(0, strip);
}
return lang;
return normLang;
}
result_t MappedFileReader::readFromFile(const string filename, string& errorDescription, bool verbose,
map<string, string>* defaults, size_t* hash, size_t* size, time_t* time) {
result_t MappedFileReader::readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
string* errorDescription, size_t* hash, size_t* size, time_t* time) {
m_mutex.lock();
m_columnNames.clear();
m_lastDefaults.clear();
@@ -237,47 +248,47 @@ result_t MappedFileReader::readFromFile(const string filename, string& errorDesc
}
size_t lastSep = filename.find_last_of('/');
string defaultsPart = lastSep == string::npos ? filename : filename.substr(lastSep+1);
extractDefaultsFromFilename(defaultsPart, m_lastDefaults[""]);
result_t result = FileReader::readFromFile(filename, errorDescription, verbose, defaults, hash, size, time);
extractDefaultsFromFilename(defaultsPart, &m_lastDefaults[""], NULL, NULL, NULL);
result_t result = FileReader::readFromFile(filename, verbose, defaults, errorDescription, hash, size, time);
m_mutex.unlock();
return result;
}
result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescription,
const string filename, unsigned int lineNo) {
result_t MappedFileReader::addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
string* errorDescription) {
result_t result;
if (lineNo == 1) { // first line defines column names
result = getFieldMap(row, errorDescription, m_preferLanguage);
result = getFieldMap(m_preferLanguage, row, errorDescription);
if (result != RESULT_OK) {
return result;
}
if (row.empty()) {
errorDescription = "missing field map";
if (row->empty()) {
*errorDescription = "missing field map";
return RESULT_ERR_EOF;
}
m_columnNames = row;
m_columnNames = *row;
return RESULT_OK;
}
if (row.empty()) {
if (row->empty()) {
return RESULT_OK;
}
if (m_columnNames.empty()) {
errorDescription = "missing field map";
*errorDescription = "missing field map";
return RESULT_ERR_INVALID_ARG;
}
map<string, string> rowMapped;
vector< map<string, string> > subRowsMapped;
bool isDefault = m_supportsDefaults && !row[0].empty() && row[0][0] == '*';
bool isDefault = m_supportsDefaults && !(*row)[0].empty() && (*row)[0][0] == '*';
if (isDefault) {
row[0] = row[0].substr(1);
(*row)[0].erase(0, 1);
}
size_t lastRepeatStart = UINT_MAX;
map<string, string>* lastMappedRow = &rowMapped;
bool empty = true;
for (size_t colIdx = 0, colNameIdx = 0; colIdx < row.size(); colIdx++, colNameIdx++) {
for (size_t colIdx = 0, colNameIdx = 0; colIdx < row->size(); colIdx++, colNameIdx++) {
if (colNameIdx >= m_columnNames.size()) {
if (lastRepeatStart == UINT_MAX) {
errorDescription = "named columns exceeded";
*errorDescription = "named columns exceeded";
return RESULT_ERR_INVALID_ARG;
}
colNameIdx = lastRepeatStart;
@@ -297,7 +308,7 @@ result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescrip
} else if (columnName == SKIP_COLUMN) {
continue;
}
string value = row[colIdx];
string value = (*row)[colIdx];
empty &= value.empty();
(*lastMappedRow)[columnName] = value;
}
@@ -308,12 +319,12 @@ result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescrip
}
}
if (isDefault) {
return addDefaultFromFile(rowMapped, subRowsMapped, errorDescription, filename, lineNo);
return addDefaultFromFile(filename, lineNo, &rowMapped, &subRowsMapped, errorDescription);
}
return addFromFile(rowMapped, subRowsMapped, errorDescription, filename, lineNo);
return addFromFile(filename, lineNo, &rowMapped, &subRowsMapped, errorDescription);
}
string MappedFileReader::combineRow(const map<string, string>& row) {
const string MappedFileReader::combineRow(const map<string, string>& row) {
ostringstream ostream;
bool first = true;
for (auto entry : row) {
+51 -39
View File
@@ -79,76 +79,88 @@ class FileReader {
/**
* Read the definitions from a file.
* @param filename the name of the file being read.
* @param errorDescription a string in which to store the error description in case of error.
* @param verbose whether to verbosely log problems.
* @param defaults the default values by name (potentially overwritten by file name), or NULL to not use defaults.
* @param errorDescription a string in which to store the error description in case of error.
* @param hash optional pointer to a @a size_t value for storing the hash of the file, or NULL.
* @param size optional pointer to a @a size_t value for storing the normalized size of the file, or NULL.
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL);
virtual result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
string* errorDescription, size_t* hash, size_t* size, time_t* time);
/**
* Read a single line definition from the stream.
* @param stream the @a istream to read from.
* @param errorDescription a string in which to store the error description in case of error.
* @param filename the name of the file being read.
* @param verbose whether to verbosely log problems.
* @param stream the @a istream to read from.
* @param lineNo the last line number (incremented with each line read).
* @param row the definition row to clear and update with the read data (for performance reasons only).
* @param verbose whether to verbosely log problems.
* @param errorDescription a string in which to store the error description in case of error.
* @param hash optional pointer to a @a size_t value for updating with the hash of the line, or NULL.
* @param size optional pointer to a @a size_t value for updating with the normalized length of the line, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readLineFromStream(istream& stream, string& errorDescription,
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose = false,
size_t* hash = NULL, size_t* size = NULL);
virtual result_t readLineFromStream(const string& filename, bool verbose, istream* stream,
unsigned int* lineNo, vector<string>* row, string* errorDescription, size_t* hash, size_t* size);
/**
* Add a definition that was read from a file.
* @param row the definition row.
* @param errorDescription a string in which to store the error description in case of error.
* @param filename the name of the file being read.
* @param lineNo the current line number in the file being read.
* @param row the definition row (allowed to be modified).
* @param errorDescription a string in which to store the error description in case of error.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t addFromFile(vector<string>& row, string& errorDescription,
const string filename, unsigned int lineNo) = 0;
virtual result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
string* errorDescription) = 0;
/**
* Left and right trim the string.
* @param str the @a string to trim.
*/
static void trim(string& str);
static void trim(string* str);
/**
* Convert all upper case characters in the string to lower case.
* @param str the @a string to convert.
*/
static void tolower(string& str);
static void tolower(string* str);
/**
* Split the next line(s) from the @a istream into fields.
* @param ifs the @a istream to read from.
* @param stream the @a istream to read from.
* @param row the @a vector to which to add the fields. This will be empty for completely empty and comment lines.
* @param lineNo the current line number (incremented with each line read).
* @param hash optional pointer to a @a size_t value for combining the hash of the line with, or NULL.
* @param size optional pointer to a @a size_t value to add the trimmed line length to, or NULL.
* @return true if there are more lines to read, false when there are no more lines left.
*/
static bool splitFields(istream& ifs, vector<string>& row, unsigned int& lineNo,
static bool splitFields(istream* stream, vector<string>* row, unsigned int* lineNo,
size_t* hash = NULL, size_t* size = NULL);
/**
* Format the specified hash as 8 hex digits to the output stream.
* @param hash the hash code.
* @param str the @a ostream to write to.
* @param stream the @a ostream to write to.
*/
static void formatHash(size_t hash, ostream& str) {
str << std::hex << std::setw(8) << std::setfill('0') << (hash & 0xffffffff) << std::dec << std::setw(0);
static void formatHash(size_t hash, ostream* stream) {
*stream << std::hex << std::setw(8) << std::setfill('0') << (hash & 0xffffffff) << std::dec << std::setw(0);
}
/**
* Format the error description with the input data.
* @param filename the name of the file.
* @param lineNo the line number in the file.
* @param row the definition row.
* @param result the result code.
* @param error the error message.
* @param errorDescription a string in which to store the error description.
* @return the result code.
*/
static result_t formatError(const string& filename, unsigned int lineNo, result_t result,
const string& error, string* errorDescription);
};
@@ -163,8 +175,8 @@ class MappedFileReader : public FileReader {
* @param supportsDefaults whether this instance supports rows with defaults (starting with a star).
* @param preferLanguage the preferred language code, or empty.
*/
explicit MappedFileReader(bool supportsDefaults, const string preferLanguage = "")
: FileReader(), m_supportsDefaults(supportsDefaults), m_preferLanguage(normalizeLanguage(preferLanguage)) {
explicit MappedFileReader(bool supportsDefaults, const string& preferLanguage = "")
: FileReader(), m_supportsDefaults(supportsDefaults), m_preferLanguage(normalizeLanguage(preferLanguage)) {
}
/**
@@ -181,11 +193,11 @@ class MappedFileReader : public FileReader {
* @param lang the language string to normalize.
* @return the normalized language code.
*/
static string normalizeLanguage(string lang);
static const string normalizeLanguage(const string& lang);
// @copydoc
result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL) override;
result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
string* errorDescription, size_t* hash, size_t* size, time_t* time) override;
/**
* Extract default values from the file name.
@@ -196,14 +208,14 @@ class MappedFileReader : public FileReader {
* @param hardware a pointer to a in which to store the numeric hardware version, or NULL.
* @return true if the minimum parts were extracted, false otherwise.
*/
virtual bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const {
virtual bool extractDefaultsFromFilename(const string& filename, map<string, string>* defaults,
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const {
return false;
}
// @copydoc
result_t addFromFile(vector<string>& row, string& errorDescription,
const string filename, unsigned int lineNo) override;
result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
string* errorDescription) override;
/**
* Get the field mapping from the given first line.
@@ -214,7 +226,7 @@ class MappedFileReader : public FileReader {
* @param preferLanguage the preferred language code (up to 2 characters), or empty.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const = 0;
virtual result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const = 0;
/**
* Add a default row that was read from a file.
@@ -225,23 +237,23 @@ class MappedFileReader : public FileReader {
* @param lineNo the current line number in the file being read.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) {
errorDescription = "defaults not supported";
virtual result_t addDefaultFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) {
*errorDescription = "defaults not supported";
return RESULT_ERR_INVALID_ARG;
}
/**
* Add a definition that was read from a file.
* @param row the main definition row by field name.
* @param subRows the sub definition rows, each by field name.
* @param errorDescription a string in which to store the error description in case of error.
* @param filename the name of the file being read.
* @param lineNo the current line number in the file being read.
* @param row the main definition row by field name (may be modified).
* @param subRows the sub definition rows, each by field name (may be modified).
* @param errorDescription a string in which to store the error description in case of error.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) = 0;
virtual result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) = 0;
/**
* @return a reference to all previously extracted default values by type and field name.
@@ -262,7 +274,7 @@ class MappedFileReader : public FileReader {
* @param row the mapped row.
* @return the combined string.
*/
static string combineRow(const map<string, string>& row);
static const string combineRow(const map<string, string>& row);
private:
/** whether this instance supports rows with defaults (starting with a star). */
+439 -434
View File
File diff suppressed because it is too large Load Diff
+165 -180
View File
@@ -92,12 +92,12 @@ class Message : public AttributedItem {
* @param pollPriority the priority for polling, or 0 for no polling at all.
* @param condition the @a Condition for this message, or NULL.
*/
Message(const string circuit, const string level, const string name,
const bool isWrite, const bool isPassive, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id,
const DataField* data, const bool deleteData,
const size_t pollPriority = 0,
Message(const string& circuit, const string& level, const string& name,
bool isWrite, bool isPassive, const map<string, string>& attributes,
symbol_t srcAddress, symbol_t dstAddress,
const vector<symbol_t>& id,
const DataField* data, bool deleteData,
size_t pollPriority = 0,
Condition* condition = NULL);
@@ -113,9 +113,9 @@ class Message : public AttributedItem {
* @param data the @a DataField for encoding/decoding the message.
* @param deleteData whether to delete the @a DataField during destruction.
*/
Message(const string circuit, const string level, const string name,
const symbol_t pb, const symbol_t sb,
const bool broadcast, const DataField* data, const bool deleteData);
Message(const string& circuit, const string& level, const string& name,
symbol_t pb, symbol_t sb,
bool broadcast, const DataField* data, bool deleteData);
public:
@@ -134,9 +134,8 @@ class Message : public AttributedItem {
* @param dstAddress the destination address, or @a SYN for any (set later).
* @return the key for the ID.
*/
static uint64_t createKey(const vector<symbol_t> id,
const bool isWrite, const bool isPassive,
const symbol_t srcAddress, const symbol_t dstAddress);
static uint64_t createKey(const vector<symbol_t>& id, bool isWrite, bool isPassive, symbol_t srcAddress,
symbol_t dstAddress);
/**
* Calculate the key for the @a MasterSymbolString.
@@ -154,7 +153,7 @@ class Message : public AttributedItem {
* @param broadcast true for broadcast scan message, false for scan message to be sent to a slave address.
* @return the key for the scan message.
*/
static uint64_t createKey(const symbol_t pb, const symbol_t sb, const bool broadcast);
static uint64_t createKey(symbol_t pb, symbol_t sb, bool broadcast);
/**
* Get the length field from the key.
@@ -169,26 +168,29 @@ class Message : public AttributedItem {
* @param id the vector to which to add the parsed values.
* @return @a RESULT_OK on success, or an error code.
*/
static result_t parseId(string input, vector<symbol_t>& id);
static result_t parseId(const string& input, vector<symbol_t>* id);
/**
* Factory method for creating new instances.
* @param row the mapped message definition row.
* @param subRows the mapped field definition rows.
* @param rowDefaults the mapped message definition defaults.
* @param subRowDefaults the mapped field definition defaults.
* @param errorDescription a string in which to store the error description in case of error.
* @param condition the @a Condition instance for the message, or NULL.
* @param filename the name of the file being read.
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
* @param rowDefaults the mapped message definition defaults.
* @param subRowDefaults the mapped field definition defaults.
* @param typeStr the single type of message to create.
* @param condition the @a Condition instance for the message, or NULL.
* @param row the mapped message definition row (may be modified).
* @param subRows the mapped field definition rows (may be modified).
* @param errorDescription a string in which to store the error description in case of error.
* @param messages the @a vector to which to add created instances.
* @return @a RESULT_OK on success, or an error code.
* Note: the caller needs to free the created instances.
*/
static result_t create(map<string, string> row, vector< map<string, string> > subRows,
map<string, map<string, string> >& rowDefaults, map<string, vector< map<string, string> > >& subRowDefaults,
string& errorDescription, Condition* condition, const string filename, DataFieldTemplates* templates,
vector<Message*>& messages);
static result_t create(const string& filename, const DataFieldTemplates* templates,
const map<string, map<string, string> >& rowDefaults,
const map<string, vector< map<string, string> > >& subRowDefaults,
const string& typeStr, Condition* condition,
map<string, string>* row, vector< map<string, string> >* subRows,
string* errorDescription, vector<Message*>* messages);
/**
* Create a new scan @a Message instance.
@@ -200,11 +202,11 @@ class Message : public AttributedItem {
/**
* Extract the known field names from the input string.
* @param str the input string with the field names separated by @a FIELD_SEPARATOR.
* @param fields the vector to update with the extracted normalized field names with.
* @param checkAbbreviated true to also check for abbreviated field names.
* @param fields the vector to update with the extracted normalized field names with.
* @return true when all fields are valid.
*/
static bool extractFieldNames(string str, vector<string>& fields, bool checkAbbreviated = true);
static bool extractFieldNames(const string& str, bool checkAbbreviated, vector<string>* fields);
/**
* Set that this is a special scanning @a Message instance.
@@ -224,8 +226,7 @@ class Message : public AttributedItem {
* @param circuit the new circuit name, or empty to use the current circuit name.
* @return the derived @a Message instance.
*/
virtual Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
const string circuit = "") const;
virtual Message* derive(symbol_t dstAddress, symbol_t srcAddress, const string& circuit) const;
/**
* Derive a new @a Message from this message.
@@ -233,7 +234,7 @@ class Message : public AttributedItem {
* @param extendCircuit whether to extend the current circuit name with a dot and the new destination address in hex.
* @return the derived @a ScanMessage instance.
*/
Message* derive(const symbol_t dstAddress, const bool extendCircuit) const;
Message* derive(symbol_t dstAddress, bool extendCircuit) const;
/**
* Get the optional circuit name.
@@ -254,7 +255,7 @@ class Message : public AttributedItem {
* level to check.
* @return true when access is granted.
*/
bool hasLevel(const string levels, bool includeEmpty = true) const {
bool hasLevel(const string& levels, bool includeEmpty = true) const {
return m_level.empty() ? (includeEmpty || levels.empty()) : checkLevel(m_level, levels);
}
@@ -264,14 +265,14 @@ class Message : public AttributedItem {
* @param checkLevels the access levels to check against, separated by semicolon.
* @return whether the access level matches.
*/
static bool checkLevel(const string level, const string checkLevels);
static bool checkLevel(const string& level, const string& checkLevels);
/**
* Get the specified field name.
* @param fieldIndex the index of the field.
* @return the field name, or the index as string if not unique or not available.
*/
virtual string getFieldName(const ssize_t fieldIndex) const { return m_data->getName(fieldIndex); }
virtual string getFieldName(ssize_t fieldIndex) const { return m_data->getName(fieldIndex); }
/**
* Get whether this is a write message.
@@ -329,14 +330,14 @@ class Message : public AttributedItem {
* @param index the variable in which to store the message part index, or NULL to ignore.
* @return true if the ID matches, false otherwise.
*/
virtual bool checkId(const MasterSymbolString& master, size_t* index = NULL) const;
virtual bool checkId(const MasterSymbolString& master, size_t* index) const;
/**
* Check the ID against the other @a Message.
* @param other the other @a Message to check against.
* @return true if the ID matches, false otherwise.
*/
virtual bool checkId(Message& other) const;
virtual bool checkId(const Message& other) const;
/**
* Return the key for storing in @a MessageMap.
@@ -349,7 +350,7 @@ class Message : public AttributedItem {
* @param dstAddress the destination address for the derivation.
* @return the derived key for storing in @a MessageMap.
*/
uint64_t getDerivedKey(const symbol_t dstAddress) const;
uint64_t getDerivedKey(symbol_t dstAddress) const;
/**
* Get the polling priority, or 0 for no polling at all.
@@ -362,7 +363,7 @@ class Message : public AttributedItem {
* @param priority the polling priority, or 0 for no polling at all.
* @return true when the priority was changed and polling was not enabled before, false otherwise.
*/
bool setPollPriority(size_t priority);
bool setPollPriority(const size_t priority);
/**
* Set the poll priority suitable for resolving a @a Condition.
@@ -396,30 +397,28 @@ class Message : public AttributedItem {
/**
* Prepare the master @a SymbolString for sending a query or command to the bus.
* @param srcAddress the source address to set.
* @param master the @a MasterSymbolString for writing symbols to.
* @param input the @a istringstream to parse the formatted value(s) from.
* @param separator the separator character between multiple fields.
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
* @param index the index of the part to prepare.
* @param srcAddress the source address to set.
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
* @param separator the separator character between multiple fields (e.g. @a UI_FIELD_SEPARATOR).
* @param input the @a istringstream to parse the formatted value(s) from.
* @param master the @a MasterSymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code.
*/
result_t prepareMaster(const symbol_t srcAddress, MasterSymbolString& master,
istringstream& input, char separator = UI_FIELD_SEPARATOR,
const symbol_t dstAddress = SYN, size_t index = 0);
result_t prepareMaster(size_t index, symbol_t srcAddress, symbol_t dstAddress,
char separator, istringstream* input, MasterSymbolString* master);
protected:
/**
* Prepare a part of the master data @a SymbolString for sending (everything including NN).
* @param master the @a MasterSymbolString for writing symbols to.
* @param input the @a istringstream to parse the formatted value(s) from.
* @param separator the separator character between multiple fields.
* @param index the index of the part to prepare.
* @param separator the separator character between multiple fields.
* @param input the @a istringstream to parse the formatted value(s) from.
* @param master the @a MasterSymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t prepareMasterPart(MasterSymbolString& master, istringstream& input, char separator,
size_t index);
virtual result_t prepareMasterPart(size_t index, char separator, istringstream* input, MasterSymbolString* master);
public:
@@ -429,7 +428,7 @@ class Message : public AttributedItem {
* @param slave the @a SlaveSymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t prepareSlave(istringstream& input, SlaveSymbolString& slave);
virtual result_t prepareSlave(istringstream* input, SlaveSymbolString* slave);
/**
* Store the last seen master and slave data.
@@ -437,68 +436,57 @@ class Message : public AttributedItem {
* @param slave the last seen @a SlaveSymbolString.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t storeLastData(MasterSymbolString& master, SlaveSymbolString& slave);
virtual result_t storeLastData(const MasterSymbolString& master, const SlaveSymbolString& slave);
/**
* Store last seen master data.
* @param data the last @a MasterSymbolString.
* @param index the index of the part to store.
* @param data the last @a MasterSymbolString.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t storeLastData(MasterSymbolString& data, size_t index);
virtual result_t storeLastData(size_t index, const MasterSymbolString& data);
/**
* Store last seen slave data.
* @param data the last seen @a SlaveSymbolString.
* @param index the index of the part to store.
* @param data the last seen @a SlaveSymbolString.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t storeLastData(SlaveSymbolString& data, size_t index);
virtual result_t storeLastData(size_t index, const SlaveSymbolString& data);
/**
* Decode the value from the last stored master data.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* Decode the value from the last stored master or slave data.
* @param master true for deocding the master data, false for slave.
* @param leadingSeparator whether to prepend a separator before the formatted value.
* @param fieldName the optional name of a field to limit the output to.
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostream to append the formatted value to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t decodeLastMasterData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
virtual result_t decodeLastData(bool master, bool leadingSeparator, const char* fieldName,
ssize_t fieldIndex, OutputFormat outputFormat, ostream* output) const;
/**
* Decode the value from the last stored slave data.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* Decode the value from the last stored master and slave data.
* @param leadingSeparator whether to prepend a separator before the formatted value.
* @param fieldName the optional name of a field to limit the output to.
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
/**
* Decode the value from the last stored data.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* @param leadingSeparator whether to prepend a separator before the formatted value.
* @param fieldName the optional name of a field to limit the output to.
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
* @param output the @a ostream to append the formatted value to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
virtual result_t decodeLastData(bool leadingSeparator, const char* fieldName,
ssize_t fieldIndex, OutputFormat outputFormat, ostream* output) const;
/**
* Decode a particular numeric field value from the last stored data.
* @param output the variable in which to store the value.
* @param fieldName the name of the field to decode, or NULL for the first field.
* @param fieldIndex the optional index of the named field, or -1.
* @param output the variable in which to store the value.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex = -1) const;
virtual result_t decodeLastDataNumField(const char* fieldName, ssize_t fieldIndex, unsigned int* output) const;
/**
* Get the last seen master data.
@@ -539,36 +527,36 @@ class Message : public AttributedItem {
/**
* Write the message definition header or parts of it to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldNames the list of field names to write, or NULL for all.
* @param output the @a ostream to append the formatted value to.
*/
static void dumpHeader(ostream& output, vector<string>* fieldNames = NULL);
static void dumpHeader(const vector<string>* fieldNames, ostream* output);
/**
* Write the message definition or parts of it to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldNames the list of field names to write, or NULL for all.
* @param withConditions whether to include the optional conditions prefix.
* @param output the @a ostream to append the formatted value to.
*/
void dump(ostream& output, vector<string>* fieldNames = NULL, bool withConditions = false) const;
void dump(const vector<string>* fieldNames, bool withConditions, ostream* output) const;
/**
* Write the specified field to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldName the field name to write.
* @param withConditions whether to include the optional conditions prefix.
* @param output the @a ostream to append the formatted value to.
*/
virtual void dumpField(ostream& output, string fieldName, bool withConditions = false) const;
virtual void dumpField(const string& fieldName, bool withConditions, ostream* output) const;
/**
* Decode the message from the last stored data.
* @param output the @a ostringstream to append the decoded value(s) to.
* @param outputFormat the @a OutputFormat options to use.
* @param leadingSeparator whether to prepend a separator before the first value.
* @param fields the list of message and/or data field fields to write, or NULL for all.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostringstream to append the decoded value(s) to.
*/
virtual void decode(ostringstream& output, OutputFormat outputFormat = 0, bool leadingSeparator = false,
vector<string>* fields = NULL) const;
virtual void decode(bool leadingSeparator, const vector<string>* fields,
OutputFormat outputFormat, ostringstream* output) const;
protected:
/** the optional circuit name. */
@@ -676,29 +664,28 @@ class ChainedMessage : public Message {
* @param pollPriority the priority for polling, or 0 for no polling at all.
* @param condition the @a Condition for this message, or NULL.
*/
ChainedMessage(const string circuit, const string level, const string name,
const bool isWrite, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id,
vector< vector<symbol_t> > ids, vector<size_t> lengths,
const DataField* data, const bool deleteData,
const size_t pollPriority,
ChainedMessage(const string& circuit, const string& level, const string& name,
bool isWrite, const map<string, string>& attributes,
symbol_t srcAddress, symbol_t dstAddress,
const vector<symbol_t>& id,
const vector< vector<symbol_t> >& ids, const vector<size_t>& lengths,
const DataField* data, bool deleteData,
size_t pollPriority = 0,
Condition* condition = NULL);
virtual ~ChainedMessage();
// @copydoc
Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
const string circuit = "") const override;
Message* derive(symbol_t dstAddress, symbol_t srcAddress, const string& circuit) const override;
// @copydoc
size_t getIdLength() const override { return m_ids[0].size() - 2; }
// @copydoc
bool checkId(const MasterSymbolString& master, size_t* index = NULL) const override;
bool checkId(const MasterSymbolString& master, size_t* index) const override;
// @copydoc
bool checkId(Message& other) const override;
bool checkId(const Message& other) const override;
// @copydoc
size_t getCount() const override { return m_ids.size(); }
@@ -706,19 +693,19 @@ class ChainedMessage : public Message {
protected:
// @copydoc
result_t prepareMasterPart(MasterSymbolString& master, istringstream& input, char separator,
size_t index) override;
result_t prepareMasterPart(size_t index, const char separator, istringstream* input,
MasterSymbolString* master) override;
public:
// @copydoc
result_t storeLastData(MasterSymbolString& master, SlaveSymbolString& slave) override;
result_t storeLastData(const MasterSymbolString& master, const SlaveSymbolString& slave) override;
// @copydoc
result_t storeLastData(MasterSymbolString& data, size_t index) override;
result_t storeLastData(size_t index, const MasterSymbolString& data) override;
// @copydoc
result_t storeLastData(SlaveSymbolString& data, size_t index) override;
result_t storeLastData(size_t index, const SlaveSymbolString& data) override;
/**
* Combine all last stored data.
@@ -728,7 +715,7 @@ class ChainedMessage : public Message {
protected:
// @copydoc
void dumpField(ostream& output, string fieldName, bool withConditions = false) const override;
void dumpField(const string& fieldName, bool withConditions, ostream* output) const override;
private:
@@ -810,27 +797,27 @@ class Condition {
/**
* Factory method for creating a new instance.
* @param condName the name of the condition.
* @param row the mapped definition row.
* @param rowDefaults the mapped definition defaults.
* @param row the mapped definition row.
* @param returnValue the variable in which to store the created instance.
* @return @a RESULT_OK on success, or an error code.
*/
static result_t create(const string condName, map<string, string> row, map<string, string> rowDefaults,
SimpleCondition*& returnValue);
static result_t create(const string& condName, const map<string, string>& rowDefaults,
map<string, string>* row, SimpleCondition** returnValue);
/**
* Derive a new @a SimpleCondition from this condition.
* @param valueList the @a string with the new list of values.
* @return the derived @a SimpleCondition instance, or NULL if the value list is invalid.
*/
virtual SimpleCondition* derive(string valueList) const { return NULL; }
virtual SimpleCondition* derive(const string& valueList) const { return NULL; }
/**
* Write the condition definition or resolved expression to the @a ostream.
* @param output the @a ostream to append to.
* @param matched true for dumping the matched value if the condition is true, false for dumping the definition.
* @param output the @a ostream to append to.
*/
virtual void dump(ostream& output, bool matched = false) const = 0;
virtual void dump(bool matched, ostream* output) const = 0;
/**
* Combine this condition with another instance using a logical and.
@@ -842,12 +829,12 @@ class Condition {
/**
* Resolve the referred @a Message instance(s) and field index(es).
* @param messages the @a MessageMap instance for resolving.
* @param errorMessage a @a ostringstream to which to add optional error messages.
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
* @param errorMessage a @a ostringstream to which to add optional error messages.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
void (*readMessageFunc)(Message* message) = NULL) = 0;
virtual result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
ostringstream* errorMessage) = 0;
/**
* Check and return whether this condition is fulfilled.
@@ -882,8 +869,8 @@ class SimpleCondition : public Condition {
* @param field the field name.
* @param hasValues whether a value has to be checked against.
*/
SimpleCondition(const string condName, const string refName, const string circuit, const string level,
const string name, const symbol_t dstAddress, const string field, const bool hasValues = false)
SimpleCondition(const string& condName, const string& refName, const string& circuit, const string& level,
const string& name, symbol_t dstAddress, const string& field, bool hasValues = false)
: Condition(),
m_condName(condName), m_refName(refName), m_circuit(circuit), m_level(level), m_name(name),
m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
@@ -894,17 +881,17 @@ class SimpleCondition : public Condition {
virtual ~SimpleCondition() {}
// @copydoc
SimpleCondition* derive(string valueList) const override;
SimpleCondition* derive(const string& valueList) const override;
// @copydoc
void dump(ostream& output, bool matched = false) const override;
void dump(bool matched, ostream* output) const override;
// @copydoc
CombinedCondition* combineAnd(Condition* other) override;
// @copydoc
result_t resolve(MessageMap* messages, ostringstream& errorMessage,
void (*readMessageFunc)(Message* message) = NULL) override;
result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
ostringstream* errorMessage) override;
// @copydoc
bool isTrue() override;
@@ -923,7 +910,7 @@ class SimpleCondition : public Condition {
* @param field the field name to check against, or empty for first field.
* @return whether the field matches one of the valid values.
*/
virtual bool checkValue(Message* message, const string field) { return true; }
virtual bool checkValue(const Message* message, const string& field) { return true; }
/** the value that matched in @a checkValue. */
string m_matchedValue;
@@ -976,8 +963,8 @@ class SimpleNumericCondition : public SimpleCondition {
* @param field the field name.
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
*/
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string level,
const string name, const symbol_t dstAddress, const string field, const vector<unsigned int> valueRanges)
SimpleNumericCondition(const string& condName, const string& refName, const string& circuit, const string& level,
const string& name, symbol_t dstAddress, const string& field, const vector<unsigned int>& valueRanges)
: SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
m_valueRanges(valueRanges) { }
@@ -989,7 +976,7 @@ class SimpleNumericCondition : public SimpleCondition {
protected:
// @copydoc
bool checkValue(Message* message, const string field) override;
bool checkValue(const Message* message, const string& field) override;
private:
@@ -1014,8 +1001,8 @@ class SimpleStringCondition : public SimpleCondition {
* @param field the field name.
* @param values the valid values.
*/
SimpleStringCondition(const string condName, const string refName, const string circuit, const string level,
const string name, const symbol_t dstAddress, const string field, const vector<string> values)
SimpleStringCondition(const string& condName, const string& refName, const string& circuit, const string& level,
const string& name, symbol_t dstAddress, const string& field, const vector<string>& values)
: SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
m_values(values) { }
@@ -1030,7 +1017,7 @@ class SimpleStringCondition : public SimpleCondition {
protected:
// @copydoc
bool checkValue(Message* message, const string field) override;
bool checkValue(const Message* message, const string& field) override;
private:
@@ -1056,14 +1043,14 @@ class CombinedCondition : public Condition {
virtual ~CombinedCondition() {}
// @copydoc
void dump(ostream& output, bool matched = false) const override;
void dump(bool matched, ostream* output) const override;
// @copydoc
CombinedCondition* combineAnd(Condition* other) override { m_conditions.push_back(other); return this; }
// @copydoc
result_t resolve(MessageMap* messages, ostringstream& errorMessage,
void (*readMessageFunc)(Message* message) = NULL) override;
result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
ostringstream* errorMessage) override;
// @copydoc
bool isTrue() override;
@@ -1087,7 +1074,7 @@ class Instruction {
* executed for the same source file.
* @param defaults the mapped definition defaults.
*/
Instruction(Condition* condition, const bool singleton, const map<string, string>& defaults)
Instruction(bool singleton, const map<string, string>& defaults, Condition* condition)
: m_condition(condition), m_singleton(singleton), m_defaults(defaults) { }
/**
@@ -1105,9 +1092,9 @@ class Instruction {
* @param returnValue the variable in which to store the created instance.
* @return @a RESULT_OK on success, or an error code.
*/
static result_t create(const string& contextPath, const string type,
Condition* condition, map<string, string>& row, map<string, string>& defaults,
Instruction*& returnValue);
static result_t create(const string& contextPath, const string& type,
Condition* condition, const map<string, string>& row, const map<string, string>& defaults,
Instruction** returnValue);
/**
* Return the @a Condition this instruction requires.
@@ -1133,13 +1120,12 @@ class Instruction {
* Execute the instruction.
* @param messages the @a MessageMap.
* @param log the @a ostringstream to log success messages to (if necessary).
* @param condition the @a Condition that was successfully evaluated for execution, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t execute(MessageMap* messages, ostringstream& log, Condition* condition) = 0;
virtual result_t execute(MessageMap* messages, ostringstream* log) = 0;
private:
protected:
/** the @a Condition this instruction requires, or null. */
Condition* m_condition;
@@ -1147,8 +1133,6 @@ class Instruction {
* same source file. */
const bool m_singleton;
protected:
/** the defaults by field name. */
map<string, string> m_defaults;
};
@@ -1167,8 +1151,9 @@ class LoadInstruction : public Instruction {
* @param defaults the mapped definition defaults.
* @param filename the name of the file to load.
*/
LoadInstruction(Condition* condition, const bool singleton, map<string, string>& defaults, const string filename)
: Instruction(condition, singleton, defaults), m_filename(filename) { }
LoadInstruction(bool singleton, const map<string, string>& defaults, const string& filename,
Condition* condition)
: Instruction(singleton, defaults, condition), m_filename(filename) { }
/**
* Destructor.
@@ -1176,7 +1161,7 @@ class LoadInstruction : public Instruction {
virtual ~LoadInstruction() { }
// @copydoc
result_t execute(MessageMap* messages, ostringstream& log, Condition* condition) override;
result_t execute(MessageMap* messages, ostringstream* log) override;
private:
@@ -1215,7 +1200,7 @@ class MessageMap : public MappedFileReader {
* @param addAll whether to add all messages, even if duplicate.
* @param preferLanguage the preferred language to use, or empty.
*/
explicit MessageMap(const string configPath, const bool addAll = false, const string preferLanguage = "")
explicit MessageMap(const string& configPath, bool addAll = false, const string& preferLanguage = "")
: MappedFileReader::MappedFileReader(true),
m_configPath(configPath),
m_addAll(addAll), m_additionalScanMessages(false), m_maxIdLength(0), m_maxBroadcastIdLength(0),
@@ -1244,7 +1229,7 @@ class MessageMap : public MappedFileReader {
* @param filename the name of the configuration file (including relative path).
* @return the relative file name.
*/
const string getRelativePath(const string filename) const;
const string getRelativePath(const string& filename) const;
/**
* Add a @a Message instance to this set.
@@ -1253,36 +1238,36 @@ class MessageMap : public MappedFileReader {
* @return @a RESULT_OK on success, or an error code.
* Note: the caller may not free the added instance on success.
*/
result_t add(Message* message, bool storeByName = true);
result_t add(bool storeByName, Message* message);
// @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override;
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override;
// @copydoc
result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override;
result_t addDefaultFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override;
/**
* Read the @a Condition instance(s) from the types field.
* @param types the field from which to read the @a Condition instance(s).
* @param filename the name of the file being read.
* @param types the field from which to read the @a Condition instance(s) and remove the definition prefix.
* @param errorDescription a string in which to store the error description in case of error.
* @param condition the variable in which to store the result.
* @return @a RESULT_OK on success, or an error code.
*/
result_t readConditions(string& types, const string filename, string& errorDescription, Condition*& condition);
result_t readConditions(const string& filename, string* types, string* errorDescription, Condition** condition);
// @copydoc
bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const override;
bool extractDefaultsFromFilename(const string& filename, map<string, string>* defaults,
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const override;
// @copydoc
result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL) override;
result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
string* errorDescription, size_t* hash, size_t* size, time_t* time) override;
// @copydoc
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override;
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override;
/**
* Get the scan @a Message instance for the specified address.
@@ -1299,30 +1284,30 @@ class MessageMap : public MappedFileReader {
/**
* Resolve all @a Condition instances.
* @param errorDescription a string in which to store the error description in case of error.
* @param verbose whether to verbosely add all problems to the error message.
* @param errorDescription a string in which to store the error description in case of error.
* @return @a RESULT_OK on success, or an error code.
*/
result_t resolveConditions(string& errorDescription, bool verbose = false);
result_t resolveConditions(bool verbose, string* errorDescription);
/**
* Resolve a @a Condition.
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
* @param condition the @a Condition to resolve.
* @param errorDescription a string in which to store the error description in case of error.
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
* @return @a RESULT_OK on success, or an error code.
*/
result_t resolveCondition(Condition* condition, string& errorDescription,
void (*readMessageFunc)(Message* message) = NULL);
result_t resolveCondition(void (*readMessageFunc)(Message* message), Condition* condition,
string* errorDescription);
/**
* Run all executable @a Instruction instances.
* @param log the @a ostringstream to log success messages to (if necessary).
* @param readMessageFunc the function to call for immediate reading of a
* @a Message values from the bus required for singleton instructions, or NULL.
* @param log the @a ostringstream to log success messages to (if necessary).
* @return @a RESULT_OK on success, or an error code.
*/
result_t executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message) = NULL);
result_t executeInstructions(void (*readMessageFunc)(Message* message), ostringstream* log);
/**
* Add a loaded file to a participant.
@@ -1330,14 +1315,14 @@ class MessageMap : public MappedFileReader {
* @param filename the name of the configuration file (including relative path).
* @param comment an optional comment.
*/
void addLoadedFile(const symbol_t address, const string filename, const string comment = "");
void addLoadedFile(symbol_t address, const string& filename, const string& comment = "");
/**
* Get the loaded files for a participant.
* @param address the slave address.
* @return the loaded configuration files (list of file names with relative path).
*/
const vector<string>& getLoadedFiles(const symbol_t address) const;
const vector<string>& getLoadedFiles(symbol_t address) const;
/**
* Get all loaded files.
@@ -1354,7 +1339,7 @@ class MessageMap : public MappedFileReader {
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
* @return true if the file info was found, false otherwise.
*/
bool getLoadedFileInfo(const string filename, string& comment, size_t* hash = NULL, size_t* size = NULL,
bool getLoadedFileInfo(const string& filename, string* comment, size_t* hash = NULL, size_t* size = NULL,
time_t* time = NULL) const;
/**
@@ -1363,7 +1348,7 @@ class MessageMap : public MappedFileReader {
* @return the found @a Message instances, or NULL.
* Note: the caller may not free the returned instances.
*/
const vector<Message*>* getByKey(const uint64_t key) const;
const vector<Message*>* getByKey(uint64_t key) const;
/**
* Find the @a Message instance for the specified circuit and name.
@@ -1375,8 +1360,8 @@ class MessageMap : public MappedFileReader {
* @return the @a Message instance, or NULL.
* Note: the caller may not free the returned instance.
*/
Message* find(const string& circuit, const string& name, const string& levels, const bool isWrite,
const bool isPassive = false) const;
Message* find(const string& circuit, const string& name, const string& levels, bool isWrite,
bool isPassive = false) const;
/**
* Find all active get @a Message instances for the specified circuit and name.
@@ -1400,9 +1385,9 @@ class MessageMap : public MappedFileReader {
* Note: the caller may not free the returned instances.
*/
deque<Message*> findAll(const string& circuit, const string& name, const string& levels,
const bool completeMatch = true, const bool withRead = true, const bool withWrite = false,
const bool withPassive = false, const bool includeEmptyLevel = true, const bool onlyAvailable = true,
const time_t since = 0, const time_t until = 0) const;
bool completeMatch = true, bool withRead = true, bool withWrite = false,
bool withPassive = false, bool includeEmptyLevel = true, bool onlyAvailable = true,
time_t since = 0, time_t until = 0) const;
/**
* Find the @a Message instance for the specified master data.
@@ -1416,8 +1401,8 @@ class MessageMap : public MappedFileReader {
* @return the @a Message instance, or NULL.
* Note: the caller may not free the returned instance.
*/
Message* find(const MasterSymbolString& master, const bool anyDestination = false, const bool withRead = true,
const bool withWrite = true, const bool withPassive = true, const bool onlyAvailable = true) const;
Message* find(const MasterSymbolString& master, bool anyDestination = false, bool withRead = true,
bool withWrite = true, bool withPassive = true, bool onlyAvailable = true) const;
/**
* Invalidate cached data of the @a Message and all other instances with a matching name key.
@@ -1427,19 +1412,19 @@ class MessageMap : public MappedFileReader {
/**
* Add a @a Message to the list of instances to poll.
* @param message the @a Message to poll.
* @param toFront whether to add the @a Message to the very front of the poll queue.
* @param message the @a Message to poll.
*/
void addPollMessage(Message* message, bool toFront = false);
void addPollMessage(bool toFront, Message* message);
/**
* Decode circuit specific data.
* @param circuit the name of the circuit.
* @param output the @a ostringstream to append the decoded value(s) to.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostringstream to append the decoded value(s) to.
* @return true if data was added, false otherwise.
*/
bool decodeCircuit(const string circuit, ostringstream& output, OutputFormat outputFormat) const;
bool decodeCircuit(const string& circuit, OutputFormat outputFormat, ostringstream* output) const;
/**
* Removes all @a Message instances.
@@ -1491,10 +1476,10 @@ class MessageMap : public MappedFileReader {
/**
* Write the message definitions to the @a ostream.
* @param output the @a ostream to append the formatted messages to.
* @param withConditions whether to include the optional conditions prefix.
* @param output the @a ostream to append the formatted messages to.
*/
void dump(ostream& output, const bool withConditions = false) const;
void dump(bool withConditions, ostream* output) const;
private:
+19 -19
View File
@@ -54,59 +54,59 @@ static const symbol_t CRC_LOOKUP_TABLE[] = {
};
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
result_t& result, size_t* length) {
unsigned int parseInt(const char* str, int base, unsigned int minValue, unsigned int maxValue,
result_t* result, size_t* length) {
char* strEnd = NULL;
unsigned long ret = strtoul(str, &strEnd, base);
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
*result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
*result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
*result = RESULT_OK;
return (unsigned int)ret;
}
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
size_t* length) {
int parseSignedInt(const char* str, int base, int minValue, int maxValue,
result_t* result, size_t* length) {
char* strEnd = NULL;
long ret = strtol(str, &strEnd, base);
if (strEnd == NULL || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
*result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
*result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
*result = RESULT_OK;
return static_cast<int>(ret);
}
void SymbolString::updateCrc(symbol_t& crc, const symbol_t value) {
crc = CRC_LOOKUP_TABLE[crc]^value;
void SymbolString::updateCrc(symbol_t value, symbol_t* crc) {
*crc = CRC_LOOKUP_TABLE[*crc]^value;
}
result_t SymbolString::parseHex(const string& str) {
result_t result;
for (size_t i = 0; i < str.size(); i += 2) {
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, &result);
if (result != RESULT_OK) {
return result;
}
@@ -119,7 +119,7 @@ result_t SymbolString::parseHexEscaped(const string& str) {
result_t result;
bool inEscape = false;
for (size_t i = 0; i < str.size(); i += 2) {
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, &result);
if (result != RESULT_OK) {
return result;
}
@@ -162,13 +162,13 @@ symbol_t SymbolString::calcCrc() const {
for (size_t i = 0; i < m_data.size(); i++) {
symbol_t value = m_data[i];
if (value == ESC) {
updateCrc(crc, ESC);
updateCrc(crc, 0x00);
updateCrc(ESC, &crc);
updateCrc(0x00, &crc);
} else if (value == SYN) {
updateCrc(crc, ESC);
updateCrc(crc, 0x01);
updateCrc(ESC, &crc);
updateCrc(0x01, &crc);
} else {
updateCrc(crc, value);
updateCrc(value, &crc);
}
}
return crc;
+14 -14
View File
@@ -96,8 +96,8 @@ typedef unsigned char symbol_t;
* @param length the optional variable in which to store the number of read characters.
* @return the parsed value.
*/
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
result_t& result, size_t* length = NULL);
unsigned int parseInt(const char* str, int base, unsigned int minValue, unsigned int maxValue,
result_t* result, size_t* length = NULL);
/**
* Parse a signed int value.
@@ -109,8 +109,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
* @param length the optional variable in which to store the number of read characters.
* @return the parsed value.
*/
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
size_t* length = NULL);
int parseSignedInt(const char* str, int base, int minValue, int maxValue,
result_t* result, size_t* length = NULL);
/**
* A string of unescaped bus symbols.
@@ -121,15 +121,15 @@ class SymbolString {
* Creates a new empty instance.
* @param isMaster whether this instance if for the master part.
*/
explicit SymbolString(const bool isMaster = false) { m_isMaster = isMaster; }
explicit SymbolString(bool isMaster = false) { m_isMaster = isMaster; }
public:
/**
* Update the CRC by adding a value.
* @param crc the current CRC to update.
* @param value the escaped value to add to the current CRC.
* @param crc the current CRC to update.
*/
static void updateCrc(symbol_t& crc, const symbol_t value);
static void updateCrc(symbol_t value, symbol_t* crc);
/**
* Return whether this instance if for the master part.
@@ -175,7 +175,7 @@ class SymbolString {
* @param index the index of the symbol to return.
* @return the reference to the symbol at the specified index, or SYN if not available.
*/
symbol_t operator[](const size_t index) const {
symbol_t operator[](size_t index) const {
if (index >= m_data.size()) {
return SYN;
}
@@ -187,7 +187,7 @@ class SymbolString {
* @param other the other instance.
* @return true if this instance is equal to the other instance.
*/
bool operator == (SymbolString& other) {
bool operator == (const SymbolString& other) {
return m_isMaster == other.m_isMaster && m_data == other.m_data;
}
@@ -196,7 +196,7 @@ class SymbolString {
* @param other the other instance.
* @return true if this instance is different from the other instance.
*/
bool operator != (SymbolString& other) {
bool operator != (const SymbolString& other) {
return m_isMaster != other.m_isMaster || m_data != other.m_data;
}
@@ -207,7 +207,7 @@ class SymbolString {
* 1 if the data is completely different,
* 2 if both instances are a master part and the data only differs in the first byte (the master address).
*/
int compareTo(SymbolString& other) {
int compareTo(const SymbolString& other) const {
if (m_data.size() != other.m_data.size() || m_isMaster != other.m_isMaster) {
return 1;
}
@@ -230,7 +230,7 @@ class SymbolString {
* Append a symbol to the end of the symbol string.
* @param value the symbol to append.
*/
void push_back(const symbol_t value) { m_data.push_back(value); }
void push_back(symbol_t value) { m_data.push_back(value); }
/**
* Return the number of symbols in this symbol string.
@@ -277,7 +277,7 @@ class SymbolString {
* @param index the index of the data byte (within DD) to return.
* @return the data byte at the specified index, or 0 if not available.
*/
symbol_t dataAt(const size_t index) const {
symbol_t dataAt(size_t index) const {
size_t offset = (m_isMaster ? 5 : 1) + index;
if (offset < m_data.size()) {
return m_data[offset];
@@ -290,7 +290,7 @@ class SymbolString {
* @param index the index of the data byte (within DD) to return.
* @return the reference to the data byte at the specified index.
*/
symbol_t& dataAt(const size_t index) {
symbol_t& dataAt(size_t index) {
size_t offset = (m_isMaster ? 5 : 1) + index;
if (offset >= m_data.size()) {
m_data.resize(offset+1, 0);
+30 -31
View File
@@ -53,34 +53,34 @@ class TestReader : public MappedFileReader {
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
m_fields(NULL) {}
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
if (row.empty()) {
row.push_back("*name");
row.push_back("part");
row.push_back("type");
row.push_back("divisor/values");
row.push_back("unit");
row.push_back("comment");
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
if (row->empty()) {
row->push_back("*name");
row->push_back("part");
row->push_back("type");
row->push_back("divisor/values");
row->push_back("unit");
row->push_back("comment");
return RESULT_OK;
}
if (row[0][0] != '*') {
if ((*row)[0][0] != '*') {
return RESULT_ERR_INVALID_ARG;
}
return RESULT_OK; // leave it to DataField::create
}
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override {
if (!row.empty() || subRows.empty()) {
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override {
if (!row->empty() || subRows->empty()) {
cout << "read line " << static_cast<unsigned>(lineNo) << ": read error: got "
<< static_cast<unsigned>(row.size()) << "/0 main, " << static_cast<unsigned>(subRows.size())
<< static_cast<unsigned>(row->size()) << "/0 main, " << static_cast<unsigned>(subRows->size())
<< "/>=3 sub" << endl;
return RESULT_ERR_EOF;
}
cout << "read line " << static_cast<unsigned>(lineNo) << ": read OK" << endl;
return DataField::create(subRows, errorDescription, m_templates, m_fields, m_isSet, false, m_isMasterDest);
return DataField::create(m_isSet, false, m_isMasterDest, MAX_POS, m_templates, subRows, errorDescription, &m_fields);
}
private:
DataFieldTemplates* m_templates;
const DataFieldTemplates* m_templates;
const bool m_isSet;
const bool m_isMasterDest;
public:
@@ -508,7 +508,7 @@ int main() {
istringstream dummystr("#");
string errorDescription;
vector<string> row;
templates->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row);
templates->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
const DataField* fields = NULL;
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i];
@@ -558,7 +558,7 @@ int main() {
}
if (isTemplate) {
lineNo = baseLine + i;
result = templates->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row, false);
result = templates->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": template read error: " << getResultCode(result) << ", "
<< errorDescription << endl;
@@ -570,7 +570,7 @@ int main() {
lineNo = 0;
dummystr.clear();
dummystr.str("#");
result = reader.readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row);
result = reader.readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": reader header error: " << getResultCode(result) << ", " << errorDescription
<< endl;
@@ -578,7 +578,7 @@ int main() {
continue;
}
lineNo = baseLine + i;
result = reader.readLineFromStream(isstr, errorDescription, "", lineNo, row);
result = reader.readLineFromStream("", false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
fields = reader.m_fields;
if (failedCreate) {
if (result == RESULT_OK) {
@@ -600,7 +600,7 @@ int main() {
continue;
}
cout << "\"" << check[0] << "\"=\"";
fields->dump(cout);
fields->dump(&cout);
cout << "\": create OK" << endl;
ostringstream output;
@@ -616,22 +616,21 @@ int main() {
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
error = true;
}
result = fields->read(mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false);
result = fields->read(mstr, 0, false, NULL, -1, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
if (result >= RESULT_OK) {
result = fields->read(sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1,
!output.str().empty());
result = fields->read(sstr, 0, !output.str().empty(), NULL, -1, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
}
if (failedRead) {
if (result >= RESULT_OK) {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< error: unexpectedly succeeded" << endl;
error = true;
} else {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< OK" << endl;
}
} else if (result < RESULT_OK) {
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
cout << " read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
<< "< error: " << getResultCode(result) << endl;
error = true;
} else {
@@ -641,21 +640,21 @@ int main() {
if (verbosity == 0) {
istringstream input(expectStr);
result = fields->write(input, writeMstr, 0);
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeMstr, NULL);
if (result >= RESULT_OK) {
result = fields->write(input, writeSstr, 0);
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeSstr, NULL);
}
if (failedWrite) {
if (result >= RESULT_OK) {
cout << " failed write " << fields->getName() << " >"
cout << " failed write " << fields->getName(-1) << " >"
<< expectStr << "< error: unexpectedly succeeded" << endl;
error = true;
} else {
cout << " failed write " << fields->getName() << " >"
cout << " failed write " << fields->getName(-1) << " >"
<< expectStr << "< OK" << endl;
}
} else if (result < RESULT_OK) {
cout << " write " << fields->getName() << " >" << expectStr
cout << " write " << fields->getName(-1) << " >" << expectStr
<< "< error: " << getResultCode(result) << endl;
error = true;
} else {
+1 -1
View File
@@ -40,7 +40,7 @@ int main() {
while (1) {
symbol_t byte = 0;
result = device->recv(0, byte);
result = device->recv(0, &byte);
if (result == RESULT_OK) {
cout << hex << setw(2) << setfill('0')
+24 -24
View File
@@ -73,8 +73,8 @@ static unsigned int baseLine = 0;
class NoopReader : public FileReader {
public:
result_t addFromFile(vector<string>& row, string& errorDescription,
const string filename, unsigned int lineNo) override {
result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
string* errorDescription) override {
return RESULT_OK;
}
};
@@ -83,25 +83,25 @@ class TestReader : public MappedFileReader {
public:
TestReader(size_t expectedCols, size_t langCols)
: MappedFileReader::MappedFileReader(false, ""), m_expectedCols(expectedCols), m_langCols(langCols) {}
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
if (row.size() == m_expectedCols+m_langCols) {
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
if (row->size() == m_expectedCols+m_langCols) {
cout << "get field map: split OK" << endl;
if (m_langCols == 1) {
row[0] = SKIP_COLUMN;
size_t pos = row[1].find_last_of('.');
row[1] = row[1].substr(0, pos);
(*row)[0] = SKIP_COLUMN;
size_t pos = (*row)[1].find_last_of('.');
(*row)[1] = (*row)[1].substr(0, pos);
}
return RESULT_OK;
}
cout << "get field map: error got " << static_cast<unsigned>(row.size()) << " columns, expected " <<
cout << "get field map: error got " << static_cast<unsigned>(row->size()) << " columns, expected " <<
static_cast<unsigned>(m_expectedCols+m_langCols) << endl;
return RESULT_ERR_EOF;
}
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override {
if (row.empty() || (m_expectedCols == 3) != subRows.empty()) {
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
vector< map<string, string> >* subRows, string* errorDescription) override {
if (row->empty() || (m_expectedCols == 3) != subRows->empty()) {
cout << "read line " << static_cast<unsigned>(baseLine + lineNo) << ": read error: got "
<< static_cast<unsigned>(row.size()) << "/3 main, " << static_cast<unsigned>(subRows.size())
<< static_cast<unsigned>(row->size()) << "/3 main, " << static_cast<unsigned>(subRows->size())
<< (m_expectedCols == 3 ? "/0 sub" : "/>0 sub") << endl;
return RESULT_ERR_EOF;
}
@@ -111,7 +111,7 @@ class TestReader : public MappedFileReader {
}
cout << "read line " << static_cast<unsigned>(baseLine + lineNo) << ": split OK" << endl;
string resultline[3] = resultlines[lineNo - 1];
if (row.empty()) {
if (row->empty()) {
cout << " result empty";
if (resultline[0] == "") {
cout << ": OK" << endl;
@@ -127,7 +127,7 @@ class TestReader : public MappedFileReader {
map<string, string>& defaults = getDefaults()[""];
for (size_t colIdx = 0; colIdx < 3; colIdx++) {
string col = colnames[colIdx];
string got = row[col] + defaults[col];
string got = (*row)[col] + defaults[col];
string expect = resultline[colIdx];
ostringstream type;
type << "line " << static_cast<unsigned>(baseLine + lineNo) << " column \"" << col << "\"";
@@ -137,17 +137,17 @@ class TestReader : public MappedFileReader {
error = true;
}
}
if (row.size() > 3) {
if (row->size() > 3) {
ostringstream type;
type << "line " << static_cast<unsigned>(baseLine + lineNo);
verify(false, type.str(), "", false, "", "extra column");
error = true;
}
for (size_t subIdx = 0; subIdx < subRows.size(); subIdx++) {
for (size_t subIdx = 0; subIdx < subRows->size(); subIdx++) {
string resultsubline[4] = resultsublines[lineNo - 1][subIdx];
row = subRows[subIdx];
if (row.empty()) {
*row = (*subRows)[subIdx];
if (row->empty()) {
cout << " sub " << subIdx << " result empty";
if (resultline[0] == "") {
cout << ": OK" << endl;
@@ -161,7 +161,7 @@ class TestReader : public MappedFileReader {
vector< map<string, string> >& subDefaults = getSubDefaults()[""];
for (size_t colIdx = 0; colIdx < 2; colIdx++) {
string col = resultsubline[colIdx*2];
string got = row[col];
string got = (*row)[col];
if (subIdx < subDefaults.size()) {
got += subDefaults[subIdx][col];
}
@@ -174,7 +174,7 @@ class TestReader : public MappedFileReader {
error = true;
}
}
if (row.size() > 2) {
if (row->size() > 2) {
ostringstream type;
type << "line " << static_cast<unsigned>(baseLine + lineNo) << " sub " << subIdx;
verify(false, type.str(), "", false, "", "extra sub column");
@@ -196,14 +196,14 @@ int main(int argc, char** argv) {
size_t hash = 0, size = 0;
time_t time = 0;
string errorDescription;
result_t result = reader.readFromFile(argv[argpos], errorDescription, false, NULL, &hash, &size, &time);
result_t result = reader.readFromFile(argv[argpos], false, NULL, &errorDescription, &hash, &size, &time);
cout << argv[argpos] << " ";
if (result != RESULT_OK) {
cout << getResultCode(result) << ", " << errorDescription << endl;
error = true;
continue;
}
FileReader::formatHash(hash, cout);
FileReader::formatHash(hash, &cout);
cout << " " << size << " " << time << endl;
}
return error ? 1 : 0;
@@ -226,7 +226,7 @@ int main(int argc, char** argv) {
string errorDescription;
while (ifs.peek() != EOF) {
istringstream str;
result_t result = reader.readLineFromStream(ifs, errorDescription, "", lineNo, row, true, &hash, &size);
result_t result = reader.readLineFromStream("", true, &ifs, &lineNo, &row, &errorDescription, &hash, &size);
if (result != RESULT_OK) {
cout << " error " << getResultCode(result) << endl;
error = true;
@@ -267,7 +267,7 @@ int main(int argc, char** argv) {
subDefaults[0]["subcol 2"] = ";default of sub 0 subcol 2";
while (ifs.peek() != EOF) {
istringstream str;
result_t result = reader2.readLineFromStream(ifs, errorDescription, "", lineNo, row, true, &hash, &size);
result_t result = reader2.readLineFromStream("", true, &ifs, &lineNo, &row, &errorDescription, &hash, &size);
if (result != RESULT_OK) {
cout << " error " << getResultCode(result) << endl;
error = true;
+14 -10
View File
@@ -54,7 +54,7 @@ DataFieldTemplates* templates = NULL;
namespace ebusd {
DataFieldTemplates* getTemplates(const string filename) {
DataFieldTemplates* getTemplates(const string& filename) {
if (filename == "") { // avoid compiler warning
return templates;
}
@@ -71,7 +71,9 @@ int main() {
unsigned int baseLine = __LINE__+1;
string checks[][5] = {
{"date,HDA:3,,,Datum", "", "", "", "template"},
{"bdate:date,BDA,,,Datum", "", "", "", "template"},
{"time,VTI,,,", "", "", "", "template"},
{"btime:time,BTI,,,Uhrzeit", "", "", "", "template"},
{"dcfstate,UCH,0=nosignal;1=ok;2=sync;3=valid,,", "", "", "", "template"},
{"temp,D2C,,°C,Temperatur", "", "", "", "template"},
{"temp1,D1C,,°C,Temperatur", "", "", "", "template"},
@@ -93,6 +95,8 @@ int main() {
{"r,cir,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", ""},
{"u,cir,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
{"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""},
{"u,broadcast,datetime,Datum/Uhrzeit,,fe,0700,,outsidetemp,,temp2,,°C,Aussentemperatur,time,,btime,,,,date,,BDA,,,Datum", "outsidetemp=14.500 °C [Aussentemperatur];time=12:25:01 [Uhrzeit];date=01.05.2017 [Datum]", "10fe070009800e01251201050017", "", "D"},
{"u,broadcast,datetime,Datum Uhrzeit,,fe,0700,,,,temp2;btime;bdate", "temp2=14.500 °C [Temperatur];time=12:25:01 [Uhrzeit];date=01.05.2017 [Datum]", "10fe070009800e01251201050017", "", "D"},
{"w,cir,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", ""},
{"w,cir,first,,,15,b509", "", "ff15b50900", "00", ""},
{"*w,,,,,,b505,2d", "", "", "", ""},
@@ -147,12 +151,12 @@ int main() {
istringstream dummystr("#");
string errorDescription;
vector<string> row;
templates->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row, false);
templates->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
lineNo = 0;
MessageMap* messages = new MessageMap("");
dummystr.clear();
dummystr.str("#");
messages->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row, false);
messages->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
vector< vector<string> > defaultsRows;
Message* message = NULL;
vector<MasterSymbolString*> mstrs;
@@ -183,7 +187,7 @@ int main() {
lineNo = baseLine + i;
cout << "line " << (lineNo+1) << " ";
if (isTemplate) {
result = templates->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
result = templates->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": template read error: " << getResultCode(result) << ", " << errorDescription
<< endl;
@@ -197,7 +201,7 @@ int main() {
}
if (isstr.peek() == '*') {
// store defaults or condition
result = messages->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
result = messages->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": default read error: " << getResultCode(result) << ", " << errorDescription << endl;
error = true;
@@ -279,7 +283,7 @@ int main() {
}
cout << "\"" << check[2] << "\": find OK" << endl;
} else {
result = messages->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
result = messages->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
if (failedCreate) {
if (result == RESULT_OK) {
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
@@ -345,11 +349,11 @@ int main() {
}
ostringstream output;
if (withMessageDump && !decodeJson) {
message->dump(output, NULL, true);
message->dump(NULL, true, &output);
output << ": ";
}
result = message->decodeLastData(output,
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
result = message->decodeLastData(false, NULL, -1,
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), &output);
if (result != RESULT_OK) {
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
<< getResultCode(result) << endl;
@@ -385,7 +389,7 @@ int main() {
if (!message->isPassive() && (withInput || !decode)) {
istringstream input(inputStr);
MasterSymbolString writeMstr;
result = message->prepareMaster(0xff, writeMstr, input);
result = message->prepareMaster(0, 0xff, SYN, UI_FIELD_SEPARATOR, &input, &writeMstr);
if (failedPrepare) {
if (result == RESULT_OK) {
cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl;