changed streamScanfN to return number of read bytes
This commit is contained in:
@ -27,7 +27,7 @@ class BCDConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
long scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
int BCDConverter::
|
||||
@ -39,64 +39,65 @@ parse(const StreamFormat& fmt, StreamBuffer&, const char*&, bool)
|
||||
bool BCDConverter::
|
||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
{
|
||||
unsigned char bcd[6]={0,0,0,0,0,0}; // sufficient for 2^32
|
||||
int i;
|
||||
int prec = fmt.prec; // number of nibbles
|
||||
if (prec == -1)
|
||||
{
|
||||
prec = 2 * sizeof (value);
|
||||
}
|
||||
int width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2;
|
||||
unsigned char bcd;
|
||||
bool neg = false;
|
||||
long i;
|
||||
unsigned long prec = fmt.prec < 0 ? 2 * sizeof(value) : fmt.prec; // number of nibbles
|
||||
unsigned long width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2;
|
||||
if (fmt.width > width) width = fmt.width;
|
||||
if (fmt.flags & sign_flag && value < 0)
|
||||
if (fmt.flags & sign_flag && value < 0 && prec > 0)
|
||||
{
|
||||
// negative BCD value, I hope "F" as "-" is OK
|
||||
bcd[5] = 0xF0;
|
||||
neg = true;
|
||||
value = -value;
|
||||
}
|
||||
if (prec > 10) prec = 10;
|
||||
for (i = 0; i < prec; i++)
|
||||
{
|
||||
bcd[i/2] |= (value % 10) << (4 * (i & 1));
|
||||
value /= 10;
|
||||
}
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
// least significant byte first (little endian)
|
||||
for (i = 0; i < (prec + 1) / 2; i++)
|
||||
while (width-- && prec)
|
||||
{
|
||||
output.append(bcd[i]);
|
||||
bcd = value%10;
|
||||
if (--prec)
|
||||
{
|
||||
--prec;
|
||||
value /= 10;
|
||||
bcd |= (value%10)<<4;
|
||||
value /= 10;
|
||||
}
|
||||
output.append(bcd);
|
||||
}
|
||||
for (; i < width; i++)
|
||||
{
|
||||
output.append('\0');
|
||||
}
|
||||
output[-1] |= bcd[5];
|
||||
if (width)
|
||||
output.append('\0', width);
|
||||
if (neg) output[-1] |= 0xf0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// most significant byte first (big endian)
|
||||
int firstbyte = output.length();
|
||||
for (i = 0; i < width - (prec + 1) / 2; i++)
|
||||
output.append('\0', width);
|
||||
if (neg) output[-width] |= 0xf0;
|
||||
i = 0;
|
||||
while (width-- && prec)
|
||||
{
|
||||
output.append('\0');
|
||||
bcd = value%10;
|
||||
if (--prec)
|
||||
{
|
||||
--prec;
|
||||
value /= 10;
|
||||
bcd |= (value%10)<<4;
|
||||
value /= 10;
|
||||
}
|
||||
output[--i]=bcd;
|
||||
}
|
||||
for (i = (prec - 1) / 2; i >= 0; i--)
|
||||
{
|
||||
output.append(bcd[i]);
|
||||
}
|
||||
output[firstbyte] |= bcd[5];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int BCDConverter::
|
||||
long BCDConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
int length = 0;
|
||||
int val = 0;
|
||||
long length = 0;
|
||||
long val = 0;
|
||||
unsigned char bcd1, bcd10;
|
||||
int width = fmt.width;
|
||||
long width = fmt.width;
|
||||
if (width == 0) width = 1;
|
||||
if (fmt.flags & alt_flag)
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ class BinaryConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
long scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
int BinaryConverter::
|
||||
@ -77,7 +77,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
if (x <= 0x3FFFFFFF) { prec -= 2; x <<=2; }
|
||||
if (x <= 0x7FFFFFFF) { prec -= 1; }
|
||||
}
|
||||
int width = prec;
|
||||
unsigned long width = prec;
|
||||
if (fmt.width > width) width = fmt.width;
|
||||
char zero = fmt.info[0];
|
||||
char one = fmt.info[1];
|
||||
@ -88,7 +88,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
if (!(fmt.flags & left_flag))
|
||||
{
|
||||
// pad left
|
||||
while (width > prec)
|
||||
while (width > (unsigned int)prec)
|
||||
{
|
||||
output.append(' ');
|
||||
width--;
|
||||
@ -112,7 +112,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
if (!(fmt.flags & left_flag))
|
||||
{
|
||||
// pad left
|
||||
while (width > prec)
|
||||
while (width > (unsigned int)prec)
|
||||
{
|
||||
output.append(fill);
|
||||
width--;
|
||||
@ -132,13 +132,13 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int BinaryConverter::
|
||||
long BinaryConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
long val = 0;
|
||||
int width = fmt.width;
|
||||
long width = fmt.width;
|
||||
if (width == 0) width = -1;
|
||||
int length = 0;
|
||||
long length = 0;
|
||||
char zero = fmt.info[0];
|
||||
char one = fmt.info[1];
|
||||
if (!isspace(zero) && !isspace(one))
|
||||
|
@ -500,7 +500,7 @@ class ChecksumConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse (const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printPseudo(const StreamFormat&, StreamBuffer&);
|
||||
int scanPseudo(const StreamFormat&, StreamBuffer&, long& cursor);
|
||||
long scanPseudo(const StreamFormat&, StreamBuffer&, long& cursor);
|
||||
};
|
||||
|
||||
int ChecksumConverter::
|
||||
@ -535,7 +535,7 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool)
|
||||
source+=3;
|
||||
notflag = true;
|
||||
}
|
||||
unsigned fnum;
|
||||
unsigned char fnum;
|
||||
int len = p-source;
|
||||
unsigned int init, xorout;
|
||||
for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++)
|
||||
@ -573,7 +573,7 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
const char* info = format.info;
|
||||
unsigned int init = extract<unsigned int>(info);
|
||||
unsigned int xorout = extract<unsigned int>(info);
|
||||
int fnum = extract<char>(info);
|
||||
unsigned char fnum = extract<unsigned char>(info);
|
||||
|
||||
int start = format.width;
|
||||
int length = output.length()-format.width;
|
||||
@ -641,7 +641,7 @@ printPseudo(const StreamFormat& format, StreamBuffer& output)
|
||||
return true;
|
||||
}
|
||||
|
||||
int ChecksumConverter::
|
||||
long ChecksumConverter::
|
||||
scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
{
|
||||
unsigned int sum;
|
||||
@ -649,8 +649,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor)
|
||||
unsigned int init = extract<unsigned int>(info);
|
||||
unsigned int xorout = extract<unsigned int>(info);
|
||||
int start = format.width;
|
||||
int fnum = extract<char>(info);
|
||||
int length = cursor-format.width;
|
||||
unsigned char fnum = extract<unsigned char>(info);
|
||||
long length = cursor-format.width;
|
||||
|
||||
if (format.prec > 0) length -= format.prec;
|
||||
|
||||
|
@ -29,7 +29,7 @@ class EnumConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
long scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
// info format: <numEnums><index><string>0<index><string>0...
|
||||
@ -148,7 +148,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int EnumConverter::
|
||||
long EnumConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
debug("EnumConverter::scanLong(%%%c, \"%s\")\n",
|
||||
@ -156,7 +156,7 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
const char* s = fmt.info;
|
||||
long numEnums = extract<long>(s);
|
||||
long index;
|
||||
int length;
|
||||
long length;
|
||||
|
||||
bool match;
|
||||
while (numEnums--)
|
||||
|
@ -39,7 +39,7 @@
|
||||
class MantissaExponentConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual int scanDouble(const StreamFormat&, const char*, double&);
|
||||
virtual long scanDouble(const StreamFormat&, const char*, double&);
|
||||
virtual bool printDouble(const StreamFormat&, StreamBuffer&, double);
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ parse(const StreamFormat&, StreamBuffer&,
|
||||
return double_format;
|
||||
}
|
||||
|
||||
int MantissaExponentConverter::
|
||||
long MantissaExponentConverter::
|
||||
scanDouble(const StreamFormat& fmt, const char* input, double& value)
|
||||
{
|
||||
int mantissa;
|
||||
|
@ -27,7 +27,7 @@ class RawConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
int scanLong(const StreamFormat&, const char*, long&);
|
||||
long scanLong(const StreamFormat&, const char*, long&);
|
||||
};
|
||||
|
||||
int RawConverter::
|
||||
@ -40,10 +40,9 @@ parse(const StreamFormat& fmt, StreamBuffer&,
|
||||
bool RawConverter::
|
||||
printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
{
|
||||
int prec = fmt.prec; // number of bytes from value
|
||||
if (prec == -1) prec = 1; // default: 1 byte
|
||||
int width = prec; // number of bytes in output
|
||||
if (prec > (int)sizeof(long)) prec=sizeof(long);
|
||||
unsigned int prec = fmt.prec < 0 ? 1 : fmt.prec; // number of bytes from value, default 1
|
||||
unsigned long width = prec; // number of bytes in output
|
||||
if (prec > sizeof(long)) prec=sizeof(long);
|
||||
if (fmt.width > width) width = fmt.width;
|
||||
|
||||
char byte = 0;
|
||||
@ -96,12 +95,12 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int RawConverter::
|
||||
long RawConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
long length = 0;
|
||||
long val = 0;
|
||||
int width = fmt.width;
|
||||
unsigned long width = fmt.width;
|
||||
if (width == 0) width = 1; // default: 1 byte
|
||||
if (fmt.flags & skip_flag)
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ class RawFloatConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printDouble(const StreamFormat&, StreamBuffer&, double);
|
||||
int scanDouble(const StreamFormat&, const char*, double&);
|
||||
long scanDouble(const StreamFormat&, const char*, double&);
|
||||
};
|
||||
|
||||
int RawFloatConverter::
|
||||
@ -90,7 +90,7 @@ printDouble(const StreamFormat& format, StreamBuffer& output, double value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int RawFloatConverter::
|
||||
long RawFloatConverter::
|
||||
scanDouble(const StreamFormat& format, const char* input, double& value)
|
||||
{
|
||||
int nbOfBytes;
|
||||
|
@ -38,8 +38,8 @@
|
||||
class RegexpConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse (const StreamFormat& fmt, StreamBuffer&, const char*&, bool);
|
||||
int scanString(const StreamFormat& fmt, const char*, char*, size_t);
|
||||
int scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor);
|
||||
long scanString(const StreamFormat& fmt, const char*, char*, unsigned long&);
|
||||
long scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor);
|
||||
bool printPseudo(const StreamFormat& fmt, StreamBuffer& output);
|
||||
};
|
||||
|
||||
@ -54,7 +54,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
if (fmt.prec > 9)
|
||||
{
|
||||
error("Subexpression index %d too big (>9)\n", fmt.prec);
|
||||
error("Subexpression index %ld too big (>9)\n", fmt.prec);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -115,14 +115,13 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
return string_format;
|
||||
}
|
||||
|
||||
int RegexpConverter::
|
||||
long RegexpConverter::
|
||||
scanString(const StreamFormat& fmt, const char* input,
|
||||
char* value, size_t maxlen)
|
||||
char* value, unsigned long& size)
|
||||
{
|
||||
int ovector[30];
|
||||
int rc;
|
||||
unsigned int l;
|
||||
|
||||
const char* info = fmt.info;
|
||||
pcre* code = extract<pcre*>(info);
|
||||
int length = fmt.width > 0 ? fmt.width : strlen(input);
|
||||
@ -141,17 +140,18 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
if (fmt.flags & skip_flag) return ovector[subexpr*2+1];
|
||||
|
||||
l = ovector[subexpr*2+1] - ovector[subexpr*2];
|
||||
if (l >= maxlen) {
|
||||
if (l >= size) {
|
||||
if (!(fmt.flags & sign_flag)) {
|
||||
error("Regexp: Matching string \"%s\" too long (%d>%ld bytes). You may want to try the + flag: \"%%+/.../\"\n",
|
||||
StreamBuffer(input + ovector[subexpr*2],l).expand()(),
|
||||
l, (long)maxlen-1);
|
||||
l, (long)size-1);
|
||||
return -1;
|
||||
}
|
||||
l = maxlen-1;
|
||||
l = size-1;
|
||||
}
|
||||
memcpy(value, input + ovector[subexpr*2], l);
|
||||
value[l] = '\0';
|
||||
size = l+1; // update number of bytes written to value
|
||||
return ovector[1]; // consume input until end of match
|
||||
}
|
||||
|
||||
@ -159,8 +159,8 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
{
|
||||
const char* subst = fmt.info;
|
||||
pcre* code = extract<pcre*>(subst);
|
||||
long length;
|
||||
int rc, l, c, r, rl, n;
|
||||
unsigned long length, c;
|
||||
int rc, l, r, rl, n;
|
||||
int ovector[30];
|
||||
StreamBuffer s;
|
||||
|
||||
@ -176,7 +176,7 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
for (c = 0, n = 1; c < length; n++)
|
||||
{
|
||||
rc = pcre_exec(code, NULL, buffer(start+c), length-c, 0, 0, ovector, 30);
|
||||
debug("pcre_exec match \"%.*s\" result = %d\n", (int)length-c, buffer(start+c), rc);
|
||||
debug("pcre_exec match \"%.*s\" result = %d\n", (int)(length-c), buffer(start+c), rc);
|
||||
if (rc < 0) // no match
|
||||
return;
|
||||
|
||||
@ -229,7 +229,7 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start)
|
||||
}
|
||||
}
|
||||
|
||||
int RegexpConverter::
|
||||
long RegexpConverter::
|
||||
scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor)
|
||||
{
|
||||
/* re-write input buffer */
|
||||
|
@ -1215,6 +1215,7 @@ normal_format:
|
||||
{
|
||||
long ldummy;
|
||||
double ddummy;
|
||||
long unsigned size=0;
|
||||
switch (fmt.type)
|
||||
{
|
||||
case unsigned_format:
|
||||
@ -1229,7 +1230,7 @@ normal_format:
|
||||
break;
|
||||
case string_format:
|
||||
consumed = StreamFormatConverter::find(fmt.conv)->
|
||||
scanString(fmt, inputLine(consumedInput), NULL, 0);
|
||||
scanString(fmt, inputLine(consumedInput), NULL, size);
|
||||
break;
|
||||
case pseudo_format:
|
||||
// pass complete input
|
||||
@ -1482,7 +1483,7 @@ scanValue(const StreamFormat& fmt, long& value)
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1;
|
||||
if (fmt.flags & fix_width_flag && (unsigned long)consumed != fmt.width) return -1;
|
||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||
debug("StreamCore::scanValue(%s) scanned %li\n",
|
||||
name(), value);
|
||||
@ -1514,7 +1515,7 @@ scanValue(const StreamFormat& fmt, double& value)
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
if (fmt.flags & fix_width_flag && (consumed != (fmt.width + fmt.prec + 1))) return -1;
|
||||
if (fmt.flags & fix_width_flag && ((unsigned long)consumed != (fmt.width + fmt.prec + 1))) return -1;
|
||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||
debug("StreamCore::scanValue(%s) scanned %#g\n",
|
||||
name(), value);
|
||||
@ -1523,7 +1524,7 @@ scanValue(const StreamFormat& fmt, double& value)
|
||||
}
|
||||
|
||||
long StreamCore::
|
||||
scanValue(const StreamFormat& fmt, char* value, long maxlen)
|
||||
scanValue(const StreamFormat& fmt, char* value, unsigned long& size)
|
||||
{
|
||||
if (fmt.type != string_format)
|
||||
{
|
||||
@ -1531,13 +1532,12 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen)
|
||||
name(), fmt.conv);
|
||||
return -1;
|
||||
}
|
||||
if (maxlen < 0) maxlen = 0;
|
||||
flags |= ScanTried;
|
||||
if (!matchSeparator()) return -1;
|
||||
long consumed = StreamFormatConverter::find(fmt.conv)->
|
||||
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)());
|
||||
scanString(fmt, inputLine(consumedInput), value, size);
|
||||
debug("StreamCore::scanValue(%s, format=%%%c, char*, size=%ld) input=\"%s\"\n",
|
||||
name(), fmt.conv, size, inputLine.expand(consumedInput)());
|
||||
if (consumed < 0)
|
||||
{
|
||||
if (fmt.flags & default_flag)
|
||||
@ -1547,11 +1547,11 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen)
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1;
|
||||
if (fmt.flags & fix_width_flag && (unsigned long)consumed != fmt.width) return -1;
|
||||
if (consumed > inputLine.length()-consumedInput) return -1;
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("StreamCore::scanValue(%s) scanned \"%s\"\n",
|
||||
name(), StreamBuffer(value, maxlen).expand()());
|
||||
name(), StreamBuffer(value, size).expand()());
|
||||
#endif
|
||||
flags |= GotValue;
|
||||
return consumed;
|
||||
|
@ -137,7 +137,7 @@ protected:
|
||||
bool printValue(const StreamFormat& format, char* value);
|
||||
long scanValue(const StreamFormat& format, long& value);
|
||||
long scanValue(const StreamFormat& format, double& value);
|
||||
long scanValue(const StreamFormat& format, char* value, long maxlen);
|
||||
long scanValue(const StreamFormat& format, char* value, unsigned long& size);
|
||||
long scanValue(const StreamFormat& format);
|
||||
|
||||
StreamBuffer protocolname;
|
||||
|
@ -157,7 +157,7 @@ class Stream : protected StreamCore
|
||||
long initRecord(const char* filename, const char* protocol,
|
||||
const char* busname, int addr, const char* busparam);
|
||||
bool print(format_t *format, va_list ap);
|
||||
bool scan(format_t *format, void* pvalue, size_t maxStringSize);
|
||||
long scan(format_t *format, void* pvalue, size_t maxStringSize);
|
||||
bool process();
|
||||
|
||||
// device support functions
|
||||
@ -554,19 +554,21 @@ long streamPrintf(dbCommon *record, format_t *format, ...)
|
||||
long streamScanfN(dbCommon* record, format_t *format,
|
||||
void* value, size_t maxStringSize)
|
||||
{
|
||||
long size;
|
||||
debug("streamScanfN(%s,format=%%%c,maxStringSize=%ld)\n",
|
||||
record->name, format->priv->conv, (long)maxStringSize);
|
||||
Stream* pstream = (Stream*)record->dpvt;
|
||||
if (!pstream) return ERROR;
|
||||
if (!pstream->scan(format, value, maxStringSize))
|
||||
size = pstream->scan(format, value, maxStringSize);
|
||||
if (size == ERROR)
|
||||
{
|
||||
return ERROR;
|
||||
debug("streamScanfN(%s) failed\n", record->name);
|
||||
}
|
||||
#ifndef NO_TEMPORARY
|
||||
debug("streamScanfN(%s) success, value=\"%s\"\n",
|
||||
record->name, StreamBuffer((char*)value).expand()());
|
||||
#endif
|
||||
return OK;
|
||||
return size;
|
||||
}
|
||||
|
||||
// Stream methods ////////////////////////////////////////////////////////
|
||||
@ -800,11 +802,12 @@ print(format_t *format, va_list ap)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Stream::
|
||||
long Stream::
|
||||
scan(format_t *format, void* value, size_t maxStringSize)
|
||||
{
|
||||
// called by streamScanfN
|
||||
|
||||
unsigned long size = maxStringSize;
|
||||
// first remove old value from inputLine (if we are scanning arrays)
|
||||
consumedInput += currentValueLength;
|
||||
currentValueLength = 0;
|
||||
@ -820,20 +823,17 @@ scan(format_t *format, void* value, size_t maxStringSize)
|
||||
break;
|
||||
case DBF_STRING:
|
||||
currentValueLength = scanValue(*format->priv, (char*)value,
|
||||
maxStringSize);
|
||||
size);
|
||||
break;
|
||||
default:
|
||||
error("INTERNAL ERROR (%s): Illegal format type\n", name());
|
||||
return false;
|
||||
}
|
||||
if (currentValueLength < 0)
|
||||
{
|
||||
currentValueLength = 0;
|
||||
return false;
|
||||
return ERROR;
|
||||
}
|
||||
// Don't remove scanned value from inputLine yet, because
|
||||
// we might need the string in a later error message.
|
||||
return true;
|
||||
if (currentValueLength == ERROR) return ERROR;
|
||||
if (format->type == DBF_STRING) return size;
|
||||
return OK;
|
||||
}
|
||||
|
||||
// epicsTimerNotify virtual method ///////////////////////////////////////
|
||||
@ -1163,6 +1163,7 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
int status;
|
||||
const char* putfunc;
|
||||
format_s fmt;
|
||||
unsigned long stringsize = MAX_STRING_SIZE;
|
||||
|
||||
fmt.type = dbfMapping[format.type];
|
||||
fmt.priv = &format;
|
||||
@ -1172,10 +1173,18 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
// to field of this or other record.
|
||||
StreamBuffer fieldBuffer;
|
||||
DBADDR* pdbaddr = (DBADDR*)fieldaddress;
|
||||
long nord;
|
||||
long nelem = pdbaddr->no_elements;
|
||||
size_t size = nelem * dbValueSize(fmt.type);
|
||||
buffer = fieldBuffer.clear().reserve(size);
|
||||
size_t size;
|
||||
unsigned long nord;
|
||||
unsigned long nelem = pdbaddr->no_elements;
|
||||
if (format.type == string_format &&
|
||||
(pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR))
|
||||
{
|
||||
// string to char array
|
||||
size = nelem;
|
||||
}
|
||||
else
|
||||
size = nelem * dbValueSize(fmt.type);
|
||||
buffer = fieldBuffer.clear().reserve(size); // maybe write to field directly in case types match?
|
||||
for (nord = 0; nord < nelem; nord++)
|
||||
{
|
||||
debug("Stream::matchValue(%s): buffer before: %s\n",
|
||||
@ -1232,24 +1241,27 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
}
|
||||
case string_format:
|
||||
{
|
||||
if (pdbaddr->field_type == DBF_CHAR)
|
||||
if (pdbaddr->field_type == DBF_CHAR ||
|
||||
pdbaddr->field_type == DBF_UCHAR)
|
||||
{
|
||||
// string to char array
|
||||
consumed = scanValue(format, buffer, nelem);
|
||||
stringsize = nelem;
|
||||
consumed = scanValue(format, buffer, stringsize);
|
||||
debug("Stream::matchValue(%s): %s.%s = \"%.*s\"\n",
|
||||
name(), pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
(int)consumed, buffer);
|
||||
nord = nelem;
|
||||
nord = nelem; // this shortcuts the loop
|
||||
}
|
||||
else
|
||||
{
|
||||
stringsize = MAX_STRING_SIZE;
|
||||
consumed = scanValue(format,
|
||||
buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE);
|
||||
buffer+MAX_STRING_SIZE*nord, stringsize);
|
||||
debug("Stream::matchValue(%s): %s.%s[%li] = \"%.*s\"\n",
|
||||
name(), pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
nord, MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord);
|
||||
nord, (int)stringsize, buffer+MAX_STRING_SIZE*nord);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1290,7 +1302,7 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
/* convert from Unix epoch (1 Jan 1970) to EPICS epoch (1 Jan 1990) */
|
||||
dval = dval-631152000u;
|
||||
pdbaddr->precord->time.secPastEpoch = (long)dval;
|
||||
// rouding: we don't have 9 digits precision
|
||||
// rounding: we don't have 9 digits precision
|
||||
// in a double of today's number of seconds
|
||||
pdbaddr->precord->time.nsec = (long)((dval-(long)dval)*1e6)*1000;
|
||||
debug("Stream::matchValue(%s): writing %i.%i to %s.TIME field\n",
|
||||
@ -1307,10 +1319,11 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
#endif
|
||||
}
|
||||
if (format.type == string_format &&
|
||||
(pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR))
|
||||
(pdbaddr->field_type == DBF_CHAR ||
|
||||
pdbaddr->field_type == DBF_UCHAR))
|
||||
{
|
||||
/* write strings to [U]CHAR arrays */
|
||||
nord = consumed;
|
||||
nord = stringsize;
|
||||
fmt.type = DBF_CHAR;
|
||||
}
|
||||
if (pdbaddr->precord == record || INIT_RUN)
|
||||
@ -1349,25 +1362,26 @@ matchValue(const StreamFormat& format, const void* fieldaddress)
|
||||
case DBF_ULONG:
|
||||
case DBF_LONG:
|
||||
case DBF_ENUM:
|
||||
error("%s: %s(%s.%s, %s, %li) failed\n",
|
||||
error("%s: %s(%s.%s, %s, %li, %lu) failed\n",
|
||||
name(), putfunc, pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
pamapdbfType[fmt.type].strvalue,
|
||||
lval);
|
||||
lval, nord);
|
||||
return false;
|
||||
case DBF_DOUBLE:
|
||||
error("%s: %s(%s.%s, %s, %#g) failed\n",
|
||||
error("%s: %s(%s.%s, %s, %#g, %lu) failed\n",
|
||||
name(), putfunc, pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
pamapdbfType[fmt.type].strvalue,
|
||||
dval);
|
||||
dval, nord);
|
||||
return false;
|
||||
case DBF_STRING:
|
||||
error("%s: %s(%s.%s, %s, \"%.*s\") failed\n",
|
||||
case DBF_CHAR:
|
||||
error("%s: %s(%s.%s, %s, \"%.*s\", %lu) failed\n",
|
||||
name(), putfunc, pdbaddr->precord->name,
|
||||
((dbFldDes*)pdbaddr->pfldDes)->name,
|
||||
pamapdbfType[fmt.type].strvalue,
|
||||
(int)consumed, buffer);
|
||||
(int)consumed, buffer, nord);
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
|
@ -50,9 +50,9 @@ typedef struct StreamFormat
|
||||
char conv;
|
||||
StreamFormatType type;
|
||||
unsigned short flags;
|
||||
short prec;
|
||||
unsigned short width;
|
||||
unsigned short infolen;
|
||||
long prec;
|
||||
unsigned long width;
|
||||
unsigned long infolen;
|
||||
const char* info;
|
||||
} StreamFormat;
|
||||
|
||||
|
@ -113,12 +113,12 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm
|
||||
char* p;
|
||||
val = strtoul (source, &p, 10);
|
||||
source = p;
|
||||
if (val > 0xFFFF)
|
||||
if (val > LONG_MAX)
|
||||
{
|
||||
error("Field width %ld out of range\n", val);
|
||||
return false;
|
||||
}
|
||||
streamFormat.width = (unsigned short)val;
|
||||
streamFormat.width = val;
|
||||
// look for prec
|
||||
streamFormat.prec = -1;
|
||||
if (*source == '.')
|
||||
@ -132,7 +132,7 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm
|
||||
return false;
|
||||
}
|
||||
source = p;
|
||||
if (val > 0x7FFF)
|
||||
if (val > SHRT_MAX)
|
||||
{
|
||||
error("Precision %ld out of range\n", val);
|
||||
return false;
|
||||
@ -205,7 +205,7 @@ printPseudo(const StreamFormat& fmt, StreamBuffer&)
|
||||
return false;
|
||||
}
|
||||
|
||||
int StreamFormatConverter::
|
||||
long StreamFormatConverter::
|
||||
scanLong(const StreamFormat& fmt, const char*, long&)
|
||||
{
|
||||
error("Unimplemented scanLong method for %%%c format\n",
|
||||
@ -213,7 +213,7 @@ scanLong(const StreamFormat& fmt, const char*, long&)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int StreamFormatConverter::
|
||||
long StreamFormatConverter::
|
||||
scanDouble(const StreamFormat& fmt, const char*, double&)
|
||||
{
|
||||
error("Unimplemented scanDouble method for %%%c format\n",
|
||||
@ -221,15 +221,15 @@ scanDouble(const StreamFormat& fmt, const char*, double&)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int StreamFormatConverter::
|
||||
scanString(const StreamFormat& fmt, const char*, char*, size_t)
|
||||
long StreamFormatConverter::
|
||||
scanString(const StreamFormat& fmt, const char*, char*, unsigned long&)
|
||||
{
|
||||
error("Unimplemented scanString method for %%%c format\n",
|
||||
fmt.conv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int StreamFormatConverter::
|
||||
long StreamFormatConverter::
|
||||
scanPseudo(const StreamFormat& fmt, StreamBuffer&, long&)
|
||||
{
|
||||
error("Unimplemented scanPseudo method for %%%c format\n",
|
||||
@ -255,11 +255,11 @@ static void copyFormatString(StreamBuffer& info, const char* source)
|
||||
|
||||
// Standard Long Converter for 'diouxX'
|
||||
|
||||
static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg)
|
||||
static long prepareval(const StreamFormat& fmt, const char*& input, bool& neg)
|
||||
{
|
||||
int length = 0;
|
||||
long consumed = 0;
|
||||
neg = false;
|
||||
while (isspace(*input)) { input++; length++; }
|
||||
while (isspace(*input)) { input++; consumed++; }
|
||||
if (fmt.width)
|
||||
{
|
||||
// take local copy because strto* don't have width parameter
|
||||
@ -268,7 +268,7 @@ static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg)
|
||||
{
|
||||
// normally whitespace does not count to width
|
||||
// but do so if space flag is present
|
||||
width -= length;
|
||||
width -= consumed;
|
||||
}
|
||||
strncpy((char*)fmt.info, input, width);
|
||||
((char*)fmt.info)[width] = 0;
|
||||
@ -283,21 +283,21 @@ static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg)
|
||||
neg = true;
|
||||
skipsign:
|
||||
input++;
|
||||
length++;
|
||||
consumed++;
|
||||
}
|
||||
if (isspace(*input))
|
||||
{
|
||||
// allow space after sign only if # flag is set
|
||||
if (!(fmt.flags & alt_flag)) return -1;
|
||||
}
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
class StdLongConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat& fmt, StreamBuffer& output, const char*& value, bool scanFormat);
|
||||
bool printLong(const StreamFormat& fmt, StreamBuffer& output, long value);
|
||||
int scanLong(const StreamFormat& fmt, const char* input, long& value);
|
||||
long scanLong(const StreamFormat& fmt, const char* input, long& value);
|
||||
};
|
||||
|
||||
int StdLongConverter::
|
||||
@ -306,7 +306,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
{
|
||||
if (scanFormat && fmt.prec >= 0)
|
||||
{
|
||||
error("Use of precision field '.%d' not allowed with %%%c input conversion\n",
|
||||
error("Use of precision field '.%ld' not allowed with %%%c input conversion\n",
|
||||
fmt.prec, fmt.conv);
|
||||
return false;
|
||||
}
|
||||
@ -334,17 +334,17 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int StdLongConverter::
|
||||
long StdLongConverter::
|
||||
scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
{
|
||||
char* end;
|
||||
int length;
|
||||
long consumed;
|
||||
bool neg;
|
||||
int base;
|
||||
long v;
|
||||
|
||||
length = prepareval(fmt, input, neg);
|
||||
if (length < 0) return -1;
|
||||
consumed = prepareval(fmt, input, neg);
|
||||
if (consumed < 0) return -1;
|
||||
switch (fmt.conv)
|
||||
{
|
||||
case 'd':
|
||||
@ -366,9 +366,9 @@ scanLong(const StreamFormat& fmt, const char* input, long& value)
|
||||
}
|
||||
v = strtoul(input, &end, base);
|
||||
if (end == input) return -1;
|
||||
length += end-input;
|
||||
consumed += end-input;
|
||||
value = neg ? -v : v;
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (StdLongConverter, "diouxX");
|
||||
@ -379,7 +379,7 @@ class StdDoubleConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual bool printDouble(const StreamFormat&, StreamBuffer&, double);
|
||||
virtual int scanDouble(const StreamFormat&, const char*, double&);
|
||||
virtual long scanDouble(const StreamFormat&, const char*, double&);
|
||||
};
|
||||
|
||||
int StdDoubleConverter::
|
||||
@ -388,7 +388,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
{
|
||||
if (scanFormat && fmt.prec >= 0)
|
||||
{
|
||||
error("Use of precision field '.%d' not allowed with %%%c input conversion\n",
|
||||
error("Use of precision field '.%ld' not allowed with %%%c input conversion\n",
|
||||
fmt.prec, fmt.conv);
|
||||
return false;
|
||||
}
|
||||
@ -411,20 +411,20 @@ printDouble(const StreamFormat& fmt, StreamBuffer& output, double value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int StdDoubleConverter::
|
||||
long StdDoubleConverter::
|
||||
scanDouble(const StreamFormat& fmt, const char* input, double& value)
|
||||
{
|
||||
char* end;
|
||||
int length;
|
||||
long consumed;
|
||||
bool neg;
|
||||
|
||||
length = prepareval(fmt, input, neg);
|
||||
if (length < 0) return -1;
|
||||
consumed = prepareval(fmt, input, neg);
|
||||
if (consumed < 0) return -1;
|
||||
value = strtod(input, &end);
|
||||
if (neg) value = -value;
|
||||
if (end == input) return -1;
|
||||
length += end-input;
|
||||
return length;
|
||||
consumed += end-input;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (StdDoubleConverter, "feEgG");
|
||||
@ -435,7 +435,7 @@ class StdStringConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual bool printString(const StreamFormat&, StreamBuffer&, const char*);
|
||||
virtual int scanString(const StreamFormat&, const char*, char*, size_t);
|
||||
virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&);
|
||||
};
|
||||
|
||||
int StdStringConverter::
|
||||
@ -451,7 +451,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
if (scanFormat && fmt.prec >= 0)
|
||||
{
|
||||
error("Use of precision field '.%d' not allowed with %%%c input conversion\n",
|
||||
error("Use of precision field '.%ld' not allowed with %%%c input conversion\n",
|
||||
fmt.prec, fmt.conv);
|
||||
return false;
|
||||
}
|
||||
@ -483,17 +483,17 @@ printString(const StreamFormat& fmt, StreamBuffer& output, const char* value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int StdStringConverter::
|
||||
long StdStringConverter::
|
||||
scanString(const StreamFormat& fmt, const char* input,
|
||||
char* value, size_t maxlen)
|
||||
char* value, unsigned long &size)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
long consumed = 0;
|
||||
long space_left = size;
|
||||
int width = fmt.width;
|
||||
|
||||
if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0;
|
||||
if ((fmt.flags & skip_flag) || value == NULL) space_left = 0;
|
||||
|
||||
// if user does not specify width assume "ininity" (-1)
|
||||
// if user does not specify width assume "infinity" (-1)
|
||||
if (width == 0)
|
||||
{
|
||||
if (fmt.conv == 'c') width = 1;
|
||||
@ -506,14 +506,14 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
// but do so if space flag is present
|
||||
if (fmt.flags & space_flag)
|
||||
{
|
||||
if (maxlen > 1)
|
||||
if (space_left > 1) // keep space for terminal null byte
|
||||
{
|
||||
*value++ = *input;
|
||||
maxlen--;
|
||||
space_left--;
|
||||
}
|
||||
width--;
|
||||
}
|
||||
length++;
|
||||
consumed++;
|
||||
input++;
|
||||
}
|
||||
while (*input && width)
|
||||
@ -521,20 +521,22 @@ scanString(const StreamFormat& fmt, const char* input,
|
||||
// normally whitespace ends string
|
||||
// but don't end if # flag is present
|
||||
if (!(fmt.flags & alt_flag) && isspace(*input)) break;
|
||||
if (maxlen > 1)
|
||||
if (space_left > 1)
|
||||
{
|
||||
*value++ = *input;
|
||||
maxlen--;
|
||||
space_left--;
|
||||
}
|
||||
length++;
|
||||
consumed++;
|
||||
width--;
|
||||
input++;
|
||||
}
|
||||
if (maxlen > 0)
|
||||
if (space_left)
|
||||
{
|
||||
*value = '\0';
|
||||
space_left--;
|
||||
size -= space_left; // update number of bytes copied to value
|
||||
}
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (StdStringConverter, "s");
|
||||
@ -545,7 +547,7 @@ class StdCharsConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual bool printLong(const StreamFormat&, StreamBuffer&, long);
|
||||
virtual int scanString(const StreamFormat&, const char*, char*, size_t);
|
||||
virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&);
|
||||
};
|
||||
|
||||
int StdCharsConverter::
|
||||
@ -560,7 +562,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
if (scanFormat && fmt.prec >= 0)
|
||||
{
|
||||
error("Use of precision field '.%d' not allowed with %%%c input conversion\n",
|
||||
error("Use of precision field '.%ld' not allowed with %%%c input conversion\n",
|
||||
fmt.prec, fmt.conv);
|
||||
return false;
|
||||
}
|
||||
@ -581,35 +583,37 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value)
|
||||
return true;
|
||||
}
|
||||
|
||||
int StdCharsConverter::
|
||||
long StdCharsConverter::
|
||||
scanString(const StreamFormat& fmt, const char* input,
|
||||
char* value, size_t maxlen)
|
||||
char* value, unsigned long& size)
|
||||
{
|
||||
int length = 0;
|
||||
long consumed = 0;
|
||||
long width = fmt.width;
|
||||
long space_left = size;
|
||||
|
||||
int width = fmt.width;
|
||||
|
||||
if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0;
|
||||
if ((fmt.flags & skip_flag) || value == NULL) space_left = 0;
|
||||
|
||||
// if user does not specify width assume 1
|
||||
if (width == 0) width = 1;
|
||||
|
||||
while (*input && width)
|
||||
{
|
||||
if (maxlen > 1)
|
||||
if (space_left > 1) // keep space for terminal null byte
|
||||
{
|
||||
*value++ = *input;
|
||||
maxlen--;
|
||||
space_left--;
|
||||
}
|
||||
length++;
|
||||
consumed++;
|
||||
width--;
|
||||
input++;
|
||||
}
|
||||
if (maxlen > 0)
|
||||
if (space_left)
|
||||
{
|
||||
*value = '\0';
|
||||
space_left--;
|
||||
size -= space_left; // update number of bytes written to value
|
||||
}
|
||||
return length;
|
||||
return consumed; // return number of bytes consumed from input
|
||||
}
|
||||
|
||||
RegisterConverter (StdCharsConverter, "c");
|
||||
@ -619,7 +623,7 @@ RegisterConverter (StdCharsConverter, "c");
|
||||
class StdCharsetConverter : public StreamFormatConverter
|
||||
{
|
||||
virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
virtual int scanString(const StreamFormat&, const char*, char*, size_t);
|
||||
virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&);
|
||||
// no print method, %[ is readonly
|
||||
};
|
||||
|
||||
@ -651,7 +655,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
}
|
||||
if (scanFormat && fmt.prec >= 0)
|
||||
{
|
||||
error("Use of precision field '.%d' not allowed with %%%c input conversion\n",
|
||||
error("Use of precision field '.%ld' not allowed with %%%c input conversion\n",
|
||||
fmt.prec, fmt.conv);
|
||||
return false;
|
||||
}
|
||||
@ -698,35 +702,38 @@ parse(const StreamFormat& fmt, StreamBuffer& info,
|
||||
return string_format;
|
||||
}
|
||||
|
||||
int StdCharsetConverter::
|
||||
long StdCharsetConverter::
|
||||
scanString(const StreamFormat& fmt, const char* input,
|
||||
char* value, size_t maxlen)
|
||||
char* value, unsigned long& size)
|
||||
{
|
||||
int length = 0;
|
||||
int width = fmt.width;
|
||||
long consumed = 0;
|
||||
long width = fmt.width;
|
||||
long space_left = size;
|
||||
|
||||
if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0;
|
||||
if ((fmt.flags & skip_flag) || value == NULL) space_left = 0;
|
||||
|
||||
// if user does not specify width assume "ininity" (-1)
|
||||
// if user does not specify width assume "infinity" (-1)
|
||||
if (width == 0) width = -1;
|
||||
|
||||
while (*input && width)
|
||||
{
|
||||
if (fmt.info[*input>>3] & 1<<(*input&7)) break;
|
||||
if (maxlen > 1)
|
||||
if (space_left > 1) // keep space for terminal null byte
|
||||
{
|
||||
*value++ = *input;
|
||||
maxlen--;
|
||||
space_left--;
|
||||
}
|
||||
length++;
|
||||
consumed++;
|
||||
width--;
|
||||
input++;
|
||||
}
|
||||
if (maxlen > 0)
|
||||
if (space_left)
|
||||
{
|
||||
*value = '\0';
|
||||
space_left--;
|
||||
size -= space_left; // update number of bytes written to value
|
||||
}
|
||||
return length;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
RegisterConverter (StdCharsetConverter, "[");
|
||||
|
@ -56,13 +56,13 @@ public:
|
||||
StreamBuffer& output, const char* value);
|
||||
virtual bool printPseudo(const StreamFormat& fmt,
|
||||
StreamBuffer& output);
|
||||
virtual int scanLong(const StreamFormat& fmt,
|
||||
virtual long scanLong(const StreamFormat& fmt,
|
||||
const char* input, long& value);
|
||||
virtual int scanDouble(const StreamFormat& fmt,
|
||||
virtual long scanDouble(const StreamFormat& fmt,
|
||||
const char* input, double& value);
|
||||
virtual int scanString(const StreamFormat& fmt,
|
||||
const char* input, char* value, size_t maxlen);
|
||||
virtual int scanPseudo(const StreamFormat& fmt,
|
||||
virtual long scanString(const StreamFormat& fmt,
|
||||
const char* input, char* value, unsigned long& size);
|
||||
virtual long scanPseudo(const StreamFormat& fmt,
|
||||
StreamBuffer& inputLine, long& cursor);
|
||||
};
|
||||
|
||||
@ -130,8 +130,8 @@ void* ref_##converter = ®istrar_##converter\
|
||||
* You only need to implement the flavour of print and/or scan suitable for
|
||||
* the datatype returned by parse().
|
||||
*
|
||||
* Now, fmt.type contains the value returned by parse(). With fmt.info()
|
||||
* you will get the string you have written to info in parse() (null terminated).
|
||||
* Now, fmt.type contains the value returned by parse(). With fmt.info() you
|
||||
* will get the string you have written to info in parse() (null terminated).
|
||||
* The length of the info string can be found in fmt.infolen.
|
||||
*
|
||||
* In print*(), append the converted value to output. Do not modify what is
|
||||
@ -139,9 +139,14 @@ void* ref_##converter = ®istrar_##converter\
|
||||
* Return true on success, false on failure.
|
||||
*
|
||||
* In scan*(), read the value from input and return the number of consumed
|
||||
* bytes. In the string version, don't write more bytes than maxlen! If the
|
||||
* skip_flag is set, you don't need to write to value, since the value will be
|
||||
* discarded anyway. Return -1 on failure.
|
||||
* bytes.
|
||||
* In the string version, don't write more bytes than size including a
|
||||
* mandatory terminating null byte. Update size with the number of bytes
|
||||
* written into the value, wich may differ from the number of bytes consumed
|
||||
* from the input (e.g. due to leading space). If the skip_flag is set, the
|
||||
* input will be discarded. Thus, don't write to value. You also don't need
|
||||
* to update size.
|
||||
* Return -1 on failure.
|
||||
*
|
||||
*
|
||||
* Register your class
|
||||
|
@ -1484,7 +1484,7 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr,
|
||||
buffer.append(infoString);
|
||||
|
||||
debug("StreamProtocolParser::Protocol::compileFormat: format.type=%s, "
|
||||
"infolen=%d infostring=\"%s\"\n",
|
||||
"infolen=%ld infostring=\"%s\"\n",
|
||||
StreamFormatTypeStr[streamFormat.type],
|
||||
streamFormat.infolen, infoString.expand()());
|
||||
formatstr = source; // move pointer after parsed format
|
||||
|
@ -75,7 +75,7 @@ class TimestampConverter : public StreamFormatConverter
|
||||
{
|
||||
int parse(const StreamFormat&, StreamBuffer&, const char*&, bool);
|
||||
bool printDouble(const StreamFormat&, StreamBuffer&, double);
|
||||
int scanDouble(const StreamFormat&, const char*, double&);
|
||||
long scanDouble(const StreamFormat&, const char*, double&);
|
||||
};
|
||||
|
||||
int TimestampConverter::
|
||||
@ -516,9 +516,7 @@ startover:
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int TimestampConverter::
|
||||
long TimestampConverter::
|
||||
scanDouble(const StreamFormat& format, const char* input, double& value)
|
||||
{
|
||||
struct tm brokenDownTime;
|
||||
|
@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format)
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
memset(aai->bptr, 0, aai->nelm);
|
||||
aai->nord = 0;
|
||||
if (streamScanfN(record, format,
|
||||
(char *)aai->bptr, aai->nelm) == ERROR)
|
||||
if ((lval = streamScanfN(record, format,
|
||||
(char *)aai->bptr, aai->nelm)) == ERROR)
|
||||
{
|
||||
memset(aai->bptr, 0, aai->nelm);
|
||||
return ERROR;
|
||||
}
|
||||
((char*)aai->bptr)[aai->nelm-1] = 0;
|
||||
for (lval = aai->nelm-2;
|
||||
lval >= 0 && ((char*)aai->bptr)[lval] == 0;
|
||||
lval--);
|
||||
aai->nord = lval+1;
|
||||
if ((size_t)lval < aai->nelm)
|
||||
{
|
||||
memset(((char*)aai->bptr)+lval , 0, aai->nelm-lval);
|
||||
lval++;
|
||||
}
|
||||
else
|
||||
{
|
||||
((char*)aai->bptr)[aai->nelm-1] = 0;
|
||||
}
|
||||
aai->nord = lval;
|
||||
return OK;
|
||||
default:
|
||||
errlogSevPrintf(errlogFatal,
|
||||
|
@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format)
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
memset(aao->bptr, 0, aao->nelm);
|
||||
aao->nord = 0;
|
||||
if (streamScanfN(record, format,
|
||||
(char *)aao->bptr, aao->nelm) == ERROR)
|
||||
if ((lval = streamScanfN(record, format,
|
||||
(char *)aao->bptr, aao->nelm)) == ERROR)
|
||||
{
|
||||
memset(aao->bptr, 0, aao->nelm);
|
||||
return ERROR;
|
||||
}
|
||||
((char*)aao->bptr)[aao->nelm-1] = 0;
|
||||
for (lval = aao->nelm-2;
|
||||
lval >= 0 && ((char*)aao->bptr)[lval] == 0;
|
||||
lval--);
|
||||
aao->nord = lval+1;
|
||||
if ((size_t)lval < aao->nelm)
|
||||
{
|
||||
memset(((char*)aao->bptr)+lval , 0, aao->nelm-lval);
|
||||
lval++;
|
||||
}
|
||||
else
|
||||
{
|
||||
((char*)aao->bptr)[aao->nelm-1] = 0;
|
||||
}
|
||||
aao->nord = lval;
|
||||
return OK;
|
||||
default:
|
||||
errlogSevPrintf(errlogFatal,
|
||||
|
@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format)
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
memset(wf->bptr, 0, wf->nelm);
|
||||
wf->nord = 0;
|
||||
if (streamScanfN(record, format,
|
||||
(char *)wf->bptr, wf->nelm) == ERROR)
|
||||
if ((lval = streamScanfN(record, format,
|
||||
(char *)wf->bptr, wf->nelm)) == ERROR)
|
||||
{
|
||||
memset(wf->bptr, 0, wf->nelm);
|
||||
return ERROR;
|
||||
}
|
||||
((char*)wf->bptr)[wf->nelm-1] = 0;
|
||||
for (lval = wf->nelm-2;
|
||||
lval >= 0 && ((char*)wf->bptr)[lval] == 0;
|
||||
lval--);
|
||||
wf->nord = lval+1;
|
||||
if ((size_t)lval < wf->nelm)
|
||||
{
|
||||
memset(((char*)wf->bptr)+lval , 0, wf->nelm-lval);
|
||||
lval++;
|
||||
}
|
||||
else
|
||||
{
|
||||
((char*)wf->bptr)[wf->nelm-1] = 0;
|
||||
}
|
||||
wf->nord = lval;
|
||||
return OK;
|
||||
default:
|
||||
errlogSevPrintf(errlogFatal,
|
||||
|
Reference in New Issue
Block a user