Space handling in separartors and literal input:
Any amount of whitespace matches space character in litrals and if space is first character of a separator.
This commit is contained in:
@ -1299,6 +1299,10 @@ matchInput()
|
|||||||
// ignore next input byte
|
// ignore next input byte
|
||||||
consumedInput++;
|
consumedInput++;
|
||||||
break;
|
break;
|
||||||
|
case ' ':
|
||||||
|
// any number of whitespace (including 0)
|
||||||
|
while (isspace(inputLine[consumedInput])) consumedInput++;
|
||||||
|
break;
|
||||||
case esc:
|
case esc:
|
||||||
// escaped literal byte
|
// escaped literal byte
|
||||||
command = *commandIndex++;
|
command = *commandIndex++;
|
||||||
@ -1374,19 +1378,29 @@ matchSeparator()
|
|||||||
{
|
{
|
||||||
// called before value is read, first value has Separator flag cleared
|
// called before value is read, first value has Separator flag cleared
|
||||||
// for second and next value set Separator flag
|
// for second and next value set Separator flag
|
||||||
// first jump over leading separator (all but first value)
|
// first skip over leading separator (all but first value)
|
||||||
// then find next separator and terminate with null byte to
|
// then find next separator and terminate with null byte to
|
||||||
// help parsing one value (e.g. %s)
|
// help parsing one value (e.g. %s)
|
||||||
|
|
||||||
if (!separator) return true;
|
if (!separator) {
|
||||||
|
separatorStart = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (flags & Separator)
|
if (flags & Separator)
|
||||||
{
|
{
|
||||||
// not first element in array: expect to be at the separator
|
// not first element in array: expect to be at the separator
|
||||||
|
|
||||||
if (separatorStart == -1) return false;
|
if (separatorStart == -1) {
|
||||||
|
return false; // no separator found
|
||||||
// restore deleted char for proper debug and error output
|
}
|
||||||
inputLine[separatorStart] = separatorStore;
|
if (separator[0] == ' ' && separator.length() == 1
|
||||||
|
&& consumedInput != separatorStart)
|
||||||
|
{
|
||||||
|
// space-only separator may have matched zero spaces
|
||||||
|
// last found separator is still ahead
|
||||||
|
inputLine[separatorStart] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (consumedInput != separatorStart)
|
if (consumedInput != separatorStart)
|
||||||
{
|
{
|
||||||
@ -1401,38 +1415,62 @@ matchSeparator()
|
|||||||
}
|
}
|
||||||
consumedInput = separatorEnd;
|
consumedInput = separatorEnd;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
flags |= Separator;
|
flags |= Separator;
|
||||||
|
}
|
||||||
|
|
||||||
// find next Separator and replace first byte with '\0' to help parsing elements
|
// find next Separator and replace first byte with '\0' to help parsing elements
|
||||||
if (separator[0] == ' ' && separator[1] != ' ')
|
// don't worry now if there is none, just set separatorStart = -1
|
||||||
|
if (separator[0] == ' ' && separator.length() == 1)
|
||||||
{
|
{
|
||||||
// skip leading whitespaces
|
// space-only separator: find any whitespace after non-whitespace
|
||||||
separatorStart = inputLine.find(separator(1), separator.length() - 1, consumedInput);
|
long j = consumedInput;
|
||||||
if (separatorStart == -1) return true;
|
while (isspace(inputLine[j])) j++;
|
||||||
separatorEnd = separatorStart + separator.length() - 1;
|
if (!inputLine[j]) {
|
||||||
while (separatorStart > consumedInput && isspace(inputLine[separatorStart - 1])) separatorStart--;
|
separatorStart = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
while (inputLine[j] && !isspace(inputLine[j])) j++;
|
||||||
|
separatorStart = j;
|
||||||
|
while (isspace(inputLine[j])) j++;
|
||||||
|
separatorEnd = j;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
separatorStart = inputLine.find(separator, consumedInput);
|
long i = 0;
|
||||||
|
if (separator[0] == ' ' && separator[1] != ' ')
|
||||||
|
i = 1; // handle leading whitespaces later
|
||||||
|
separatorStart = inputLine.find(separator[i], consumedInput);
|
||||||
if (separatorStart == -1) return true;
|
if (separatorStart == -1) return true;
|
||||||
separatorEnd = separatorStart + separator.length();
|
|
||||||
|
// check rest of separator and handle escapes
|
||||||
|
long j;
|
||||||
|
for (j = separatorStart+1; ++i < separator.length(); j++)
|
||||||
|
{
|
||||||
|
if (separator[i] == StreamProtocolParser::skip) continue; // wildcard
|
||||||
|
// allow format here?
|
||||||
|
if (separator[i] == esc) i++; // escaped literal byte
|
||||||
|
if (separator[i] != inputLine[j])
|
||||||
|
{
|
||||||
|
separatorStart = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
separatorEnd = j;
|
||||||
|
// separator found
|
||||||
|
if (separator[0] == ' ' && separator[1] != ' ')
|
||||||
|
{
|
||||||
|
// now skip leading whitespaces
|
||||||
|
while (separatorStart > consumedInput &&
|
||||||
|
isspace(inputLine[separatorStart - 1])) separatorStart--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
separatorStore = inputLine[separatorStart];
|
separatorStore = inputLine[separatorStart];
|
||||||
inputLine[separatorStart] = '\0';
|
inputLine[separatorStart] = '\0';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamCore::
|
|
||||||
scanSeparator()
|
|
||||||
{
|
|
||||||
// for compatibility only
|
|
||||||
// read and remove separator
|
|
||||||
if (!matchSeparator()) return false;
|
|
||||||
flags &= ~Separator;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
long StreamCore::
|
long StreamCore::
|
||||||
scanValue(const StreamFormat& fmt, long& value)
|
scanValue(const StreamFormat& fmt, long& value)
|
||||||
{
|
{
|
||||||
@ -1446,6 +1484,7 @@ scanValue(const StreamFormat& fmt, long& value)
|
|||||||
if (!matchSeparator()) return -1;
|
if (!matchSeparator()) return -1;
|
||||||
long consumed = StreamFormatConverter::find(fmt.conv)->
|
long consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
scanLong(fmt, inputLine(consumedInput), value);
|
scanLong(fmt, inputLine(consumedInput), value);
|
||||||
|
if (separatorStart >= 0) inputLine[separatorStart] = separatorStore;
|
||||||
debug("StreamCore::scanValue(%s, format=%%%c, long) input=\"%s\"\n",
|
debug("StreamCore::scanValue(%s, format=%%%c, long) input=\"%s\"\n",
|
||||||
name(), fmt.conv, inputLine.expand(consumedInput)());
|
name(), fmt.conv, inputLine.expand(consumedInput)());
|
||||||
if (consumed < 0)
|
if (consumed < 0)
|
||||||
@ -1477,6 +1516,7 @@ scanValue(const StreamFormat& fmt, double& value)
|
|||||||
if (!matchSeparator()) return -1;
|
if (!matchSeparator()) return -1;
|
||||||
long consumed = StreamFormatConverter::find(fmt.conv)->
|
long consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
scanDouble(fmt, inputLine(consumedInput), value);
|
scanDouble(fmt, inputLine(consumedInput), value);
|
||||||
|
if (separatorStart >= 0) inputLine[separatorStart] = separatorStore;
|
||||||
debug("StreamCore::scanValue(%s, format=%%%c, double) input=\"%s\"\n",
|
debug("StreamCore::scanValue(%s, format=%%%c, double) input=\"%s\"\n",
|
||||||
name(), fmt.conv, inputLine.expand(consumedInput, 20)());
|
name(), fmt.conv, inputLine.expand(consumedInput, 20)());
|
||||||
if (consumed < 0)
|
if (consumed < 0)
|
||||||
@ -1509,6 +1549,7 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen)
|
|||||||
if (!matchSeparator()) return -1;
|
if (!matchSeparator()) return -1;
|
||||||
long consumed = StreamFormatConverter::find(fmt.conv)->
|
long consumed = StreamFormatConverter::find(fmt.conv)->
|
||||||
scanString(fmt, inputLine(consumedInput), value, maxlen);
|
scanString(fmt, inputLine(consumedInput), value, maxlen);
|
||||||
|
if (separatorStart >= 0) inputLine[separatorStart] = separatorStore;
|
||||||
debug("StreamCore::scanValue(%s, format=%%%c, char*, maxlen=%ld) input=\"%s\"\n",
|
debug("StreamCore::scanValue(%s, format=%%%c, char*, maxlen=%ld) input=\"%s\"\n",
|
||||||
name(), fmt.conv, maxlen, inputLine.expand(consumedInput)());
|
name(), fmt.conv, maxlen, inputLine.expand(consumedInput)());
|
||||||
if (consumed < 0)
|
if (consumed < 0)
|
||||||
|
Reference in New Issue
Block a user