Skip to content

Commit

Permalink
Merge pull request #91 from mbehr1/ut_meter_file
Browse files Browse the repository at this point in the history
fix and unit tests for MeterFile custom format.
  • Loading branch information
andig committed Jan 3, 2015
2 parents 6d04a3a + 8bd33a9 commit 1d27228
Show file tree
Hide file tree
Showing 4 changed files with 280 additions and 58 deletions.
18 changes: 9 additions & 9 deletions include/Reading.hpp
Expand Up @@ -45,8 +45,8 @@ class ReadingIdentifier {
virtual ~ReadingIdentifier(){};

virtual size_t unparse(char *buffer, size_t n) = 0;
virtual bool operator==( ReadingIdentifier &cmp);
bool compare( ReadingIdentifier *lhs, ReadingIdentifier *rhs);
virtual bool operator==( ReadingIdentifier const &cmp) const;
bool compare( ReadingIdentifier const *lhs, ReadingIdentifier const *rhs) const;

virtual const std::string toString() = 0;

Expand All @@ -68,7 +68,7 @@ class ObisIdentifier : public ReadingIdentifier {
virtual ~ObisIdentifier(){};

size_t unparse(char *buffer, size_t n);
bool operator==(ObisIdentifier &cmp);
bool operator==(ObisIdentifier const &cmp) const;
const std::string toString() {
std::ostringstream oss;
oss << "ObisItentifier:" << _obis.toString();
Expand All @@ -92,7 +92,7 @@ class StringIdentifier : public ReadingIdentifier {

void parse(const char *buffer);
size_t unparse(char *buffer, size_t n);
bool operator==(StringIdentifier &cmp);
bool operator==(StringIdentifier const &cmp) const;
const std::string toString() {
std::ostringstream oss;
oss << "StringItentifier:";
Expand All @@ -111,7 +111,7 @@ class ChannelIdentifier : public ReadingIdentifier {

void parse(const char *string);
size_t unparse(char *buffer, size_t n);
bool operator==(ChannelIdentifier &cmp);
bool operator==(ChannelIdentifier const &cmp) const;
const std::string toString() {
std::ostringstream oss;
oss << "ChannelItentifier:";
Expand All @@ -126,7 +126,7 @@ class NilIdentifier : public ReadingIdentifier {
public:
NilIdentifier() {}
size_t unparse(char *buffer, size_t n);
bool operator==(NilIdentifier &cmp);
bool operator==(NilIdentifier const &cmp) const;
const std::string toString() {
std::ostringstream oss;
oss << "NilIdentifier";
Expand All @@ -152,10 +152,10 @@ class Reading {
double value() const { return _value; }

double tvtod() const;
double tvtod(struct timeval tv) const;
double tvtod(struct timeval const &tv) const;
void time() { gettimeofday(&_time, NULL); }
void time(struct timeval &v) { _time = v; }
struct timeval dtotv(double ts);
void time(struct timeval const &v) { _time = v; }
struct timeval dtotv(double const &ts) const; // doesn't set the time, just returns a timeval!

void identifier(ReadingIdentifier *rid) { _identifier.reset(rid); }
const ReadingIdentifier::Ptr identifier() { return _identifier; }
Expand Down
34 changes: 17 additions & 17 deletions src/Reading.cpp
Expand Up @@ -71,14 +71,14 @@ Reading::Reading(
}

double Reading::tvtod() const {
return _time.tv_sec + _time.tv_usec / 1e6;
return (double)_time.tv_sec + ((double)_time.tv_usec / 1e6);
}

double Reading::tvtod(struct timeval tv) const {
return tv.tv_sec + tv.tv_usec / 1e6;
double Reading::tvtod(struct timeval const &tv) const {
return (double)tv.tv_sec + ((double)tv.tv_usec / 1e6);
}

struct timeval Reading::dtotv(double ts) {
struct timeval Reading::dtotv(double const &ts) const {
double integral;
double fraction = modf(ts, &integral);

Expand Down Expand Up @@ -170,28 +170,28 @@ size_t Reading::unparse(
#endif
}

bool ReadingIdentifier::operator==( ReadingIdentifier &cmp) {
bool ReadingIdentifier::operator==( ReadingIdentifier const &cmp) const {
return this->compare(this, &cmp);
}

bool ReadingIdentifier::compare( ReadingIdentifier *lhs, ReadingIdentifier *rhs) {
if (ObisIdentifier* lhsx = dynamic_cast<ObisIdentifier*>(lhs)) {
if (ObisIdentifier* rhsx = dynamic_cast<ObisIdentifier*>(rhs)) {
bool ReadingIdentifier::compare( ReadingIdentifier const *lhs, ReadingIdentifier const *rhs) const {
if (ObisIdentifier const* lhsx = dynamic_cast<ObisIdentifier const*>(lhs)) {
if (ObisIdentifier const* rhsx = dynamic_cast<ObisIdentifier const*>(rhs)) {
return *lhsx == *rhsx;
} else { return false; }
} else
if (StringIdentifier* lhsx = dynamic_cast<StringIdentifier*>(rhs)) {
if (StringIdentifier* rhsx = dynamic_cast<StringIdentifier*>(lhs)) {
if (StringIdentifier const* lhsx = dynamic_cast<StringIdentifier const*>(lhs)) {
if (StringIdentifier const* rhsx = dynamic_cast<StringIdentifier const*>(rhs)) {
return *lhsx == *rhsx;
} else { return false; }
} else
if (ChannelIdentifier* lhsx = dynamic_cast<ChannelIdentifier*>(lhs)) {
if (ChannelIdentifier* rhsx = dynamic_cast<ChannelIdentifier*>(rhs)) {
if (ChannelIdentifier const* lhsx = dynamic_cast<ChannelIdentifier const*>(lhs)) {
if (ChannelIdentifier const* rhsx = dynamic_cast<ChannelIdentifier const*>(rhs)) {
return *lhsx == *rhsx;
} else { return false; }
} else
if (NilIdentifier* lhsx = dynamic_cast<NilIdentifier*>(lhs)) {
if (NilIdentifier* rhsx = dynamic_cast<NilIdentifier*>(rhs)) {
if (NilIdentifier const* lhsx = dynamic_cast<NilIdentifier const*>(lhs)) {
if (NilIdentifier const* rhsx = dynamic_cast<NilIdentifier const*>(rhs)) {
(void)lhsx; (void) rhsx; // avoid compiler warning about unused vars.
return true;
} else { return false; }
Expand All @@ -203,12 +203,12 @@ bool ReadingIdentifier::compare( ReadingIdentifier *lhs, ReadingIdentifier *rhs
size_t ObisIdentifier::unparse(char *buffer, size_t n) {
return _obis.unparse(buffer, n);
}
bool ObisIdentifier::operator==(ObisIdentifier &cmp) {
bool ObisIdentifier::operator==(ObisIdentifier const &cmp) const {
return (_obis == cmp.obis());
}

/* StringIdentifier */
bool StringIdentifier::operator==(StringIdentifier &cmp) {
bool StringIdentifier::operator==(StringIdentifier const &cmp) const{
return (_string == cmp._string);
}

Expand All @@ -227,7 +227,7 @@ size_t StringIdentifier::unparse(char *buffer, size_t n) {
}

/* ChannelIdentifier */
bool ChannelIdentifier::operator==(ChannelIdentifier &cmp) {
bool ChannelIdentifier::operator==(ChannelIdentifier const &cmp) const {
return (_channel == cmp._channel);
}

Expand Down
71 changes: 39 additions & 32 deletions src/protocols/MeterFile.cpp
Expand Up @@ -44,32 +44,32 @@ MeterFile::MeterFile(std::list<Option> options)
throw;
}

/* a optional format string for scanf() */
// a optional format string for scanf()
try {
const char *config_format = optlist.lookup_string(options, "format");

/**
* Compiling the provided format string in a format string for scanf
* by replacing the following tokens
*
* "$v" => "%1$f" (value)
* "$v" => "%1$lf" (value)
* "$i" => "%2$ms" (identifier) (memory gets allocated by sscanf())
* "$t" => "%3$f" (timestamp)
* "$t" => "%3$lf" (timestamp)
*/

int config_len = strlen(config_format);
int scanf_len = config_len + 8; /* adding extra space for longer conversion specification in scanf_format */
int scanf_len = config_len + 15; // adding extra space for longer conversion specification in scanf_format

char *scanf_format = (char *)malloc(scanf_len); /* the scanf format string */
char *scanf_format = (char *)malloc(scanf_len); // the scanf format string

int i = 0; /* index in config_format string */
int j = 0; /* index in scanf_format string */
int i = 0; // index in config_format string
int j = 0; // index in scanf_format string
while (i <= config_len && j <= scanf_len) {
switch (config_format[i]) {
case '$':
if (i+1 < config_len) { /* introducing a token */
if (i+1 < config_len) { // introducing a token
switch (config_format[i+1]) {
case 'v': j += sprintf(scanf_format+j, "%%1$f"); break;
case 'v': j += sprintf(scanf_format+j, "%%1$lf"); break;
case 'i': j += sprintf(scanf_format+j, "%%2$ms"); break;
case 't': j += sprintf(scanf_format+j, "%%3$lf"); break;
}
Expand All @@ -78,10 +78,10 @@ MeterFile::MeterFile(std::list<Option> options)
break;

case '%':
scanf_format[j++] = '%'; /* add double %% to escape a conversion identifier */

scanf_format[j++] = '%'; // add double %% to escape a conversion identifier
// nobreak;
default:
scanf_format[j++] = config_format[i]; /* just copying */
scanf_format[j++] = config_format[i]; // just copying
}

i++;
Expand All @@ -90,18 +90,18 @@ MeterFile::MeterFile(std::list<Option> options)
print(log_debug, "Parsed format string \"%s\" => \"%s\"", name().c_str(), config_format, scanf_format);
_format = scanf_format;
} catch (vz::OptionNotFoundException &e) {
_format = ""; /* use default format */
_format = ""; // use default format
} catch (vz::VZException &e) {
print(log_error, "Failed to parse format", name().c_str());
throw;
}

/* should we start each time at the beginning of the file? */
/* or do we read from a logfile (append) */
// should we start each time at the beginning of the file?
// or do we read from a logfile (append)
try {
_rewind = optlist.lookup_bool(options, "rewind");
} catch (vz::OptionNotFoundException &e) {
_rewind = FALSE; /* do not rewind file by default */
_rewind = FALSE; // do not rewind file by default
} catch (vz::InvalidTypeException &e) {
print(log_error, "Invalid type for 'rewind'", name().c_str());
throw;
Expand Down Expand Up @@ -133,51 +133,58 @@ int MeterFile::close() {

ssize_t MeterFile::read(std::vector<Reading> &rds, size_t n) {

// TODO use inotify to block eading until file changes
// TODO use inotify to block reading until file changes

char line[256], *endptr;
char string[256];
char *string=0;

/* reset file pointer to beginning of file */
// reset file pointer to beginning of file
if (_rewind) {
rewind(_fd);
}

unsigned int i = 0;
print(log_debug, "MeterFile::read: %d, %d", "", rds.size(), n);

while (fgets(line, 256, _fd) && i < n) {
while (i<n && fgets(line, 256, _fd)) {
char *nl;
if ((nl = strrchr(line, '\n'))) *nl = '\0'; /* remove trailing newline */
if ((nl = strrchr(line, '\n'))) *nl = '\0'; // remove trailing newlines
if ((nl = strrchr(line, '\r'))) *nl = '\0';

if (_format != "") {
double timestamp;
double timestamp=-1.0;

/* at least the value has to been read */
double value;
// at least the value has to been read
double value=0.0;

print(log_debug, "MeterFile::read: '%s'", "", line);
int found = sscanf(line, format(), &value, string, &timestamp);
print(log_debug, "MeterFile::read: %f, %s, %ld", "", value, string, timestamp);
int found = sscanf(line, format(), &value, &string, &timestamp);
print(log_debug, "MeterFile::read: %lf, %s, %lf", "", value, string? string : "<null>", timestamp);


rds[i].value(value);
ReadingIdentifier *rid(new StringIdentifier(string));
ReadingIdentifier *rid(new StringIdentifier(string ? string : "<null>"));
rds[i].identifier(rid);
if (found >= 1) { // TODO free() space allocated for identifier string
rds[i].dtotv(timestamp); /* convert double to timeval */
i++; /* read successfully */
if (found >= 1) {
if (timestamp >=0.0)
rds[i].time(rds[i].dtotv(timestamp)); // convert double to timevals
else
rds[i].time(); // use current timestamp
i++; // read successfully
}
if (string){
free(string);
string = 0;
}
}
else { /* just reading a value per line */
else { // just reading a value per line
rds[i].value(strtod(line, &endptr));
rds[i].time();
ReadingIdentifier* rid(new StringIdentifier(""));
rds[i].identifier(rid);

if (endptr != line) {
i++; /* read successfully */
i++; // read successfully
}
}
}
Expand Down

0 comments on commit 1d27228

Please sign in to comment.