00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "../basex.h"
00026 #include "profile.h"
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <unistd.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <fcntl.h>
00034 #include <errno.h>
00035 #include <string.h>
00036 #include <time.h>
00037 #include <ctype.h>
00038
00039
00040 #ifndef MIN
00041 #define MIN(a,b) (((a)<(b))?(a):(b))
00042 #endif
00043
00044 #define BASE64 64
00045 #define Q_BASE64 640
00046 #define BASE16 16
00047
00048 #ifndef BASEX
00049 #define BASEX BASE16
00050 #endif
00051
00052 #if BASEX == Q_BASE64
00053
00054 #warning Q_BASE64
00055 #define B_ENC q_base64_enc
00056 #define B_DEC q_base64_dec
00057 #define B_ENC_LEN(l) (((l)+2)/3*4)
00058
00059 #elif BASEX == BASE16
00060
00061 #warning BASE16
00062 #define B_ENC base16_enc
00063 #define B_DEC base16_dec
00064 #define B_ENC_LEN(l) ((l)*2)
00065
00066 #else
00067
00068 #warning BASE64
00069 #define B_ENC base64_enc
00070 #define B_DEC base64_dec
00071 #define B_ENC_LEN(l) (((l)+2)/3*4)
00072
00073
00074 #endif
00075
00076
00077 #define QUOTE_MACRO(x) QUOTEME(x)
00078 #define QUOTEME(x) #x
00079
00080 static char* id="$Id$";
00081 static char* version="basex test 0.1 "
00082 "BASE" QUOTE_MACRO(BASEX) ": " QUOTE_MACRO(B_ENC) ", " QUOTE_MACRO(B_DEC) ""
00083 #if defined BASE64_LOOKUP_TABLE
00084 #ifdef BASE64_LOOKUP_LARGE
00085 " (large b64 lookup table)"
00086 #else
00087 " (lookup b64 table)"
00088 #endif
00089 #else
00090 " (no b64 lookup table)"
00091 #endif
00092 #if defined BASE16_LOOKUP_TABLE
00093 #ifdef BASE16_LOOKUP_LARGE
00094 " (large b16 lookup table)"
00095 #else
00096 " (lookup b16 table)"
00097 #endif
00098 #else
00099 " (no b16 lookup table)"
00100 #endif
00101 #if defined BASE64_READ_WHOLE_INTS || defined BASE16_READ_WHOLE_INTS
00102 " (read 4 bytes at a time)"
00103 #else
00104 " (read 1 byte at a time)"
00105 #endif
00106 ;
00107
00108 static char* help_msg="\
00109 Usage: basex [-hv] ... [options]\n\
00110 Options:\n\
00111 -m min minimum length\n\
00112 -M max maximum length\n\
00113 -o offset offset from the start of the buffer (alignment tests)\n\
00114 -e offset offset from the start of the dst. buf. (alignment tests)\n\
00115 -n no. number of test loops\n\
00116 -v increase verbosity\n\
00117 -V version number\n\
00118 -h this help message\n\
00119 ";
00120
00121
00122
00123 struct profile_data pf1, pf2, pf3, pf4, pf5, pf6;
00124
00125
00126 void dump_profile_info(struct profile_data* pd)
00127 {
00128 printf("profiling for %s (%ld/%ld): %lld/%lld/%lld (max/avg/last),"
00129 " total %lld\n",
00130 pd->name, pd->entries, pd->exits, pd->max_cycles,
00131 pd->entries?pd->total_cycles/pd->entries:0, pd->cycles,
00132 pd->total_cycles);
00133 }
00134
00135
00136
00137 int seed_prng()
00138 {
00139 int seed, rfd;
00140
00141 if ((rfd=open("/dev/urandom", O_RDONLY))!=-1){
00142 try_again:
00143 if (read(rfd, (void*)&seed, sizeof(seed))==-1){
00144 if (errno==EINTR) goto try_again;
00145 fprintf(stderr, "WARNING: could not read from /dev/urandom: "
00146 " %s (%d)\n", strerror(errno), errno);
00147 }
00148 close(rfd);
00149 }else{
00150 fprintf(stderr, "WARNING: could not open /dev/urandom: %s (%d)\n",
00151 strerror(errno), errno);
00152 }
00153 seed+=getpid()+time(0);
00154 srand(seed);
00155 return 0;
00156 }
00157
00158
00159
00160 void fill_rand(unsigned char* buf, int len)
00161 {
00162 unsigned char* end;
00163 int v;
00164
00165
00166 #if RAND_MAX >= 0xffffffff
00167 #define RAND_BYTES 4
00168 #warning RAND_BYTES is 4
00169 #elif RAND_MAX >= 0xffffff
00170 #define RAND_BYTES 3
00171 #warning RAND_BYTES is 3
00172 #elif RAND_MAX >= 0xffff
00173 #define RAND_BYTES 2
00174 #warning RAND_BYTES is 2
00175 #else
00176 #define RAND_BYTES 1
00177 #endif
00178
00179 end=buf+len/RAND_BYTES*RAND_BYTES;
00180 for(;buf<end;buf+=RAND_BYTES){
00181 v=rand();
00182 buf[0]=v;
00183 #if RAND_BYTES > 1
00184 buf[1]=v>>8;
00185 #endif
00186 #if RAND_BYTES > 2
00187 buf[2]=v>>16;
00188 #endif
00189 #if RAND_BYTES > 4
00190 buf[3]=v>>24;
00191 #endif
00192 }
00193 v=rand();
00194 switch(end-buf){
00195 case 3:
00196 #if RAND_BYTES > 2
00197 buf[2]=v>>16;
00198 #else
00199 buf[2]=rand();
00200 #endif
00201 case 2:
00202 #if RAND_BYTES > 1
00203 buf[1]=v>>8;
00204 #else
00205 buf[1]=rand();
00206 #endif
00207 case 1:
00208 buf[0]=v;
00209 case 0:
00210 break;
00211 }
00212 }
00213
00214
00215
00216 int main(int argc, char** argv)
00217 {
00218
00219 int loops, min_len, max_len, offset, e_offset;
00220 unsigned char* ibuf;
00221 unsigned char* enc_buf;
00222 unsigned char* dec_buf;
00223 int ibuf_len, enc_buf_len, dec_buf_len;
00224 int offs, c_len, e_len, l;
00225 int r;
00226 int verbose;
00227 int c;
00228 char* tmp;
00229
00230 verbose=0;
00231 min_len=max_len=offset=-1;
00232 e_offset=0;
00233 loops=1024;
00234 opterr=0;
00235 while ((c=getopt(argc, argv, "n:m:M:o:e:vhV"))!=-1){
00236 switch(c){
00237 case 'n':
00238 loops=strtol(optarg, &tmp, 0);
00239 if ((tmp==0)||(*tmp)||(loops<0)){
00240 fprintf(stderr, "bad number: -%c %s\n", c, optarg);
00241 goto error;
00242 }
00243 break;
00244 case 'm':
00245 min_len=strtol(optarg, &tmp, 0);
00246 if ((tmp==0)||(*tmp)||(min_len<0)){
00247 fprintf(stderr, "bad number: -%c %s\n", c, optarg);
00248 goto error;
00249 }
00250 break;
00251 case 'M':
00252 max_len=strtol(optarg, &tmp, 0);
00253 if ((tmp==0)||(*tmp)||(max_len<0)){
00254 fprintf(stderr, "bad number: -%c %s\n", c, optarg);
00255 goto error;
00256 }
00257 break;
00258 case 'o':
00259 offset=strtol(optarg, &tmp, 0);
00260 if ((tmp==0)||(*tmp)||(offset<0)){
00261 fprintf(stderr, "bad number: -%c %s\n", c, optarg);
00262 goto error;
00263 }
00264 break;
00265 case 'e':
00266 e_offset=strtol(optarg, &tmp, 0);
00267 if ((tmp==0)||(*tmp)||(e_offset<0)){
00268 fprintf(stderr, "bad number: -%c %s\n", c, optarg);
00269 goto error;
00270 }
00271 break;
00272 case 'v':
00273 verbose++;
00274 break;
00275 case 'V':
00276 printf("version: %s\n", version);
00277 printf("%s\n", id);
00278 exit(0);
00279 break;
00280 case 'h':
00281 printf("version: %s\n", version);
00282 printf("%s", help_msg);
00283 exit(0);
00284 break;
00285 case '?':
00286 if (isprint(optopt))
00287 fprintf(stderr, "Unknown option `-%c\n", optopt);
00288 else
00289 fprintf(stderr, "Unknown character `\\x%x\n", optopt);
00290 goto error;
00291 case ':':
00292 fprintf(stderr, "Option `-%c requires an argument.\n",
00293 optopt);
00294 goto error;
00295 break;
00296 default:
00297 abort();
00298 }
00299 }
00300 if (min_len==-1 && max_len==-1){
00301 min_len=0;
00302 max_len=4*1024*1024;
00303 }else if (min_len==-1)
00304 min_len=0;
00305 else if (max_len==-1)
00306 max_len=min_len;
00307
00308 ibuf_len=max_len;
00309 ibuf=malloc(ibuf_len);
00310 if (ibuf==0){
00311 fprintf(stderr, "ERROR: 1. memory allocation error (%d bytes)\n",
00312 ibuf_len);
00313 exit(-1);
00314 }
00315 enc_buf_len=B_ENC_LEN(ibuf_len);
00316 enc_buf=malloc(enc_buf_len+e_offset);
00317 if (enc_buf==0){
00318 fprintf(stderr, "ERROR: 2. memory allocation error (%d bytes)\n",
00319 enc_buf_len);
00320 exit(-1);
00321 }
00322 enc_buf+=e_offset;
00323
00324 dec_buf_len=ibuf_len;
00325 dec_buf=malloc(dec_buf_len+e_offset);
00326 if (dec_buf==0){
00327 fprintf(stderr, "ERROR: 3. memory allocation error (%d bytes)\n",
00328 dec_buf_len+e_offset);
00329 exit(-1);
00330 }
00331 dec_buf+=e_offset;
00332
00333
00334
00335 seed_prng();
00336
00337 profile_init(&pf1, "encode");
00338 profile_init(&pf2, "decode");
00339
00340 init_basex();
00341 if (verbose)
00342 printf("starting (loops %d, min size %d, max size %d, offset %d,"
00343 ", e_offset %d, buffer sizes %d %d %d)\n",
00344 loops, min_len, max_len, offset, e_offset, ibuf_len,
00345 enc_buf_len, dec_buf_len);
00346
00347 for (r=0; r<loops; r++){
00348 if (min_len!=max_len)
00349
00350 c_len= min_len+(int)((float)(max_len-min_len+1)*
00351 (rand()/(RAND_MAX+1.0)));
00352 else
00353
00354 c_len=max_len;
00355 if (offset==-1)
00356
00357 offs= (int)((float)(MIN(c_len,3)+1)*(rand()/(RAND_MAX+1.0)));
00358 else if (offset>c_len)
00359 offs=0;
00360 else
00361 offs=offset;
00362 if (verbose>2)
00363 printf("loop %d, current len %d, offset %d, start %p\n",
00364 r, c_len-offs, offs, &ibuf[offs]);
00365 else if ((verbose >1) && (r %10==0)) putchar('.');
00366
00367 fill_rand(ibuf, c_len);
00368
00369 c_len-=offs;
00370 e_len=B_ENC_LEN(c_len);
00371 profile_start(&pf1);
00372 l=B_ENC(&ibuf[offs], c_len, enc_buf, e_len);
00373 profile_end(&pf1);
00374 if (l != e_len){
00375 fprintf(stderr, "ERROR: invalid length for encoding: %d "
00376 "instead of %d (loops=%d)\n", l, e_len, r);
00377 exit(-1);
00378 }
00379 profile_start(&pf2);
00380 l=B_DEC(enc_buf, e_len, dec_buf, c_len);
00381 profile_end(&pf2);
00382 if (l != c_len){
00383 fprintf(stderr, "ERROR: invalid length for decoding: %d "
00384 "instead of %d (loops=%d)\n", l, c_len, r);
00385 exit(-1);
00386 }
00387 if (memcmp(&ibuf[offs], dec_buf, c_len)!=0){
00388 fprintf(stderr, "ERROR: decoding mismatch "
00389 "(loops=%d, c_len=%d)\n", r, c_len);
00390 abort();
00391 exit(-1);
00392 }
00393 }
00394 if (verbose >1) putchar('\n');
00395
00396 dump_profile_info(&pf1);
00397 dump_profile_info(&pf2);
00398 return 0;
00399 error:
00400 exit(-1);
00401 }