1 /*
2   Copyright (C) 2021  The Blosc Developers <blosc@blosc.org>
3   https://blosc.org
4   License: BSD 3-Clause (see LICENSE.txt)
5 
6    Example program demonstrating use of the Blosc filter from C code.
7 
8   To compile this program:
9 
10   $ gcc urfilters.c -o urfilters -lblosc2
11 
12   To run:
13 
14   $ ./urfilters
15 
16  */
17 
18 
19 #include "stdio.h"
20 #include <blosc2.h>
21 
22 #define KB  1024.
23 #define MB  (1024*KB)
24 #define GB  (1024*MB)
25 
26 #define CHUNKSIZE (1000 * 1000)
27 #define NCHUNKS 100
28 #define NTHREADS 4
29 
30 
filter_forward(const uint8_t * src,uint8_t * dest,int32_t size,uint8_t meta,blosc2_cparams * cparams)31 int filter_forward(const uint8_t* src, uint8_t* dest, int32_t size, uint8_t meta, blosc2_cparams *cparams) {
32   blosc2_schunk *schunk = cparams->schunk;
33 
34   for (int i = 0; i < size / schunk->typesize; ++i) {
35     switch (schunk->typesize) {
36       case 8:
37         ((int64_t *) dest)[i] = ((int64_t *) src)[i] + 1;
38         break;
39       case 4:
40         ((int32_t *) dest)[i] = ((int32_t *) src)[i] + 1;
41         break;
42       case 2:
43         ((int16_t *) dest)[i] = ((int16_t *) src)[i] + 1;
44         break;
45       default:
46         BLOSC_TRACE_ERROR("Item size %d not supported", schunk->typesize);
47         return BLOSC2_ERROR_FAILURE;
48     }
49   }
50   return BLOSC2_ERROR_SUCCESS;
51 }
52 
filter_backward(const uint8_t * src,uint8_t * dest,int32_t size,uint8_t meta,blosc2_dparams * dparams)53 int filter_backward(const uint8_t* src, uint8_t* dest, int32_t size, uint8_t meta, blosc2_dparams *dparams) {
54   blosc2_schunk *schunk = dparams->schunk;
55 
56   for (int i = 0; i < size / schunk->typesize; ++i) {
57     switch (schunk->typesize) {
58       case 8:
59         ((int64_t *) dest)[i] = ((int64_t *) src)[i] - 1;
60         break;
61       case 4:
62         ((int32_t *) dest)[i] = ((int32_t *) src)[i] - 1;
63         break;
64       case 2:
65         ((int16_t *) dest)[i] = ((int16_t *) src)[i] - 1;
66         break;
67       default:
68         BLOSC_TRACE_ERROR("Item size %d not supported", schunk->typesize);
69         return BLOSC2_ERROR_FAILURE;
70     }
71   }
72   return BLOSC2_ERROR_SUCCESS;
73 }
74 
main(void)75 int main(void) {
76   static int32_t data[CHUNKSIZE];
77   static int32_t data_dest[CHUNKSIZE];
78   int32_t isize = CHUNKSIZE * sizeof(int32_t);
79   int dsize;
80   int64_t nbytes, cbytes;
81 
82   blosc2_filter urfilter;
83     urfilter.id = 250;
84     urfilter.forward = filter_forward;
85     urfilter.backward = filter_backward;
86 
87   blosc2_register_filter(&urfilter);
88 
89   blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
90   cparams.filters[4] = urfilter.id;
91   cparams.filters_meta[4] = 0;
92 
93   blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;
94 
95 
96   blosc2_schunk* schunk;
97   int i, nchunk;
98   blosc_timestamp_t last, current;
99   double ttotal;
100 
101   printf("Blosc version info: %s (%s)\n", blosc_get_version_string(), BLOSC_VERSION_DATE);
102 
103   /* Create a super-chunk container */
104   cparams.typesize = sizeof(int32_t);
105   cparams.clevel = 9;
106   blosc2_storage storage = {.cparams=&cparams, .dparams=&dparams};
107   schunk = blosc2_schunk_new(&storage);
108 
109   blosc_set_timestamp(&last);
110   for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
111     for (i = 0; i < CHUNKSIZE; i++) {
112       data[i] = i * nchunk;
113     }
114     int nchunks = blosc2_schunk_append_buffer(schunk, data, isize);
115     if (nchunks != nchunk + 1) {
116       printf("Unexpected nchunks!");
117       return -1;
118     }
119   }
120   /* Gather some info */
121   nbytes = schunk->nbytes;
122   cbytes = schunk->cbytes;
123   blosc_set_timestamp(&current);
124   ttotal = blosc_elapsed_secs(last, current);
125   printf("Compression ratio: %.1f MB -> %.1f MB (%.1fx)\n",
126          nbytes / MB, cbytes / MB, (1. * nbytes) / cbytes);
127   printf("Compression time: %.3g s, %.1f MB/s\n",
128          ttotal, nbytes / (ttotal * MB));
129 
130   /* Retrieve and decompress the chunks (0-based count) */
131   blosc_set_timestamp(&last);
132   for (nchunk = NCHUNKS-1; nchunk >= 0; nchunk--) {
133     dsize = blosc2_schunk_decompress_chunk(schunk, nchunk, data_dest, isize);
134     if (dsize < 0) {
135       printf("Decompression error.  Error code: %d\n", dsize);
136       return dsize;
137     }
138   }
139   blosc_set_timestamp(&current);
140   ttotal = blosc_elapsed_secs(last, current);
141   printf("Decompression time: %.3g s, %.1f MB/s\n",
142          ttotal, nbytes / (ttotal * MB));
143 
144   /* Check integrity of the second chunk (made of non-zeros) */
145   blosc2_schunk_decompress_chunk(schunk, 1, data_dest, isize);
146   for (i = 0; i < CHUNKSIZE; i++) {
147     if (data_dest[i] != i) {
148       printf("Decompressed data differs from original %d, %d!\n",
149              i, data_dest[i]);
150       return -1;
151     }
152   }
153 
154   printf("Successful roundtrip data <-> schunk !\n");
155 
156   /* Free resources */
157   /* Destroy the super-chunk */
158   blosc2_schunk_free(schunk);
159 
160   return 0;
161 }
162