Fossil SCM

fossil-scm / compat / zlib / contrib / puff / pufftest.c
Source Blame History 168 lines
7ef7284… drh 1 /*
7ef7284… drh 2 * pufftest.c
6ea30fb… florian 3 * Copyright (C) 2002-2026 Mark Adler
7ef7284… drh 4 * For conditions of distribution and use, see copyright notice in puff.h
7ef7284… drh 5 */
7ef7284… drh 6
7ef7284… drh 7 /* Example of how to use puff().
7ef7284… drh 8
7ef7284… drh 9 Usage: puff [-w] [-f] [-nnn] file
7ef7284… drh 10 ... | puff [-w] [-f] [-nnn]
7ef7284… drh 11
7ef7284… drh 12 where file is the input file with deflate data, nnn is the number of bytes
7ef7284… drh 13 of input to skip before inflating (e.g. to skip a zlib or gzip header), and
7ef7284… drh 14 -w is used to write the decompressed data to stdout. -f is for coverage
7ef7284… drh 15 testing, and causes pufftest to fail with not enough output space (-f does
7ef7284… drh 16 a write like -w, so -w is not required). */
7ef7284… drh 17
6ea30fb… florian 18 #if defined(_WIN32) && !defined(_CRT_NONSTDC_NO_DEPRECATE)
6ea30fb… florian 19 # define _CRT_NONSTDC_NO_DEPRECATE
6ea30fb… florian 20 #endif
6ea30fb… florian 21
7ef7284… drh 22 #include <stdio.h>
7ef7284… drh 23 #include <stdlib.h>
7ef7284… drh 24 #include "puff.h"
7ef7284… drh 25
6ea30fb… florian 26 #if defined(MSDOS) || defined(OS2) || defined(_WIN32) || defined(__CYGWIN__)
7ef7284… drh 27 # include <fcntl.h>
7ef7284… drh 28 # include <io.h>
7ef7284… drh 29 # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
7ef7284… drh 30 #else
7ef7284… drh 31 # define SET_BINARY_MODE(file)
7ef7284… drh 32 #endif
7ef7284… drh 33
7ef7284… drh 34 #define local static
7ef7284… drh 35
7ef7284… drh 36 /* Return size times approximately the cube root of 2, keeping the result as 1,
7ef7284… drh 37 3, or 5 times a power of 2 -- the result is always > size, until the result
7ef7284… drh 38 is the maximum value of an unsigned long, where it remains. This is useful
7ef7284… drh 39 to keep reallocations less than ~33% over the actual data. */
7ef7284… drh 40 local size_t bythirds(size_t size)
7ef7284… drh 41 {
7ef7284… drh 42 int n;
7ef7284… drh 43 size_t m;
7ef7284… drh 44
7ef7284… drh 45 m = size;
7ef7284… drh 46 for (n = 0; m; n++)
7ef7284… drh 47 m >>= 1;
7ef7284… drh 48 if (n < 3)
7ef7284… drh 49 return size + 1;
7ef7284… drh 50 n -= 3;
7ef7284… drh 51 m = size >> n;
7ef7284… drh 52 m += m == 6 ? 2 : 1;
7ef7284… drh 53 m <<= n;
7ef7284… drh 54 return m > size ? m : (size_t)(-1);
7ef7284… drh 55 }
7ef7284… drh 56
7ef7284… drh 57 /* Read the input file *name, or stdin if name is NULL, into allocated memory.
7ef7284… drh 58 Reallocate to larger buffers until the entire file is read in. Return a
7ef7284… drh 59 pointer to the allocated data, or NULL if there was a memory allocation
7ef7284… drh 60 failure. *len is the number of bytes of data read from the input file (even
7ef7284… drh 61 if load() returns NULL). If the input file was empty or could not be opened
7ef7284… drh 62 or read, *len is zero. */
7ef7284… drh 63 local void *load(const char *name, size_t *len)
7ef7284… drh 64 {
7ef7284… drh 65 size_t size;
7ef7284… drh 66 void *buf, *swap;
7ef7284… drh 67 FILE *in;
7ef7284… drh 68
7ef7284… drh 69 *len = 0;
7ef7284… drh 70 buf = malloc(size = 4096);
7ef7284… drh 71 if (buf == NULL)
7ef7284… drh 72 return NULL;
7ef7284… drh 73 in = name == NULL ? stdin : fopen(name, "rb");
7ef7284… drh 74 if (in != NULL) {
7ef7284… drh 75 for (;;) {
7ef7284… drh 76 *len += fread((char *)buf + *len, 1, size - *len, in);
7ef7284… drh 77 if (*len < size) break;
7ef7284… drh 78 size = bythirds(size);
7ef7284… drh 79 if (size == *len || (swap = realloc(buf, size)) == NULL) {
7ef7284… drh 80 free(buf);
7ef7284… drh 81 buf = NULL;
7ef7284… drh 82 break;
7ef7284… drh 83 }
7ef7284… drh 84 buf = swap;
7ef7284… drh 85 }
7ef7284… drh 86 fclose(in);
7ef7284… drh 87 }
7ef7284… drh 88 return buf;
7ef7284… drh 89 }
7ef7284… drh 90
7ef7284… drh 91 int main(int argc, char **argv)
7ef7284… drh 92 {
7ef7284… drh 93 int ret, put = 0, fail = 0;
7ef7284… drh 94 unsigned skip = 0;
7ef7284… drh 95 char *arg, *name = NULL;
7ef7284… drh 96 unsigned char *source = NULL, *dest;
7ef7284… drh 97 size_t len = 0;
7ef7284… drh 98 unsigned long sourcelen, destlen;
7ef7284… drh 99
7ef7284… drh 100 /* process arguments */
7ef7284… drh 101 while (arg = *++argv, --argc)
7ef7284… drh 102 if (arg[0] == '-') {
7ef7284… drh 103 if (arg[1] == 'w' && arg[2] == 0)
7ef7284… drh 104 put = 1;
7ef7284… drh 105 else if (arg[1] == 'f' && arg[2] == 0)
7ef7284… drh 106 fail = 1, put = 1;
7ef7284… drh 107 else if (arg[1] >= '0' && arg[1] <= '9')
7ef7284… drh 108 skip = (unsigned)atoi(arg + 1);
7ef7284… drh 109 else {
7ef7284… drh 110 fprintf(stderr, "invalid option %s\n", arg);
7ef7284… drh 111 return 3;
7ef7284… drh 112 }
7ef7284… drh 113 }
7ef7284… drh 114 else if (name != NULL) {
7ef7284… drh 115 fprintf(stderr, "only one file name allowed\n");
7ef7284… drh 116 return 3;
7ef7284… drh 117 }
7ef7284… drh 118 else
7ef7284… drh 119 name = arg;
7ef7284… drh 120 source = load(name, &len);
7ef7284… drh 121 if (source == NULL) {
7ef7284… drh 122 fprintf(stderr, "memory allocation failure\n");
7ef7284… drh 123 return 4;
7ef7284… drh 124 }
7ef7284… drh 125 if (len == 0) {
7ef7284… drh 126 fprintf(stderr, "could not read %s, or it was empty\n",
7ef7284… drh 127 name == NULL ? "<stdin>" : name);
7ef7284… drh 128 free(source);
7ef7284… drh 129 return 3;
7ef7284… drh 130 }
7ef7284… drh 131 if (skip >= len) {
7ef7284… drh 132 fprintf(stderr, "skip request of %d leaves no input\n", skip);
7ef7284… drh 133 free(source);
7ef7284… drh 134 return 3;
7ef7284… drh 135 }
7ef7284… drh 136
7ef7284… drh 137 /* test inflate data with offset skip */
7ef7284… drh 138 len -= skip;
7ef7284… drh 139 sourcelen = (unsigned long)len;
7ef7284… drh 140 ret = puff(NIL, &destlen, source + skip, &sourcelen);
7ef7284… drh 141 if (ret)
7ef7284… drh 142 fprintf(stderr, "puff() failed with return code %d\n", ret);
7ef7284… drh 143 else {
7ef7284… drh 144 fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
7ef7284… drh 145 if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
7ef7284… drh 146 len - sourcelen);
7ef7284… drh 147 }
7ef7284… drh 148
a9e589c… florian 149 /* if requested, inflate again and write decompressed data to stdout */
7ef7284… drh 150 if (put && ret == 0) {
7ef7284… drh 151 if (fail)
7ef7284… drh 152 destlen >>= 1;
7ef7284… drh 153 dest = malloc(destlen);
7ef7284… drh 154 if (dest == NULL) {
7ef7284… drh 155 fprintf(stderr, "memory allocation failure\n");
7ef7284… drh 156 free(source);
7ef7284… drh 157 return 4;
7ef7284… drh 158 }
7ef7284… drh 159 puff(dest, &destlen, source + skip, &sourcelen);
7ef7284… drh 160 SET_BINARY_MODE(stdout);
7ef7284… drh 161 fwrite(dest, 1, destlen, stdout);
7ef7284… drh 162 free(dest);
7ef7284… drh 163 }
7ef7284… drh 164
7ef7284… drh 165 /* clean up */
7ef7284… drh 166 free(source);
7ef7284… drh 167 return ret;
7ef7284… drh 168 }

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button