diff --git a/docs/formats.html b/docs/formats.html index 2bee92d..5479bb5 100644 --- a/docs/formats.html +++ b/docs/formats.html @@ -485,6 +485,12 @@ than 9.
This is not a normal "converter", because no user data is converted. Instead, a checksum is calculated from the input or output. + +Any pre-processing of input, e.g. by the regsub converter +if ignored for the calculation of the checksum. + +
+The width field is the byte number from which to start calculating the checksum. Default is 0, i.e. the first byte of the input or output of the current @@ -711,10 +717,14 @@ However if an empty string is matched, searching advances by 1 character in orde avoid matching the same empty string again.
-In input this converter pre-processes data received from the device before +In input, this converter pre-processes data received from the device before following converters read it. Converters preceding this one will read unmodified input. Thus place this converter before those whose input should be pre-processed. + +However, checksum converters will always use the unmodified +input as sent by the device because the modified input would not match the checksum. +
In output it post-processes data already formatted by preceding converters
diff --git a/src/ChecksumConverter.cc b/src/ChecksumConverter.cc
index 376efb8..dad08bc 100644
--- a/src/ChecksumConverter.cc
+++ b/src/ChecksumConverter.cc
@@ -682,13 +682,13 @@ static uint32_t mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
class ChecksumConverter : public StreamFormatConverter
{
- int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
+ int parse (const StreamFormat&, StreamBuffer&, const char*&, bool scanFormat);
bool printPseudo(const StreamFormat&, StreamBuffer&);
ssize_t scanPseudo(const StreamFormat&, StreamBuffer&, size_t& cursor);
};
int ChecksumConverter::
-parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
+parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool scanFormat)
{
const char* p = strchr(source, '>');
if (!p)
@@ -742,7 +742,7 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
info.append(&xorout, sizeof(xorout));
info.append(fnum);
source = p+1;
- return pseudo_format;
+ return scanFormat ? needs_original_format : pseudo_format;
}
}
@@ -847,7 +847,7 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
else length = 0;
}
- debug("ChecksumConverter %s: input to check: \"%s\n",
+ debug("ChecksumConverter %s: input to check: \"%s\"\n",
checksumMap[fnum].name, input.expand(start,length)());
uint8_t nDigits =
@@ -859,8 +859,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, size_t& cursor)
if ((ssize_t)( input.length() - cursor ) < expectedLength)
{
- debug("ChecksumConverter %s: Input '%s' too short for checksum\n",
- checksumMap[fnum].name, input.expand(cursor)());
+ debug("ChecksumConverter %s: Input '%s' too short (%zu-%zu<%zu) for checksum\n",
+ checksumMap[fnum].name, input.expand(cursor)(), input.length(), cursor, expectedLength);
return -1;
}
diff --git a/src/StreamCore.cc b/src/StreamCore.cc
index 2f3df07..a157c07 100644
--- a/src/StreamCore.cc
+++ b/src/StreamCore.cc
@@ -1184,6 +1184,7 @@ matchInput()
char command;
const char* fieldName = NULL;
StreamBuffer formatstring;
+ ssize_t delta = 0;
consumedInput = 0;
@@ -1218,7 +1219,7 @@ normal_format:
debug("StreamCore::matchInput(%s): format = \"%%%s\"\n",
name(), formatstring());
- if (fmt.flags & skip_flag || fmt.type == pseudo_format)
+ if (fmt.flags & skip_flag || fmt.type == pseudo_format || fmt.type == needs_original_format)
{
long ldummy;
double ddummy;
@@ -1240,9 +1241,20 @@ normal_format:
scanString(fmt, inputLine(consumedInput), NULL, size);
break;
case pseudo_format:
- // pass complete input
+ // pass complete input line for scan and/or re-write
+ size = inputLine.length();
consumed = StreamFormatConverter::find(fmt.conv)->
scanPseudo(fmt, inputLine, consumedInput);
+ delta += inputLine.length() - size; // track length changes
+ debug("after rewrite delta=%zi\n", delta);
+ break;
+ case needs_original_format:
+ // pass original input with adjusted current position
+ debug("before checksum delta=%zi\n", delta);
+ consumedInput -= delta; // correct for length changes
+ consumed = StreamFormatConverter::find(fmt.conv)->
+ scanPseudo(fmt, inputBuffer, consumedInput);
+ consumedInput += delta;
break;
default:
error("INTERNAL ERROR (%s): illegal format.type 0x%02x\n",
diff --git a/src/StreamFormat.h b/src/StreamFormat.h
index 0e0e278..19bb6ae 100644
--- a/src/StreamFormat.h
+++ b/src/StreamFormat.h
@@ -42,7 +42,8 @@ typedef enum {
enum_format,
double_format,
string_format,
- pseudo_format
+ pseudo_format,
+ needs_original_format
} StreamFormatType;
extern const char* StreamFormatTypeStr[];
diff --git a/streamApp/tests/testChecksum b/streamApp/tests/testChecksum
index 797b87d..3e3dae5 100755
--- a/streamApp/tests/testChecksum
+++ b/streamApp/tests/testChecksum
@@ -256,6 +256,9 @@ set protocol {
out "bitsum8 %s %#-9.1