Changeset 4004


Ignore:
Timestamp:
11/22/09 19:54:31 (4 years ago)
Author:
sam
Message:

Refactor zzcat for clarity.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/test/zzcat.c

    r4002 r4004  
    11/* 
    22 *  zzcat - various cat reimplementations for testing purposes 
    3  *  Copyright (c) 2006, 2007 Sam Hocevar <sam@zoy.org> 
     3 *  Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net> 
    44 *                All Rights Reserved 
    55 * 
     
    3838#include <string.h> 
    3939 
     40static int zzcat_read(char const *, unsigned char *, int64_t); 
     41static int zzcat_fread(char const *, unsigned char *, int64_t); 
     42static int zzcat_getc(char const *, unsigned char *, int64_t, int); 
     43static int zzcat_fgetc(char const *, unsigned char *, int64_t); 
     44#if defined HAVE_GETLINE 
     45static int zzcat_getdelim_getc(char const *, unsigned char *, int64_t, int); 
     46#endif 
     47static int zzcat_fread_getc(char const *, unsigned char *, int64_t, int); 
     48static int zzcat_random_socket(char const *, unsigned char *, int64_t); 
     49static int zzcat_random_stream(char const *, unsigned char *, int64_t); 
     50#if defined HAVE_MMAP 
     51static int zzcat_random_mmap(char const *, unsigned char *, int64_t); 
     52#endif 
     53 
    4054static inline unsigned int myrand(void) 
    4155{ 
     
    5367    unsigned char *data; 
    5468    char const *name; 
    55     FILE *stream; 
    56     int cmd, i, j, fd; 
    57     char c; 
     69    int ret, cmd, fd; 
    5870 
    5971    if(argc != 3) 
     
    7789    switch((cmd = atoi(argv[1]))) 
    7890    { 
    79     /* 0x: simple fd calls 
    80      * 1x: complex fd calls */ 
    81     case 0: /* only read() calls */ 
    82         fd = open(name, O_RDONLY); 
    83         if(fd < 0) 
    84             return EXIT_FAILURE; 
    85         for(i = 0; i < len; i++) 
    86             read(fd, data + i, 1); 
    87         close(fd); 
    88         break; 
    89     /* 2x: simple stdio calls 
    90      * 3x: complex stdio calls */ 
    91     case 20: /* only fread() calls */ 
    92         stream = fopen(name, "r"); 
    93         if(!stream) 
    94             return EXIT_FAILURE; 
    95         for(i = 0; i < len; i++) 
    96             fread(data + i, 1, 1, stream); 
    97         fclose(stream); 
    98         break; 
    99     case 21: /* only getc() calls */ 
     91        case 0: ret = zzcat_read(name, data, len); break; 
     92        case 20: ret = zzcat_fread(name, data, len); break; 
     93        case 21: ret = zzcat_getc(name, data, len, 0); break; 
    10094#if defined HAVE_GETC_UNLOCKED 
    101     case 22: /* only getc_unlocked() calls */ 
    102 #endif 
    103         stream = fopen(name, "r"); 
    104         if(!stream) 
    105             return EXIT_FAILURE; 
    106         for(i = 0; i < len; i++) 
    107 #if defined HAVE_GETC_UNLOCKED 
    108             data[i] = cmd == 21 ? getc(stream) 
    109                                 : getc_unlocked(stream); 
    110 #else 
    111             data[i] = getc(stream); 
    112 #endif 
    113         fclose(stream); 
    114         break; 
    115     case 23: /* only fgetc() calls */ 
    116         stream = fopen(name, "r"); 
    117         if(!stream) 
    118             return EXIT_FAILURE; 
    119         for(i = 0; i < len; i++) 
    120             data[i] = fgetc(stream); 
    121         fclose(stream); 
    122         break; 
     95        case 22: ret = zzcat_getc(name, data, len, 1); break; 
     96#endif 
     97        case 23: ret = zzcat_fgetc(name, data, len); break; 
    12398#if defined HAVE_GETLINE 
    124     case 24: /* getline() and getc() calls */ 
    125 #if defined HAVE_GETC_UNLOCKED 
    126     case 25: /* getline() and getc_unlocked() calls */ 
    127 #endif 
    128         stream = fopen(name, "r"); 
    129         if(!stream) 
    130             return EXIT_FAILURE; 
    131         i = 0; 
    132 #if defined HAVE_GETC_UNLOCKED 
    133         while ((c = (cmd == 24 ? getc(stream) 
    134                                : getc_unlocked(stream))) != EOF) 
    135 #else 
    136         while ((c = getc(stream)) != EOF) 
    137 #endif 
    138         { 
    139             char *line; 
    140             ssize_t ret; 
    141             size_t n; 
    142  
    143             ungetc(c, stream); 
    144             line = NULL; 
    145             ret = getline(&line, &n, stream); 
    146             for (j = 0; j < ret; i++, j++) 
    147                 data[i] = line[j]; 
    148         } 
    149         fclose(stream); 
    150         break; 
    151 #endif 
    152     case 30: /* one fread(), then only getc() calls */ 
    153         stream = fopen(name, "r"); 
    154         if(!stream) 
    155             return EXIT_FAILURE; 
    156         fread(data, 1, 10, stream); 
    157         for(i = 10; i < len; i++) 
    158             data[i] = getc(stream); 
    159         fclose(stream); 
    160         break; 
    161     case 31: /* one fread(), then only fgetc() calls */ 
    162         stream = fopen(name, "r"); 
    163         if(!stream) 
    164             return EXIT_FAILURE; 
    165         fread(data, 1, 10, stream); 
    166         for(i = 10; i < len; i++) 
    167             data[i] = fgetc(stream); 
    168         fclose(stream); 
    169         break; 
    170     /* 4x: complex, random stuff */ 
    171     case 40: /* socket seeks and reads */ 
    172         fd = open(name, O_RDONLY); 
    173         if(fd < 0) 
    174             return EXIT_FAILURE; 
    175         for(i = 0; i < 128; i++) 
    176         { 
    177             lseek(fd, myrand() % len, SEEK_SET); 
    178             for(j = 0; j < 4; j++) 
    179                 read(fd, data + lseek(fd, 0, SEEK_CUR), myrand() % 4096); 
    180 #ifdef HAVE_LSEEK64 
    181             lseek64(fd, myrand() % len, SEEK_SET); 
    182             for(j = 0; j < 4; j++) 
    183                 read(fd, data + lseek(fd, 0, SEEK_CUR), myrand() % 4096); 
    184 #endif 
    185         } 
    186         close(fd); 
    187         break; 
    188     case 41: /* std streams seeks and reads */ 
    189         stream = fopen(name, "r"); 
    190         if(!stream) 
    191             return EXIT_FAILURE; 
    192         for(i = 0; i < 128; i++) 
    193         { 
    194             long int now; 
    195             fseek(stream, myrand() % len, SEEK_SET); 
    196             for(j = 0; j < 4; j++) 
    197                 fread(data + ftell(stream), 
    198                       myrand() % (len - ftell(stream)), 1, stream); 
    199             fseek(stream, myrand() % len, SEEK_SET); 
    200             now = ftell(stream); 
    201             for(j = 0; j < 16; j++) 
    202                 data[now + j] = getc(stream); 
    203             now = ftell(stream); 
    204             for(j = 0; j < 16; j++) 
    205                 data[now + j] = fgetc(stream); 
    206         } 
    207         fclose(stream); 
    208         break; 
    209     case 42: /* mmap() */ 
    210         fd = open(name, O_RDONLY); 
    211         if(fd < 0) 
    212             return EXIT_FAILURE; 
    213 #ifdef HAVE_MMAP 
    214         for(i = 0; i < 128; i++) 
    215         { 
    216             char *map; 
    217             int moff, mlen, pgsz = len + 1; 
    218 #ifdef HAVE_GETPAGESIZE 
    219             pgsz = getpagesize(); 
    220 #endif 
    221             moff = len < pgsz ? 0 : (myrand() % (len / pgsz)) * pgsz; 
    222             mlen = 1 + (myrand() % (len - moff)); 
    223             map = mmap(NULL, mlen, PROT_READ, MAP_PRIVATE, fd, moff); 
    224             if(map == MAP_FAILED) 
    225                 return EXIT_FAILURE; 
    226             for(j = 0; j < 128; j++) 
    227             { 
    228                 int x = myrand() % mlen; 
    229                 data[moff + x] = map[x]; 
    230             } 
    231             munmap(map, mlen); 
    232         } 
    233 #endif 
    234         close(fd); 
    235         break; 
    236     default: 
    237         return EXIT_FAILURE; 
     99        case 24: ret = zzcat_getdelim_getc(name, data, len, 0); break; 
     100#   if defined HAVE_GETC_UNLOCKED 
     101        case 25: ret = zzcat_getdelim_getc(name, data, len, 1); break; 
     102#   endif 
     103#endif 
     104        case 30: ret = zzcat_fread_getc(name, data, len, 0); break; 
     105        case 31: ret = zzcat_fread_getc(name, data, len, 1); break; 
     106        case 40: ret = zzcat_random_socket(name, data, len); break; 
     107        case 41: ret = zzcat_random_stream(name, data, len); break; 
     108#if defined HAVE_MMAP 
     109        case 42: ret = zzcat_random_mmap(name, data, len); break; 
     110#endif 
     111        default: ret = EXIT_SUCCESS; 
    238112    } 
    239113 
     
    242116    free(data); 
    243117 
    244     return EXIT_SUCCESS; 
    245 } 
    246  
     118    return ret; 
     119} 
     120 
     121/* Only read(1) calls */ 
     122static int zzcat_read(char const *name, unsigned char *data, int64_t len) 
     123{ 
     124    int i, fd = open(name, O_RDONLY); 
     125    if(fd < 0) 
     126        return EXIT_FAILURE; 
     127    for(i = 0; i < len; i++) 
     128        read(fd, data + i, 1); 
     129    close(fd); 
     130    return EXIT_SUCCESS; 
     131} 
     132 
     133/* Only fread() calls */ 
     134static int zzcat_fread(char const *name, unsigned char *data, int64_t len) 
     135{ 
     136    FILE *stream = fopen(name, "r"); 
     137    int i; 
     138    if(!stream) 
     139        return EXIT_FAILURE; 
     140    for(i = 0; i < len; i++) 
     141        fread(data + i, 1, 1, stream); 
     142    fclose(stream); 
     143    return EXIT_SUCCESS; 
     144} 
     145 
     146/* Only getc() or getc_unlocked() calls */ 
     147static int zzcat_getc(char const *name, unsigned char *data, int64_t len, 
     148                      int unlocked) 
     149{ 
     150    FILE *stream = fopen(name, "r"); 
     151    int i; 
     152    if(!stream) 
     153        return EXIT_FAILURE; 
     154    for(i = 0; i < len; i++) 
     155#if defined HAVE_GETC_UNLOCKED 
     156        data[i] = unlocked ? getc_unlocked(stream) 
     157                           : getc(stream); 
     158#else 
     159        data[i] = getc(stream); 
     160#endif 
     161    fclose(stream); 
     162    return EXIT_SUCCESS; 
     163} 
     164 
     165/* Only fgetc() calls */ 
     166static int zzcat_fgetc(char const *name, unsigned char *data, int64_t len) 
     167{ 
     168    FILE *stream = fopen(name, "r"); 
     169    int i; 
     170    if(!stream) 
     171        return EXIT_FAILURE; 
     172    for(i = 0; i < len; i++) 
     173        data[i] = fgetc(stream); 
     174    fclose(stream); 
     175    return EXIT_SUCCESS; 
     176} 
     177 
     178#if defined HAVE_GETLINE 
     179/* getdelim() and getc() calls */ 
     180static int zzcat_getdelim_getc(char const *name, unsigned char *data, 
     181                               int64_t len, int unlocked) 
     182{ 
     183    FILE *stream = fopen(name, "r"); 
     184    int i = 0, j; 
     185    char c; 
     186    if(!stream) 
     187        return EXIT_FAILURE; 
     188    (void)len; 
     189#if defined HAVE_GETC_UNLOCKED 
     190    while ((c = (unlocked ? getc_unlocked(stream) : getc(stream))) != EOF) 
     191#else 
     192    while ((c = getc(stream)) != EOF) 
     193#endif 
     194    { 
     195        char *line; 
     196        ssize_t ret; 
     197        size_t n; 
     198 
     199        ungetc(c, stream); 
     200        line = NULL; 
     201        ret = getline(&line, &n, stream); 
     202        for (j = 0; j < ret; i++, j++) 
     203            data[i] = line[j]; 
     204    } 
     205    fclose(stream); 
     206    return EXIT_SUCCESS; 
     207} 
     208#endif 
     209 
     210/* One fread(), then only getc() or fgetc() calls */ 
     211static int zzcat_fread_getc(char const *name, unsigned char *data, 
     212                            int64_t len, int use_fgetc) 
     213{ 
     214    FILE *stream = fopen(name, "r"); 
     215    int i; 
     216    if(!stream) 
     217        return EXIT_FAILURE; 
     218    fread(data, 1, 10, stream); 
     219    for(i = 10; i < len; i++) 
     220        data[i] = use_fgetc ? fgetc(stream) : getc(stream); 
     221    fclose(stream); 
     222    return EXIT_SUCCESS; 
     223} 
     224 
     225/* Socket seeks and reads */ 
     226static int zzcat_random_socket(char const *name, unsigned char *data, 
     227                               int64_t len) 
     228{ 
     229    int i, j, fd = open(name, O_RDONLY); 
     230    if(fd < 0) 
     231        return EXIT_FAILURE; 
     232    for(i = 0; i < 128; i++) 
     233    { 
     234        lseek(fd, myrand() % len, SEEK_SET); 
     235        for(j = 0; j < 4; j++) 
     236            read(fd, data + lseek(fd, 0, SEEK_CUR), myrand() % 4096); 
     237#ifdef HAVE_LSEEK64 
     238        lseek64(fd, myrand() % len, SEEK_SET); 
     239        for(j = 0; j < 4; j++) 
     240            read(fd, data + lseek(fd, 0, SEEK_CUR), myrand() % 4096); 
     241#endif 
     242    } 
     243    close(fd); 
     244    return EXIT_SUCCESS; 
     245} 
     246 
     247/* Standard stream seeks and reads */ 
     248static int zzcat_random_stream(char const *name, unsigned char *data, 
     249                               int64_t len) 
     250{ 
     251    FILE *stream = fopen(name, "r"); 
     252    int i, j; 
     253    if(!stream) 
     254        return EXIT_FAILURE; 
     255    for(i = 0; i < 128; i++) 
     256    { 
     257        long int now; 
     258        fseek(stream, myrand() % len, SEEK_SET); 
     259        for(j = 0; j < 4; j++) 
     260            fread(data + ftell(stream), 
     261                  myrand() % (len - ftell(stream)), 1, stream); 
     262        fseek(stream, myrand() % len, SEEK_SET); 
     263        now = ftell(stream); 
     264        for(j = 0; j < 16; j++) 
     265            data[now + j] = getc(stream); 
     266        now = ftell(stream); 
     267        for(j = 0; j < 16; j++) 
     268            data[now + j] = fgetc(stream); 
     269    } 
     270    fclose(stream); 
     271    return EXIT_SUCCESS; 
     272} 
     273 
     274#ifdef HAVE_MMAP 
     275/* mmap() followed by random memory reads */ 
     276static int zzcat_random_mmap(char const *name, unsigned char *data, 
     277                               int64_t len) 
     278{ 
     279    int i, j, fd = open(name, O_RDONLY); 
     280    if(fd < 0) 
     281        return EXIT_FAILURE; 
     282    for(i = 0; i < 128; i++) 
     283    { 
     284        char *map; 
     285        int moff, mlen, pgsz = len + 1; 
     286#ifdef HAVE_GETPAGESIZE 
     287        pgsz = getpagesize(); 
     288#endif 
     289        moff = len < pgsz ? 0 : (myrand() % (len / pgsz)) * pgsz; 
     290        mlen = 1 + (myrand() % (len - moff)); 
     291        map = mmap(NULL, mlen, PROT_READ, MAP_PRIVATE, fd, moff); 
     292        if(map == MAP_FAILED) 
     293            return EXIT_FAILURE; 
     294        for(j = 0; j < 128; j++) 
     295        { 
     296            int x = myrand() % mlen; 
     297            data[moff + x] = map[x]; 
     298        } 
     299        munmap(map, mlen); 
     300    } 
     301    close(fd); 
     302    return EXIT_SUCCESS; 
     303} 
     304#endif 
     305 
Note: See TracChangeset for help on using the changeset viewer.