Trisurf Monte Carlo simulator
Samo Penic
2019-10-19 2669d703518e4e334a17b8283cca2d4d039a378b
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};
2669d7 81     fprintf(stderr,"Header before encoding: %d, %d, %d, %d\n", header[0],header[1],header[2], header[3]);
dba66b 82     char *encoded_header=(char *)base64_encode((unsigned char *)header, 4*sizeof(ts_uint), &nbase2);
SP 83     char *return_value=malloc((nbase1+nbase2+1)*sizeof(char));
84     strncpy(return_value,encoded_header,nbase2);
85     strncpy(return_value+nbase2,encoded_compressed,nbase1);
86     *(return_value+nbase1+nbase2)=0;
87
88     free(encoded_compressed);
89     free(encoded_header);
2669d7 90
SP 91     //test decoding and decompression
92     char *test_data = ts_decompress((unsigned char *)return_value, nbase1+nbase2, data_len);
93     free(test_data);
94     fprintf(stderr,"WAS HERE!\n");
dba66b 95     return return_value;
2669d7 96 }
SP 97
98 char  *ts_decompress(unsigned char *compressed_data, unsigned int data_len, unsigned int result_len){
99     const size_t encoded_header_len=24;
100     ts_uint *header;
101     size_t nbase1=0,nbase2=0;
102     header=(ts_uint *)base64_decode((const char *)compressed_data, encoded_header_len, &nbase2);
103     if(header==NULL) fprintf(stderr, "Error decoding header\n");
104     fprintf(stderr,"Header=%d, %d, %d, %d\n", header[0],header[1], header[2], header[3]);
105     unsigned char *decoded_data=base64_decode((const char *)&compressed_data[encoded_header_len], data_len-encoded_header_len, &nbase1);
106     unsigned char *return_value=(unsigned char *)malloc(result_len*sizeof(char));
107     uncompress(return_value, (unsigned long *)&result_len, decoded_data, header[3]);
108     free(decoded_data);
109     free(header);
110     return (char *)return_value;
dba66b 111 }
SP 112
113 ts_uint ts_decompress_string64(char *b64, ts_uint data_len, char **decompressed){
114 return TS_SUCCESS;
115 }
116
117 /* base64 encoding, taken from http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c */
118 static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
119                                 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
120                                 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
121                                 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
122                                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
123                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
124                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
125                                 '4', '5', '6', '7', '8', '9', '+', '/'};
126 static char *decoding_table = NULL;
127 static int mod_table[] = {0, 2, 1};
128
129
130 char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) {
131     *output_length = 4 * ((input_length + 2) / 3);
132     int i,j;
133     char *encoded_data = malloc(*output_length);
134     if (encoded_data == NULL) return NULL;
135     
136     for (i = 0, j = 0; i < input_length;) {
137
138            uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
139         uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
140            uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
141         uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
142
143            encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
144            encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
145            encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
146            encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
147     }
148
149     for (i = 0; i < mod_table[input_length % 3]; i++)
150            encoded_data[*output_length - 1 - i] = '=';
151
152     return encoded_data;
153 }
154
155
156 unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) {
157     int i,j;
158     if (decoding_table == NULL) build_decoding_table();
159
160     if (input_length % 4 != 0) return NULL;
161
162     *output_length = input_length / 4 * 3;
163     if (data[input_length - 1] == '=') (*output_length)--;
164     if (data[input_length - 2] == '=') (*output_length)--;
165
166     unsigned char *decoded_data = malloc(*output_length);
167     if (decoded_data == NULL) return NULL;
168
169     for (i = 0, j = 0; i < input_length;) {
170            uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
171            uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
172            uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
173            uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
174
175            uint32_t triple = (sextet_a << 3 * 6)
176             + (sextet_b << 2 * 6)
177             + (sextet_c << 1 * 6)
178             + (sextet_d << 0 * 6);
179
180            if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
181            if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
182            if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
183     }
184     if(decoding_table !=NULL) free(decoding_table);
185     return decoded_data;
186 }
187
188
189 void build_decoding_table() {
190
191     decoding_table = malloc(256);
192     int i;
193     for (i = 0; i < 64; i++)
194         decoding_table[(unsigned char) encoding_table[i]] = i;
195 }
196
197
198 void base64_cleanup() {
199     free(decoding_table);
200 }
201
202
203