Changeset 4004 for zzuf/trunk


Ignore:
Timestamp:
Nov 22, 2009, 7:54:31 PM (10 years ago)
Author:
Sam Hocevar
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.