scan_*longlong now properly abort if the number would not fit

master
leitner 11 years ago
parent 9a1addce2f
commit 18afec7d68

@ -5,6 +5,11 @@
change buffer to have a destructor function pointer
SECURITY: fmt_strn would write one byte too many (returned right length though, so usually not a problem as that byte would be overwritten with \0 by the caller anyway)
fmt_pad and fmt_fill fail more gracefully when srclen > maxlen
You can now say $ make WERROR=-Werror (compiling t.c will fail but that's not part of the library)
scan_html now decodes HTML entities based on the actual w3c list (from entities.json, say gmake update to fetch the current version)
added fmt_escapechar* to fmt.h (implement various escaping mechanisms also found in textcode but for a single char not a whole string, and they always escape, not just when they think it's needed)
scan_ushort was supposed to abort early and return 5 when attempting to parse "65536", because the result does not fit. It did not. Now it does.
scan_*long, scan_*int, scan_*short now properly abort if the number would not fit
0.29:
save 8 bytes in taia.h for 64-bit systems

@ -0,0 +1,14 @@
#include "scan.h"
size_t scan_8longlong(const char *src,unsigned long long *dest) {
register const char *tmp=src;
register unsigned long long l=0;
register unsigned char c;
while ((c=*tmp-'0')<8) {
if (l>>(sizeof(l)*8-3)) break;
l=l*8+c;
++tmp;
}
*dest=l;
return tmp-src;
}

@ -1,11 +1,18 @@
#include "scan.h"
static const unsigned long maxlong = ((unsigned long)-1)>>1;
size_t scan_longlong(const char* src,signed long long* dest) {
unsigned int i,o;
unsigned long long l;
char c=src[0];
int neg=c=='-';
o=c=='-' || c=='+';
if ((i=scan_ulonglong(src+o,&l))) {
if (i>0 && l>maxlong+neg) {
l/=10;
--i;
}
if (i+o) *dest=c=='-'?-l:l;
return i+o;
} return 0;

@ -4,7 +4,7 @@ size_t scan_xlonglong(const char* src,unsigned long long* dest) {
register const char *tmp=src;
register long long l=0;
register unsigned char c;
while ((c=scan_fromhex(*tmp))<16) {
while ((l>>(sizeof(l)*8-4))==0 && (c=scan_fromhex(*tmp))<16) {
l=(l<<4)+c;
++tmp;
}

@ -15,12 +15,10 @@ int main() {
unsigned long ul;
unsigned int ui;
unsigned short us;
unsigned char uc;
signed long long ll;
signed long l;
signed int i;
signed short s;
signed char c;
// check utf8 encoding
zap(); assert(fmt_utf8(NULL,12345) == 3);
@ -172,8 +170,7 @@ int main() {
assert(scan_long("+9223372036854775807",&l)==20 && l==0x7fffffffffffffffll);
assert(scan_long("+9223372036854775808",&l)==19 && l==922337203685477580ll);
assert(scan_long("-9223372036854775807",&l)==20 && l==-9223372036854775807ll);
x=scan_long("-9223372036854775808",&l);
assert(scan_long("-9223372036854775808",&l)==20 && l==0x8000000000000000);
assert(scan_long("-9223372036854775808",&l)==20 && l==(signed long long)0x8000000000000000ull);
assert(scan_long("-9223372036854775809",&l)==19 && l==-922337203685477580ll);
}
@ -206,4 +203,22 @@ int main() {
assert(scan_short("+032767",&s)==7 && s==32767);
assert(scan_short("-32768",&s)==6 && s==-32768);
assert(scan_short("-032769",&s)==6 && s==-3276);
assert(scan_ulonglong("18446744073709551615",&ull)==20 && ull==0xffffffffffffffffull);
assert(scan_ulonglong("18446744073709551616",&ull)==19 && ull==1844674407370955161ull);
assert(scan_xlonglong("ffffffffffffffff",&ull)==16 && ull==0xffffffffffffffffull);
assert(scan_xlonglong("ffffffffffffffff0",&ull)==16 && ull==0xffffffffffffffffull);
assert(scan_8longlong("1777777777777777777777",&ull)==22 && ull==0xffffffffffffffffull);
assert(scan_8longlong("17777777777777777777770",&ull)==22 && ull==0xffffffffffffffffull);
assert(scan_longlong("9223372036854775807",&ll)==19 && ll==0x7fffffffffffffffll);
assert(scan_longlong("09223372036854775807",&ll)==20 && ll==0x7fffffffffffffffll);
assert(scan_longlong("092233720368547758070",&ll)==20 && ll==0x7fffffffffffffffll);
assert(scan_longlong("+9223372036854775807",&ll)==20 && ll==0x7fffffffffffffffll);
assert(scan_longlong("+9223372036854775808",&ll)==19 && ll==922337203685477580ll);
assert(scan_longlong("-9223372036854775807",&ll)==20 && ll==-9223372036854775807ll);
assert(scan_longlong("-9223372036854775808",&ll)==20 && ll==(signed long long)0x8000000000000000ull);
assert(scan_longlong("-9223372036854775809",&ll)==19 && ll==-922337203685477580ll);
return 0;
}

Loading…
Cancel
Save