add scan_ulongn, scan_8longn, scan_xlongn and scan_longn

master
leitner 11 years ago
parent ee4a2c0cdb
commit 69eb8c01e3

@ -17,21 +17,45 @@ extern "C" {
#define __pure__
#endif
/* interpret src as ASCII decimal number, write number to dest and
* return the number of bytes that were parsed */
/* This file declared functions used to decode / scan / unmarshal
* integer or string values from a buffer.
* The first argument is always the source buffer, the second argument
* is a pointer to the destination (where to store the result). The
* return value is number of bytes scanned successfully. */
/* Interpret src as ASCII decimal number, write number to dest and
* return the number of bytes that were parsed.
* scan_ulong("23",&i) -> i=23, return 2
* NB: leading + or - or space not accepted:
* scan_ulong("+23",&i) -> return 0
* scan_ulong("-23",&i) -> return 0
* scan_ulong(" 23",&i) -> return 0
* scan_ulong("23,42",&i) -> i=23, return 2
* NB: 023 for octal or 0x23 for hex are not supported!
* scan_ulong("0x23",&i) -> i=0, return 1
* NB: will detect integer overflow and abort on excessively large
* values, i.e. on a 32-bit system:
* scan_ulong("4294967296",&i" -> i=429496729, return 9 */
size_t scan_ulong(const char *src,unsigned long *dest);
size_t scan_ulongn(const char* src,size_t n,unsigned long* dest);
/* interpret src as ASCII hexadecimal number, write number to dest and
* return the number of bytes that were parsed */
/* Interpret src as ASCII hexadecimal number, write number to dest and
* return the number of bytes that were parsed.
* Note: leading '+' or '-' not accepted! */
size_t scan_xlong(const char *src,unsigned long *dest);
size_t scan_xlongn(const char *src,size_t n,unsigned long *dest);
/* interpret src as ASCII octal number, write number to dest and
* return the number of bytes that were parsed */
* return the number of bytes that were parsed.
* Note: leading '+' or '-' not accepted! */
size_t scan_8long(const char *src,unsigned long *dest);
size_t scan_8longn(const char *src,size_t n,unsigned long *dest);
/* interpret src as signed ASCII decimal number, write number to dest
* and return the number of bytes that were parsed */
* and return the number of bytes that were parsed.
* Note: leading spaces not accepted! */
size_t scan_long(const char *src,signed long *dest);
size_t scan_longn(const char *src,size_t n,signed long *dest);
size_t scan_longlong(const char *src,signed long long *dest);
size_t scan_ulonglong(const char *src,unsigned long long *dest);
@ -84,7 +108,17 @@ size_t scan_utf8(const char* in,size_t len,uint32_t* n) __pure__;
size_t scan_asn1derlength(const char* in,size_t len,unsigned long long* n) __pure__;
size_t scan_asn1dertag(const char* in,size_t len,unsigned long long* n) __pure__;
/* a few internal function that might be useful independently */
/* parse a netstring, input buffer is in (len bytes).
* if parsing is successful:
* *dest points to string and *slen is size of string
* return number of bytes parsed
* else
* return 0
* Note: *dest will point inside the input buffer!
*/
size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen) __pure__;
/* internal function that might be useful independently */
/* convert from hex ASCII, return 0 to 15 for success or -1 for failure */
int scan_fromhex(unsigned char c);

@ -0,0 +1,13 @@
#include "scan.h"
size_t scan_8longn(const char *src,size_t n,unsigned long *dest) {
register const char *tmp=src;
register unsigned long l=0;
register unsigned char c;
while (n-->0 && (c=*tmp-'0')<8) {
l=l*8+c;
++tmp;
}
*dest=l;
return tmp-src;
}

@ -0,0 +1,23 @@
#include "scan.h"
size_t scan_longn(const char *src,size_t n,long *dest) {
register const char *tmp;
register long int l;
register unsigned char c;
int neg;
int ok;
if (!n--) return 0;
tmp=src; l=0; ok=neg=0;
switch (*tmp) {
case '-': neg=1;
case '+': ++tmp;
}
while (n-->0 && (c=*tmp-'0')<10) {
l=l*10+c;
++tmp;
ok=1;
}
if (!ok) return 0;
*dest=(neg?-l:l);
return tmp-src;
}

@ -0,0 +1,25 @@
#include "scan.h"
size_t scan_ulongn(const char* src,size_t n,unsigned long int* dest) {
register const char *tmp=src;
register unsigned long int l=0;
register unsigned char c;
while (n-->0 && (c=*tmp-'0')<10) {
unsigned long int n;
/* we want to do: l=l*10+c
* but we need to check for integer overflow.
* to check whether l*10 overflows, we could do
* if ((l*10)/10 != l)
* however, multiplication and division are expensive.
* so instead of *10 we do (l<<3) (i.e. *8) + (l<<1) (i.e. *2)
* and check for overflow on all the intermediate steps */
n=l<<3; if ((n>>3)!=l) break;
if (n+(l<<1) < n) break;
n+=l<<1;
if (n+c < n) break;
l=n+c;
++tmp;
}
if (tmp-src) *dest=l;
return tmp-src;
}

@ -0,0 +1,13 @@
#include "scan.h"
size_t scan_xlongn(const char *src,size_t n,unsigned long *dest) {
register const char *tmp=src;
register unsigned long l=0;
register unsigned char c;
while (n-->0 && (c=scan_fromhex(*tmp))<16) {
l=(l<<4)+c;
++tmp;
}
*dest=l;
return tmp-src;
}
Loading…
Cancel
Save