From ddfdd4d07721220a08faf35a6307ed265915dfd0 Mon Sep 17 00:00:00 2001 From: leitner Date: Sun, 8 Nov 2020 00:29:35 +0000 Subject: [PATCH] add compiler.h to abstract gcc attributes --- CHANGES | 1 + GNUmakefile | 2 +- array.h | 46 ++++++----- buffer.h | 44 ++++++---- buffer/bs_capacityleft.c | 2 +- buffer/bs_err.c | 2 +- byte.h | 67 +++++++-------- case.h | 14 ++++ cdb.h | 26 +++--- cdb/cdb.c | 8 +- cdb/cdb_find.3 | 4 +- cdb/cdb_firstkey.3 | 2 +- cdb/cdb_hash.c | 2 +- cdb/cdb_init.3 | 2 +- cdb/cdb_make.c | 4 +- cdb/cdb_nextkey.3 | 2 +- cdb/cdb_read.3 | 2 +- cdb/cdb_successor.3 | 2 +- cdb_make.h | 12 +-- compiler.h | 110 +++++++++++++++++++++++++ compiletimeassert.h | 12 ++- critbit.h | 22 ++--- dns.h | 6 +- fmt.h | 171 +++++++++++++++++++++++++++------------ iarray.h | 2 +- io.h | 38 +++++++-- io/io_appendfile.3 | 4 +- io/io_createfile.3 | 4 +- io/io_readfile.3 | 4 +- io/io_readwritefile.3 | 4 +- iob.h | 15 +++- ip6.h | 4 +- open.h | 8 ++ openreadclose.h | 4 +- parse.h | 48 ++++++++++- rangecheck.h | 6 ++ safemult.h | 6 +- scan.h | 154 ++++++++++++++++++++--------------- socket.h | 14 +++- str.h | 27 ++++--- stralloc.h | 66 ++++++++------- t.c | 2 + tai.h | 2 +- taia.h | 4 +- textcode.h | 60 +++++++++----- 45 files changed, 705 insertions(+), 336 deletions(-) create mode 100644 compiler.h diff --git a/CHANGES b/CHANGES index 38523af..ed3d6ca 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ add automated way to run unit test: make check add parse.h add bytestream abstraction for parsing data from a buffer or a file + add compiler.h to abstract gcc attributes 0.32: remove OpenBSD #warning (obsd maintainer says no longer needed) diff --git a/GNUmakefile b/GNUmakefile index 886ae0c..76a3b69 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -209,7 +209,7 @@ INCLUDES=buffer.h byte.h fmt.h ip4.h ip6.h mmap.h scan.h socket.h str.h stralloc uint16.h uint32.h uint64.h open.h textcode.h tai.h taia.h dns.h iopause.h case.h \ openreadclose.h readclose.h ndelay.h array.h io.h safemult.h iob.h havealloca.h \ errmsg.h cdb.h cdb_make.h rangecheck.h iarray.h va_narg.h isset.h \ -compiletimeassert.h critbit.h parse.h +compiletimeassert.h critbit.h parse.h compiler.h libowfat: -mkdir libowfat diff --git a/array.h b/array.h index 0a212d7..0a0ec6f 100644 --- a/array.h +++ b/array.h @@ -3,7 +3,8 @@ #define ARRAY_H #include -#include "uint64.h" +#include +#include #ifdef __cplusplus extern "C" { @@ -21,25 +22,30 @@ typedef struct { size_t headroom; /* the actual pointer for free() and realloc() is p-headroom */ } array; -void* array_allocate(array* x,uint64 membersize,int64 pos); -void* array_get(const array* const x,uint64 membersize,int64 pos); -void* array_start(const array* const x); -int64 array_length(const array* const x,uint64 membersize); -int64 array_bytes(const array* const x); -void array_truncate(array* x,uint64 membersize,int64 len); -void array_trunc(array* x); -void array_reset(array* x); -void array_fail(array* x); -int array_equal(const array* const x,const array* const y); -void array_cat(array* to,const array* const from); -void array_catb(array* to,const char* from,uint64 len); -void array_cats(array* to,const char* from); -void array_cats0(array* to,const char* from); -void array_cat0(array* to); -void array_cate(array* to,const array* const from,int64 pos,int64 stop); - -void array_shift(array* x,uint64 membersize,uint64 members); -void array_chop(array* x,uint64 membersize,uint64 members); +void* array_allocate(array* x,uint64 membersize,int64 pos) noexcept; +void* array_get(const array* const x,uint64 membersize,int64 pos) noexcept; +void* array_start(const array* const x) noexcept; + +att_pure +int64 array_length(const array* const x,uint64 membersize) noexcept; + +att_pure +int64 array_bytes(const array* const x) noexcept; + +void array_truncate(array* x,uint64 membersize,int64 len) noexcept; +void array_trunc(array* x) noexcept; +void array_reset(array* x) noexcept; +void array_fail(array* x) noexcept; +int array_equal(const array* const x,const array* const y) noexcept; +void array_cat(array* to,const array* const from) noexcept; +void array_catb(array* to,const char* from,uint64 len) noexcept; +void array_cats(array* to,const char* from) noexcept; +void array_cats0(array* to,const char* from) noexcept; +void array_cat0(array* to) noexcept; +void array_cate(array* to,const array* const from,int64 pos,int64 stop) noexcept; + +void array_shift(array* x,uint64 membersize,uint64 members) noexcept; +void array_chop(array* x,uint64 membersize,uint64 members) noexcept; #define array_failed(x) (array_bytes(x)==-1) #define array_unallocated(x) (array_bytes(x)==0) diff --git a/buffer.h b/buffer.h index 19e806c..6705792 100644 --- a/buffer.h +++ b/buffer.h @@ -9,6 +9,8 @@ /* for strlen */ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -43,12 +45,12 @@ typedef struct buffer { /* Initialize a buffer with an existing memory area, which the buffer * will NOT take ownership of (i.e. won't free the memory when it's done */ -__writememsz__(4,5) +att_writen(4,5) void buffer_init(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen); /* Initialize a buffer with an existing memory area, which the buffer * WILL take ownership of (it will call free() on it when it's done) */ -__writememsz__(4,5) +att_writen(4,5) void buffer_init_free(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen); /* Initialize a buffer without actual I/O. @@ -57,10 +59,12 @@ void buffer_init_free(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen); * that memory area. If it reaches the end, it will signal EOF and never * actually attempt to read from any actual file. * Does not take ownership. Useful for testing. */ +att_readn(2,3) void buffer_init_staticcontents(buffer* b,char* y,size_t ylen); /* Same but the buffer takes ownership of the static buffer and frees it * in buffer_close. */ +att_readn(2,3) void buffer_init_staticcontents_free(buffer* b,char* y,size_t ylen); @@ -74,6 +78,7 @@ void buffer_munmap(void* buf); /* Initialize a buffer so it will read from this file by memory mapping * the whole thing. */ +att_read(2) int buffer_mmapread(buffer* b,const char* filename); /* Indicate you are done with a buffer. @@ -86,17 +91,22 @@ void buffer_close(buffer* b); * the data in the buffer. */ int buffer_flush(buffer* b); -__readmemsz__(2,3) +att_readn(2,3) int buffer_put(buffer* b,const char* x,size_t len); -__readmemsz__(2,3) + +att_readn(2,3) int buffer_putalign(buffer* b,const char* x,size_t len); -__readmemsz__(2,3) + +att_readn(2,3) int buffer_putflush(buffer* b,const char* x,size_t len); -__readmem__(2) + +att_read(2) int buffer_puts(buffer* b,const char* x); -__readmem__(2) + +att_read(2) int buffer_putsalign(buffer* b,const char* x); -__readmem__(2) + +att_read(2) int buffer_putsflush(buffer* b,const char* x); #if defined(__GNUC__) && !defined(__LIBOWFAT_INTERNAL) @@ -121,22 +131,22 @@ int buffer_putnlflush(buffer* b); /* put \n and flush */ : buffer_put((s),&(c),1) \ ) -__writememsz__(2,3) +att_writen(2,3) ssize_t buffer_get(buffer* b,char* x,size_t len); ssize_t buffer_feed(buffer* b); ssize_t buffer_getc(buffer* b,char* x); ssize_t buffer_peekc(buffer* b,char* x); -__writememsz__(2,3) +att_writen(2,3) ssize_t buffer_getn(buffer* b,char* x,size_t len); /* read bytes until the destination buffer is full (len bytes), end of * file is reached or the read char is in charset (setlen bytes). An * empty line when looking for \n will write '\n' to x and return 0. If * EOF is reached, \0 is written to the buffer */ -__writememsz__(2,3) -__readmemsz__(4,5) +att_writen(2,3) +att_readn(4,5) ssize_t buffer_get_token(buffer* b,char* x,size_t len,const char* charset,size_t setlen); -__writememsz__(2,3) +att_writen(2,3) ssize_t buffer_getline(buffer* b,char* x,size_t len); /* this predicate is given the string as currently read from the buffer @@ -144,7 +154,7 @@ ssize_t buffer_getline(buffer* b,char* x,size_t len); typedef int (*string_predicate)(const char* x,size_t len); /* like buffer_get_token but the token ends when your predicate says so */ -__writememsz__(2,3) +att_writen(2,3) ssize_t buffer_get_token_pred(buffer* b,char* x,size_t len,string_predicate p); char *buffer_peek(buffer* b); @@ -194,13 +204,13 @@ int buffer_putsaflush(buffer* b,const stralloc* sa); * data is available. */ /* read token from buffer to stralloc */ -__readmemsz__(3,4) +att_readn(3,4) int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* read line from buffer to stralloc */ int buffer_getline_sa(buffer* b,stralloc* sa); /* same as buffer_get_token_sa but empty sa first */ -__readmemsz__(3,4) +att_readn(3,4) int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* same as buffer_getline_sa but empty sa first */ int buffer_getnewline_sa(buffer* b,stralloc* sa); @@ -218,7 +228,7 @@ void buffer_fromsa(buffer* b,const stralloc* sa); /* read from sa */ int buffer_tosa(buffer*b,stralloc* sa); /* write to sa, auto-growing it */ #endif -__readmemsz__(2,3) +att_readn(2,3) void buffer_frombuf(buffer* b,const char* x,size_t l); /* buffer reads from static buffer */ #ifdef ARRAY_H diff --git a/buffer/bs_capacityleft.c b/buffer/bs_capacityleft.c index 100a23f..898aedc 100644 --- a/buffer/bs_capacityleft.c +++ b/buffer/bs_capacityleft.c @@ -1,6 +1,6 @@ #include "parse.h" -size_t bs_capacityleft(struct bytestream* bs) { +size_t bs_capacityleft(const struct bytestream* bs) { if (bs->cur>=bs->max) // if EOF or error, return 0 return 0; return bs->max - bs->cur; diff --git a/buffer/bs_err.c b/buffer/bs_err.c index f7867b5..16c5733 100644 --- a/buffer/bs_err.c +++ b/buffer/bs_err.c @@ -1,6 +1,6 @@ #include "parse.h" -int bs_err(struct bytestream* bs) { +int bs_err(const struct bytestream* bs) { return (bs->cur > bs->max); } diff --git a/byte.h b/byte.h index a84f1aa..45b6988 100644 --- a/byte.h +++ b/byte.h @@ -9,76 +9,69 @@ extern "C" { #endif -/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ -#ifndef __pure__ -#define __pure__ -#endif - -#ifndef __writememsz__ -#define __writememsz__(a,b) -#define __readmemsz__(a,b) -#endif - -#ifndef __readmem__ -#define __readmem__(a) -#endif +#include /* byte_chr returns the smallest integer i between 0 and len-1 * inclusive such that one[i] equals needle, or len if not found. */ -__readmemsz__(1,2) -size_t byte_chr(const void* haystack, size_t len, char needle) __pure__; +att_readn(1,2) +size_t byte_chr(const void* haystack, size_t len, char needle) noexcept; /* byte_rchr returns the largest integer i between 0 and len-1 inclusive * such that one[i] equals needle, or len if not found. */ -__readmemsz__(1,2) -size_t byte_rchr(const void* haystack,size_t len,char needle) __pure__; +att_pure +att_readn(1,2) +size_t byte_rchr(const void* haystack,size_t len,char needle) noexcept; /* byte_copy copies in[0] to out[0], in[1] to out[1], ... and in[len-1] * to out[len-1]. */ -__writememsz__(1,2) -__readmemsz__(3,2) -void byte_copy(void* out, size_t len, const void* in); +att_writen(1,2) +att_readn(3,2) +void byte_copy(void* out, size_t len, const void* in) noexcept; /* byte_copyr copies in[len-1] to out[len-1], in[len-2] to out[len-2], * ... and in[0] to out[0] */ -__writememsz__(1,2) -__readmemsz__(3,2) -void byte_copyr(void* out, size_t len, const void* in); +att_writen(1,2) +att_readn(3,2) +void byte_copyr(void* out, size_t len, const void* in) noexcept; /* byte_diff returns negative, 0, or positive, depending on whether the * string a[0], a[1], ..., a[len-1] is lexicographically smaller * than, equal to, or greater than the string b[0], b[1], ..., * b[len-1]. When the strings are different, byte_diff does not read * bytes past the first difference. */ -__readmemsz__(1,2) -__readmemsz__(3,2) -int byte_diff(const void* a, size_t len, const void* b) __pure__; +att_pure +att_readn(1,2) +att_readn(3,2) +int byte_diff(const void* a, size_t len, const void* b) noexcept; /* byte_zero sets the bytes out[0], out[1], ..., out[len-1] to 0 */ -__writememsz__(1,2) -void byte_zero(void* out, size_t len); +att_writen(1,2) +void byte_zero(void* out, size_t len) noexcept; #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) /* Return 1 iff (b,blen) is a prefix of (a,alen), 0 otherwise. * Will abort early on mismatch */ -__readmemsz__(1,2) -__readmemsz__(3,4) -int byte_start(const void* a,size_t alen,const void* b,size_t blen) __pure__; +att_pure +att_readn(1,2) +att_readn(3,4) +int byte_start(const void* a,size_t alen,const void* b,size_t blen) noexcept; /* equivalent to byte_start(a,alen,str,strlen(str)) */ -__readmemsz__(1,2) -__readmem__(3) -int byte_starts(const void* a,size_t alen,const char* str) __pure__; +att_pure +att_readn(1,2) +att_read(3) +int byte_starts(const void* a,size_t alen,const char* str) noexcept; #if defined(__GNUC__) && !defined(__LIBOWFAT_INTERNAL) /* If str is a string constant, strlen will be done at compile time */ #define byte_starts(a,alen,str) (__builtin_constant_p(str) ? byte_start(a,alen,str,strlen(str)) : byte_starts(a,alen,str)) #endif -__readmemsz__(1,2) -__readmemsz__(3,2) -int byte_equal_notimingattack(const void* a, size_t len,const void* b) __pure__; +att_pure +att_readn(1,2) +att_readn(3,2) +int byte_equal_notimingattack(const void* a, size_t len,const void* b) noexcept; #if defined(__i386__) || defined(__x86_64__) #define UNALIGNED_ACCESS_OK diff --git a/case.h b/case.h index 59d9470..471c3af 100644 --- a/case.h +++ b/case.h @@ -3,22 +3,36 @@ #define CASE_H #include +#include #ifdef __cplusplus extern "C" { #endif /* turn upper case letters to lower case letters, ASCIIZ */ +att_mangle(1) void case_lowers(char *s); + /* turn upper case letters to lower case letters, binary */ +att_manglen(1,2) void case_lowerb(void *buf,size_t len); /* like str_diff, ignoring case */ +att_pure +att_read(1) +att_read(2) int case_diffs(const char *,const char *); + /* like byte_diff, ignoring case */ +att_pure +att_readn(1,2) +att_readn(3,2) int case_diffb(const void *,size_t ,const void *); /* like str_start, ignoring case */ +att_pure +att_read(1) +att_read(2) int case_starts(const char *,const char *); #define case_equals(s,t) (!case_diffs((s),(t))) diff --git a/cdb.h b/cdb.h index 667013a..2efbd7a 100644 --- a/cdb.h +++ b/cdb.h @@ -2,16 +2,22 @@ #ifndef CDB_H #define CDB_H -#include "uint32.h" -#include "uint64.h" +#include +#include +#include +#include #ifdef __cplusplus extern "C" { #endif #define CDB_HASHSTART 5381 -extern uint32 cdb_hashadd(uint32 h,unsigned char c); -extern uint32 cdb_hash(const unsigned char *buf,unsigned long int len); +att_const +uint32 cdb_hashadd(uint32 h, unsigned char c); + +att_pure +att_read(1) +uint32 cdb_hash(const unsigned char *buf, size_t len); struct cdb { char *map; /* 0 if no map is available */ @@ -26,19 +32,19 @@ struct cdb { uint32 dlen; /* initialized if cdb_findnext() returns 1 */ } ; -extern void cdb_free(struct cdb *); -extern void cdb_init(struct cdb *,int64 fd); +void cdb_free(struct cdb *); +void cdb_init(struct cdb *, int64 fd); -extern int cdb_read(struct cdb *,unsigned char *,unsigned long int,uint32); +int cdb_read(struct cdb * restrict, unsigned char * restrict, size_t, uint32); extern void cdb_findstart(struct cdb *); -extern int cdb_findnext(struct cdb *,const unsigned char *,unsigned long int); -extern int cdb_find(struct cdb *,const unsigned char *,unsigned long int); +extern int cdb_findnext(struct cdb *, const unsigned char *, size_t); +extern int cdb_find(struct cdb *, const unsigned char *, size_t); extern int cdb_firstkey(struct cdb *c,uint32 *kpos); extern int cdb_nextkey(struct cdb *c,uint32 *kpos); -extern int cdb_successor(struct cdb *c,const unsigned char *,unsigned long int); +extern int cdb_successor(struct cdb *c, const unsigned char *, size_t); #define cdb_datapos(c) ((c)->dpos) #define cdb_datalen(c) ((c)->dlen) diff --git a/cdb/cdb.c b/cdb/cdb.c index cbba320..d52c31b 100644 --- a/cdb/cdb.c +++ b/cdb/cdb.c @@ -58,7 +58,7 @@ void cdb_init(struct cdb *c,int64 fd) { #endif } -int cdb_read(struct cdb *c,unsigned char *buf,unsigned long len,uint32 pos) { +int cdb_read(struct cdb *c, unsigned char *buf, size_t len, uint32 pos) { if (c->map) { if ((pos > c->size) || (c->size - pos < len)) goto FORMAT; byte_copy(buf,len,c->map + pos); @@ -96,7 +96,7 @@ int cdb_read(struct cdb *c,unsigned char *buf,unsigned long len,uint32 pos) { return -1; } -static int match(struct cdb *c,const unsigned char *key,unsigned long int len,uint32 pos) { +static int match(struct cdb * restrict c, const unsigned char * restrict key, size_t len, uint32 pos) { unsigned char buf[32]; unsigned long n; @@ -112,7 +112,7 @@ static int match(struct cdb *c,const unsigned char *key,unsigned long int len,ui return 1; } -int cdb_findnext(struct cdb *c,const unsigned char *key,unsigned long int len) { +int cdb_findnext(struct cdb *c, const unsigned char *key, size_t len) { unsigned char buf[8]; uint32 pos; uint32 u; @@ -156,7 +156,7 @@ int cdb_findnext(struct cdb *c,const unsigned char *key,unsigned long int len) { return 0; } -int cdb_find(struct cdb *c,const unsigned char *key,unsigned long int len) { +int cdb_find(struct cdb *c, const unsigned char *key, size_t len) { cdb_findstart(c); return cdb_findnext(c,key,len); } diff --git a/cdb/cdb_find.3 b/cdb/cdb_find.3 index 54ceca7..1b9b0c0 100644 --- a/cdb/cdb_find.3 +++ b/cdb/cdb_find.3 @@ -6,13 +6,13 @@ cdb_find \- look up a key in a constant database .br .B #include -int cdb_find(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned long int \fIkeylen\fR); +int cdb_find(struct cdb *\fIc\fR, char *\fIkey\fR, size_t \fIkeylen\fR); .br int cdb_datalen(struct cdb *\fIc\fR); .br int cdb_datapos(struct cdb *\fIc\fR); .br -int cdb_findnext(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned long int \fIkeylen\fR); +int cdb_findnext(struct cdb *\fIc\fR, char *\fIkey\fR, size_t \fIkeylen\fR); .SH DESCRIPTION \fBcdb_find\fR looks for \fIkey\fR. If cdb_find returns 0, the database diff --git a/cdb/cdb_firstkey.3 b/cdb/cdb_firstkey.3 index ce2feb6..e2e7ade 100644 --- a/cdb/cdb_firstkey.3 +++ b/cdb/cdb_firstkey.3 @@ -6,7 +6,7 @@ cdb_firstkey \- find first physical record in constant database .br .B #include -int cdb_firstkey(struct cdb *\fIc\fR,uint32 *\fIkpos\fR); +int cdb_firstkey(struct cdb *\fIc\fR, uint32 *\fIkpos\fR); .SH DESCRIPTION \fBcdb_firstkey\fR finds the physically first record in the constant diff --git a/cdb/cdb_hash.c b/cdb/cdb_hash.c index 4211486..6d8a0b8 100644 --- a/cdb/cdb_hash.c +++ b/cdb/cdb_hash.c @@ -6,7 +6,7 @@ uint32 cdb_hashadd(uint32 h,unsigned char c) { return h ^ c; } -uint32 cdb_hash(const unsigned char *buf,unsigned long int len) { +uint32 cdb_hash(const unsigned char *buf,size_t len) { uint32 h; h = CDB_HASHSTART; diff --git a/cdb/cdb_init.3 b/cdb/cdb_init.3 index 368bef4..0d9f04b 100644 --- a/cdb/cdb_init.3 +++ b/cdb/cdb_init.3 @@ -4,7 +4,7 @@ cdb_init \- open a constant database .SH SYNTAX .B #include -int cdb_init(struct cdb *\fIc\fR,int \fIfd\fR); +int cdb_init(struct cdb *\fIc\fR, int \fIfd\fR); .SH DESCRIPTION .B cdb_init diff --git a/cdb/cdb_make.c b/cdb/cdb_make.c index 0366f4a..95f517a 100644 --- a/cdb/cdb_make.c +++ b/cdb/cdb_make.c @@ -55,7 +55,7 @@ int cdb_make_addend(struct cdb_make *c,unsigned long int keylen,unsigned long in return 0; } -int cdb_make_addbegin(struct cdb_make *c,unsigned long int keylen,unsigned long int datalen) { +int cdb_make_addbegin(struct cdb_make *c, size_t keylen, size_t datalen) { char buf[8]; if (keylen > 0xffffffff) { errno = ENOMEM; return -1; } @@ -67,7 +67,7 @@ int cdb_make_addbegin(struct cdb_make *c,unsigned long int keylen,unsigned long return 0; } -int cdb_make_add(struct cdb_make *c,const unsigned char *key,unsigned long int keylen,const unsigned char *data,unsigned long int datalen) +int cdb_make_add(struct cdb_make *c, const unsigned char *key, size_t keylen, const unsigned char *data, size_t datalen) { if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1; if (buffer_putalign(&c->b,(char*)key,keylen) == -1) return -1; diff --git a/cdb/cdb_nextkey.3 b/cdb/cdb_nextkey.3 index 460b3d4..4ce466a 100644 --- a/cdb/cdb_nextkey.3 +++ b/cdb/cdb_nextkey.3 @@ -6,7 +6,7 @@ cdb_nextkey \- find next physical record in constant database .br .B #include -int cdb_nextkey(struct cdb *\fIc\fR,uint32 *\fIkpos\fR); +int cdb_nextkey(struct cdb *\fIc\fR, uint32 *\fIkpos\fR); .SH DESCRIPTION \fBcdb_nextkey\fR finds the next physical record in the constant diff --git a/cdb/cdb_read.3 b/cdb/cdb_read.3 index 1e2b5b1..68b9507 100644 --- a/cdb/cdb_read.3 +++ b/cdb/cdb_read.3 @@ -6,7 +6,7 @@ cdb_read \- read bytes from a constant database .br .B #include -int cdb_read(struct cdb *\fIc\fR,char *\fIbuf\fR,unsigned long int \fIlen\fR,uint32 \fIposition\fR); +int cdb_read(struct cdb *\fIc\fR, char *\fIbuf\fR, size_t \fIlen\fR, uint32 \fIposition\fR); .SH DESCRIPTION \fBcdb_read\fR reads \fIlen\fR bytes starting at \fIposition\fR from diff --git a/cdb/cdb_successor.3 b/cdb/cdb_successor.3 index d5fd801..c2865df 100644 --- a/cdb/cdb_successor.3 +++ b/cdb/cdb_successor.3 @@ -4,7 +4,7 @@ cdb_successor \- find next record .SH SYNTAX .B #include -int cdb_successor(struct cdb *\fIc\fR,char *\fIkey\fR,unsigned long int \fIklen\fR); +int cdb_successor(struct cdb *\fIc\fR, char *\fIkey\fR, size_t \fIklen\fR); .SH DESCRIPTION \fBcdb_successor\fR finds the record that follows \fIkey\fR. If diff --git a/cdb_make.h b/cdb_make.h index f7e6e70..c18506c 100644 --- a/cdb_make.h +++ b/cdb_make.h @@ -2,9 +2,9 @@ #ifndef CDB_MAKE_H #define CDB_MAKE_H -#include "buffer.h" -#include "uint64.h" -#include "uint32.h" +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -35,9 +35,9 @@ struct cdb_make { } ; extern int cdb_make_start(struct cdb_make *,int64); -extern int cdb_make_addbegin(struct cdb_make *,unsigned long int,unsigned long int); -extern int cdb_make_addend(struct cdb_make *,unsigned long int,unsigned long int,uint32); -extern int cdb_make_add(struct cdb_make *,const unsigned char *,unsigned long int,const unsigned char *,unsigned long int); +extern int cdb_make_addbegin(struct cdb_make *, size_t, size_t); +extern int cdb_make_addend(struct cdb_make *, size_t, size_t, uint32); +extern int cdb_make_add(struct cdb_make *, const unsigned char *, size_t, const unsigned char *, size_t); extern int cdb_make_finish(struct cdb_make *); #ifdef __cplusplus diff --git a/compiler.h b/compiler.h new file mode 100644 index 0000000..6d33ff0 --- /dev/null +++ b/compiler.h @@ -0,0 +1,110 @@ +#ifndef LIBOWFAT_ATTRIBUTES_H +#define LIBOWFAT_ATTRIBUTES_H + +#ifndef __GNUC__ +// macro attribute declarations away if we don't have gcc or clang +#define __attribute__(x) +#define __extension__ +#endif + +#ifndef __cplusplus +#define noexcept +#endif + +#define GCC_VERSION_ATLEAST(a,b) (__GNUC__ > a) || ((__GNUC__ == a) && (__GNUC_MINOR__ >= b)) + +#if GCC_VERSION_ATLEAST(2,95) && !defined(__STRICT_ANSI__) +#undef restrict +#else +#define restrict +#endif + +#if GCC_VERSION_ATLEAST(3,0) +#define likely(a) __builtin_expect((a), 1) +#define unlikely(a) __builtin_expect((a), 0) +#else +#define likely(a) (a) +#define unlikely(a) (a) +#endif + +#if GCC_VERSION_ATLEAST(2, 5) +#define att_const __attribute__((__const__)) +#else +#define att_const +#endif + +#if GCC_VERSION_ATLEAST(2, 96) +#define att_pure __attribute__((__pure__)) +#else +#define att_pure +#endif + +#if GCC_VERSION_ATLEAST(3, 0) +#define att_malloc __attribute__((__malloc__)) +#else +#define att_malloc +#endif + +#if GCC_VERSION_ATLEAST(3, 4) +#define att_warn_unused_result __attribute__((__warn_unused_result__)) +#else +#define att_warn_unused_result +#endif + +#if GCC_VERSION_ATLEAST(4, 3) +#define att_hot __attribute__((__hot__)) +#define att_cold __attribute__((__cold__)) +#else +#define att_hot +#define att_cold +#endif + +#if GCC_VERSION_ATLEAST(4, 3) +#define att_alloc(x) __attribute__((alloc_size(x))) +#define att_calloc(x,y) __attribute__((alloc_size(x,y))) +#else +#define att_alloc +#define att_calloc +#endif + +#if GCC_VERSION_ATLEAST(10, 0) +#define att_read(argno_ptr) __attribute__((access(read_only, argno_ptr))) +#define att_readn(argno_ptr, argno_size) __attribute__((access(read_only, argno_ptr, argno_size))) +#define att_write(argno_ptr) __attribute__((access(write_only, argno_ptr))) +#define att_writen(argno_ptr, argno_size) __attribute__((access(write_only, argno_ptr, argno_size))) +#define att_mangle(argno_ptr) __attribute__((access(read_write, argno_ptr))) +#define att_manglen(argno_ptr, argno_size) __attribute__((access(read_write, argno_ptr, argno_size))) +#else +#define att_read(argno_ptr) +#define att_readn(argno_ptr, argno_size) +#define att_write(argno_ptr) +#define att_writen(argno_ptr, argno_size) +#define att_mangle(argno_ptr) +#define att_manglen(argno_ptr, argno_size) +#endif + +#if GCC_VERSION_ATLEAST(3, 2) +#define att_dontuse __attribute__((__deprecated__)) +#else +#define att_dontuse +#endif + +#if GCC_VERSION_ATLEAST(3, 3) +#define att_nonnull(params) __attribute__((__nonnull__(params))) +#else +#define att_nonnull(params)l +#endif + +#if GCC_VERSION_ATLEAST(4, 3) +#define att_warn(message) __attribute__((__warning__(message))) +#define att_error(message) __attribute__((__warning__(message))) +#else +#define att_warn(message) +#define att_error(message) +#endif + +#ifndef __GNUC__ +#define __builtin_constant_p(x) 0 +#endif + +#endif diff --git a/compiletimeassert.h b/compiletimeassert.h index 2b71aa8..b21e9c3 100644 --- a/compiletimeassert.h +++ b/compiletimeassert.h @@ -1,11 +1,17 @@ -#if __STDC_VERSION__ >= 201710L +#ifdef __clang__ -#define compiletimeassert(cond) _Static_assert(cond) +// clang already includes the condition in the error message and emits +// an additional warning here if we use the variant without message +#define compiletimeassert(cond) _Static_assert(cond,"") + +#elif __STDC_VERSION__ >= 201710L + +#define compiletimeassert(cond) _Static_assert(cond,#cond) #elif __STDC_VERSION__ >= 201112L -#define compiletimeassert(cond) _Static_assert(cond,"") +#define compiletimeassert(cond) _Static_assert(cond,#cond) #else diff --git a/critbit.h b/critbit.h index f9ceb3c..dfd5a68 100644 --- a/critbit.h +++ b/critbit.h @@ -5,23 +5,23 @@ extern "C" { #endif -/* for __pure__ if we are compiling under dietlibc */ -#include - -#ifndef __pure__ -#define __pure__ -#endif +#include typedef struct { void *root; } critbit0_tree; -int critbit0_contains(critbit0_tree *t, const char *u) __pure__; -int critbit0_insert(critbit0_tree *t, const char *u); -int critbit0_delete(critbit0_tree *t, const char *u); -void critbit0_clear(critbit0_tree *t); +att_pure +int critbit0_contains(critbit0_tree *t, const char *u) noexcept; + +int critbit0_insert(critbit0_tree *t, const char *u) noexcept; + +int critbit0_delete(critbit0_tree *t, const char *u) noexcept; + +void critbit0_clear(critbit0_tree *t) noexcept; + int critbit0_allprefixed(critbit0_tree *t, const char *prefix, - int (*handle) (const char *, void *), void *arg); + int (*handle) (const char *, void *), void *arg) noexcept; #ifdef __cplusplus }; diff --git a/dns.h b/dns.h index 4fd75a5..587695b 100644 --- a/dns.h +++ b/dns.h @@ -2,9 +2,9 @@ #ifndef DNS_H #define DNS_H -#include "stralloc.h" -#include "iopause.h" -#include "taia.h" +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/fmt.h b/fmt.h index 7c0858d..648f7fd 100644 --- a/fmt.h +++ b/fmt.h @@ -13,16 +13,13 @@ #include #endif /* for byte_copy */ -#include "byte.h" +#include +#include #ifdef __cplusplus extern "C" { #endif -#ifndef __pure__ -#define __pure__ -#endif - #define FMT_LONG 41 /* enough space to hold -2^127 in decimal, plus \0 */ #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ #define FMT_8LONG 44 /* enough space to hold 2^128 - 1 in octal, plus \0 */ @@ -50,31 +47,38 @@ extern "C" { /* convert signed src integer -23 to ASCII '-','2','3', return number of * bytes of value in output format (3 in this example). * If dest is not NULL, write result to dest */ -size_t fmt_long(char *dest,signed long src) __pure__; +att_write(1) +size_t fmt_long(char *dest,signed long src) noexcept; /* convert unsigned src integer 23 to ASCII '2','3', return number of * bytes of value in output format (2 in this example). * If dest is not NULL, write result to dest */ -size_t fmt_ulong(char *dest,unsigned long src) __pure__; +att_write(1) +size_t fmt_ulong(char *dest,unsigned long src) noexcept; /* convert unsigned src integer 0x23 to ASCII '2','3', return number of * bytes of value in output format (2 in this example). * If dest is not NULL, write result to dest */ -size_t fmt_xlong(char *dest,unsigned long src) __pure__; +att_write(1) +size_t fmt_xlong(char *dest,unsigned long src) noexcept; /* convert unsigned src integer 023 to ASCII '2','3', return number of * bytes of value in output format (2 in this example). * If dest is not NULL, write result to dest */ -size_t fmt_8long(char *dest,unsigned long src) __pure__; +att_write(1) +size_t fmt_8long(char *dest,unsigned long src) noexcept; /* like fmt_long but for long long */ -size_t fmt_longlong(char *dest,signed long long src) __pure__; +att_write(1) +size_t fmt_longlong(char *dest,signed long long src) noexcept; /* like fmt_ulong but for unsigned long long */ -size_t fmt_ulonglong(char *dest,unsigned long long src) __pure__; +att_write(1) +size_t fmt_ulonglong(char *dest,unsigned long long src) noexcept; /* like fmt_xlong but for unsigned long long */ -size_t fmt_xlonglong(char *dest,unsigned long long src) __pure__; +att_write(1) +size_t fmt_xlonglong(char *dest,unsigned long long src) noexcept; #define fmt_uint(dest,src) fmt_ulong(dest,src) #define fmt_int(dest,src) fmt_long(dest,src) @@ -85,22 +89,26 @@ size_t fmt_xlonglong(char *dest,unsigned long long src) __pure__; * Does not truncate! */ /* fmt_ulong0(buf,23,4) -> '0','0','2','3' return 4 */ /* fmt_ulong0(buf,234,2) -> '2','3','4', return 3 */ -size_t fmt_ulong0(char *,unsigned long src,size_t padto) __pure__; +att_write(1) +size_t fmt_ulong0(char *,unsigned long src,size_t padto) noexcept; #define fmt_uint0(buf,src,padto) fmt_ulong0(buf,src,padto) /* convert src double 1.7 to ASCII '1','.','7', return length. * If dest is not NULL, write result to dest */ -size_t fmt_double(char *dest, double d,int max,int prec) __pure__; +att_write(1) +size_t fmt_double(char *dest, double d,int max,int prec) noexcept; /* if src is negative, write '-' and return 1. * if src is positive, write '+' and return 1. * otherwise return 0 */ -size_t fmt_plusminus(char *dest,int src) __pure__; +att_write(1) +size_t fmt_plusminus(char *dest,int src) noexcept; /* if src is negative, write '-' and return 1. * otherwise return 0. */ -size_t fmt_minus(char *dest,int src) __pure__; +att_write(1) +size_t fmt_minus(char *dest,int src) noexcept; /* copy str to dest until \0 byte, return number of copied bytes. */ /* fmt_str(NULL,str) == strlen(str) */ @@ -112,13 +120,17 @@ size_t fmt_minus(char *dest,int src) __pure__; * This is more efficient because strcat needs to scan the string to * find the end and append. */ -size_t fmt_str(char *dest,const char *src) __pure__; +att_write(1) +size_t fmt_str(char *dest,const char *src) noexcept; /* copy str to dest until \0 byte or limit bytes copied. * return number of copied bytes. */ -size_t fmt_strn(char *dest,const char *src,size_t limit) __pure__; +att_writen(1,3) +att_readn(2,3) +size_t fmt_strn(char *dest,const char *src,size_t limit) noexcept; /* copy n bytes from src to dest, return n */ +att_writen(1,3) static inline size_t fmt_copybytes(char* dest,const char* src,size_t n) { if (dest) byte_copy(dest,n,src); return n; @@ -135,59 +147,103 @@ static inline size_t fmt_copybytes(char* dest,const char* src,size_t n) { * write padlen-srclen spaces, if that is >= 0. Then copy srclen * characters from src. Truncate only if total length is larger than * maxlen. Return number of characters written. */ -size_t fmt_pad(char* dest,const char* src,size_t srclen,size_t padlen,size_t maxlen) __pure__; +att_writen(1,5) +att_readn(2,3) +size_t fmt_pad(char* dest,const char* src,size_t srclen,size_t padlen,size_t maxlen) noexcept; /* "foo" -> "foo " * append padlen-srclen spaces after dest, if that is >= 0. Truncate * only if total length is larger than maxlen. Return number of * characters written. */ -size_t fmt_fill(char* dest,size_t srclen,size_t padlen,size_t maxlen) __pure__; +att_writen(1,4) +size_t fmt_fill(char* dest,size_t srclen,size_t padlen,size_t maxlen) noexcept; /* 1 -> "1", 4900 -> "4.9k", 2300000 -> "2.3M" */ -size_t fmt_human(char* dest,unsigned long long l) __pure__; +att_write(1) +size_t fmt_human(char* dest,unsigned long long l) noexcept; /* 1 -> "1", 4900 -> "4.8k", 2300000 -> "2.2M" */ -size_t fmt_humank(char* dest,unsigned long long l) __pure__; +att_write(1) +size_t fmt_humank(char* dest,unsigned long long l) noexcept; /* "Sun, 06 Nov 1994 08:49:37 GMT" */ -size_t fmt_httpdate(char* dest,time_t t); /* not marked pure because it calls gmtime */ +att_write(1) +size_t fmt_httpdate(char* dest,time_t t) noexcept; /* not marked pure because it calls gmtime */ /* "2014-05-27T19:22:16.247Z" */ -size_t fmt_iso8601(char* dest,time_t t) __pure__; +att_write(1) +size_t fmt_iso8601(char* dest,time_t t) noexcept; #define FMT_UTF8 5 #define FMT_ASN1LENGTH 17 /* enough space to hold 2^128-1 */ #define FMT_ASN1TAG 19 /* enough space to hold 2^128-1 */ /* some variable length encodings for integers */ -size_t fmt_utf8(char* dest,uint32_t n) __pure__; /* can store 0-0x7fffffff */ -size_t fmt_utf8_scratch(char* dest,uint32_t n) __pure__; /* same, but is allowed to overwrite up to 7 additional bytes */ -size_t fmt_asn1derlength(char* dest,unsigned long long l) __pure__; /* 0-0x7f: 1 byte, above that 1+bytes_needed bytes */ -size_t fmt_asn1derlength_scratch(char* dest,unsigned long long l) __pure__; /* same, but is allowed to overwrite up to 7 additional bytes */ -size_t fmt_asn1dertag(char* dest,unsigned long long l) __pure__; /* 1 byte for each 7 bits; upper bit = more bytes coming */ -size_t fmt_asn1dertag_scratch(char* dest,unsigned long long l) __pure__;/* same, but is allowed to overwrite up to 7 additional bytes */ +att_write(1) +size_t fmt_utf8(char* dest,uint32_t n) noexcept; /* can store 0-0x7fffffff */ + +att_write(1) +size_t fmt_utf8_scratch(char* dest,uint32_t n) noexcept; /* same, but is allowed to overwrite up to 7 additional bytes */ + +att_write(1) +size_t fmt_asn1derlength(char* dest,unsigned long long l) noexcept; /* 0-0x7f: 1 byte, above that 1+bytes_needed bytes */ + +att_write(1) +size_t fmt_asn1derlength_scratch(char* dest,unsigned long long l) noexcept; /* same, but is allowed to overwrite up to 7 additional bytes */ + +att_write(1) +size_t fmt_asn1dertag(char* dest,unsigned long long l) noexcept; /* 1 byte for each 7 bits; upper bit = more bytes coming */ + +att_write(1) +size_t fmt_asn1dertag_scratch(char* dest,unsigned long long l) noexcept;/* same, but is allowed to overwrite up to 7 additional bytes */ /* Google Protocol Buffers, https://developers.google.com/protocol-buffers/docs/encoding */ -size_t fmt_varint(char* dest,unsigned long long l) __pure__; /* protocol buffers encoding; like asn1dertag but little endian */ -size_t fmt_pb_tag(char* dest,size_t fieldno,unsigned char type) __pure__; /* protocol buffer tag */ -size_t fmt_pb_type0_int(char* dest,unsigned long long l) __pure__; /* protocol buffers encoding: type 0 bool/enum/int32/uint32/int64/uint64 */ -size_t fmt_pb_type0_sint(char* dest,signed long long l) __pure__;/* protocol buffers encoding: type 0 sint32/sint64 */ -size_t fmt_pb_type1_double(char* dest,double d) __pure__; /* protocol buffers encoding: double (64-bit little endian blob) */ -size_t fmt_pb_type1_fixed64(char* dest,uint64_t l) __pure__; /* protocol buffers encoding: 64-bit little endian blob */ +att_write(1) +size_t fmt_varint(char* dest,unsigned long long l) noexcept; /* protocol buffers encoding; like asn1dertag but little endian */ + +att_write(1) +size_t fmt_pb_tag(char* dest,size_t fieldno,unsigned char type) noexcept; /* protocol buffer tag */ + +att_write(1) +size_t fmt_pb_type0_int(char* dest,unsigned long long l) noexcept; /* protocol buffers encoding: type 0 bool/enum/int32/uint32/int64/uint64 */ + +att_write(1) +size_t fmt_pb_type0_sint(char* dest,signed long long l) noexcept;/* protocol buffers encoding: type 0 sint32/sint64 */ + +att_write(1) +size_t fmt_pb_type1_double(char* dest,double d) noexcept; /* protocol buffers encoding: double (64-bit little endian blob) */ + +att_write(1) +size_t fmt_pb_type1_fixed64(char* dest,uint64_t l) noexcept; /* protocol buffers encoding: 64-bit little endian blob */ /* fmt_pb_type2_string can return 0 if (s,l) is clearly invalid */ -size_t fmt_pb_type2_string(char* dest,const char* s,size_t l) __pure__; /* protocol buffers encoding: varint length + blob */ -size_t fmt_pb_type5_float(char* dest,float f) __pure__; /* protocol buffers encoding: float (32-bit little endian blob) */ -size_t fmt_pb_type5_fixed32(char* dest,uint32_t l) __pure__; /* protocol buffers encoding: 32-bit little endian blob */ +att_write(1) +size_t fmt_pb_type2_string(char* dest,const char* s,size_t l) noexcept; /* protocol buffers encoding: varint length + blob */ + +att_write(1) +size_t fmt_pb_type5_float(char* dest,float f) noexcept; /* protocol buffers encoding: float (32-bit little endian blob) */ + +att_write(1) +size_t fmt_pb_type5_fixed32(char* dest,uint32_t l) noexcept; /* protocol buffers encoding: 32-bit little endian blob */ + +att_write(1) +size_t fmt_pb_int(char* dest,size_t fieldno,unsigned long long l) noexcept; -size_t fmt_pb_int(char* dest,size_t fieldno,unsigned long long l) __pure__; -size_t fmt_pb_sint(char* dest,size_t fieldno,signed long long l) __pure__; -size_t fmt_pb_double(char* dest,size_t fieldno,double d) __pure__; -size_t fmt_pb_float(char* dest,size_t fieldno,float f) __pure__; -size_t fmt_pb_string(char* dest,size_t fieldno,const char* s,size_t l) __pure__; +att_write(1) +size_t fmt_pb_sint(char* dest,size_t fieldno,signed long long l) noexcept; + +att_write(1) +size_t fmt_pb_double(char* dest,size_t fieldno,double d) noexcept; + +att_write(1) +size_t fmt_pb_float(char* dest,size_t fieldno,float f) noexcept; + +att_writen(1,4) +size_t fmt_pb_string(char* dest,size_t fieldno,const char* s,size_t l) noexcept; /* fmt_netstring can return 0 if (src,len) is clearly invalid */ -size_t fmt_netstring(char* dest,const char* src,size_t len) __pure__; +att_writen(1,3) +size_t fmt_netstring(char* dest,const char* src,size_t len) noexcept; /* Marshaling helper functions. * Escape one character, no matter if it needs escaping or not. @@ -199,27 +255,36 @@ size_t fmt_netstring(char* dest,const char* src,size_t len) __pure__; * unicode codepoint) may be limited to 0x7f, 0xff or 0x10ffff. */ /* XML escaping: '&' -> '&', '<' -> '<', 'ö' -> 'ö' */ -size_t fmt_escapecharxml(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharxml(char* dest,uint32_t ch) noexcept; + /* HTML escaping is the same as XML escaping. */ -size_t fmt_escapecharhtml(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharhtml(char* dest,uint32_t ch) noexcept; /* JSON escaping: '\' -> '\\', '"' -> '\"', 'ö' -> '\u00f6' */ -size_t fmt_escapecharjson(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharjson(char* dest,uint32_t ch) noexcept; /* MIME quoted-printable escaping: 'ö' -> '=f6', characters > 0xff not supported */ -size_t fmt_escapecharquotedprintable(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharquotedprintable(char* dest,uint32_t ch) noexcept; /* MIME quoted-printable escaping with UTF-8: 'ö' -> '=c3=b6', characters > 0x7fffffff not supported */ -size_t fmt_escapecharquotedprintableutf8(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharquotedprintableutf8(char* dest,uint32_t ch) noexcept; /* C99 style escaping: '\' -> '\\', newline -> '\n', 0xc2 -> '\302' */ -size_t fmt_escapecharc(char* dest,uint32_t ch) __pure__; +att_write(1) +size_t fmt_escapecharc(char* dest,uint32_t ch) noexcept; /* internal functions, may be independently useful */ -char fmt_tohex(char c) __attribute__((__const__)); +att_const +char fmt_tohex(char c); #define fmt_strm(b,...) fmt_strm_internal(b,__VA_ARGS__,(char*)0) -size_t fmt_strm_internal(char* dest,...) __pure__; +att_write(1) +size_t fmt_strm_internal(char* dest,...) noexcept; #ifndef MAX_ALLOCA #define MAX_ALLOCA 100000 diff --git a/iarray.h b/iarray.h index 7a72201..d697b09 100644 --- a/iarray.h +++ b/iarray.h @@ -9,7 +9,7 @@ * - the compiler supports it via __sync_val_compare_and_swap */ -#include "uint64.h" +#include #include #ifdef _WIN32 #include diff --git a/io.h b/io.h index 02b2dc7..1f52a21 100644 --- a/io.h +++ b/io.h @@ -4,8 +4,9 @@ /* http://cr.yp.to/lib/io.html */ -#include "uint64.h" -#include "taia.h" +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -13,33 +14,52 @@ extern "C" { /* like open(s,O_RDONLY) */ /* return 1 if ok, 0 on error */ -int io_readfile(int64* d,const char* s); +att_read(2) +att_write(1) +int io_readfile(int64* d,const char* filename); + /* like open(s,O_WRONLY|O_CREAT|O_TRUNC,0600) */ /* return 1 if ok, 0 on error */ -int io_createfile(int64* d,const char* s); +att_read(2) +att_write(1) +int io_createfile(int64* d,const char* filename); + /* like open(s,O_RDWR) */ /* return 1 if ok, 0 on error */ -int io_readwritefile(int64* d,const char* s); +att_read(2) +att_write(1) +int io_readwritefile(int64* d,const char* filename); + /* like open(s,O_WRONLY|O_APPEND|O_CREAT,0600) */ /* return 1 if ok, 0 on error */ -int io_appendfile(int64* d,const char* s); +att_read(2) +att_write(1) +int io_appendfile(int64* d,const char* filename); + /* like pipe(d) */ /* return 1 if ok, 0 on error */ +att_write(1) int io_pipe(int64* d); + /* like socketpair() */ /* return 1 if ok, 0 on error */ +att_write(1) int io_socketpair(int64* d); /* non-blocking read(), -1 for EAGAIN and -3+errno for other errors */ +att_writen(2, 3) int64 io_tryread(int64 d,char* buf,int64 len); /* blocking read(), with -3 instead of -1 for errors */ +att_writen(2, 3) int64 io_waitread(int64 d,char* buf,int64 len); /* non-blocking write(), -1 for EAGAIN and -3+errno for other errors */ +att_readn(2, 3) int64 io_trywrite(int64 d,const char* buf,int64 len); /* blocking write(), with -3 instead of -1 for errors */ +att_readn(2, 3) int64 io_waitwrite(int64 d,const char* buf,int64 len); /* modify timeout attribute of file descriptor */ @@ -47,10 +67,12 @@ void io_timeout(int64 d,tai6464 t); /* like io_tryread but will return -2,errno=ETIMEDOUT if d has a timeout * associated and it is passed without input being there */ +att_writen(2, 3) int64 io_tryreadtimeout(int64 d,char* buf,int64 len); /* like io_trywrite but will return -2,errno=ETIMEDOUT if d has a timeout * associated and it is passed without being able to write */ +att_readn(2, 3) int64 io_trywritetimeout(int64 d,const char* buf,int64 len); void io_wantread(int64 d); @@ -95,7 +117,9 @@ int io_fd(int64 d); /* use this for sockets before you called connect() or acce int io_fd_canwrite(int64 d); /* use this for connected sockets (assumes socket is writable) */ int io_fd_flags(int64 d,int flags); /* can be used to tell io_fd to skip one syscall */ +att_write(2) void io_setcookie(int64 d,void* cookie); + void* io_getcookie(int64 d); /* put descriptor in non-blocking mode */ @@ -128,9 +152,11 @@ int64 io_receivefd(int64 sock); int io_starteventloopthread(unsigned int threads); #define HAVE_IO_QUEUEFORREAD + /* Artificially queue a file descriptor as readable. * The next call to io_canread will return this descriptor. */ int io_queueforread(int64 d); + /* Artificially queue a file descriptor as writable. * The next call to io_canread will return this descriptor. */ int io_queueforwrite(int64 d); diff --git a/io/io_appendfile.3 b/io/io_appendfile.3 index c246f72..31ab216 100644 --- a/io/io_appendfile.3 +++ b/io/io_appendfile.3 @@ -4,10 +4,10 @@ io_appendfile \- open a file for appending .SH SYNTAX .B #include -int \fBio_appendfile\fP(int64* d,const char* s); +int \fBio_appendfile\fP(int64* d,const char* filename); .SH DESCRIPTION io_appendfile sets d to the number of a new descriptor writing to the -end of the disk file named \fIs\fR, and returns 1. If the file does not +end of the disk file named \fIfilename\fR, and returns 1. If the file does not exist, it will be created with mode 0600. If something goes wrong, io_appendfile sets \fIerrno\fR to indicate the error, and diff --git a/io/io_createfile.3 b/io/io_createfile.3 index 692bf44..d7ff471 100644 --- a/io/io_createfile.3 +++ b/io/io_createfile.3 @@ -4,10 +4,10 @@ io_createfile \- create a file .SH SYNTAX .B #include -int \fBio_createfile\fP(int64* d,const char* s); +int \fBio_createfile\fP(int64* d,const char* filename); .SH DESCRIPTION io_createfile sets d to the number of a new descriptor writing to the disk file -named \fIs\fR, and returns 1. If \fIs\fR already existed, it is truncated to length 0; +named \fIs\fR, and returns 1. If \fIfilename\fR already existed, it is truncated to length 0; otherwise, it is created, with mode 0600. If something goes wrong, io_createfile sets \fIerrno\fR to indicate the error, and diff --git a/io/io_readfile.3 b/io/io_readfile.3 index 437b4a1..c355562 100644 --- a/io/io_readfile.3 +++ b/io/io_readfile.3 @@ -4,10 +4,10 @@ io_readfile \- open a file for reading .SH SYNTAX .B #include -int \fBio_readfile\fP(int64* d,const char* s); +int \fBio_readfile\fP(int64* d,const char* filename); .SH DESCRIPTION io_readfile sets d to the number of a new descriptor reading from the -disk file named \fIs\fR, and returns 1. +disk file named \fIfilename\fR, and returns 1. If something goes wrong, io_readfile sets \fIerrno\fR to indicate the error, and returns 0; it does not create a new descriptor, and it does not touch d. diff --git a/io/io_readwritefile.3 b/io/io_readwritefile.3 index bffc87e..3310a57 100644 --- a/io/io_readwritefile.3 +++ b/io/io_readwritefile.3 @@ -4,10 +4,10 @@ io_readfile \- open a file for reading and writing .SH SYNTAX .B #include -int \fBio_readwritefile\fP(int64* d,const char* s); +int \fBio_readwritefile\fP(int64* d,const char* filename); .SH DESCRIPTION io_readwritefile sets d to the number of a new descriptor reading from -and writing to the disk file named \fIs\fR, and returns 1. The file +and writing to the disk file named \fIfilename\fR, and returns 1. The file needs to exist. If something goes wrong, io_readwritefile sets \fIerrno\fR to indicate the error, and diff --git a/iob.h b/iob.h index 2dcff21..e04d579 100644 --- a/iob.h +++ b/iob.h @@ -13,8 +13,9 @@ * frames as possible. On Linux it will also use the TCP_CORK socket * option. */ -#include "libowfat/io.h" -#include "libowfat/array.h" +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -27,10 +28,20 @@ typedef struct io_batch { } io_batch; io_batch* iob_new(int hint_entries); + +att_readn(2,3) int iob_addbuf(io_batch* b,const void* buf,uint64 n); + +att_readn(2,3) int iob_addbuf_free(io_batch* b,const void* buf,uint64 n); + +att_readn(2,3) int iob_addbuf_munmap(io_batch* b,const void* buf,uint64 n); + +att_read(2) int iob_adds(io_batch* b,const char* s); + +att_read(2) int iob_adds_free(io_batch* b,const char* s); int iob_addfile(io_batch* b,int64 fd,uint64 off,uint64 n); int iob_addfile_close(io_batch* b,int64 fd,uint64 off,uint64 n); diff --git a/ip6.h b/ip6.h index c85cfa1..39db80e 100644 --- a/ip6.h +++ b/ip6.h @@ -2,8 +2,8 @@ #ifndef IP6_H #define IP6_H -#include "byte.h" -#include "uint32.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/open.h b/open.h index 045f0e3..76f7aaa 100644 --- a/open.h +++ b/open.h @@ -6,11 +6,15 @@ extern "C" { #endif +#include + /* open filename for reading and return the file handle or -1 on error */ +att_read(1) int open_read(const char* filename); /* create filename for exclusive write only use (mode 0600) and return * the file handle or -1 on error */ +att_read(1) int open_excl(const char* filename); /* open filename for appending write only use (mode 0600) @@ -18,19 +22,23 @@ int open_excl(const char* filename); * All write operation will append after the last byte, regardless of * seeking or other processes also appending to the file. The file will * be created if it does not exist. */ +att_read(1) int open_append(const char* filename); /* open filename for writing (mode 0644). Create the file if it does * not exist, truncate it to zero length otherwise. Return the file * handle or -1 on error. */ +att_read(1) int open_trunc(const char* filename); /* open filename for writing. Create the file if it does not exist. * Return the file handle or -1 on error. */ +att_read(1) int open_write(const char* filename); /* open filename for reading and writing. Create file if not there. * Return file handle or -1 on error. */ +att_read(1) int open_rw(const char* filename); #ifdef __cplusplus diff --git a/openreadclose.h b/openreadclose.h index c30daad..9aa8321 100644 --- a/openreadclose.h +++ b/openreadclose.h @@ -2,12 +2,14 @@ #ifndef OPENREADCLOSE_H #define OPENREADCLOSE_H -#include "stralloc.h" +#include +#include #ifdef __cplusplus extern "C" { #endif +att_read(1) int openreadclose(const char *filename,stralloc *buf,size_t initiallength); #ifdef __cplusplus diff --git a/parse.h b/parse.h index b82a44a..5e5186a 100644 --- a/parse.h +++ b/parse.h @@ -7,6 +7,8 @@ /* for uint32_t: */ #include +#include + #include #include @@ -63,11 +65,20 @@ struct bytestream { } u; }; +att_write(1) +att_read(2) void bs_init_membuf(struct bytestream* bs,const unsigned char* membuf,size_t len); +att_write(1) +att_mangle(2) void bs_init_iobuf(struct bytestream* bs,struct buffer* b); + +att_write(1) +att_mangle(2) void bs_init_iobuf_size(struct bytestream* bs,struct buffer* b,size_t maxlen); +att_write(1) +att_mangle(2) void bs_init_bstream_size(struct bytestream* bs,struct bytestream* parent,size_t maxlen); #define BS_FROM_MEMBUF(buf,len) { .type=MEMBUF, .max=(len), .u.base=(const unsigned char*)(buf) } @@ -75,51 +86,80 @@ void bs_init_bstream_size(struct bytestream* bs,struct bytestream* parent,size_t #define BS_FROM_BUFFER_SIZE(buffer,len) { .type=IOBUF, .max=(len), u.b=(buffer) } /* return next byte from stream or 0 if EOF or read error. */ +att_mangle(1) unsigned char bs_get(struct bytestream* bs); /* like bs_get but do not advance position in stream. */ +// This is NOT read-only because it sets bs to error state if it hits EOF +att_mangle(1) unsigned char bs_peek(struct bytestream* bs); /* was there a read error or did we attempt to read more than maxlen bytes? */ -int bs_err(struct bytestream* bs); +att_pure +att_read(1) +int bs_err(const struct bytestream* bs); /* mark bytestream as erroneous */ +att_mangle(1) void bs_seterrorstate(struct bytestream* b); /* Can we read this much more bytes from the bytestream? */ /* returns 1 for yes, 0 for no */ +att_pure +att_read(1) int bs_capacitycheck(struct bytestream* bs,size_t capacity); + /* Like bs_capacitycheck but will set stream to error state on fail */ +att_pure +att_mangle(1) int bs_capacityassert(struct bytestream* bs,size_t capacity); /* Return number of bytes left before limit, or 0 on error. */ /* If the backend is an iobuf without limit, return max size_t value. */ -size_t bs_capacityleft(struct bytestream* bs); +att_pure +att_read(1) +size_t bs_capacityleft(const struct bytestream* bs); /* Assert there are no more bytes left in a bytestream. */ /* Useful to make sure that you parsed the whole packet * and there were no slack bytes in the end. * Return 1 if there really were no more bytes in the stream. * If there ARE bytes left, will set error flag in stream and return 0 */ +att_mangle(1) int bs_nomoredataassert(struct bytestream* bs); /* Consume all bytes left before limit */ /* Useful for nested structs or when the backing store is an iobuf */ /* Return number of bytes consumed */ +att_mangle(1) size_t bs_consumeleftovers(struct bytestream* bs); /* Skip n bytes, return number skipped (or 0 if error) */ +att_mangle(1) size_t bs_skip(struct bytestream* bs, size_t n); /* Read n bytes from stream. Return n. * Set stream to error state if not enough space or I/O error. */ +att_mangle(1) +att_writen(2,3) ssize_t prs_readblob(struct bytestream* bs,unsigned char* dest,size_t destlen); +att_mangle(1) uint16_t prs_u16(struct bytestream* bs); + +att_mangle(1) uint16_t prs_u16_big(struct bytestream* bs); + +att_mangle(1) uint32_t prs_u32(struct bytestream* bs); + +att_mangle(1) uint32_t prs_u32_big(struct bytestream* bs); + +att_mangle(1) uint64_t prs_u64(struct bytestream* bs); + +att_mangle(1) uint64_t prs_u64_big(struct bytestream* bs); /* Read an asciiz string from the byte stream, up to len bytes (including the 0 terminator). */ @@ -127,6 +167,8 @@ uint64_t prs_u64_big(struct bytestream* bs); /* If there is no 0 byte in these len bytes, set error flag in stream and return -1. */ /* Calling this function with destsize==0 is an error. */ /* destsize will be clamped to the maximum number representable in ssize_t */ +att_mangle(1) +att_writen(2, 3) ssize_t prs_asciiz(struct bytestream* bs, char* dest, size_t destsize); /* Some protocols have a fixed field length for a string, @@ -137,6 +179,8 @@ ssize_t prs_asciiz(struct bytestream* bs, char* dest, size_t destsize); * For a field of length 8, you need to pass destsize as 9 so we can add * a 0 terminator. This function will consume the 8 bytes and add a 0 byte. * The return value is strlen(dest). */ +att_mangle(1) +att_writen(2, 3) ssize_t prs_asciiz_fixedlen(struct bytestream* bs, char* dest, size_t destsize); #ifdef __cplusplus diff --git a/rangecheck.h b/rangecheck.h index f15ed14..ec56621 100644 --- a/rangecheck.h +++ b/rangecheck.h @@ -5,6 +5,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -105,16 +107,20 @@ __static inline __gnuinline int range_bufinbuf(const void* buf1,size_t len1,cons /* does an array of "elements" members of size "membersize" starting at * "arraystart" lie inside buf1[0..len-1]? */ +att_const int range_arrayinbuf(const void* buf,size_t len, const void* arraystart,size_t elements,size_t membersize); /* does an ASCIIZ string starting at "ptr" lie in buf[0..len-1]? */ +att_const int range_strinbuf(const void* buf,size_t len,const void* stringstart); /* does an UTF-16 string starting at "ptr" lie in buf[0..len-1]? */ +att_const int range_str2inbuf(const void* buf,size_t len,const void* stringstart); /* does an UTF-32 string starting at "ptr" lie in buf[0..len-1]? */ +att_const int range_str4inbuf(const void* buf,size_t len,const void* stringstart); diff --git a/safemult.h b/safemult.h index a6f3417..acdbd42 100644 --- a/safemult.h +++ b/safemult.h @@ -2,9 +2,9 @@ #ifndef SAFEMULT_H #define SAFEMULT_H -#include "uint16.h" -#include "uint32.h" -#include "uint64.h" +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/scan.h b/scan.h index 9921405..37cb672 100644 --- a/scan.h +++ b/scan.h @@ -11,20 +11,12 @@ /* for struct timespec: */ #include +#include + #ifdef __cplusplus extern "C" { #endif -/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ -#ifndef __pure__ -#define __pure__ -#endif - -#ifndef __writememsz__ -#define __writememsz__(a,b) -#define __readmemsz__(a,b) -#endif - /* This file declares functions used to decode / scan / unmarshal * integer or string values from a buffer. * The first argument is always the source buffer, the second argument @@ -44,72 +36,90 @@ extern "C" { * 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); -__readmemsz__(1,2) -size_t scan_ulongn(const char* src,size_t n,unsigned long* dest); +att_read(1) att_write(2) +size_t scan_ulong(const char *src,unsigned long *dest) noexcept; +att_readn(1,2) att_write(3) +size_t scan_ulongn(const char* src,size_t n,unsigned long* dest) noexcept; /* 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); -__readmemsz__(1,2) -size_t scan_xlongn(const char *src,size_t n,unsigned long *dest); +att_read(1) att_write(2) +size_t scan_xlong(const char *src,unsigned long *dest) noexcept; +att_readn(1,2) att_write(3) +size_t scan_xlongn(const char *src,size_t n,unsigned long *dest) noexcept; /* interpret src as ASCII octal number, write number to dest and * return the number of bytes that were parsed. * Note: leading '+' or '-' not accepted! */ -size_t scan_8long(const char *src,unsigned long *dest); -__readmemsz__(1,2) -size_t scan_8longn(const char *src,size_t n,unsigned long *dest); +att_read(1) att_write(2) +size_t scan_8long(const char *src,unsigned long *dest) noexcept; +att_readn(1,2) att_write(3) +size_t scan_8longn(const char *src,size_t n,unsigned long *dest) noexcept; /* interpret src as signed ASCII decimal number, write number to dest * and return the number of bytes that were parsed. * Note: leading spaces not accepted! */ -size_t scan_long(const char *src,signed long *dest); -__readmemsz__(1,2) -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); -size_t scan_xlonglong(const char *src,unsigned long long *dest); -size_t scan_8longlong(const char *src,unsigned long long *dest); - -size_t scan_uint(const char *src,unsigned int *dest); -size_t scan_xint(const char *src,unsigned int *dest); -size_t scan_8int(const char *src,unsigned int *dest); -size_t scan_int(const char *src,signed int *dest); - -size_t scan_ushort(const char *src,unsigned short *dest); -size_t scan_xshort(const char *src,unsigned short *dest); -size_t scan_8short(const char *src,unsigned short *dest); -size_t scan_short(const char *src,signed short *dest); +att_read(1) att_write(2) +size_t scan_long(const char *src,signed long *dest) noexcept; +att_readn(1,2) att_write(3) +size_t scan_longn(const char *src,size_t n,signed long *dest) noexcept; + +att_read(1) att_write(2) +size_t scan_longlong(const char *src,signed long long *dest) noexcept; +att_read(1) att_write(2) +size_t scan_ulonglong(const char *src,unsigned long long *dest) noexcept; +att_read(1) att_write(2) +size_t scan_xlonglong(const char *src,unsigned long long *dest) noexcept; +att_read(1) att_write(2) +size_t scan_8longlong(const char *src,unsigned long long *dest) noexcept; + +att_read(1) att_write(2) +size_t scan_uint(const char *src,unsigned int *dest) noexcept; +att_read(1) att_write(2) +size_t scan_xint(const char *src,unsigned int *dest) noexcept; +att_read(1) att_write(2) +size_t scan_8int(const char *src,unsigned int *dest) noexcept; +att_read(1) att_write(2) +size_t scan_int(const char *src,signed int *dest) noexcept; + +att_read(1) att_write(2) +size_t scan_ushort(const char *src,unsigned short *dest) noexcept; +att_read(1) att_write(2) +size_t scan_xshort(const char *src,unsigned short *dest) noexcept; +att_read(1) att_write(2) +size_t scan_8short(const char *src,unsigned short *dest) noexcept; +att_read(1) att_write(2) +size_t scan_short(const char *src,signed short *dest) noexcept; /* interpret src as double precision floating point number, * write number to dest and return the number of bytes that were parsed */ -size_t scan_double(const char *in, double *dest); +att_read(1) att_write(2) +size_t scan_double(const char *in, double *dest) noexcept; /* if *src=='-', set *dest to -1 and return 1. * if *src=='+', set *dest to 1 and return 1. * otherwise set *dest to 1 return 0. */ -size_t scan_plusminus(const char *src,signed int *dest); +att_read(1) att_write(2) +size_t scan_plusminus(const char *src,signed int *dest) noexcept; /* return the highest integer n<=limit so that isspace(in[i]) for all 0<=i<=n */ -__readmemsz__(1,2) -size_t scan_whitenskip(const char *in,size_t limit) __pure__; +att_pure att_readn(1,2) +size_t scan_whitenskip(const char *in,size_t limit) noexcept; /* return the highest integer n<=limit so that !isspace(in[i]) for all 0<=i<=n */ -__readmemsz__(1,2) -size_t scan_nonwhitenskip(const char *in,size_t limit) __pure__; +att_pure att_readn(1,2) +size_t scan_nonwhitenskip(const char *in,size_t limit) noexcept; /* return the highest integer n<=limit so that in[i] is element of * charset (ASCIIZ string) for all 0<=i<=n */ -__readmemsz__(1,3) -size_t scan_charsetnskip(const char *in,const char *charset,size_t limit) __pure__; +att_pure att_readn(1,3) att_read(2) +size_t scan_charsetnskip(const char *in,const char *charset,size_t limit) noexcept; /* return the highest integer n<=limit so that in[i] is not element of * charset (ASCIIZ string) for all 0<=i<=n */ -__readmemsz__(1,3) -size_t scan_noncharsetnskip(const char *in,const char *charset,size_t limit) __pure__; +att_pure att_readn(1,3) att_read(2) +size_t scan_noncharsetnskip(const char *in,const char *charset,size_t limit) noexcept; /* try to parse ASCII GMT date; does not understand time zones. */ /* example dates: @@ -117,17 +127,23 @@ size_t scan_noncharsetnskip(const char *in,const char *charset,size_t limit) __p * "Sunday, 06-Nov-94 08:49:37 GMT" * "Sun Nov 6 08:49:37 1994" */ -size_t scan_httpdate(const char *in,time_t *t) __pure__; +att_read(1) att_write(2) +size_t scan_httpdate(const char *in,time_t *t) noexcept; /* try to parse ASCII ISO-8601 date; does not understand time zones. */ /* example date: "2014-05-27T19:22:16Z" */ -size_t scan_iso8601(const char* in,struct timespec* t) __pure__; +att_pure att_read(1) att_write(2) +size_t scan_iso8601(const char* in,struct timespec* t) noexcept; /* some variable length encodings for integers */ -size_t scan_utf8(const char* in,size_t len,uint32_t* n) __pure__; -size_t scan_utf8_sem(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__; +att_pure att_readn(1, 2) att_write(3) +size_t scan_utf8(const char* in,size_t len,uint32_t* n) noexcept; +att_pure att_readn(1, 2) att_write(3) +size_t scan_utf8_sem(const char* in,size_t len,uint32_t* n) noexcept; +att_pure att_readn(1, 2) att_write(3) +size_t scan_asn1derlength(const char* in,size_t len,unsigned long long* n) noexcept; +att_pure att_readn(1, 2) att_write(3) +size_t scan_asn1dertag(const char* in,size_t len,unsigned long long* n) noexcept; /* Google protocol buffers */ /* A protocol buffer is a sequence of (tag,value). @@ -136,15 +152,21 @@ size_t scan_asn1dertag(const char* in,size_t len,unsigned long long* n) __pure__ * 0, double type 1, strings type 2 and floats type 5. However, you * have to check this yourself. */ -size_t scan_varint(const char* in,size_t len, unsigned long long* n) __pure__; /* internal */ -size_t scan_pb_tag(const char* in,size_t len, size_t* fieldno,unsigned char* type) __pure__; +att_readn(1, 2) att_write(3) +size_t scan_varint(const char* in, size_t len, unsigned long long* n); /* internal */ +att_readn(1, 2) att_write(3) att_write(4) +size_t scan_pb_tag(const char* in, size_t len, size_t* fieldno,unsigned char* type); /* Then, depending on the field number, validate the type and call the * corresponding of these functions to parse the value */ -size_t scan_pb_type0_int(const char* in,size_t len,unsigned long long* l) __pure__; -size_t scan_pb_type0_sint(const char* in,size_t len,signed long long* l) __pure__; -size_t scan_pb_type1_double(const char* in,size_t len,double* d) __pure__; -size_t scan_pb_type1_fixed64(const char* in,size_t len,uint64_t* b) __pure__; +att_readn(1, 2) att_write(3) +size_t scan_pb_type0_int(const char* in,size_t len,unsigned long long* l); +att_readn(1, 2) att_write(3) +size_t scan_pb_type0_sint(const char* in,size_t len,signed long long* l); +att_readn(1, 2) att_write(3) +size_t scan_pb_type1_double(const char* in,size_t len,double* d); +att_readn(1, 2) att_write(3) +size_t scan_pb_type1_fixed64(const char* in,size_t len,uint64_t* b); /* NOTE: scan_pb_type2_stringlen only parses the length of the string, * not the string itself. It will return the number of bytes parsed in * the length, then set slen to the value of the length integer it just @@ -155,9 +177,12 @@ size_t scan_pb_type1_fixed64(const char* in,size_t len,uint64_t* b) __pure__; * parsing early without having to read and allocate memory for the rest * (potentially gigabytes) of the data announced by one unreasonable * string length value. */ -size_t scan_pb_type2_stringlen(const char* in,size_t len,const char** string, size_t* slen) __pure__; -size_t scan_pb_type5_float(const char* in,size_t len,float* f) __pure__; -size_t scan_pb_type5_fixed32(const char* in,size_t len,uint32_t* b) __pure__; +att_readn(1, 2) att_write(3) att_write(4) +size_t scan_pb_type2_stringlen(const char* in,size_t len,const char** string, size_t* slen); +att_readn(1, 2) att_write(3) +size_t scan_pb_type5_float(const char* in,size_t len,float* f); +att_readn(1, 2) att_write(3) +size_t scan_pb_type5_fixed32(const char* in,size_t len,uint32_t* b); /* parse a netstring, input buffer is in (len bytes). * if parsing is successful: @@ -167,11 +192,12 @@ size_t scan_pb_type5_fixed32(const char* in,size_t len,uint32_t* b) __pure__; * return 0 * Note: *dest will point inside the input buffer! */ -__readmemsz__(1,2) -size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen) __pure__; +att_readn(1, 2) att_write(3) att_write(4) +size_t scan_netstring(const char* in,size_t len,char** dest,size_t* slen); /* internal function that might be useful independently */ /* convert from hex ASCII, return 0 to 15 for success or -1 for failure */ +att_const int scan_fromhex(unsigned char c); #ifdef __cplusplus diff --git a/socket.h b/socket.h index 20b6f91..175674e 100644 --- a/socket.h +++ b/socket.h @@ -4,8 +4,9 @@ #include -#include "uint16.h" -#include "uint32.h" +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -38,12 +39,21 @@ int socket_bind6_reuse(int s,const char* ip,uint16 port,uint32 scope_id); int socket_listen(int s,unsigned int backlog); int socket_accept4(int s,char* ip,uint16* port); int socket_accept6(int s,char* ip,uint16* port,uint32* scope_id); + +att_writen(2,3) att_nonnull(2) ssize_t socket_recv4(int s,char* buf,size_t len,char* ip,uint16* port); +att_writen(2,3) att_nonnull(2) ssize_t socket_recv6(int s,char* buf,size_t len,char* ip,uint16* port,uint32* scope_id); + +att_readn(2,3) att_nonnull(2) ssize_t socket_send4(int s,const char* buf,size_t len,const char* ip,uint16 port); +att_readn(2,3) att_nonnull(2) ssize_t socket_send4_flag(int s,const char* buf,size_t len,const char* ip,uint16 port,int flags); +att_readn(2,3) att_nonnull(2) ssize_t socket_send6(int s,const char* buf,size_t len,const char* ip,uint16 port,uint32 scope_id); +att_readn(2,3) att_nonnull(2) ssize_t socket_send6_flag(int s,const char* buf,size_t len,const char* ip,uint16 port,uint32 scope_id,int flags); + int socket_local4(int s,char* ip,uint16* port); int socket_local6(int s,char* ip,uint16* port,uint32* scope_id); int socket_remote4(int s,char* ip,uint16* port); diff --git a/str.h b/str.h index 100a37b..71d728a 100644 --- a/str.h +++ b/str.h @@ -4,24 +4,24 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif -#ifndef __pure__ -#define __pure__ -#endif - /* str_copy copies leading bytes from in to out until \0. * return number of copied bytes. */ -size_t str_copy(char *out,const char *in); +att_write(1) att_read(2) +size_t str_copy(char *out,const char *in) noexcept; /* str_diff returns negative, 0, or positive, depending on whether the * string a[0], a[1], ..., a[n]=='\0' is lexicographically smaller than, * equal to, or greater than the string b[0], b[1], ..., b[m-1]=='\0'. * If the strings are different, str_diff does not read bytes past the * first difference. */ -int str_diff(const char *a,const char *b) __pure__; +att_pure att_read(1) att_read(2) +int str_diff(const char *a,const char *b) noexcept; /* str_diffn returns negative, 0, or positive, depending on whether the * string a[0], a[1], ..., a[n]=='\0' is lexicographically smaller than, @@ -29,24 +29,29 @@ int str_diff(const char *a,const char *b) __pure__; * If the strings are different, str_diffn does not read bytes past the * first difference. The strings will be considered equal if the first * limit characters match. */ -int str_diffn(const char *a,const char *b,size_t limit) __pure__; +att_pure att_read(1) att_read(2) +int str_diffn(const char *a,const char *b,size_t limit) noexcept; #ifdef __dietlibc__ #include #define str_len(foo) strlen(foo) #else /* str_len returns the index of \0 in s */ -size_t str_len(const char *s) __pure__; +att_pure att_read(1) +size_t str_len(const char *s) noexcept; #endif /* str_chr returns the index of the first occurance of needle or \0 in haystack */ -size_t str_chr(const char *haystack,char needle) __pure__; +att_pure att_read(1) +size_t str_chr(const char *haystack,char needle) noexcept; /* str_rchr returns the index of the last occurance of needle or \0 in haystack */ -size_t str_rchr(const char *haystack,char needle) __pure__; +att_pure att_read(1) +size_t str_rchr(const char *haystack,char needle) noexcept; /* str_start returns 1 if the b is a prefix of a, 0 otherwise */ -int str_start(const char *a,const char *b) __pure__; +att_pure att_read(1) att_read(2) +int str_start(const char *a,const char *b) noexcept; /* convenience shortcut to test for string equality */ #define str_equal(s,t) (!str_diff((s),(t))) diff --git a/stralloc.h b/stralloc.h index 18a3f8b..93e9f6e 100644 --- a/stralloc.h +++ b/stralloc.h @@ -4,20 +4,12 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif -/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ -#ifndef __pure__ -#define __pure__ -#endif - -#ifndef __writememsz__ -#define __writememsz__(a,b) -#define __readmemsz__(a,b) -#endif - /* stralloc is the internal data structure all functions are working on. * s is the string. * len is the used length of the string. @@ -33,7 +25,7 @@ typedef struct stralloc { /* stralloc_init will initialize a stralloc. * Previously allocated memory will not be freed; use stralloc_free for * that. To assign an empty string, use stralloc_copys(sa,""). */ -void stralloc_init(stralloc* sa); +void stralloc_init(stralloc* sa) noexcept; /* stralloc_ready makes sure that sa has enough space allocated to hold * len bytes: If sa is not allocated, stralloc_ready allocates at least @@ -42,53 +34,56 @@ void stralloc_init(stralloc* sa); * bytes of space, copies the old string into the new space, frees the * old space, and returns 1. Note that this changes sa.s. If the * allocation fails, stralloc_ready leaves sa alone and returns 0. */ -int stralloc_ready(stralloc* sa,size_t len); +int stralloc_ready(stralloc* sa,size_t len) noexcept; /* stralloc_readyplus is like stralloc_ready except that, if sa is * already allocated, stralloc_readyplus adds the current length of sa * to len. */ -int stralloc_readyplus(stralloc* sa,size_t len); +int stralloc_readyplus(stralloc* sa,size_t len) noexcept; /* stralloc_copyb copies the string buf[0], buf[1], ..., buf[len-1] into * sa, allocating space if necessary, and returns 1. If it runs out of * memory, stralloc_copyb leaves sa alone and returns 0. */ -__readmemsz__(2,3) -int stralloc_copyb(stralloc* sa,const char* buf,size_t len); +att_readn(2, 3) +int stralloc_copyb(stralloc* sa,const char* buf,size_t len) noexcept; /* stralloc_copys copies a \0-terminated string from buf into sa, * without the \0. It is the same as * stralloc_copyb(&sa,buf,str_len(buf)). */ -int stralloc_copys(stralloc* sa,const char* buf); +att_read(2) +int stralloc_copys(stralloc* sa,const char* buf) noexcept; /* stralloc_copy copies the string stored in sa2 into sa. It is the same * as stralloc_copyb(&sa,sa2.s,sa2.len). sa2 must already be allocated. */ -int stralloc_copy(stralloc* sa,const stralloc* sa2); +int stralloc_copy(stralloc* sa,const stralloc* sa2) noexcept; /* stralloc_catb adds the string buf[0], buf[1], ... buf[len-1] to the * end of the string stored in sa, allocating space if necessary, and * returns 1. If sa is unallocated, stralloc_catb is the same as * stralloc_copyb. If it runs out of memory, stralloc_catb leaves sa * alone and returns 0. */ -__readmemsz__(2,3) -int stralloc_catb(stralloc* sa,const char* in,size_t len); +att_readn(2, 3) +int stralloc_catb(stralloc* sa,const char* in,size_t len) noexcept; /* stralloc_cats is analogous to stralloc_copys */ -int stralloc_cats(stralloc* sa,const char* in); +att_read(2) +int stralloc_cats(stralloc* sa,const char* in) noexcept; -void stralloc_zero(stralloc* sa); +void stralloc_zero(stralloc* sa) noexcept; /* like stralloc_cats but can cat more than one string at once */ -int stralloc_catm_internal(stralloc* sa,...); +int stralloc_catm_internal(stralloc* sa,...) noexcept; #define stralloc_catm(sa,...) stralloc_catm_internal(sa,__VA_ARGS__,(char*)0) #define stralloc_copym(sa,...) (stralloc_zero(sa), stralloc_catm_internal(sa,__VA_ARGS__,(char*)0)) /* stralloc_cat is analogous to stralloc_copy */ -int stralloc_cat(stralloc* sa,const stralloc* in); +int stralloc_cat(stralloc* sa,const stralloc* in) noexcept; /* stralloc_append adds one byte in[0] to the end of the string stored * in sa. It is the same as stralloc_catb(&sa,in,1). */ -int stralloc_append(stralloc* sa,const char* in); /* beware: this takes a pointer to 1 char */ +att_read(2) +int stralloc_append(stralloc* sa,const char* in) noexcept; /* beware: this takes a pointer to 1 char */ #if 0 #define stralloc_APPEND(sa,in) \ @@ -109,17 +104,20 @@ static inline int stralloc_APPEND(stralloc* sa,const char* in) { /* stralloc_starts returns 1 if the \0-terminated string in "in", without * the terminating \0, is a prefix of the string stored in sa. Otherwise * it returns 0. sa must already be allocated. */ -int stralloc_starts(stralloc* sa,const char* in) __pure__; +att_pure att_read(2) +int stralloc_starts(stralloc* sa,const char* in) noexcept; /* stralloc_diff returns negative, 0, or positive, depending on whether * a is lexicographically smaller than, equal to, or greater than the * string b. */ -int stralloc_diff(const stralloc* a,const stralloc* b) __pure__; +att_pure +int stralloc_diff(const stralloc* a,const stralloc* b) noexcept; /* stralloc_diffs returns negative, 0, or positive, depending on whether * a is lexicographically smaller than, equal to, or greater than the * string b[0], b[1], ..., b[n]=='\0'. */ -int stralloc_diffs(const stralloc* a,const char* b) __pure__; +att_pure att_read(2) +int stralloc_diffs(const stralloc* a,const char* b) noexcept; #define stralloc_equal(a,b) (!stralloc_diff((a),(b))) #define stralloc_equals(a,b) (!stralloc_diffs((a),(b))) @@ -128,15 +126,15 @@ int stralloc_diffs(const stralloc* a,const char* b) __pure__; #define stralloc_0(sa) stralloc_append(sa,"") /* stralloc_catulong0 appends a '0' padded ASCII representation of in */ -int stralloc_catulong0(stralloc* sa,unsigned long int in,size_t n); +int stralloc_catulong0(stralloc* sa,unsigned long int in,size_t n) noexcept; /* stralloc_catlong0 appends a '0' padded ASCII representation of in */ /* note that the n does not include the sign: * stralloc_catlong0(&sa,-10,4) -> "-0010" */ -int stralloc_catlong0(stralloc* sa,signed long int in,size_t n); +int stralloc_catlong0(stralloc* sa,signed long int in,size_t n) noexcept; /* stralloc_free frees the storage associated with sa */ -void stralloc_free(stralloc* sa); +void stralloc_free(stralloc* sa) noexcept; #define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) #define stralloc_catulong(sa,l) (stralloc_catulong0((sa),(l),0)) @@ -146,10 +144,10 @@ void stralloc_free(stralloc* sa); #define stralloc_catuint(sa,i) (stralloc_catulong0((sa),(i),0)) /* remove last char. Return removed byte as unsigned char (or -1 if stralloc was empty). */ -int stralloc_chop(stralloc* sa); +int stralloc_chop(stralloc* sa) noexcept; /* remove trailing "\r\n", "\n" or "\r". Return number of removed chars (0,1 or 2) */ -int stralloc_chomp(stralloc* sa); +int stralloc_chomp(stralloc* sa) noexcept; #ifdef BUFFER_H /* write stralloc to buffer */ @@ -169,13 +167,13 @@ int buffer_putsaflush(buffer* b,const stralloc* sa); * data is available. */ /* read token from buffer to stralloc */ -__readmemsz__(3,4) +att_readn(3, 4) int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* read line from buffer to stralloc */ int buffer_getline_sa(buffer* b,stralloc* sa); /* same as buffer_get_token_sa but empty sa first */ -__readmemsz__(3,4) +att_readn(3, 4) int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen); /* same as buffer_getline_sa but empty sa first */ int buffer_getnewline_sa(buffer* b,stralloc* sa); diff --git a/t.c b/t.c index ea3425a..941a8e2 100644 --- a/t.c +++ b/t.c @@ -37,6 +37,8 @@ // #define atomic_add(mem,val) asm volatile ("lock; add%z0 %1, %0": "+m" (mem): "ir" (val)) +// compiletimeassert(sizeof(long) == 2); + int64 writecb(int64 fd,const void* buf,uint64 n) { (void)fd; (void)buf; diff --git a/tai.h b/tai.h index 7607e27..292d8ad 100644 --- a/tai.h +++ b/tai.h @@ -4,7 +4,7 @@ /* Times with 1 second precision */ -#include "uint64.h" +#include #ifdef __cplusplus extern "C" { diff --git a/taia.h b/taia.h index ee4c8a9..576a960 100644 --- a/taia.h +++ b/taia.h @@ -4,8 +4,8 @@ /* Times with 1 attosecond precision */ -#include "tai.h" -#include "uint32.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/textcode.h b/textcode.h index a09eff9..e49b068 100644 --- a/textcode.h +++ b/textcode.h @@ -12,71 +12,91 @@ extern "C" { * dest (if dest != NULL), returning the number of bytes written. */ /* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */ -#ifndef __writememsz__ +#ifndef __readmemsz__ #define __readmemsz__(a,b) #endif +#ifndef __writemem__ +#define __writemem__(a) +#endif + /* Needs len/3*4 bytes */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_uuencoded(char* dest,const char* src,size_t len); + /* Needs len/3*4 bytes */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_base64(char* dest,const char* src,size_t len); -__readmemsz__(2,3) + +__writemem__(1) __readmemsz__(2,3) size_t fmt_base64url(char* dest,const char* src,size_t len); + /* Worst case: len*3 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_quotedprintable(char* dest,const char* src,size_t len); + /* Worst case: len*3 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_quotedprintable2(char* dest,const char* src,size_t len,const char* escapeme); + /* Worst case: len*3 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_urlencoded(char* dest,const char* src,size_t len); + /* Worst case: len*3 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_urlencoded2(char* dest,const char* src,size_t len,const char* escapeme); + /* Worst case: len*2 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_yenc(char* dest,const char* src,size_t len); + /* Needs len*2 bytes */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_hexdump(char* dest,const char* src,size_t len); + /* Change '<' to '<' and '&' to '&' and '\n' to '
'; worst case: len*5 */ /* This is meant for outputting text that goes between tags */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_html(char* dest,const char* src,size_t len); + /* Change '<' to '<' and '&' to '&' and '"' to '"'; worst case: len*6 */ /* This is meant for outputting text that goes in a tag argument between double quotes*/ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_html_tagarg(char* dest,const char* src,size_t len); + /* Change '<' to '<' and '&' to '&'; worst case: len*5 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_xml(char* dest,const char* src,size_t len); /* Change '\' to "\\", '\n' to "\n", ^A to "\x01" etc; worst case: len*4 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_cescape(char* dest,const char* src,size_t len); + /* Worst case: len*4 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_cescape2(char* dest,const char* src,size_t len,const char* escapeme); + /* Fold whitespace to '_'; this is great for writing fields with * white spaces to a log file and still allow awk to do log analysis */ /* Worst case: same size */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_foldwhitespace(char* dest,const char* src,size_t len); + /* Worst case: len*3 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_ldapescape(char* dest,const char* src,size_t len); -__readmemsz__(2,3) + +__writemem__(1) __readmemsz__(2,3) size_t fmt_ldapescape2(char* dest,const char* src,size_t len,const char* escapeme); + /* Encode JSON string from UTF-8; will backslash-escape the bare minimum. * Invalid UTF-8 in input will output as valid UTF-8 for each byte * Worst case: len*6 */ -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_jsonescape(char* dest,const char* src,size_t len); -__readmemsz__(2,3) +__writemem__(1) __readmemsz__(2,3) size_t fmt_base85(char* dest,const char* src,size_t len); /* These read one line from src, decode it, and write the result to