Trisurf Monte Carlo simulator
Samo Penic
2019-10-19 4ca00dc38c72f67dc714fbb45b3006afec097c9c
commit | author | age
dba66b 1 #include<stdio.h>
SP 2 #include<stdlib.h>
3 #include<general.h>
4 #include<string.h>
5 #include<zlib.h>
6 #include<inttypes.h>
7 #include<b64zlib_compression.h>
8
9
10 /* zlib compression base64 encoded */
11 /* compressed must not be pre-malloced */
12 /* taken from https://gist.github.com/arq5x/5315739 */
13 /* This function is not to be used in compressing paraview data. See below. */
14 ts_uint ts_compress_data(char *data, ts_uint data_len, char **compressed){
15     z_stream defstream;
16     defstream.zalloc = Z_NULL;
17     defstream.zfree = Z_NULL;
18     defstream.opaque = Z_NULL;
19     defstream.avail_in = data_len+1;
20     defstream.next_in = (unsigned char *)data;    
21     char *compr=(char *)malloc(data_len*sizeof(char));
22     defstream.avail_out = data_len+1;
23     defstream.next_out = (unsigned char *)compr;
24     deflateInit(&defstream, 6);
25 //    deflateInit(&defstream, Z_BEST_COMPRESSION);
26         deflate(&defstream, Z_FINISH);
27         deflateEnd(&defstream);
28     *compressed=compr;
29     return defstream.total_out;
30 }
31
2669d7 32 /* This function may be used to compress lange strings, however it is not compatible with paraview */
dba66b 33 ts_uint ts_compress_string64(char *data, ts_uint data_len, char **encoded_compressed){
SP 34     size_t nbase;
35     char *compr;
36     size_t number_of_compressed_bytes=ts_compress_data(data, data_len, &compr);
37     *encoded_compressed=base64_encode((unsigned char *)compr,number_of_compressed_bytes,&nbase);
38     free(compr);
39     return nbase;
40 }
41
2669d7 42
SP 43 /** @brief Compresses and base64 encodes a specific section in VTK file. Function corresponds to rules prescribed by VTK standards.
44  *
45  *  The list of Int8, Int64 and Double precision values (or vectors) are compressed and base64 encoded according to the follow sheme:
46  *
47  * Binary data in the file are compressed when the VTKFile element is of the form
48  * 
49  * <VTKFile ... compressor="vtkZLibDataCompressor">
50  *
51  * The data corresponding to a data array are stored in a set of blocks which are each compressed using the zlib library. The block structure allows semi-random access without decompressing all data. In uncompressed form all the blocks have the same size except possibly the last block which might be smaller. The data for one array begin with a header of the form
52  *
53  * [#blocks][#u-size][#p-size][#c-size-1][#c-size-2]...[#c-size-#blocks][DATA]
54  *
55  * Each token is an integer value whose type is specified by "header_type" at the top of the file (UInt32 if no type specified). The token meanings are:
56  *
57  * [#blocks] = Number of blocks
58  * [#u-size] = Block size before compression
59  * [#p-size] = Size of last partial block (zero if it not needed)
60  * [#c-size-i] = Size in bytes of block i after compression
61  *
62  * The [DATA] portion stores contiguously every block appended together. The offset from the beginning of the data section to the beginning of a block is computed by summing the compressed block sizes from preceding blocks according to the header.
63  *
64  *
65  *  @param *data is a pointer of bytes to original vector containting double, long or char values.
66  *  @param *data_len is a number of bytes in *data pointer, NOT the number of containing values!
67  *  @returns a pointer to string containing base64 encoded compressed string. Should be freed somewhere afterwards.
68 */
dba66b 69 char *ts_compress(char *data, ts_uint data_len){
SP 70     size_t nbase1, nbase2;
71     unsigned char *compr=(unsigned char *)malloc(data_len);
72     size_t number_of_compressed_bytes=data_len;
73
74     compress(compr,&number_of_compressed_bytes, (unsigned char *)data, data_len);
75
76     char *encoded_compressed=base64_encode((unsigned char *)compr,number_of_compressed_bytes,&nbase1);
77
78     free(compr);
79
80     ts_uint header[4]={1, data_len, data_len, number_of_compressed_bytes};
81     char *encoded_header=(char *)base64_encode((unsigned char *)header, 4*sizeof(ts_uint), &nbase2);
82     char *return_value=malloc((nbase1+nbase2+1)*sizeof(char));
83     strncpy(return_value,encoded_header,nbase2);
84     strncpy(return_value+nbase2,encoded_compressed,nbase1);
85     *(return_value+nbase1+nbase2)=0;
86
87     free(encoded_compressed);
88     free(encoded_header);
2669d7 89
SP 90     //test decoding and decompression
4ca00d 91     //char *test_data = ts_decompress((unsigned char *)return_value, nbase1+nbase2, data_len);
SP 92     //for(int i=0;i<data_len;i++){
93     //    if(data[i]!=test_data[i]){
94     //        fprintf(stderr,"(DE)COMPRESSION ERROR!\n");
95     //    }
96     //}
97     //free(test_data);
dba66b 98     return return_value;
2669d7 99 }
SP 100
101 char  *ts_decompress(unsigned char *compressed_data, unsigned int data_len, unsigned int result_len){
102     const size_t encoded_header_len=24;
103     ts_uint *header;
104     size_t nbase1=0,nbase2=0;
105     header=(ts_uint *)base64_decode((const char *)compressed_data, encoded_header_len, &nbase2);
106     if(header==NULL) fprintf(stderr, "Error decoding header\n");
4ca00d 107     //fprintf(stderr,"Header=%d, %d, %d, %d\n", header[0],header[1], header[2], header[3]);
2669d7 108     unsigned char *decoded_data=base64_decode((const char *)&compressed_data[encoded_header_len], data_len-encoded_header_len, &nbase1);
c59e0b 109     if(decoded_data==NULL) fprintf(stderr, "Error decoding compressed data\n");
2669d7 110     unsigned char *return_value=(unsigned char *)malloc(result_len*sizeof(char));
SP 111     uncompress(return_value, (unsigned long *)&result_len, decoded_data, header[3]);
112     free(decoded_data);
113     free(header);
114     return (char *)return_value;
dba66b 115 }
SP 116
117 ts_uint ts_decompress_string64(char *b64, ts_uint data_len, char **decompressed){
118 return TS_SUCCESS;
119 }
120
121 /* base64 encoding, taken from http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c */
122 static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
123                                 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
124                                 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
125                                 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
126                                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
127                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
128                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
129                                 '4', '5', '6', '7', '8', '9', '+', '/'};
130 static int mod_table[] = {0, 2, 1};
131
132
133 char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) {
134     *output_length = 4 * ((input_length + 2) / 3);
135     int i,j;
136     char *encoded_data = malloc(*output_length);
137     if (encoded_data == NULL) return NULL;
138     
139     for (i = 0, j = 0; i < input_length;) {
140
141            uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
142         uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
143            uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
144         uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
145
146            encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
147            encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
148            encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
149            encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
150     }
151
152     for (i = 0; i < mod_table[input_length % 3]; i++)
153            encoded_data[*output_length - 1 - i] = '=';
154
155     return encoded_data;
156 }
157
158
159 unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) {
160     int i,j;
c59e0b 161     char *decoding_table = build_decoding_table();
dba66b 162
SP 163     if (input_length % 4 != 0) return NULL;
164
165     *output_length = input_length / 4 * 3;
166     if (data[input_length - 1] == '=') (*output_length)--;
167     if (data[input_length - 2] == '=') (*output_length)--;
168
169     unsigned char *decoded_data = malloc(*output_length);
170     if (decoded_data == NULL) return NULL;
171
172     for (i = 0, j = 0; i < input_length;) {
173            uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
174            uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
175            uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
176            uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
177
178            uint32_t triple = (sextet_a << 3 * 6)
179             + (sextet_b << 2 * 6)
180             + (sextet_c << 1 * 6)
181             + (sextet_d << 0 * 6);
182
183            if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
184            if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
185            if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
186     }
c59e0b 187     free(decoding_table);
dba66b 188     return decoded_data;
SP 189 }
190
191
c59e0b 192 char *build_decoding_table() {
SP 193     char *decoding_table = malloc(256);
dba66b 194     int i;
SP 195     for (i = 0; i < 64; i++)
196         decoding_table[(unsigned char) encoding_table[i]] = i;
c59e0b 197     return decoding_table;
dba66b 198 }
SP 199
200
201
202
203