1 // Copyright 2017 The Wuffs Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // ----------------
16 
17 /*
18 library exercises the software libraries built by `wuffs genlib`.
19 
20 To exercise the static library:
21 
22 $CC -static -I../../.. library.c ../../gen/lib/c/$CC-static/libwuffs.a
23 ./a.out
24 rm -f a.out
25 
26 To exercise the dynamic library:
27 
28 $CC -I../../.. library.c -L../../gen/lib/c/$CC-dynamic -lwuffs
29 LD_LIBRARY_PATH=../../gen/lib/c/$CC-dynamic ./a.out
30 rm -f a.out
31 
32 for a C compiler $CC, such as clang or gcc.
33 */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 // Wuffs ships as a "single file C library" or "header file library" as per
39 // https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
40 //
41 // By #include'ing it "as is" without #define'ing WUFFS_IMPLEMENTATION, we use
42 // it as a "foo.h"-like header, instead of a "foo.c"-like implementation.
43 #if defined(WUFFS_IMPLEMENTATION)
44 #error "example/library should not #define WUFFS_IMPLEMENTATION"
45 #endif
46 #include "wuffs/release/c/wuffs-unsupported-snapshot.c"
47 
48 #ifndef DST_BUFFER_SIZE
49 #define DST_BUFFER_SIZE 1024
50 #endif
51 uint8_t dst_buffer[DST_BUFFER_SIZE];
52 
53 // src_ptr and src_len hold a gzip-encoded "Hello Wuffs."
54 //
55 // $ echo "Hello Wuffs." | gzip --no-name | xxd
56 // 00000000: 1f8b 0800 0000 0000 0003 f348 cdc9 c957  ...........H...W
57 // 00000010: 082f 4d4b 2bd6 e302 003c 8475 bb0d 0000  ./MK+....<.u....
58 // 00000020: 00                                       .
59 //
60 // Passing --no-name to the gzip command line also means to skip the timestamp,
61 // which means that its output is deterministic.
62 uint8_t src_ptr[] = {
63     0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,  // 00..07
64     0x00, 0x03, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57,  // 08..0F
65     0x08, 0x2f, 0x4d, 0x4b, 0x2b, 0xd6, 0xe3, 0x02,  // 10..17
66     0x00, 0x3c, 0x84, 0x75, 0xbb, 0x0d, 0x00, 0x00,  // 18..1F
67     0x00,                                            // 20..20
68 };
69 size_t src_len = 0x21;
70 
71 #define WORK_BUFFER_SIZE WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
72 #if WORK_BUFFER_SIZE > 0
73 uint8_t work_buffer[WORK_BUFFER_SIZE];
74 #else
75 // Not all C/C++ compilers support 0-length arrays.
76 uint8_t work_buffer[1];
77 #endif
78 
decode()79 static const char* decode() {
80   wuffs_base__io_buffer dst;
81   dst.data.ptr = dst_buffer;
82   dst.data.len = DST_BUFFER_SIZE;
83   dst.meta.wi = 0;
84   dst.meta.ri = 0;
85   dst.meta.pos = 0;
86   dst.meta.closed = false;
87 
88   wuffs_base__io_buffer src;
89   src.data.ptr = src_ptr;
90   src.data.len = src_len;
91   src.meta.wi = src_len;
92   src.meta.ri = 0;
93   src.meta.pos = 0;
94   src.meta.closed = true;
95 
96   wuffs_gzip__decoder* dec =
97       (wuffs_gzip__decoder*)(calloc(sizeof__wuffs_gzip__decoder(), 1));
98   if (!dec) {
99     return "out of memory";
100   }
101   const char* status = wuffs_gzip__decoder__initialize(
102       dec, sizeof__wuffs_gzip__decoder(), WUFFS_VERSION,
103       WUFFS_INITIALIZE__ALREADY_ZEROED);
104   if (status) {
105     free(dec);
106     return status;
107   }
108   status = wuffs_gzip__decoder__decode_io_writer(
109       dec, &dst, &src,
110       wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
111   if (status) {
112     free(dec);
113     return status;
114   }
115   fwrite(dst.data.ptr, sizeof(uint8_t), dst.meta.wi, stdout);
116   free(dec);
117   return NULL;
118 }
119 
main(int argc,char ** argv)120 int main(int argc, char** argv) {
121   const char* status = decode();
122   if (status) {
123     fprintf(stderr, "%s\n", status);
124     return 1;
125   }
126   return 0;
127 }
128