blob: 8c5034b7504e4c4bb1e099213f0f0e9ebe200943 [file] [log] [blame]
Yann Collet0809a882016-07-09 18:25:10 +02001/*
2 Dictionary decompression
3 Educational program using zstd library
4 Copyright (C) Yann Collet 2016
5
6 GPL v2 License
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 You can contact the author at :
23 - zstd homepage : http://www.zstd.net/
24*/
25
26#include <stdlib.h> // malloc, exit
Yann Collet974f52f2016-07-07 14:08:00 +020027#include <stdio.h> // printf
28#include <string.h> // strerror
29#include <errno.h> // errno
30#include <sys/stat.h> // stat
Yann Collet0809a882016-07-09 18:25:10 +020031#include <zstd.h> // presumes zstd library is installed
Yann Collet974f52f2016-07-07 14:08:00 +020032
33
Yann Collet0809a882016-07-09 18:25:10 +020034static off_t fsize_X(const char *filename)
Yann Collet974f52f2016-07-07 14:08:00 +020035{
36 struct stat st;
37 if (stat(filename, &st) == 0) return st.st_size;
38 /* error */
39 printf("stat: %s : %s \n", filename, strerror(errno));
40 exit(1);
41}
42
Yann Collet0809a882016-07-09 18:25:10 +020043static FILE* fopen_X(const char *filename, const char *instruction)
Yann Collet974f52f2016-07-07 14:08:00 +020044{
45 FILE* const inFile = fopen(filename, instruction);
46 if (inFile) return inFile;
47 /* error */
48 printf("fopen: %s : %s \n", filename, strerror(errno));
49 exit(2);
50}
51
Yann Collet0809a882016-07-09 18:25:10 +020052static void* malloc_X(size_t size)
Yann Collet974f52f2016-07-07 14:08:00 +020053{
54 void* const buff = malloc(size);
55 if (buff) return buff;
56 /* error */
57 printf("malloc: %s \n", strerror(errno));
58 exit(3);
59}
60
Yann Collet0809a882016-07-09 18:25:10 +020061static void* loadFile_X(const char* fileName, size_t* size)
Yann Collet974f52f2016-07-07 14:08:00 +020062{
Yann Collet0809a882016-07-09 18:25:10 +020063 off_t const buffSize = fsize_X(fileName);
64 FILE* const inFile = fopen_X(fileName, "rb");
65 void* const buffer = malloc_X(buffSize);
Yann Collet974f52f2016-07-07 14:08:00 +020066 size_t const readSize = fread(buffer, 1, buffSize, inFile);
67 if (readSize != (size_t)buffSize) {
68 printf("fread: %s : %s \n", fileName, strerror(errno));
69 exit(4);
70 }
71 fclose(inFile);
72 *size = buffSize;
73 return buffer;
74}
75
Yann Collete66708d2016-07-09 22:56:12 +020076/* createDict() :
77 `dictFileName` is supposed to have been created using `zstd --train` */
Yann Collet974f52f2016-07-07 14:08:00 +020078static const ZSTD_DDict* createDict(const char* dictFileName)
79{
80 size_t dictSize;
Yann Collet5e80dd32016-07-13 17:38:39 +020081 printf("loading dictionary %s \n", dictFileName);
Yann Collet0809a882016-07-09 18:25:10 +020082 void* const dictBuffer = loadFile_X(dictFileName, &dictSize);
Yann Collet974f52f2016-07-07 14:08:00 +020083 const ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize);
84 free(dictBuffer);
85 return ddict;
86}
87
88
Yann Collet974f52f2016-07-07 14:08:00 +020089static void decompress(const char* fname, const ZSTD_DDict* ddict)
90{
91 size_t cSize;
Yann Collet0809a882016-07-09 18:25:10 +020092 void* const cBuff = loadFile_X(fname, &cSize);
Yann Collet974f52f2016-07-07 14:08:00 +020093 unsigned long long const rSize = ZSTD_getDecompressedSize(cBuff, cSize);
94 if (rSize==0) {
95 printf("%s : original size unknown \n", fname);
96 exit(5);
97 }
Yann Collet0809a882016-07-09 18:25:10 +020098 void* const rBuff = malloc_X(rSize);
Yann Collet974f52f2016-07-07 14:08:00 +020099
100 ZSTD_DCtx* const dctx = ZSTD_createDCtx();
101 size_t const dSize = ZSTD_decompress_usingDDict(dctx, rBuff, rSize, cBuff, cSize, ddict);
102
103 if (dSize != rSize) {
104 printf("error decoding %s : %s \n", fname, ZSTD_getErrorName(dSize));
105 exit(7);
106 }
107
108 /* success */
109 printf("%25s : %6u -> %7u \n", fname, (unsigned)cSize, (unsigned)rSize);
110
111 ZSTD_freeDCtx(dctx);
112 free(rBuff);
113 free(cBuff);
114}
115
116
117int main(int argc, const char** argv)
118{
119 const char* const exeName = argv[0];
120
121 if (argc<3) {
122 printf("wrong arguments\n");
123 printf("usage:\n");
124 printf("%s [FILES] dictionary\n", exeName);
125 return 1;
126 }
127
128 /* load dictionary only once */
129 const char* const dictName = argv[argc-1];
130 const ZSTD_DDict* const dictPtr = createDict(dictName);
131
132 int u;
133 for (u=1; u<argc-1; u++) decompress(argv[u], dictPtr);
134
Yann Colletcadd7cd2016-07-15 18:52:37 +0200135 printf("All %u files correctly decoded (in memory) \n", argc-2);
Yann Collet974f52f2016-07-07 14:08:00 +0200136}