diff --git a/src/StreamCore.cc b/src/StreamCore.cc index d598a2e..21ca523 100644 --- a/src/StreamCore.cc +++ b/src/StreamCore.cc @@ -1166,14 +1166,21 @@ matchInput() } if (consumed < 0) { - if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + if (fmt.flags & default_flag) { - error("%s: Input \"%s%s\" does not match format %%%s\n", - name(), inputLine.expand(consumedInput, 20)(), - inputLine.length()-consumedInput > 20 ? "..." : "", - formatstring); + consumed = 0; + } + else + { + if (!(flags & AsyncMode) && onMismatch[0] != in_cmd) + { + error("%s: Input \"%s%s\" does not match format %%%s\n", + name(), inputLine.expand(consumedInput, 20)(), + inputLine.length()-consumedInput > 20 ? "..." : "", + formatstring); + } + return false; } - return false; } consumedInput += consumed; break; @@ -1323,8 +1330,16 @@ scanValue(const StreamFormat& fmt, long& value) scanLong(fmt, inputLine(consumedInput), value); debug("StreamCore::scanValue(%s, format=%%%c, long) input=\"%s\"\n", name(), fmt.conv, inputLine.expand(consumedInput)()); - if (consumed < 0 || - consumed > inputLine.length()-consumedInput) return -1; + if (consumed < 0) + { + if (fmt.flags & default_flag) + { + value = 0; + consumed = 0; + } + else return -1; + } + if (consumed > inputLine.length()-consumedInput) return -1; debug("StreamCore::scanValue(%s) scanned %li\n", name(), value); flags |= GotValue; @@ -1346,8 +1361,16 @@ scanValue(const StreamFormat& fmt, double& value) scanDouble(fmt, inputLine(consumedInput), value); debug("StreamCore::scanValue(%s, format=%%%c, double) input=\"%s\"\n", name(), fmt.conv, inputLine.expand(consumedInput)()); - if (consumed < 0 || - consumed > inputLine.length()-consumedInput) return -1; + if (consumed < 0) + { + if (fmt.flags & default_flag) + { + value = 0.0; + consumed = 0; + } + else return -1; + } + if (consumed > inputLine.length()-consumedInput) return -1; debug("StreamCore::scanValue(%s) scanned %#g\n", name(), value); flags |= GotValue; @@ -1370,8 +1393,16 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen) scanString(fmt, inputLine(consumedInput), value, maxlen); debug("StreamCore::scanValue(%s, format=%%%c, char*, maxlen=%ld) input=\"%s\"\n", name(), fmt.conv, maxlen, inputLine.expand(consumedInput)()); - if (consumed < 0 || - consumed > inputLine.length()-consumedInput) return -1; + if (consumed < 0) + { + if (fmt.flags & default_flag) + { + value[0] = 0; + consumed = 0; + } + else return -1; + } + if (consumed > inputLine.length()-consumedInput) return -1; #ifndef NO_TEMPORARY debug("StreamCore::scanValue(%s) scanned \"%s\"\n", name(), StreamBuffer(value, maxlen).expand()()); diff --git a/src/StreamFormat.h b/src/StreamFormat.h index 7e049e8..cac9ff1 100644 --- a/src/StreamFormat.h +++ b/src/StreamFormat.h @@ -23,12 +23,13 @@ #define StreamFormat_h typedef enum { - left_flag = 0x01, - sign_flag = 0x02, - space_flag = 0x04, - alt_flag = 0x08, - zero_flag = 0x10, - skip_flag = 0x20 + left_flag = 0x01, + sign_flag = 0x02, + space_flag = 0x04, + alt_flag = 0x08, + zero_flag = 0x10, + skip_flag = 0x20, + default_flag = 0x40 } StreamFormatFlag; typedef enum { diff --git a/src/StreamFormatConverter.cc b/src/StreamFormatConverter.cc index 30a8686..d71c7fc 100644 --- a/src/StreamFormatConverter.cc +++ b/src/StreamFormatConverter.cc @@ -112,7 +112,7 @@ static void copyFormatString(StreamBuffer& info, const char* source) const char* p = source - 1; while (*p != '%' && *p != ')') p--; info.append('%'); - while (++p != source-1) info.append(*p); + while (++p != source-1) if (*p != '?') info.append(*p); } // Standard Long Converter for 'diouxX' @@ -278,7 +278,7 @@ scanString(const StreamFormat& fmt, const char* input, if (*input == '\0') { // match empty string - value[0] = '\0'; + if (value) value[0] = '\0'; return 0; } if (fmt.flags & skip_flag) diff --git a/src/StreamProtocol.cc b/src/StreamProtocol.cc index 7f5d2f8..446a51e 100644 --- a/src/StreamProtocol.cc +++ b/src/StreamProtocol.cc @@ -1504,6 +1504,16 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr, } streamFormat.flags |= skip_flag; break; + case '?': + if (formatType != ScanFormat) + { + errorMsg(line, + "Use of default modifier '?' " + "only allowed in input formats\n"); + return false; + } + streamFormat.flags |= default_flag; + break; default: loop = false; }