/* *$Id$ * * - various general purpose functions */ #ifndef ut_h #define ut_h #include <sys/types.h> #include <sys/time.h> #include <unistd.h> #include "dprint.h" struct sip_msg; /* returns string beginning and length without insignificant chars */ #define trim_len( _len, _begin, _mystr ) \ do{ static char _c; \ (_len)=(_mystr).len; \ while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || _c=='\n' || _c==' ' || _c=='\t' )) \ (_len)--; \ (_begin)=(_mystr).s; \ while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \ (_len)--;\ (_begin)++; \ } \ }while(0) #define trim_r( _mystr ) \ do{ static char _c; \ while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\ _c=='\r' || _c=='\n' ) \ ) \ (_mystr).len--; \ }while(0) #define translate_pointer( _new_buf , _org_buf , _p) \ ( (_p)?(_new_buf + (_p-_org_buf)):(0) ) #define via_len(_via) \ ((_via)->bsize-((_via)->name.s-\ ((_via)->hdr.s+(_via)->hdr.len))) #define via_s(_via,_p_msg) \ translate_pointer((_p_msg)->orig,(_p_msg)->buf,(_via)->name.s) /* char to hex conversion table */ static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /* converts a str to an u. short, returns the u. short and sets *err on * error and if err!=null */ static inline unsigned short str2s(unsigned char* str, unsigned int len, int *err) { unsigned short ret; int i; unsigned char *limit; unsigned char *init; /*init*/ ret=i=0; limit=str+len; init=str; for(;str<limit ;str++){ if ( (*str <= '9' ) && (*str >= '0') ){ ret=ret*10+*str-'0'; i++; if (i>5) goto error_digits; }else{ //error unknown char goto error_char; } } if (err) *err=0; return ret; error_digits: DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init); if (err) *err=1; return 0; error_char: DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init); if (err) *err=1; return 0; } /* converts a str to an ipv4 address, returns the address and sets *err * if error and err!=null */ static inline unsigned int str2ip(unsigned char* str, unsigned int len, int * err) { unsigned int ret; int i; unsigned char *limit; unsigned char *init; /*init*/ ret=i=0; limit=str+len; init=str; for(;str<limit ;str++){ if (*str=='.'){ i++; if (i>3) goto error_dots; }else if ( (*str <= '9' ) && (*str >= '0') ){ ((unsigned char*)&ret)[i]=((unsigned char*)&ret)[i]*10+ *str-'0'; }else{ //error unknown char goto error_char; } } if (err) *err=0; return ret; error_dots: DBG("str2ip: ERROR: too many dots in [%.*s]\n", (int)len, init); if (err) *err=1; return 0; error_char: DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str,(int)len, init); if (err) *err=1; return 0; } static inline int btostr( char *p, unsigned char val) { unsigned int a,b,i =0; if ( (a=val/100)!=0 ) *(p+(i++)) = a+'0'; /*first digit*/ if ( (b=val%100/10)!=0 || a) *(p+(i++)) = b+'0'; /*second digit*/ *(p+(i++)) = '0'+val%10; /*third digit*/ return i; } /* faster memchr version */ static inline char* q_memchr(char* p, int c, unsigned int size) { char* end; end=p+size; for(;p<end;p++){ if (*p==(unsigned char)c) return p; } return 0; } inline static int reverse_hex2int( char *c, int len ) { char *pc; int r; char mychar; r=0; for (pc=c+len-1; len>0; pc--, len--) { r <<= 4 ; mychar=*pc; if ( mychar >='0' && mychar <='9') r+=mychar -'0'; else if (mychar >='a' && mychar <='f') r+=mychar -'a'+10; else if (mychar >='A' && mychar <='F') r+=mychar -'A'+10; else return -1; } return r; } inline static int int2reverse_hex( char **c, int *size, int nr ) { unsigned short digit; if (*size && nr==0) { **c = '0'; (*c)++; (*size)--; return 1; } while (*size && nr ) { digit = nr & 0xf ; **c= digit >= 10 ? digit + 'a' - 10 : digit + '0'; nr >>= 4; (*c)++; (*size)--; } return nr ? -1 /* number not processed; too little space */ : 1; } /* double output length assumed ; does NOT zero-terminate */ inline static int string2hex( /* input */ unsigned char *str, int len, /* output */ char *hex ) { int orig_len; if (len==0) { *hex='0'; return 1; } orig_len=len; while ( len ) { *hex=fourbits2char[(*str) >> 4]; hex++; *hex=fourbits2char[(*str) & 0xf]; hex++; len--; str++; } return orig_len-len; } inline static void sleep_us( unsigned int nusecs ) { struct timeval tval; tval.tv_sec=nusecs/100000; tval.tv_usec=nusecs%1000000; select(0, NULL, NULL, NULL, &tval ); } #endif