changed streamScanfN to return number of read bytes

This commit is contained in:
2018-06-06 15:52:55 +02:00
parent 0dfcc0f511
commit 9f6d4ab63f
19 changed files with 272 additions and 233 deletions

View File

@ -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)
{

View File

@ -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))

View File

@ -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;

View File

@ -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--)

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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, "[");

View File

@ -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 = &registrar_##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 = &registrar_##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

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,