From c59e0b5643fcba7b95a0e47b3db9258af83d8603 Mon Sep 17 00:00:00 2001
From: Samo Penic <samo.penic@gmail.com>
Date: Sat, 19 Oct 2019 13:04:58 +0000
Subject: [PATCH] Decompression seem to work

---
 src/b64zlib_compression.c |   68 +++++++++++++++++++++++++++------
 1 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/src/b64zlib_compression.c b/src/b64zlib_compression.c
index 5279725..99c1921 100644
--- a/src/b64zlib_compression.c
+++ b/src/b64zlib_compression.c
@@ -29,6 +29,7 @@
 	return defstream.total_out;
 }
 
+/* This function may be used to compress lange strings, however it is not compatible with paraview */
 ts_uint ts_compress_string64(char *data, ts_uint data_len, char **encoded_compressed){
 	size_t nbase;
 	char *compr;
@@ -38,35 +39,80 @@
 	return nbase;
 }
 
+
+/** @brief Compresses and base64 encodes a specific section in VTK file. Function corresponds to rules prescribed by VTK standards.
+ *
+ *  The list of Int8, Int64 and Double precision values (or vectors) are compressed and base64 encoded according to the follow sheme:
+ *
+ * Binary data in the file are compressed when the VTKFile element is of the form
+ * 
+ * <VTKFile ... compressor="vtkZLibDataCompressor">
+ *
+ * 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
+ *
+ * [#blocks][#u-size][#p-size][#c-size-1][#c-size-2]...[#c-size-#blocks][DATA]
+ *
+ * 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:
+ *
+ * [#blocks] = Number of blocks
+ * [#u-size] = Block size before compression
+ * [#p-size] = Size of last partial block (zero if it not needed)
+ * [#c-size-i] = Size in bytes of block i after compression
+ *
+ * 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.
+ *
+ *
+ *  @param *data is a pointer of bytes to original vector containting double, long or char values.
+ *  @param *data_len is a number of bytes in *data pointer, NOT the number of containing values!
+ *  @returns a pointer to string containing base64 encoded compressed string. Should be freed somewhere afterwards.
+*/
 char *ts_compress(char *data, ts_uint data_len){
 	size_t nbase1, nbase2;
 	unsigned char *compr=(unsigned char *)malloc(data_len);
 	size_t number_of_compressed_bytes=data_len;
 
 	compress(compr,&number_of_compressed_bytes, (unsigned char *)data, data_len);
-//	printf("Compressdion error code=%d, Z_OK=%d, Z_BUF_ERROR=%d", errcode, Z_OK, Z_BUF_ERROR);
 
 	char *encoded_compressed=base64_encode((unsigned char *)compr,number_of_compressed_bytes,&nbase1);
 
 	free(compr);
 
 	ts_uint header[4]={1, data_len, data_len, number_of_compressed_bytes};
-
+	fprintf(stderr,"Header before encoding: %d, %d, %d, %d\n", header[0],header[1],header[2], header[3]);
 	char *encoded_header=(char *)base64_encode((unsigned char *)header, 4*sizeof(ts_uint), &nbase2);
 	char *return_value=malloc((nbase1+nbase2+1)*sizeof(char));
 	strncpy(return_value,encoded_header,nbase2);
 	strncpy(return_value+nbase2,encoded_compressed,nbase1);
 	*(return_value+nbase1+nbase2)=0;
 
-//	printf("Compressed size in bytes= %ld, size of encoded header= %ld, size of encoded compressed= %ld.\n",number_of_compressed_bytes, nbase2, nbase1);
 	free(encoded_compressed);
 	free(encoded_header);
+
+	//test decoding and decompression
+	char *test_data = ts_decompress((unsigned char *)return_value, nbase1+nbase2, data_len);
+	free(test_data);
 	return return_value;
+}
+
+char  *ts_decompress(unsigned char *compressed_data, unsigned int data_len, unsigned int result_len){
+	const size_t encoded_header_len=24;
+	ts_uint *header;
+	size_t nbase1=0,nbase2=0;
+	header=(ts_uint *)base64_decode((const char *)compressed_data, encoded_header_len, &nbase2);
+	if(header==NULL) fprintf(stderr, "Error decoding header\n");
+	fprintf(stderr,"Header=%d, %d, %d, %d\n", header[0],header[1], header[2], header[3]);
+	unsigned char *decoded_data=base64_decode((const char *)&compressed_data[encoded_header_len], data_len-encoded_header_len, &nbase1);
+	if(decoded_data==NULL) fprintf(stderr, "Error decoding compressed data\n");
+	unsigned char *return_value=(unsigned char *)malloc(result_len*sizeof(char));
+	uncompress(return_value, (unsigned long *)&result_len, decoded_data, header[3]);
+//	fprintf(stderr,"RESULT_LEN=%d\n",result_len);
+	free(decoded_data);
+	free(header);
+	return (char *)return_value;
 }
 
 ts_uint ts_decompress_string64(char *b64, ts_uint data_len, char **decompressed){
 return TS_SUCCESS;
-
 }
 
 /* base64 encoding, taken from http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c */
@@ -78,7 +124,6 @@
                                 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                 'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                 '4', '5', '6', '7', '8', '9', '+', '/'};
-static char *decoding_table = NULL;
 static int mod_table[] = {0, 2, 1};
 
 
@@ -110,7 +155,7 @@
 
 unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) {
 	int i,j;
-	if (decoding_table == NULL) build_decoding_table();
+	char *decoding_table = build_decoding_table();
 
 	if (input_length % 4 != 0) return NULL;
 
@@ -136,23 +181,20 @@
        	if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
        	if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
     }
-	if(decoding_table !=NULL) free(decoding_table);
+	free(decoding_table);
     return decoded_data;
 }
 
 
-void build_decoding_table() {
-
-    decoding_table = malloc(256);
+char *build_decoding_table() {
+    char *decoding_table = malloc(256);
 	int i;
     for (i = 0; i < 64; i++)
 		decoding_table[(unsigned char) encoding_table[i]] = i;
+	return decoding_table;
 }
 
 
-void base64_cleanup() {
-    free(decoding_table);
-}
 
 
 

--
Gitblit v1.9.3