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