diff --git a/.gitignore b/.gitignore
index 3158f7eeea28e78922541cd9d8225765aa61719b..b73bda620d62a0e9e4bc0c7ffd089a3a32bbed1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 ### C ###
 # Executables
 cmp_tool
+!test/cmp_tool
 
 # Prerequisites
 *.d
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fdbf87185732d1d4d5ba817c527ce231a3333131..f74a06c7db46a58d1de9780de5e0f7722cc58da0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
 All notable changes to this project will be documented in this file.
 
 ## [Unreleased]
+## [0.06] - 12-11-2021
+- if samples = 0 the cmp_tool counts the samples in the data file and uses them
+- if buffer_length = 0 the 2*samples parameter is used as buffer_length
+- added feature to guess the compression configuration
+- some code restructuring
+- added more detailed error messages
+- small bug fixes
 ## [0.05] - 23-04-2021
 ### Removed
 - discard old file format. Now the only input format is like: 12 AB 23 CD .. ..
diff --git a/Makefile b/Makefile
index d617c783dfc46652e014b622a76c531026dcacea..28c93b0de9d9d273e1bd1656a0996b0b389bbd14 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,11 @@ CC               = gcc
 SOURCEDIR	       = lib
 INCLUDEDIR       = include
 BUILDDIR         = ./
-CFLAGS          := -Wall -Wextra -std=gnu99 -pedantic -Wshadow
+CFLAGS          := -Wall -Wextra -std=gnu99 -pedantic -Wshadow \
+		    -Wunreachable-code #-Wdocumentation #-Wsign-conversion
 RELCFLAGS       := -O2 # Release flags
 DBCFLAGS        := -O0 -g3 #debug flags
+COVFLAGS        := -fprofile-arcs -ftest-coverage #coverage flags
 CPPFLAGS        := -I $(INCLUDEDIR)
 LDFLAGS         := -lm
 SOURCES         := cmp_tool.c \
@@ -18,7 +20,8 @@ SOURCES         := cmp_tool.c \
 		    $(SOURCEDIR)/cmp_icu.c \
 		    $(SOURCEDIR)/decmp.c \
 		    $(SOURCEDIR)/rdcu_pkt_to_file.c \
-		    $(SOURCEDIR)/tool_lib.c
+		    $(SOURCEDIR)/cmp_guess.c \
+		    $(SOURCEDIR)/cmp_tool_lib.c
 TARGET          := cmp_tool
 
 DEBUG?=1
@@ -34,3 +37,13 @@ all: $(SOURCES)
 
 debug: $(SOURCES)
 	$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $^ -o $(TARGET) $(LDFLAGS)
+
+integration: $(SOURCES)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $(COVFLAGS) $^ -o $(TARGET) $(LDFLAGS)
+	pytest test/cmp_tool/cmp_tool_integration_test.py
+	lcov --rc lcov_branch_coverage=1 --capture --directory ./ --output-file coverage.info
+	genhtml --rc lcov_branch_coverage=1 --branch-coverage coverage.info --output-directory out
+#firefox out/index.html
+
+clean:
+	rm -rf $(TARGET) *.gcno *.gcda coverage.info out
diff --git a/README.md b/README.md
index 440ec46bc5b22ef158c1ed69886ab0f6f0829724..66378e4532ab428e264fa94f5d54744bb6e66d51 100644
--- a/README.md
+++ b/README.md
@@ -1,100 +1,139 @@
 # PLATO Compression/Decompression Tool
 
-If you find a bug or have a feature request please file an [issue][1] or send me an [email][2]   
-Compiled executable can be found [here](https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/tags).
+If you find a bug or have a feature request please file an [issue][1] or send
+me an [email][2].  
+Compiled executables can be found [here][3].
 
 ## Usage
-**usage:** `./cmp_tool [options] [<argument>]`  
-### General Options  
-| Options           | Description                                                                        |
-| ----------------- | ---------------------------------------------------------------------------------- |
-| `-h, --help`      | Print this help text and exit                                                      |
-| `-V, --version`   | Print program version and exit                                                     |
-| `-v, --verbose`   | Print various debugging information                                                |
-| `-n, --model_cfg` | Print a default model configuration and exit<sup>[1](#myfootnote2)</sup>           |
-| `--diff_cfg`      | Print a default 1d-differencing configuration and exit<sup>[1](#myfootnote2)</sup> |
-| `-a, --rdcu_par`  | Print additional RDCU control parameters                                           |
-| `-o <prefix>`     | Use the `<prefix>` for output files<sup>[2](#myfootnote2)</sup>                    |
-
-<a name="myfootnote1">1</a>) **NOTE:** In the default configurations the samples and buffer_length parameter is set to 0!  
-<a name="myfootnote2">2</a>) **NOTE:** If the -o option is not used the `<prefix>` will be set to "OUTPUT".
-
-### Compression Options  
-| Options                     | Description                                                                         |
-| --------------------------- | ----------------------------------------------------------------------------------- |
-| `-c <file>`                 | File containing the compressing configuration                                       |
-| `-d <file>`                 | File containing the data to be compressed                                           |
-| `-m <file>`                 | File containing the model of the data to be compressed                              |
-| `--rdcu_pkt`                | Generate RMAP packets for a RDCU compression<sup>[3](#myfootnote3)</sup>            |
-| `--last_info  <.info file>` | Generate RMAP packets for a RDCU compression with parallel read of the last results |
-
-<a name="myfootnote2">3</a>) **NOTE:** When using the `--rdcu_pkt` option the configuration of the RMAP parameters
-      can be found in the `.rdcu_pkt_mode_cfg file`. The generated packets can be
-      found in the `TC_FILES` directory.
-
-### Decompression Options  
+
+**usage:** `cmp_tool [options] [<argument>]`
+
+### General Options
+
+| Options           | Description                                                                   |
+|:------------------|:------------------------------------------------------------------------------|
+| `-h, --help`      | Print some help text and exit                                                 |
+| `-V, --version`   | Print program version and exit                                                |
+| `-v, --verbose`   | Print various debugging information                                           |
+| `-n, --model_cfg` | Print a default model configuration and exit<sup>[1](#fnote1)</sup>           |
+| `--diff_cfg`      | Print a default 1d-differencing configuration and exit<sup>[1](#fnote1)</sup> |
+| `-a, --rdcu_par`  | Add additional RDCU control parameters                                        |
+| `-o <prefix>`     | Use the `<prefix>` for output files<sup>[2](#fnote2)</sup>                    |
+
+<a name="fnote1">1</a>) **NOTE:** In the default configurations the **samples**
+and **buffer_length** parameter is set to **0**!  
+<a name="fnote2">2</a>) **NOTE:** If the -o option is not used the `<prefix>`
+will be set to "OUTPUT".
+
+### Compression Options
+
+| Options                     | Description                                                                          |
+|:----------------------------|:-------------------------------------------------------------------------------------|
+| `-c <file>`                 | File containing the compressing configuration                                        |
+| `-d <file>`                 | File containing the data to be compressed                                            |
+| `-m <file>`                 | File containing the model of the data to be compressed                               |
+| `--rdcu_pkt`                | Generate RMAP packets for an RDCU compression<sup>[3](#fnoot3)</sup>                 |
+| `--last_info  <.info file>` | Generate RMAP packets for an RDCU compression with parallel read of the last results |
+
+<a name="foot3">3</a>) **NOTE:** When using the `--rdcu_pkt` option the
+configuration of the RMAP parameters can be found in the `.rdcu_pkt_mode_cfg file`.
+The generated packets can be found in the `TC_FILES` directory.
+
+### Decompression Options
+
 | Options     | Description                                      |
-| ----------- | ------------------------------------------------ |
+|:----------- |:-------------------------------------------------|
 | `-i <file>` | File containing the decompression information    |
-| `-d <file>` | File containing the compressed data              |  
-| `-m <file>` | File containing the model of the compressed data |  
+| `-d <file>` | File containing the compressed data              |
+| `-m <file>` | File containing the model of the compressed data |
+
+### Guessing Options
+
+| Options                 | Description                                                                     |
+|:------------------------|:--------------------------------------------------------------------------------|
+| `--guess <mode>`        | Search for a good configuration for compression \<mode\><sup>[4](#fnoot4)</sup> |
+| `-d <file>`             | File containing the data to be compressed                                       |
+| `-m <file>`             | File containing the model of the data to be compressed                          |
+| `--guess_level <level>` | Set guess level to \<level\> (optional)<sup>[5](#fnoot5)</sup>                  |
+
+<a name="fnoot4">4</a>) **NOTE:** \<mode\> can be either the compression mode
+number or the keyword: `RDCU`. The RDCU mode automatically selects the correct
+RDCU-compatible compression mode depending on if the Model (-m) option is set.  
+<a name="fnoot5">5</a>) **Supported levels:** 
 
-### Data Formart
-The input data must be formatted as two hex numbers separated by a space.  
+| guess level | Description                     |
+|:------------|:--------------------------------|
+| `1`         | fast mode (not implemented yet) |
+| `2`         | default mode                    |
+| `3`         | brute force                     |
+
+**Example of Compression Parmeter guessing:**
+
+``./cmp_tool --guess RDCU -d test_data/test_data1.dat -o myguess``
+
+This command creates the file `myguess.cfg` with the guessed compression parameters.
+
+### Data Format
+
+The input data must be formatted as two hex numbers separated by a space.
 For example: `12 AB 34 CD`.
 
 ## How to use the tool
+
 A simple example to show how the compression tool works.
 
-0.   Run `make` to build the tool
+0. Download the [tool][3] or run `make` to build the tool
 
-1.  Create a configuration file 
-*   Create a cfg directory  
+1. Create a configuration file
+* Create a cfg directory  
     `mkdir cfg`
-*  To create a default 1d-differencing mode configuration:  
+* To create a default 1d-differencing mode configuration:  
     `./cmp_tool --diff_cfg > cfg/default_config_1d.cfg`
-*  To create a default model mode configuration:  
+* To create a default model mode configuration:  
     `./cmp_tool --model_cfg > cfg/default_config_model.cfg`
-*  Change the the `samples` and `buffer_length` parameters from `0` to `50` in the `default_config_1d.cfg` and `default_config_model.cfg` files
+* Change the the **`samples`** and **`buffer_length`** parameters from `0` to `50`
+in the `default_config_1d.cfg` and `default_config_model.cfg` files
 
-2.  Compress data with the default configurations:  
-* Create a directory for the compressed data.  
-    `mkdir compressed`  
-*  1d-differencing mode compression  
+2. Compress data with the default configurations:
+* Create a directory for the compressed data  
+    `mkdir compressed`
+* 1d-differencing mode compression  
    `./cmp_tool -c cfg/default_config_1d.cfg -d test_data/test_data1.dat -o compressed/data1`  
-
-    This creates this two files in compressed directory:  
-    `data1.cmp `        -> compressed `test_data1.dat` data  
-    `data1.info`        -> decompression information for `data1.cmp`  
-    
-*  Model mode compression  
+    This creates these two files in the compressed directory:  
+    `data1.cmp`        -> compressed `test_data1.dat` file  
+    `data1.info`       -> decompression information for `data1.cmp`
+* Model mode compression  
    `./cmp_tool -c cfg/default_config_model.cfg -d test_data/test_data2.dat -m test_data/test_data1.dat -o compressed/data2`  
-    We use `test_data1.dat`as the first model for `test_data2.dat`
+    We use `test_data1.dat` as the first model for `test_data2.dat`.
 
-    Creates this three files in compressed directory:  
-    `data2.cmp `        -> compressed `test_data3.dat` data  
+    Creates these three files in the compressed directory:  
+    `data2.cmp `        -> compressed `test_data3.dat` file  
     `data2.info`        -> decompression information for `data2.cmp`  
-    `data2_upmodel.dat` -> updated model used to **compress** the next data in model mode   
-
-3.  Decompress the data
-* Create a directory for the decompressed data.
-    `mkdir decompressed`  
+    `data2_upmodel.dat` -> updated model used to **compress** the next data in model mode
 
-*  Decompress `data1.cmp`  
+3.  Decompress the data  
+* Create a directory for the decompressed data  
+    `mkdir decompressed` 
+* Decompress `data1.cmp`  
     `./cmp_tool -i compressed/data1.info -d compressed/data1.cmp -o decompressed/test_data1`  
-
-*  Decompress `data2.cmp`  
+    Creates this file in the decompressed directory:  
+    `test_data1.dat `  -> decompressed `data1.cmp` file
+* Decompress `data2.cmp`  
     `./cmp_tool -i compressed/data2.info -d compressed/data2.cmp -m decompressed/test_data1.dat -o decompressed/test_data2`  
     As for the compression we use `test_data1.dat` as our model for decompression.  
 
+    Creates these two files in the decompressed directory:  
+    `test_data2.dat `   -> decompressed `data2.cmp` file  
+    `data2_upmodel.dat` -> updated model used to **decompress** the next data in model mode
+
 4. Bonus: Check if the decompressed data are equal to the original data  
     The moment of truth!  
     `diff test_data/test_data1.dat decompressed/test_data1.dat`  
-    `diff test_data/test_data2.dat decompressed/test_data2.dat` 
+    `diff test_data/test_data2.dat decompressed/test_data2.dat`  
 
     And also check if the updated model is the same  
-    `diff compressed/data2_upmodel.dat decompressed/test_data2_upmodel.dat`  
-
+    `diff compressed/data2_upmodel.dat decompressed/test_data2_upmodel.dat`
 
 [1]: <https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/issues> "issues"
 [2]: <mailto:dominik.loidolt@univie.ac.at?subject=%5BIssue%5D%20Cmd_Tool> "email"
+[3]: <https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/releases> "release"
\ No newline at end of file
diff --git a/cmp_tool.c b/cmp_tool.c
index 90ce973e647312a0a279e3cfce7851e3d7618055..a314b8f5b3b844718a4adbd4a67c1fa0a8d7cfbe 100755
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -19,28 +19,37 @@
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <limits.h>
 #include <getopt.h>
 
-#include "include/tool_lib.h"
+#include "include/cmp_tool_lib.h"
 #include "include/cmp_icu.h"
-#include "include/cmp_rdcu.h"
 #include "include/decmp.h"
+#include "include/cmp_guess.h"
+#include "include/rdcu_pkt_to_file.h"
+
+
+#define VERSION "0.06"
+
+#define BUFFER_LENGTH_DEF_FAKTOR 2
 
-#define VERSION "0.05"
 
 /*
  * For long options that have no equivalent short option, use a
  * non-character as a pseudo short option, starting with CHAR_MAX + 1.
  */
 enum {
-	RDCU_PKT_OPTION = CHAR_MAX + 1,
-	DIFF_CFG_OPTION,
-	RDCU_PAR_OPTION,
+	DIFF_CFG_OPTION = CHAR_MAX + 1,
+	GUESS_OPTION,
+	GUESS_LEVEL,
+	RDCU_PKT_OPTION,
 	LAST_INFO,
+
 };
 
-static struct option const long_options[] = {
+static const struct option long_options[] = {
 	{"rdcu_par", no_argument, NULL, 'a'},
 	{"model_cfg", no_argument, NULL, 'n'},
 	{"help", no_argument, NULL, 'h'},
@@ -48,9 +57,41 @@ static struct option const long_options[] = {
 	{"version", no_argument, NULL, 'V'},
 	{"rdcu_pkt", no_argument, NULL, RDCU_PKT_OPTION},
 	{"diff_cfg", no_argument, NULL, DIFF_CFG_OPTION},
-	{"last_info", required_argument, NULL, LAST_INFO}
+	{"guess", required_argument, NULL, GUESS_OPTION},
+	{"guess_level", required_argument, NULL, GUESS_LEVEL},
+	{"last_info", required_argument, NULL, LAST_INFO},
+	{NULL, 0, NULL, 0}
 };
 
+/* prefix of the generated output file names */
+static const char *output_prefix = DEFAULT_OUTPUT_PREFIX;
+
+/* if non zero additional RDCU parameters are included in the compression
+ * configuration and decompression information files */
+static int print_rdcu_cfg;
+
+/* if non zero generate RDCU setup packets */
+static int rdcu_pkt_mode;
+
+/* file name of the last compression information file to generate parallel RDCU
+ * setup packets */
+static const char *last_info_file_name;
+
+/* if non zero print additional verbose output */
+static int verbose_en;
+
+
+/* find a good set of compression parameters for a given dataset */
+static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
+			  int guess_level);
+
+/* compress the data and write the results to files */
+static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
+
+/* decompress the data and write the results in file(s)*/
+static int decompression(uint32_t *decomp_input_buf, uint16_t *input_model_buf,
+			 struct cmp_info *info);
+
 
 /**
  * @brief This is the main function of the compression / decompression tool
@@ -64,38 +105,37 @@ static struct option const long_options[] = {
 
 int main(int argc, char **argv)
 {
-	int32_t opt;
+	int opt;
+	int error;
 
 	const char *cfg_file_name = NULL;
 	const char *info_file_name = NULL;
 	const char *data_file_name = NULL;
 	const char *model_file_name = NULL;
-	const char *last_info_file_name = NULL;
-	const char *output_prefix = DEFAULT_OUTPUT_PREFIX;
+	const char *guess_cmp_mode = NULL;
+	const char *program_name = argv[0];
 
+	int cmp_operation = 0;
 	int print_model_cfg = 0;
+	int guess_operation = 0;
+	int guess_level = DEFAULT_GUESS_LEVEL;
 	int print_diff_cfg = 0;
-	int print_rdcu_cfg = 1;
-	int cmp_operation = 0;
-	int verbose_en = 0;
-	int rdcu_pkt_mode = 0;
 
 	struct cmp_cfg cfg = {0}; /* compressor configuration struct */
 	struct cmp_info info = {0}; /* decompression information struct */
-	struct cmp_info last_info = {0}; /* last decompression information struct */
-	int error;
 
 	uint32_t *decomp_input_buf = NULL;
 	uint16_t *input_model_buf = NULL;
+	ssize_t size;
 
 	/* show help if no arguments are provided */
 	if (argc < 2) {
-		Print_Help(*argv);
+		print_help(program_name);
 		exit(EXIT_FAILURE);
 	}
 
-	while ((opt = getopt_long (argc, argv, "ac:d:hi:m:no:vV", long_options,
-				   NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "ac:d:hi:m:no:vV", long_options,
+				  NULL)) != -1) {
 		switch (opt) {
 		case 'a': /* --rdcu_par */
 			print_rdcu_cfg = 1;
@@ -108,7 +148,7 @@ int main(int argc, char **argv)
 			data_file_name = optarg;
 			break;
 		case 'h': /* --help */
-			Print_Help(*argv);
+			print_help(argv[0]);
 			exit(EXIT_SUCCESS);
 			break;
 		case 'i':
@@ -127,12 +167,19 @@ int main(int argc, char **argv)
 			verbose_en = 1;
 			break;
 		case 'V': /* --version */
-			printf("%s %s\n", PROGRAM_NAME, VERSION);
+			printf("%s version %s\n", PROGRAM_NAME, VERSION);
 			exit(EXIT_SUCCESS);
 			break;
 		case DIFF_CFG_OPTION:
 			print_diff_cfg = 1;
 			break;
+		case GUESS_OPTION:
+			guess_operation = 1;
+			guess_cmp_mode = optarg;
+			break;
+		case GUESS_LEVEL:
+			guess_level = atoi(optarg);
+			break;
 		case RDCU_PKT_OPTION:
 			rdcu_pkt_mode = 1;
 			break;
@@ -141,11 +188,39 @@ int main(int argc, char **argv)
 			last_info_file_name = optarg;
 			break;
 		default:
-			Print_Help(*argv);
+			print_help(program_name);
 			exit(EXIT_FAILURE);
 			break;
 		}
 	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc > 0) {
+		printf("%s: To many arguments.\n", PROGRAM_NAME);
+		print_help(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+#if 0
+	if (argc > 0) {
+		if(!data_file_name)
+			data_file_name = argv[0];
+		else {
+			printf("You can define the data file using either the -d option or the first argument, but not both.\n");
+			print_help(program_name);
+			exit(EXIT_FAILURE);
+		}
+	}
+	if (argc > 1) {
+		if(!model_file_name)
+			model_file_name = argv[1];
+		else {
+			printf("You can define the model file using either the -m option or the second argument, but not both.\n");
+			print_help(program_name);
+			exit(EXIT_FAILURE);
+		}
+	}
+#endif
 
 	if (print_model_cfg == 1) {
 		print_cfg(&DEFAULT_CFG_MODEL, print_rdcu_cfg);
@@ -162,275 +237,370 @@ int main(int argc, char **argv)
 	       VERSION);
 	printf("#########################################################\n\n");
 
-	if (!cfg_file_name && !info_file_name) {
-		fprintf(stderr, "%s: No configuration file (-c option) or decompression information file (-i option) specified.\n",
-			PROGRAM_NAME);
-		exit(EXIT_FAILURE);
-	}
-
 	if (!data_file_name) {
 		fprintf(stderr, "%s: No data file (-d option) specified.\n",
 			PROGRAM_NAME);
 			exit(EXIT_FAILURE);
 	}
 
-	/* read input data and .cfg or .info */
-	if (cmp_operation) { /* compression mode */
-		printf("### Compression ###\n");
-		printf("Importing configuration file %s ... ", cfg_file_name);
+	if (!cfg_file_name && !info_file_name && !guess_operation) {
+		fprintf(stderr, "%s: No configuration file (-c option) or decompression information file (-i option) specified.\n",
+			PROGRAM_NAME);
+		exit(EXIT_FAILURE);
+	}
 
-		error = read_cmp_cfg(cfg_file_name, &cfg, verbose_en);
-		if (error) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
-			printf("DONE\n");
+	/* read input data and .cfg or .info */
+	if (cmp_operation || guess_operation) { /* compression mode */
+		if (cmp_operation) {
+			/* printf("### Compression ###\n"); */
+			printf("Importing configuration file %s ... ", cfg_file_name);
+			error = read_cmp_cfg(cfg_file_name, &cfg, verbose_en);
+			if (error)
+				goto fail;
+			else
+				printf("DONE\n");
 
+		}
 
 		printf("Importing data file %s ... ", data_file_name);
 
-		cfg.input_buf = read_file16(data_file_name, cfg.samples,
-					   verbose_en);
+		/* count the samples in the data file when samples == 0 */
+		if (cfg.samples == 0) {
+			size = read_file16(data_file_name, NULL, 0, 0);
+			if (size < 0)
+				goto fail;
+			if (size%size_of_a_sample(cfg.cmp_mode) != 0) {
+				fprintf(stderr, "\n%s: %s: Error: The data file is not correct formatted. Expected multiple of %zu hex words.\n",
+					PROGRAM_NAME, data_file_name, size_of_a_sample(cfg.cmp_mode));
+				goto fail;
+			}
+
+			cfg.samples = size/size_of_a_sample(cfg.cmp_mode);
+			printf("\nNo samples parameter set. Use samples = %u.\n... ",
+			       cfg.samples);
+		}
+
+		cfg.input_buf = malloc(cfg.samples * size_of_a_sample(cfg.cmp_mode));
 		if (!cfg.input_buf) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
+			fprintf(stderr, "%s: Error allocating memory for input data buffer.\n", PROGRAM_NAME);
+			goto fail;
+		}
+
+		size = read_file16(data_file_name, cfg.input_buf, cfg.samples,
+				   verbose_en);
+		if (size < 0)
+			goto fail;
+		else
 			printf("DONE\n");
 
 	} else { /* decompression mode*/
 		uint32_t cmp_size_byte;
 
-		printf("### Decompression ###\n\n");
-		printf("Importing decompression information file ... ");
+		/* printf("### Decompression ###\n\n"); */
+		printf("Importing decompression information file %s ... ", info_file_name);
 
 		error  = read_cmp_info(info_file_name, &info, verbose_en);
-		if (error) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
+		if (error)
+			goto fail;
+		else
 			printf("DONE\n");
 
-
 		printf("Importing compressed data file %s ... ", data_file_name);
-
+		/* cmp_size unit is in bits */
 		cmp_size_byte = (info.cmp_size + 31) / 8;
-
-		decomp_input_buf = read_file32(data_file_name, cmp_size_byte/4,
-					      verbose_en);
+		decomp_input_buf = malloc(cmp_size_byte);
 		if (!decomp_input_buf) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
+			fprintf(stderr, "%s: Error allocating memory for decompression input buffer.\n", PROGRAM_NAME);
+			goto fail;
+		}
+
+		size = read_file32(data_file_name, decomp_input_buf,
+				   cmp_size_byte/4, verbose_en);
+		if (size < 0)
+			goto fail;
+		else
 			printf("DONE\n");
 	}
 
-	/* read in model for compressed and decompression */
+	/* read in model */
 	if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
-	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used))) {
+	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)) ||
+	    (guess_operation && model_file_name)) {
 		uint32_t model_length;
 
-		if (cmp_operation)
-			model_length = cfg.samples;
-		else
-			model_length = info.samples_used;
-
 		if (!model_file_name) {
-			fprintf(stderr, "%s: No model file (-m "
-				"option) specified.\n", PROGRAM_NAME);
-			exit(EXIT_FAILURE);
+			fprintf(stderr, "%s: No model file (-m option) specified.\n", PROGRAM_NAME);
+			goto fail;
 		}
 
 		printf("Importing model file %s ... ", model_file_name);
 
+		if (cmp_operation || guess_operation)
+			model_length = cfg.samples;
+		else
+			model_length = info.samples_used;
 
-		input_model_buf = read_file16(model_file_name, model_length,
-					     verbose_en);
+		input_model_buf = malloc(model_length * size_of_a_sample(cfg.cmp_mode));
 		if (!input_model_buf) {
-			printf("FAILED\n");
-			free(cfg.input_buf);
-			free(decomp_input_buf);
-			exit(EXIT_FAILURE);
-		} else
+			fprintf(stderr, "%s: Error allocating memory for model buffer.\n", PROGRAM_NAME);
+			goto fail;
+		}
+
+		size = read_file16(model_file_name, input_model_buf, model_length, verbose_en);
+		if (size < 0)
+			goto fail;
+		else
 			printf("DONE\n");
 
-		if (cmp_operation)
+		if (cmp_operation || guess_operation)
 			cfg.model_buf = input_model_buf;
 	}
 
-	if (cmp_operation) { /* perform a compression */
-		uint32_t cmp_size_byte;
+	if (guess_operation) {
+		error = guess_cmp_pars(&cfg, guess_cmp_mode, guess_level);
+		if (error)
+			goto fail;
+	} else if (cmp_operation) { /* perform a compression */
+		error = compression(&cfg, &info);
+		if (error)
+			goto fail;
+	} else { /* perform a decompression */
+		error = decompression(decomp_input_buf, input_model_buf, &info);
+		if (error)
+			goto fail;
+	}
 
-		if (rdcu_pkt_mode) {
-			printf("Generate compression setup packets ... \n");
-			error = init_rmap_pkt_to_file();
-			if (error) {
-				printf("... FAILED\n");
-				fprintf(stderr, "%s: Read RMAP packet config file .rdcu_pkt_mode_cfg failed.\n",
-					PROGRAM_NAME);
-				free(cfg.input_buf);
-				free(input_model_buf);
-				exit(EXIT_FAILURE);
-			}
+	/* write our the updated model for compressed or decompression */
+	if (!guess_operation &&
+	    ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
+	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)))) {
+		printf("Write updated model to file %s_upmodel.dat ... ",
+		       output_prefix);
+		error = write_to_file16(input_model_buf, info.samples_used,
+					output_prefix, "_upmodel.dat", verbose_en);
+		if (error)
+			goto fail;
+		else
+			printf("DONE\n");
+	}
 
-			if (last_info_file_name) {
-				error  = read_cmp_info(last_info_file_name,
-						       &last_info, verbose_en);
-				if (error) {
-					printf("... FAILED\n");
-					fprintf(stderr, "%s: %s: Importing last decompression information file failed.\n",
-						PROGRAM_NAME, last_info_file_name);
-					exit(EXIT_FAILURE);
-				}
-
-				error = gen_rdcu_parallel_pkts(&cfg, &last_info);
-				if (error) {
-					printf("... FAILED\n");
-					free(cfg.input_buf);
-					free(input_model_buf);
-					exit(EXIT_FAILURE);
-				}
-			}
+	free(cfg.input_buf);
+	free(decomp_input_buf);
+	free(input_model_buf);
 
-			error = gen_write_rdcu_pkts(&cfg);
+	exit(EXIT_SUCCESS);
 
-			if (error) {
-				printf("... FAILED\n");
-				free(cfg.input_buf);
-				free(input_model_buf);
-				exit(EXIT_FAILURE);
-			} else
-				printf("... DONE\n");
-		}
+fail:
+	printf("FAILED\n");
 
-		cfg.icu_output_buf = (uint32_t *)malloc(cfg.buffer_length *
-							SAM2BYT);
-		if (cfg.icu_output_buf == NULL) {
-			printf("%s: Error allocating Memory for Output Buffer."
-			       "\n", PROGRAM_NAME);
-			free(cfg.input_buf);
-			free(input_model_buf);
-			abort();
-		}
+	free(cfg.input_buf);
+	free(decomp_input_buf);
+	free(input_model_buf);
 
-		printf("Compress data ... ");
+	exit(EXIT_FAILURE);
+}
 
-		error = icu_compress_data(&cfg, &info);
-		free(cfg.input_buf);
-		if (error || info.cmp_err != 0) {
-			printf("FAILED\n");
-			printf("Compression error %#X\n", info.cmp_err);
-			free(input_model_buf);
-			free(cfg.icu_output_buf);
-			exit(EXIT_FAILURE);
-		} else
-			printf("DONE\n");
 
-		if (rdcu_pkt_mode) {
-			printf("Generate the read results packets ... ");
-			error = gen_read_rdcu_pkts(&info);
-			if (error) {
-				printf("FAILED\n");
-				free(input_model_buf);
-				free(cfg.icu_output_buf);
-				exit(EXIT_FAILURE);
-			} else
-				printf("DONE\n");
-		}
-		printf("Write compressed data to file %s.cmp ... ",
-		       output_prefix);
+/* generate packets to setup a RDCU compression */
+static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
+{
+	int error;
+
+	error = init_rmap_pkt_to_file();
+	if (error) {
+		fprintf(stderr, "%s: Read RMAP packet config file .rdcu_pkt_mode_cfg failed.\n",
+			PROGRAM_NAME);
+		return -1;
+	}
 
-		/* length of cmp_size in bytes words (round up to 4 bytes) */
-		cmp_size_byte = (info.cmp_size + 31)/32 * 4;
+	if (last_info_file_name) {
+		/* generation of packets for parallel read/write RDCU setup */
+		struct cmp_info last_info = {0};
 
-		error = write_cmp_data_file(cfg.icu_output_buf, cmp_size_byte,
-					output_prefix, ".cmp", verbose_en);
-		free(cfg.icu_output_buf);
+		error  = read_cmp_info(last_info_file_name, &last_info, verbose_en);
 		if (error) {
-			printf("FAILED\n");
-			free(input_model_buf);
-			exit(EXIT_FAILURE);
-		} else
-			printf("DONE\n");
-
-		if (model_mode_is_used(cfg.cmp_mode)) {
-			printf("Write updated model to file  %s_upmodel.dat ... "
-			       , output_prefix);
-			error = write_to_file16(input_model_buf, info.samples_used,
-						output_prefix, "_upmodel.dat",
-						verbose_en);
-			free(input_model_buf);
-			if (error) {
-				printf("FAILED\n");
-				exit(EXIT_FAILURE);
-			} else
-				printf("DONE\n");
+			fprintf(stderr, "%s: %s: Importing last decompression information file failed.\n",
+				PROGRAM_NAME, last_info_file_name);
+			return -1;
 		}
 
-		printf("Write decompression information to file %s.info ... ",
-		       output_prefix);
+		error = gen_rdcu_parallel_pkts(cfg, &last_info);
+		if (error)
+			return -1;
+	}
 
-		error = write_info(&info, output_prefix, print_rdcu_cfg);
-		if (error) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
-			printf("DONE\n");
+	/* generation of packets for non-parallel read/write RDCU setup */
+	error = gen_write_rdcu_pkts(cfg);
+	if (error)
+		return -1;
 
-		if (verbose_en) {
-			printf("\n");
-			print_cmp_info(&info);
-			printf("\n");
-		}
-	} else { /* perform a decompression */
-		uint16_t *decomp_output;
-
-		decomp_output = (uint16_t *)malloc(info.samples_used * SAM2BYT);
-		if (decomp_output == NULL) {
-			printf("Error allocating Memory for decmpr Model Buffer\n");
-			free(decomp_input_buf);
-			free(input_model_buf);
-			abort();
+	return 0;
+}
+
+
+/* find a good set of compression parameters for a given dataset */
+static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
+			  int guess_level)
+{
+	int error;
+	uint32_t cmp_size;
+	float cr;
+
+	printf("Search for a good set of compression parameters (level: %d) ... ", guess_level);
+	if (!strcmp(guess_cmp_mode, "RDCU")) {
+		if (cfg->model_buf)
+			cfg->cmp_mode = CMP_GUESS_DEF_MODE_MODEL;
+		else
+			cfg->cmp_mode = CMP_GUESS_DEF_MODE_DIFF;
+	} else {
+		error = cmp_mode_parse(guess_cmp_mode, &cfg->cmp_mode);
+		if (error) {
+			fprintf(stderr, "%s: Error: unknown compression mode: %s\n", PROGRAM_NAME, guess_cmp_mode);
+			return -1;
 		}
+	}
+	if (model_mode_is_used(cfg->cmp_mode) && !cfg->model_buf) {
+		fprintf(stderr, "%s: Error: model mode needs model data (-m option)\n", PROGRAM_NAME);
+		return -1;
+	}
 
-		printf("Decompress data ... ");
+	cmp_size = cmp_guess(cfg, guess_level);
+	if (!cmp_size)
+		return -1;
+	printf("DONE\n");
 
-		error = decompress_data(decomp_input_buf, input_model_buf,
-					&info, decomp_output);
-		free(decomp_input_buf);
-		if (error != 0) {
-			free(decomp_output);
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
-			printf("DONE\n");
+	printf("Write the guessed compression configuration to file %s.cfg ... ", output_prefix);
+	error = write_cfg(cfg, output_prefix, print_rdcu_cfg, verbose_en);
+	if (error)
+		return -1;
+	printf("DONE\n");
 
-		printf("Write decompressed data to file %s.dat ... ",
-		       output_prefix);
+	cr = (8.0 * cfg->samples * size_of_a_sample(cfg->cmp_mode))/cmp_size;
+	printf("Guessed parameters can compress the data with a CR of %.2f.\n", cr);
 
-		error = write_to_file16(decomp_output, info.samples_used,
-					output_prefix, ".dat", verbose_en);
-		free(decomp_output);
-		if (error) {
-			printf("FAILED\n");
-			exit(EXIT_FAILURE);
-		} else
+	return 0;
+}
+
+
+/* compress the data and write the results to files */
+static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
+{
+	int error;
+	uint32_t cmp_size_byte;
+
+	cfg->icu_output_buf = NULL;
+
+	if (cfg->buffer_length == 0) {
+		cfg->buffer_length = (cfg->samples+1) * BUFFER_LENGTH_DEF_FAKTOR; /* +1 to prevent malloc(0)*/
+		printf("No buffer_length parameter set. Use buffer_length = %u as compression buffer size.\n",
+		       cfg->buffer_length);
+	}
+
+	if (rdcu_pkt_mode) {
+		printf("Generate compression setup packets ...\n");
+		error = gen_rdcu_write_pkts(cfg);
+		if (error)
+			goto error_cleanup;
+		else
+			printf("... DONE\n");
+	}
+
+	printf("Compress data ... ");
+
+	cfg->icu_output_buf = malloc(cfg->buffer_length * size_of_a_sample(cfg->cmp_mode));
+	if (cfg->icu_output_buf == NULL) {
+		fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	}
+
+	error = icu_compress_data(cfg, info);
+	if (error || info->cmp_err != 0) {
+		printf("\nCompression error 0x%02X\n... ", info->cmp_err);
+		if ((info->cmp_err >> SMALL_BUFFER_ERR_BIT) & 1U)
+			fprintf(stderr, "%s: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	} else
+		printf("DONE\n");
+
+	if (rdcu_pkt_mode) {
+		printf("Generate the read results packets ... ");
+		error = gen_read_rdcu_pkts(info);
+		if (error)
+			goto error_cleanup;
+		else
 			printf("DONE\n");
+	}
 
-		if (model_mode_is_used(info.cmp_mode_used)) {
-			printf("Write updated model to file %s_upmodel.dat ... "
-			       , output_prefix);
-			error = write_to_file16(input_model_buf,
-						info.samples_used,
-						output_prefix, "_upmodel.dat",
-						verbose_en);
-			free(input_model_buf);
-			if (error) {
-				printf("FAILED\n");
-				exit(EXIT_FAILURE);
-			} else
-				printf("DONE\n");
-		}
+	printf("Write compressed data to file %s.cmp ... ", output_prefix);
+	/* length of cmp_size in bytes words (round up to 4 bytes) */
+	cmp_size_byte = (info->cmp_size + 31)/32 * 4;
+	error = write_cmp_data_file(cfg->icu_output_buf, cmp_size_byte,
+				    output_prefix, ".cmp", verbose_en);
+	if (error)
+		goto error_cleanup;
+	else
+		printf("DONE\n");
+	free(cfg->icu_output_buf);
+	cfg->icu_output_buf = NULL;
+
+	printf("Write decompression information to file %s.info ... ",
+	       output_prefix);
+	error = write_info(info, output_prefix, print_rdcu_cfg);
+	if (error)
+		goto error_cleanup;
+	else
+		printf("DONE\n");
+
+	if (verbose_en) {
+		printf("\n");
+		print_cmp_info(info);
+		printf("\n");
 	}
 
-	exit(EXIT_SUCCESS);
+	return 0;
+
+error_cleanup:
+	free(cfg->icu_output_buf);
+	return -1;
+}
+
+
+/* decompress the data and write the results in file(s)*/
+static int decompression(uint32_t *decomp_input_buf, uint16_t *input_model_buf,
+			 struct cmp_info *info)
+{
+	int error;
+	uint16_t *decomp_output;
+
+	printf("Decompress data ... ");
+
+	if (info->samples_used == 0)
+		return 0; /* nothing to decompress */
+
+	decomp_output = malloc(info->samples_used *
+			       size_of_a_sample(info->cmp_mode_used));
+	if (decomp_output == NULL) {
+		fprintf(stderr, "%s: Error allocating memory for decompressed data.\n", PROGRAM_NAME);
+		return -1;
+	}
+
+	error = decompress_data(decomp_input_buf, input_model_buf, info,
+				decomp_output);
+	if (error) {
+		free(decomp_output);
+		return -1;
+	}
+	printf("DONE\n");
+
+	printf("Write decompressed data to file %s.dat ... ", output_prefix);
+
+	error = write_to_file16(decomp_output, info->samples_used,
+				output_prefix, ".dat", verbose_en);
+	free(decomp_output);
+	if (error)
+		return -1;
+
+	printf("DONE\n");
+
+	return 0;
 }
diff --git a/include/cmp_guess.h b/include/cmp_guess.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe2ed0989a6b8ab188c92a33cb0b43a3ba2414e1
--- /dev/null
+++ b/include/cmp_guess.h
@@ -0,0 +1,38 @@
+/**
+ * @file   cmp_guess.h
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
+ * @date   2020
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief helps the user to find a good compression parameters for a given
+ *	dataset
+ */
+
+#ifndef CMP_GUESS_H
+#define CMP_GUESS_H
+
+#include "cmp_support.h"
+
+#define DEFAULT_GUESS_LEVEL 2
+
+#define CMP_GUESS_DEF_MODE_DIFF		MODE_DIFF_ZERO
+#define CMP_GUESS_DEF_MODE_MODEL	MODE_MODEL_MULTI
+
+/* how often the model is updated before it is reset default value */
+#define CMP_GUESS_N_MODEL_UPDATE_DEF	8
+
+uint32_t cmp_guess(struct cmp_cfg *cfg, int level);
+void cmp_guess_set_model_updates(int n_model_updates);
+
+uint16_t cmp_guess_model_value(int n_model_updates);
+
+#endif /* CMP_GUESS_H */
diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index a2acd62bef5653127ecd061b2829f4c0eb2d58ab..cd7f193e10ba3e6b89a863c1f259d948f7c0ce8f 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -25,4 +25,9 @@
 
 int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info);
 
+
+int cmp_pre_process(struct cmp_cfg *cfg);
+int cmp_map_to_pos(struct cmp_cfg *cfg);
+uint32_t cmp_encode_data(struct cmp_cfg *cfg);
+
 #endif /* _CMP_ICU_H_ */
diff --git a/include/cmp_support.h b/include/cmp_support.h
index 62dd1e6b08c4c3539f3fe0331979640e16fcacfa..aeafd0df6209cc39b14ed8648ad06d69f748fe29 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -62,6 +62,8 @@
 #define SAM2BYT                                                                \
 	2 /* sample to byte conversion factor; one samples has 16 bits (2 bytes) */
 
+#define CMP_GOOD_SPILL_DIFF_MULTI 2 /* good guess for the spill parameter using the MODE_DIFF_MULTI */
+
 /**
  * @brief The cmp_cfg structure can contain the complete configuration of the HW as
  *      well as the SW compressor.
@@ -163,6 +165,7 @@ int model_mode_is_used(unsigned int cmp_mode);
 int diff_mode_is_used(unsigned int cmp_mode);
 int raw_mode_is_used(unsigned int cmp_mode);
 int rdcu_supported_mode_is_used(unsigned int cmp_mode);
+int cmp_mode_available(unsigned int cmp_mode);
 
 int zero_escape_mech_is_used(unsigned int cmp_mode);
 int multi_escape_mech_is_used(unsigned int cmp_mode);
@@ -173,6 +176,7 @@ unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
 			  model_value);
 
 uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode);
+uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode);
 
 size_t size_of_a_sample(unsigned int cmp_mode);
 unsigned int size_of_bitstream(unsigned int cmp_size);
diff --git a/include/tool_lib.h b/include/cmp_tool_lib.h
similarity index 68%
rename from include/tool_lib.h
rename to include/cmp_tool_lib.h
index 3592078d00c03734ef461f0b54544dee30d6e44d..b8eadaadd57c93fdf3f4e661bdf3db575f4bba09 100644
--- a/include/tool_lib.h
+++ b/include/cmp_tool_lib.h
@@ -1,5 +1,5 @@
 /**
- * @file   tool_lib.h
+ * @file   cmp_tool_lib.h
  * @author Johannes Seelig (johannes.seelig@univie.ac.at)
  * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
  * @date   2020
@@ -15,32 +15,37 @@
  * more details.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 #include "cmp_support.h"
-#include "rdcu_pkt_to_file.h"
 
 #define PROGRAM_NAME "cmp_tool"
 #define MAX_CONFIG_LINE 256
 
 #define DEFAULT_OUTPUT_PREFIX "OUTPUT"
 
-void Print_Help(const char *argv);
+#define BUFFER_LENGTH_DEF_FAKTOR 2
+
+void print_help(const char *program_name);
 
 int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en);
 int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en);
 
-uint16_t * read_file16(const char *file_name, uint32_t samples, int verbose_en);
-uint32_t * read_file32(const char *file_name, uint32_t buf_len, int verbose_en);
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word,
+		   int verbose_en);
+ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
+		    int verbose_en);
+ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
+		    int verbose_en);
 
 int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
 			*output_prefix, const char *name_extension, int verbose);
 int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 		    *output_prefix, const char *name_extension, int verbose);
-
+int write_info(const struct cmp_info *info, const char *output_prefix,
+	       int rdcu_cfg);
+int write_cfg(const struct cmp_cfg *cfg, const char *output_prefix, int rdcu_cfg,
+	      int verbose);
 void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg);
 
-int write_info(const struct cmp_info *info, const char *output_prefix,
-	       int machine_cfg);
+uint32_t cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode);
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index e6bbe92215cb85640123e9842d062f55666130e4..1df363cb274aa698815432ef3e9ed51557c88d5b 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -17,9 +17,6 @@
  */
 
 
-#include <stddef.h>
-#include <stdio.h>
-
 #include "../include/cmp_data_types.h"
 #include "../include/cmp_support.h"
 #include "../include/cmp_debug.h"
@@ -88,7 +85,7 @@ int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
 
 	for (i = 0; i < samples_used; i++) {
 		/* check if data are not to big for a overflow */
-		uint16_t mask = (uint16_t)(~0 << (16-round_used));
+		uint16_t mask = (uint16_t)(~0U << (16-round_used));
 		if (data_buf[i] & mask) {
 			debug_print("de_lossy_rounding_16 failed!\n");
 			return -1;
@@ -152,7 +149,7 @@ int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
 
 	for (i = 0; i < samples_used; i++) {
 		/* check if data are not to big for a overflow */
-		uint32_t mask = (uint32_t)(~0 << (32-round_used));
+		uint32_t mask = (uint32_t)(~0U << (32-round_used));
 		if (data_buf[i] & mask) {
 			debug_print("de_lossy_rounding_32 failed!\n");
 			return -1;
@@ -295,7 +292,7 @@ struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
  * @note change the data buffer in-place
  * @note the exposure_flags are not rounded
  *
- * @param  data_buf	a S_FX_EFX formatted data buffer
+ * @param  data		S_FX_EFX formatted data buffer
  * @param  samples	the size of the data buffer measured in S_FX_EFX samples
  * @param  round	number of bits to round; if zero no rounding takes place
  *
@@ -318,8 +315,7 @@ int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
 	if (round == 0)
 		return 0;
 
-	for (i = 0; i < samples; i++)
-	{
+	for (i = 0; i < samples; i++) {
 		data[i].FX = round_fwd(data[i].FX, round);
 		data[i].EFX = round_fwd(data[i].EFX, round);
 	}
@@ -431,8 +427,7 @@ int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
 	if (round == 0)
 		return 0;
 
-	for (i = 0; i < samples; i++)
-	{
+	for (i = 0; i < samples; i++) {
 		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
 		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
 		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
@@ -559,8 +554,7 @@ int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
 	if (round == 0) /* round 0 means loss less compression, no further processing is necessary */
 		return 0;
 
-	for (i = 0; i < samples; i++)
-	{
+	for (i = 0; i < samples; i++) {
 		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
 		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
 		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
@@ -587,8 +581,7 @@ int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
 	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
 		return 0;
 
-	for (i = 0; i < samples_used; i++)
-	{
+	for (i = 0; i < samples_used; i++) {
 		uint32_t mask = (~0U << (32-round_used));
 
 		if (data_buf[i].FX & mask) {
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
new file mode 100644
index 0000000000000000000000000000000000000000..265b9c58ad6fe6eca4111f2feffaa177e49b03fe
--- /dev/null
+++ b/lib/cmp_guess.c
@@ -0,0 +1,319 @@
+/**
+ * @file   cmp_guess.c
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
+ * @date   2021
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief helps the user to find a good compression parameters for a given
+ *	dataset
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../include/cmp_icu.h"
+#include "../include/cmp_guess.h"
+
+
+/* how often the model is updated before it is rested */
+static int num_model_updates = CMP_GUESS_N_MODEL_UPDATE_DEF;
+
+
+/**
+ * @brief sets how often the model is updated before model reset for the
+ * cmp_guess function
+ * @note the default value is CMP_GUESS_N_MODEL_UPDATE_DEF
+ * @note this is needed to guess a good model_value
+ *
+ * @param n_model_updates number of model updates
+ */
+
+void cmp_guess_set_model_updates(int n_model_updates)
+{
+	num_model_updates = n_model_updates;
+}
+
+
+/**
+ * @brief guess a good model value
+ *
+ * @param n_model_updates number of model updates
+ *
+ * @returns guessed model_value
+ */
+
+uint16_t cmp_guess_model_value(int n_model_updates)
+{
+	if (n_model_updates <= 2)
+		return 8;
+	if (n_model_updates <= 5)
+		return 10;
+	if (n_model_updates <= 11)
+		return 11;
+	if (n_model_updates <= 21)
+		return 12;
+
+	return 13;
+}
+
+
+/**
+ * @brief guess a good configuration with pre_cal_method
+ *
+ * @param cfg compression configuration structure
+ *
+ * @returns the size in bits of the compressed data of the guessed
+ * configuration; 0 on error
+ */
+
+static uint32_t pre_cal_method(struct cmp_cfg *cfg)
+{
+	uint32_t g;
+	uint32_t cmp_size;
+	uint32_t cmp_size_best = ~0U;
+	uint32_t golomb_par_best = 0;
+	uint32_t spill_best = 0;
+
+	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
+		uint32_t s = cmp_get_good_spill(g, cfg->cmp_mode);
+
+		cfg->golomb_par = g;
+		cfg->spill = s;
+		cmp_size = cmp_encode_data(cfg);
+		if (cmp_size == 0) {
+			return 0;
+		} else if (cmp_size < cmp_size_best) {
+			cmp_size_best = cmp_size;
+			golomb_par_best = g;
+			spill_best = s;
+		}
+	}
+	cfg->golomb_par = golomb_par_best;
+	cfg->spill = spill_best;
+
+	return cmp_size_best;
+}
+
+
+/**
+ * @brief guess a good configuration with brute force method
+ *
+ * @param cfg compression configuration structure
+ *
+ * @returns the size in bits of the compressed data of the guessed
+ * configuration; 0 on error
+ */
+
+#define CMP_GUESS_MAX_CAL_STEPS 20274
+static uint32_t brute_force(struct cmp_cfg *cfg)
+{
+	uint32_t g, s;
+	uint32_t n_cal_steps = 0, last = 0;
+	const uint32_t max_cal_steps = CMP_GUESS_MAX_CAL_STEPS;
+	uint32_t cmp_size;
+	uint32_t cmp_size_best = ~0U;
+	uint32_t golomb_par_best = 0;
+	uint32_t spill_best = 0;
+	uint32_t percent;
+
+	/* short cut for zero escape mechanism */
+	if (zero_escape_mech_is_used(cfg->cmp_mode))
+		return pre_cal_method(cfg);
+
+	printf("0%%... ");
+	fflush(stdout);
+
+	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
+		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->cmp_mode); s++) {
+			cfg->golomb_par = g;
+			cfg->spill = s;
+
+			cmp_size = cmp_encode_data(cfg);
+			if (cmp_size == 0) {
+				return 0;
+			} else if (cmp_size < cmp_size_best) {
+				cmp_size_best = cmp_size;
+				golomb_par_best = g;
+				spill_best = s;
+			}
+		}
+		n_cal_steps += s;
+
+		percent = n_cal_steps*100/max_cal_steps;
+		if (percent > 5+last && percent < 100) {
+			last = percent;
+			printf("%u%%... ", percent);
+			fflush(stdout);
+		}
+	}
+	printf("100%% ");
+	cfg->golomb_par = golomb_par_best;
+	cfg->spill = spill_best;
+
+	return cmp_size_best;
+}
+
+
+/**
+ * @brief guessed rdcu specific adaptive parameters
+ *
+ * @param cfg compression configuration structure
+ * @note internal use only
+ */
+
+static void add_rdcu_pars_internal(struct cmp_cfg *cfg)
+{
+	if (cfg->golomb_par == MIN_RDCU_GOLOMB_PAR) {
+		cfg->ap1_golomb_par = cfg->golomb_par + 1;
+		cfg->ap2_golomb_par = cfg->golomb_par + 2;
+
+	} else if (cfg->golomb_par == MAX_RDCU_GOLOMB_PAR) {
+		cfg->ap1_golomb_par = cfg->golomb_par - 2;
+		cfg->ap2_golomb_par = cfg->golomb_par - 1;
+	} else {
+		cfg->ap1_golomb_par = cfg->golomb_par - 1;
+		cfg->ap2_golomb_par = cfg->golomb_par + 1;
+	}
+
+	cfg->ap1_spill = cmp_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
+	cfg->ap2_spill = cmp_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		cfg->rdcu_data_adr = DEFAULT_CFG_MODEL.rdcu_data_adr;
+		cfg->rdcu_model_adr = DEFAULT_CFG_MODEL.rdcu_model_adr;
+		cfg->rdcu_new_model_adr = DEFAULT_CFG_MODEL.rdcu_new_model_adr;
+		cfg->rdcu_buffer_adr = DEFAULT_CFG_MODEL.rdcu_buffer_adr;
+	} else {
+		cfg->rdcu_data_adr = DEFAULT_CFG_DIFF.rdcu_data_adr;
+		cfg->rdcu_model_adr = DEFAULT_CFG_DIFF.rdcu_model_adr;
+		cfg->rdcu_new_model_adr = DEFAULT_CFG_DIFF.rdcu_new_model_adr;
+		cfg->rdcu_buffer_adr = DEFAULT_CFG_DIFF.rdcu_buffer_adr;
+	}
+}
+
+
+/**
+ * @brief guess a good compression configuration
+ * @details use the referenced in the cfg struct (samples, input_buf, model_buf
+ * (optional)) and the cmp_mode to find a good set of compression parameters
+ * @note compression parameters in the cfg struct (golomb_par, spill, model_value,
+ * ap1_.., ap2_.., buffer_length, ...) are overwritten by this function
+ *
+ * @param cfg compression configuration structure
+ * @param level guess_level 1 -> fast; 2 -> default; 3 -> slow(brute force)
+ *
+ * @returns the size in bits of the compressed data of the guessed
+ * configuration; 0 on error
+ */
+
+uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
+{
+	size_t size;
+	struct cmp_cfg work_cfg;
+	int err;
+	uint32_t cmp_size = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cfg->input_buf)
+		return 0;
+
+	if (!rdcu_supported_mode_is_used(cfg->cmp_mode)) {
+		printf("This compression mode is not implied yet.\n");
+		return 0;
+	}
+	/* make a working copy of the input data (and model) because the
+	 * following function works inplace */
+	work_cfg = *cfg;
+	work_cfg.input_buf = NULL;
+	work_cfg.model_buf = NULL;
+	work_cfg.icu_new_model_buf = NULL;
+	work_cfg.icu_output_buf = NULL;
+	work_cfg.buffer_length = 0;
+
+	size = cfg->samples * size_of_a_sample(work_cfg.cmp_mode);
+	if (size == 0)
+		goto error;
+	work_cfg.input_buf = malloc(size);
+	if (!work_cfg.input_buf) {
+		printf("malloc() failed!\n");
+		goto error;
+	}
+	memcpy(work_cfg.input_buf, cfg->input_buf, size);
+
+	if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
+		work_cfg.model_buf = malloc(size);
+		if (!work_cfg.model_buf) {
+			printf("malloc() failed!\n");
+			goto error;
+		}
+		memcpy(work_cfg.model_buf, cfg->model_buf, size);
+
+		work_cfg.icu_new_model_buf = malloc(size);
+		if (!work_cfg.icu_new_model_buf) {
+			printf("malloc() failed!\n");
+			goto error;
+		}
+	}
+
+	err = cmp_pre_process(&work_cfg);
+	if (err)
+		goto error;
+
+	err = cmp_map_to_pos(&work_cfg);
+	if (err)
+		goto error;
+
+	/* find the best parameters */
+	switch (level) {
+	case 3:
+		cmp_size = brute_force(&work_cfg);
+		break;
+	case 1:
+		printf("guess level 1 not implied yet use guess level 2\n");
+		/* fall through */
+	case 2:
+		cmp_size = pre_cal_method(&work_cfg);
+		break;
+	default:
+		fprintf(stderr, "cmp_tool: guess level not supported!\n");
+		goto error;
+		break;
+	}
+	if (!cmp_size)
+		goto error;
+
+	free(work_cfg.input_buf);
+	free(work_cfg.model_buf);
+	free(work_cfg.icu_new_model_buf);
+
+	cfg->golomb_par = work_cfg.golomb_par;
+	cfg->spill = work_cfg.spill;
+
+	cfg->model_value = cmp_guess_model_value(num_model_updates);
+
+	if (rdcu_supported_mode_is_used(cfg->cmp_mode))
+		add_rdcu_pars_internal(cfg);
+
+	cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(work_cfg.cmp_mode)*8);
+
+	return cmp_size;
+
+error:
+	free(work_cfg.input_buf);
+	free(work_cfg.model_buf);
+	free(work_cfg.icu_new_model_buf);
+	return 0;
+}
+
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 1a8d1574c08e6551f5fa4baf429eed9261c60a98..21aabe7d9e444ca494a65f4720a1b2c59f4159f2 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -30,7 +30,6 @@
 #include "../include/cmp_debug.h"
 
 
-
 /**
  * @brief check if the compressor configuration is valid for a SW compression,
  *	see the user manual for more information (PLATO-UVIE-PL-UM-0001).
@@ -62,9 +61,8 @@ int icu_cmp_cfg_valid(const struct cmp_cfg *cfg, struct cmp_info *info)
 		cfg_invalid++;
 	}
 
-	if (cfg->samples == 0) {
+	if (cfg->samples == 0)
 		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
-	}
 
 	/* icu_output_buf can be NULL if rdcu compression is used */
 	if (cfg->icu_output_buf == NULL) {
@@ -226,7 +224,7 @@ static int set_info(struct cmp_cfg *cfg, struct cmp_info *info)
 	if (cfg->model_value > UINT8_MAX)
 		return -1;
 
-	if(info) {
+	if (info) {
 		info->cmp_err = 0;
 		info->cmp_mode_used = (uint8_t)cfg->cmp_mode;
 		info->model_value_used = (uint8_t)cfg->model_value;
@@ -310,7 +308,7 @@ static int diff_32(uint32_t *data_buf, unsigned int samples, unsigned int round)
  * @note change the data_buf in-place
  * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
  *
- * @param data_buf	pointer to a S_FX data buffer
+ * @param data		pointer to a S_FX data buffer
  * @param samples	amount of data samples in the data buffer
  * @param round		number of bits to round; if zero no rounding takes place
  *
@@ -344,7 +342,7 @@ static int diff_S_FX(struct S_FX *data, unsigned int samples, unsigned int
  * @note change the data_buf in-place
  * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
  *
- * @param data_buf	pointer to a S_FX_EFX data buffer
+ * @param data		pointer to a S_FX_EFX data buffer
  * @param samples	amount of data samples in the data buffer
  * @param round		number of bits to round; if zero no rounding takes place
  *
@@ -378,7 +376,7 @@ static int diff_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, unsigned
  * @note change the data_buf in-place
  * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
  *
- * @param data_buf	pointer to a S_FX_NCOB data buffer
+ * @param data		pointer to a S_FX_NCOB data buffer
  * @param samples	amount of data samples in the data buffer
  * @param round		number of bits to round; if zero no rounding takes place
  *
@@ -412,7 +410,7 @@ static int diff_S_FX_NCOB(struct S_FX_NCOB *data, unsigned int samples, unsigned
  * @note change the data_buf in-place
  * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
  *
- * @param data_buf	pointer to a S_FX_EFX_NCOB_ECOB data buffer
+ * @param data		pointer to a S_FX_EFX_NCOB_ECOB data buffer
  * @param samples	amount of data samples in the data buffer
  * @param round		number of bits to round; if zero no rounding takes place
  *
@@ -540,7 +538,6 @@ static int model_32(uint32_t *data_buf, uint32_t *model_buf, unsigned int sample
  * @note update the model_buf in-place if up_model_buf = NULL
  *
  * @param data_buf	pointer to the S_FX data buffer to process
- * @param model_buf	pointer to the model buffer of the data to process
  * @param model_buf	pointer to the updated model buffer (if NULL model_buf
  *	will be overwrite with the updated model)
  * @param samples	amount of data samples in the data_buf and model_buf buffer
@@ -607,7 +604,7 @@ int model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf,
  * @returns 0 on success, error otherwise
  */
 
-int pre_process(struct cmp_cfg *cfg)
+int cmp_pre_process(struct cmp_cfg *cfg)
 {
 	if (!cfg)
 		return -1;
@@ -934,13 +931,12 @@ static int map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
  *
  * @note change the data_buf in-place
  *
- * @param data_buf	pointer to the data to process
- * @param buf_len	length of the data to process
+ * @param cfg	configuration contains all parameters required for compression
  *
  * @returns 0 on success, error otherwise
  */
 
-static int map_to_pos(struct cmp_cfg *cfg)
+int cmp_map_to_pos(struct cmp_cfg *cfg)
 {
 	int zero_mode_used;
 
@@ -1114,7 +1110,7 @@ static encoder_ptr select_encoder(unsigned int golomb_par)
  * @param    nBits      number of bits to put in the bitstream
  * @param    destAddr   this is the pointer to the beginning of the bitstream
  * @param    dest_len   length of the bitstream buffer (starting at destAddr)
- * @returns  number of bits written, 0 if the number was too big, -1 if the
+ * @returns  TODO number of bits written, 0 if the number was too big, -2 if the
  *	     destAddr buffer is to small to store the bitstream
  * @note     works in SRAM2
  */
@@ -1127,6 +1123,9 @@ static unsigned int put_n_bits32(unsigned int value, unsigned int bitOffset,
 	unsigned int bitsLeft, shiftRight, shiftLeft, localEndPos;
 	unsigned int mask;
 
+	if (!destAddr)
+		return nBits;
+
 	/* check if destination buffer is large enough */
 	/* TODO: adapt that to the other science products */
 	if ((bitOffset + nBits) > (((dest_len+1)/2)*2 * 16)) {
@@ -1336,9 +1335,8 @@ static int encode_outlier_zero(uint32_t value_to_encode, int max_bits,
 	/* put the data unencoded in the bitstream */
 	err = put_n_bits32(value_to_encode, enc->cmp_size, max_bits,
 			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0) {
+	if (err <= 0)
 		return err;
-	}
 
 	enc->cmp_size += max_bits;
 
@@ -1449,23 +1447,18 @@ int encode_value(uint32_t value_to_encode, int bit_len, struct cmp_cfg *cfg,
 }
 
 
-static int encode_16(uint16_t *data_to_encode, struct cmp_cfg *cfg,
-		     struct encoder_struct *enc)
+static int encode_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
 {
 	size_t i;
+	uint16_t *data_to_encode;
 
 	if (!cfg)
 		return -1;
 
-	if (!cfg->samples)
-		return 0;
-
-	if (!data_to_encode)
-		return -1;
-
 	if (!enc)
 		return -1;
 
+	data_to_encode = cfg->input_buf;
 
 	for (i = 0; i < cfg->samples; i++) {
 		int err = encode_value(data_to_encode[i], 16, cfg, enc);
@@ -1614,7 +1607,7 @@ static int encode_S_FX_EFX_NCOB_ECOB(struct cmp_cfg *cfg, struct encoder_struct
 }
 
 /* pad the bitstream with zeros */
-int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size, struct cmp_info *info)
+int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size)
 {
 	int n_bits = 0;
 
@@ -1628,21 +1621,15 @@ int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size, struct cmp_info *info)
 			 n_bits = put_n_bits32(0, cmp_size, n_pad_bits,
 					       cfg->icu_output_buf,
 					       cfg->buffer_length);
-			if (n_bits <= 0) {
-				/* the icu_output_buf is to small to store the whole bitstream */
-				if (info) {
-					info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
-					info->cmp_size = 0;
-				}
+			if (n_bits <= 0)
 				return -2;
-			}
 		}
 	}
 	return n_bits;
 }
 
 
-static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
+uint32_t cmp_encode_data(struct cmp_cfg *cfg)
 {
 	struct encoder_struct enc;
 	int err, n_bits;
@@ -1659,7 +1646,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
 	case MODE_MODEL_MULTI:
 	case MODE_DIFF_ZERO:
 	case MODE_DIFF_MULTI:
-		err = encode_16((uint16_t *)cfg->input_buf, cfg, &enc);
+		err = encode_16(cfg, &enc);
 		break;
 	case MODE_RAW_S_FX:
 		err = encode_raw_S_FX(cfg, &enc);
@@ -1704,28 +1691,24 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
 		break;
 	}
 
-	if (err == -2) {
-		/* the icu_output_buf is to small to store the whole bitstream */
-		info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
-		return err;
-	}
-	if (info)
-		info->cmp_size = enc.cmp_size;
-
-	n_bits = pad_bitstream(cfg, enc.cmp_size, info);
+	n_bits = pad_bitstream(cfg, enc.cmp_size);
 	if (n_bits < 0)
 		return n_bits;
 
 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-		{
-			size_t i;
-			uint32_t *p = (uint32_t *)cfg->icu_output_buf;
+	{
+		size_t i;
+		uint32_t *p = (uint32_t *)cfg->icu_output_buf;
+		if (p)
 			for (i = 0; i < (enc.cmp_size + n_bits)/32; i++)
 				cpu_to_be32s(&p[i]);
-		}
+	}
 #endif /*__BYTE_ORDER__ */
 
-	return 0;
+	if (err)
+		return err;
+	else
+		return enc.cmp_size;
 }
 
 
@@ -1756,6 +1739,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
 int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
 {
 	int err;
+	int cmp_size = 0;
 
 	err = set_info(cfg, info);
 	if (err)
@@ -1765,17 +1749,22 @@ int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
 	if (err)
 		return err;
 
-	err = pre_process(cfg);
+	err = cmp_pre_process(cfg);
 	if (err)
 		return err;
 
-	err = map_to_pos(cfg);
+	err = cmp_map_to_pos(cfg);
 	if (err)
 		return err;
 
-	err = encode_data(cfg, info);
-	if (err)
-		return err;
+	cmp_size = cmp_encode_data(cfg);
+	if (cmp_size == -2 && info)
+		/* the icu_output_buf is to small to store the whole bitstream */
+		info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
+	if (cmp_size < 0)
+		return cmp_size;
+	if (info)
+		info->cmp_size = cmp_size;
 
 	return 0;
 }
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index 39aa61f69ce53691b54f9e7afaa13ccc23d0720d..c0783197adbfd4614e9c8cef6c2a898aa0abe1ec 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -17,7 +17,6 @@
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
 
-#include <stdio.h>
 
 #include "../include/cmp_support.h"
 #include "../include/cmp_data_types.h"
@@ -246,6 +245,26 @@ int rdcu_supported_mode_is_used(unsigned int cmp_mode)
 }
 
 
+/**
+ * @brief check if the mode is available
+ *
+ * @param cmp_mode compression mode
+ *
+ * @returns 1 when mode is available, otherwise 0
+ */
+
+int cmp_mode_available(unsigned int cmp_mode)
+{
+	if (diff_mode_is_used(cmp_mode) ||
+	    model_mode_is_used(cmp_mode) ||
+	    raw_mode_is_used(cmp_mode))
+		return 1;
+	else
+		return 0;
+
+}
+
+
 /**
  * @brief check if zero escape symbol mechanism mode is used
  *
@@ -391,28 +410,71 @@ unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
 
 uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode)
 {
-	unsigned int cutoff;
-	unsigned int max_n_sym_offset;
-	unsigned int max_cw_bits;
+	const uint32_t LUT_MAX_RDCU[MAX_RDCU_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
+		60, 72, 84, 96, 107, 118, 129, 140, 151, 162, 173, 184, 194,
+		204, 214, 224, 234, 244, 254, 264, 274, 284, 294, 304, 314, 324,
+		334, 344, 353, 362, 371, 380, 389, 398, 407, 416, 425, 434, 443,
+		452, 461, 470, 479, 488, 497, 506, 515, 524, 533, 542, 551, 560,
+		569, 578, 587, 596, 605, 614, 623 };
 
 	if (golomb_par == 0)
 		return 0;
 
 	if (rdcu_supported_mode_is_used(cmp_mode)) {
-		max_cw_bits = 16; /* the RDCU compressor can only generate code
-				   * words with a length of maximal 16 bits.
-				   */
+		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+			return 0;
+
+		return LUT_MAX_RDCU[golomb_par];
 	} else {
-		max_cw_bits = 32; /* the ICU compressor can generate code
-				   * words with a length of maximal 32 bits.
-				   */
+		if (golomb_par > MAX_ICU_GOLOMB_PAR) {
+			return 0;
+		} else {
+			/* the ICU compressor can generate code words with a length of
+			 * maximal 32 bits.  */
+			unsigned int max_cw_bits = 32;
+			unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
+			unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
+			return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
+				max_n_sym_offset - 1;
+		}
 	}
+}
 
-	cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
-	max_n_sym_offset = max_cw_bits/2 - 1;
 
-	return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
-		max_n_sym_offset - 1;
+/**
+ * @brief get a good spill threshold parameter for the selected Golomb parameter
+ *	and compression mode
+ *
+ * @param golomb_par Golomb parameter
+ * @param cmp_mode compression mode
+ *
+ * @returns a good spill parameter (optimal for zero escape mechanism)
+ * @warning icu compression not support yet!
+ */
+
+uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode)
+{
+	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
+		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
+		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
+		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
+		317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
+		405, 411, 418, 424, 431, 452 };
+
+	if (zero_escape_mech_is_used(cmp_mode))
+		return get_max_spill(golomb_par, cmp_mode);
+
+	if (cmp_mode == MODE_MODEL_MULTI) {
+		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+			return 0;
+		else
+			return LUT_RDCU_MULIT[golomb_par];
+	}
+
+	if (cmp_mode == MODE_DIFF_MULTI)
+		return CMP_GOOD_SPILL_DIFF_MULTI;
+
+	return 0;
 }
 
 
@@ -501,7 +563,7 @@ size_t size_of_a_sample(unsigned int cmp_mode)
  *
  * @param cmp_size compressed data size, measured in bits
  *
- * @returns the size in bytes to sore the hole bitstream
+ * @returns the size in bytes to store the hole bitstream
  */
 
 unsigned int size_of_bitstream(unsigned int cmp_size)
@@ -513,9 +575,10 @@ unsigned int size_of_bitstream(unsigned int cmp_size)
 /**
  * @brief calculate the need bytes for the model
  *
- * @param cmp_size compressed data size, measured in bits
+ * @param samples amount of model samples
+ * @param cmp_mode compression mode
  *
- * @returns the size in bytes to sore the hole bitstream
+ * @returns the size in bytes to store the hole bitstream
  */
 
 unsigned int size_of_model(unsigned int samples, unsigned int cmp_mode)
@@ -548,18 +611,16 @@ void print_cmp_cfg(const struct cmp_cfg *cfg)
 	printf("input_buf: %p\n", (void *)cfg->input_buf);
 	if (cfg->input_buf != NULL) {
 		printf("input data:");
-		for (i = 0; i < cfg->samples; i++) {
+		for (i = 0; i < cfg->samples; i++)
 			printf(" %04X", ((uint16_t *)cfg->input_buf)[i]);
-		}
 		printf("\n");
 	}
 	printf("rdcu_data_adr: 0x%06X\n", cfg->rdcu_data_adr);
 	printf("model_buf: %p\n", (void *)cfg->model_buf);
 	if (cfg->model_buf != NULL) {
 		printf("model data:");
-		for (i = 0; i < cfg->samples; i++) {
+		for (i = 0; i < cfg->samples; i++)
 			printf(" %04X", ((uint16_t *)cfg->model_buf)[i]);
-		}
 		printf("\n");
 	}
 	printf("rdcu_model_adr: 0x%06X\n", cfg->rdcu_model_adr);
diff --git a/lib/tool_lib.c b/lib/cmp_tool_lib.c
similarity index 63%
rename from lib/tool_lib.c
rename to lib/cmp_tool_lib.c
index 5318366153f4c571b75fa1900b972c637aad67b8..41f7763f80ea0cff5e4dcb23325deac548820ccd 100644
--- a/lib/tool_lib.c
+++ b/lib/cmp_tool_lib.c
@@ -1,5 +1,5 @@
 /**
- * @file   tool_lib.c
+ * @file   cmp_tool_lib.c
  * @author Johannes Seelig (johannes.seelig@univie.ac.at)
  * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
  * @date   2020
@@ -22,7 +22,7 @@
 #include <ctype.h>
 #include <sys/stat.h>
 
-#include "../include/tool_lib.h"
+#include "../include/cmp_tool_lib.h"
 #include "../include/cmp_support.h"
 #include "../include/rdcu_cmd.h"
 #include "../include/byteorder.h"
@@ -31,30 +31,35 @@
 /**
  * @brief print help information
  *
- * @param argv	argument vector
+ * @param program_name	name of the program
  */
 
-void Print_Help(const char *argv)
+void print_help(const char *program_name)
 {
-	printf("usage: %s [options] [<argument>]\n", &argv[0]);
+	printf("usage: %s [options] [<argument>]\n", program_name);
 	printf("General Options:\n");
 	printf("  -h, --help               Print this help text and exit\n");
 	printf("  -V, --version            Print program version and exit\n");
 	printf("  -v, --verbose            Print various debugging information\n");
 	printf("  -n, --model_cfg          Print a default model configuration and exit\n");
 	printf("  --diff_cfg               Print a default 1d-differencing configuration and exit\n");
-	printf("  -a, --rdcu_par           Print additional RDCU control parameters\n");
+	printf("  -a, --rdcu_par           Add additional RDCU control parameters\n");
 	printf("  -o <prefix>              Use the <prefix> for output files\n");
 	printf("Compression Options:\n");
 	printf("  -c <file>                File containing the compressing configuration\n");
 	printf("  -d <file>                File containing the data to be compressed\n");
 	printf("  -m <file>                File containing the model of the data to be compressed\n");
-	printf("  --rdcu_pkt               Generate RMAP packets for a RDCU compression\n");
+	printf("  --rdcu_pkt               Generate RMAP packets for an RDCU compression\n");
+	printf("  --last_info <.info file> Generate RMAP packets for an RDCU compression with parallel read of the last results\n");
 	printf("Decompression Options:\n");
 	printf("  -i <file>                File containing the decompression information\n");
 	printf("  -d <file>                File containing the compressed data\n");
 	printf("  -m <file>                File containing the model of the compressed data\n");
-	printf("\n");
+	printf("Guessing Options:\n");
+	printf("  --guess <mode>           Search for a good configuration for compression <mode>\n");
+	printf("  -d <file>                File containing the data to be compressed\n");
+	printf("  -m <file>                File containing the model of the data to be compressed\n");
+	printf("  --guess_level <level>    Set guess level to <level> (optional)\n");
 }
 
 
@@ -72,14 +77,13 @@ void Print_Help(const char *argv)
 
 static FILE *open_file(const char *dirname, const char *filename)
 {
-	FILE *fp;
 	char *pathname;
 	int n;
 
 	if (!dirname)
 		return NULL;
 
-	if(!filename)
+	if (!filename)
 		return NULL;
 
 	errno = 0;
@@ -104,9 +108,7 @@ static FILE *open_file(const char *dirname, const char *filename)
 		abort();
 	}
 
-	fp = fopen(pathname, "w");
-	free(pathname);
-	return fp;
+	return fopen(pathname, "w");
 }
 
 
@@ -144,7 +146,7 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 	}
 
 	for (i = 0; i < buf_len; i++) {
-		fprintf(fp, "%02X %02X",buf[i] >> 8 ,buf[i] & 0xFF);
+		fprintf(fp, "%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
 		if ((i + 1) % 16 == 0)
 			fprintf(fp, "\n");
 		else
@@ -157,7 +159,7 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 	if (verbose) {
 		printf("\n\n");
 			for (i = 0; i < buf_len; i++) {
-				printf("%02X %02X",buf[i] >> 8 ,buf[i] & 0xFF);
+				printf("%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
 			if ((i + 1) % 16 == 0)
 				printf("\n");
 			else
@@ -185,12 +187,12 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
  * @returns 0 on success, error otherwise
  */
 
-int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
-		    *output_prefix, const char *name_extension, int verbose)
+int write_cmp_data_file(const void *buf, uint32_t buf_size, const char *output_prefix,
+			const char *name_extension, int verbose)
 {
 	unsigned int i;
 	FILE *fp;
-	uint8_t *p = (uint8_t *)buf;
+	const uint8_t *p = (const uint8_t *)buf;
 
 	if (!buf)
 		abort();
@@ -248,7 +250,7 @@ static void remove_spaces(char *s)
 
 	do {
 		while (*d == ' ' || *d == '\t')
-			++d;
+			d++;
 	} while ((*s++ = *d++) != '\0');
 }
 
@@ -326,7 +328,7 @@ static int sram_addr_to_int(const char *addr)
  * @see https://eternallyconfuzzled.com/atoi-is-evil-c-learn-why-atoi-is-awful
  */
 
-static int atoui32(const char *dep_str , const char *val_str, uint32_t *red_val)
+static int atoui32(const char *dep_str, const char *val_str, uint32_t *red_val)
 {
 	long temp;
 	char *end = NULL;
@@ -340,14 +342,14 @@ static int atoui32(const char *dep_str , const char *val_str, uint32_t *red_val)
 	if (!red_val)
 		return -1;
 
+	errno = 0;
 	temp = strtol(val_str, &end, 10);
-	if (end != val_str && errno != ERANGE && temp >= 0 && temp <=
-	    UINT32_MAX) {
+	if (end != val_str && errno != ERANGE && temp >= 0 &&
+	    temp <= UINT32_MAX) {
 		*red_val = (uint32_t)temp;
 		return 0;
 	} else {
-		fprintf(stderr, "%s: Error read in %s.\n", PROGRAM_NAME,
-			dep_str);
+		fprintf(stderr, "%s: Error read in %s.\n", PROGRAM_NAME, dep_str);
 		*red_val = 0;
 		return -1;
 	}
@@ -355,14 +357,64 @@ static int atoui32(const char *dep_str , const char *val_str, uint32_t *red_val)
 
 
 /**
-* @brief  parse a file containing a compressing configuration
-*
-* @param fp	FILE pointer
-* @param cfg	compression configuration structure holding the read in
-*		configuration
-*
-* @returns 0 on success, error otherwise
-*/
+ * @brief parse a compression mode vale string to a integer
+ * @note string can be either a number or the name of the compression mode
+ *
+ * @param cmp_mode_str	string containing the compression mode value to parse
+ * @param cmp_mode	address where the parsed result is written
+ *
+ * @returns 0 on success, error otherwise
+ */
+
+uint32_t cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
+{
+	size_t j;
+	static const struct {
+		uint32_t  cmp_mode;
+		const char *str;
+	} conversion[] = {
+		{MODE_RAW, "MODE_RAW"},
+		{MODE_MODEL_ZERO, "MODE_MODEL_ZERO"},
+		{MODE_DIFF_ZERO, "MODE_DIFF_ZERO"},
+		{MODE_MODEL_MULTI, "MODE_MODEL_MULTI"},
+		{MODE_DIFF_MULTI, "MODE_DIFF_MULTI"},
+	};
+
+	if (!cmp_mode_str)
+		return -1;
+	if (!cmp_mode)
+		return -1;
+
+	if (isalpha(cmp_mode_str[0])) {  /* check if mode is given as text */
+		for (j = 0;  j < sizeof(conversion) / sizeof(conversion[0]);  ++j) {
+			if (!strcmp(cmp_mode_str, conversion[j].str)) {
+				*cmp_mode = conversion[j].cmp_mode;
+				return 0;
+			}
+		}
+		return -1;
+	} else {
+		if (atoui32(cmp_mode_str, cmp_mode_str, cmp_mode))
+			return -1;
+	}
+
+	if (!cmp_mode_available(*cmp_mode))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief parse a file containing a compressing configuration
+ * @note internal use only!
+ *
+ * @param fp	FILE pointer
+ * @param cfg	compression configuration structure holding the read in
+ *		configuration
+ *
+ * @returns 0 on success, error otherwise
+ */
 
 static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 {
@@ -379,7 +431,7 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 		if (line[0] == '#' || line[0] == '\n')
 			continue; /* skip #'ed or empty lines */
 
-		if (!strchr(line, '\n')){ /* detect a to long line */
+		if (!strchr(line, '\n')) { /* detect a to long line */
 			fprintf(stderr, "%s: Error read in line to long. Maximal line length is %d characters.\n",
 				PROGRAM_NAME, MAX_CONFIG_LINE-1);
 			return -1;
@@ -538,6 +590,7 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 
 int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 {
+	int err;
 	FILE *fp;
 
 	if (!file_name)
@@ -547,8 +600,8 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 		abort();
 
 	if (strstr(file_name, ".info")) {
-	    fprintf(stderr, "%s: %s: .info file extension found on configuration file. You may have selected the wrong file.\n",
-		    PROGRAM_NAME, file_name);
+		fprintf(stderr, "%s: %s: .info file extension found on configuration file. You may have selected the wrong file.\n",
+			PROGRAM_NAME, file_name);
 	}
 
 	fp = fopen(file_name, "r");
@@ -559,10 +612,10 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 		return -1;
 	}
 
-	if (parse_cfg(fp, cfg))
-		return -1;
-
+	err = parse_cfg(fp, cfg);
 	fclose(fp);
+	if (err)
+		return err;
 
 	if (verbose_en) {
 		printf("\n\n");
@@ -582,6 +635,7 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 
 /**
  * @brief  parse a file containing a decompression information
+ * @note internal use only!
  *
  * @param fp	FILE pointer
  * @param info	decompression information structure holding the read in
@@ -605,7 +659,7 @@ static int parse_info(FILE *fp, struct cmp_info *info)
 		if (line[0] == '#' || line[0] == '\n')
 			continue; /* skip #'ed or empty lines */
 
-		if (!strchr(line, '\n')){ /* detect a to long line */
+		if (!strchr(line, '\n')) { /* detect a to long line */
 			fprintf(stderr, "%s: Error read in line to long. Maximal line length is %d characters.\n",
 				PROGRAM_NAME, MAX_CONFIG_LINE-1);
 			return -1;
@@ -738,8 +792,7 @@ static int parse_info(FILE *fp, struct cmp_info *info)
 			int i = sram_addr_to_int(token2);
 
 			if (i < 0) {
-				fprintf(stderr,"%s: Error read in "
-				       "rdcu_cmp_adr_used\n",
+				fprintf(stderr, "%s: Error read in rdcu_cmp_adr_used\n",
 				       PROGRAM_NAME);
 				return -1;
 			}
@@ -786,10 +839,9 @@ int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en)
 	if (!info)
 		abort();
 
-	if (strstr(file_name, ".cfg")) {
-	    fprintf(stderr, "%s: %s: .cfg file extension found on decompression information file. You may have selected the wrong file.\n",
-		    PROGRAM_NAME, file_name);
-	}
+	if (strstr(file_name, ".cfg"))
+		fprintf(stderr, "%s: %s: .cfg file extension found on decompression information file. You may have selected the wrong file.\n",
+			PROGRAM_NAME, file_name);
 
 	fp = fopen(file_name, "r");
 	if (fp == NULL) {
@@ -813,297 +865,383 @@ int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en)
 
 
 /**
- * @brief reads a hex encoded uint8_t data (or model) file, returns a buffer
- *	containing the read in data
+ * @brief reads n_word words of a hex-encoded data (or model) file to
+ *	a uint8_t buffer
  *
- * @note data must be encode has 4 hex digits separated by a white space or new
- *	line character e.g. "ABCD 1234 AB12\n"
+ * @note data must be encoded as 2 hex digits separated by a white space or new
+ *	line character e.g. "AB CD 12\n34 AB 12\n"
  *
- * @param file_name	data file name
- * @param samples	amount of uint16_t data samples to read in
+ * @param file_name	data/model file name
+ * @param buf		buffer to write the file content (can be NULL)
+ * @param n_word	number of uint8_t data words to read in
  * @param verbose_en	print verbose output if not zero
  *
- * @returns address to the buffer containing the read in data, NULL on error
+ * @returns read data words; if buf == NULL the size in bytes to store the file
+ *	content; negative on error
  */
 
-uint8_t *read_file8(const char *file_name, uint32_t samples, int verbose_en)
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int verbose_en)
 {
-	uint32_t i;
+	/* This is a rather slow implementation. Performance can be improved by
+	 * reading larger chunks */
+	ssize_t n;
 	FILE *fp;
-	uint8_t *buffer;
-	char tmp_str[4]; /* 6 = 2 hex digit's + 1 white space + 1 \0 */
+	char tmp_str[4]; /* 4 = 2 hex digit's + 1 white space + 1 \0 */
 
 	if (!file_name)
-		abort();
-
-	if (!samples)
-		return NULL;
+		return -1;
 
 	fp = fopen(file_name, "r");
 	if (fp == NULL) {
 		fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, file_name,
 			strerror(errno));
-		return NULL;
+		return -1;
 	}
 
-	buffer = (uint8_t *)malloc(samples * SAM2BYT);
-	if (buffer == NULL) {
-		fprintf(stderr, "%s: Error allocating memory.\n", PROGRAM_NAME);
-		fclose(fp);
-		return NULL;
-	}
+	/* if buf is NULL we count the words in the file */
+	if (!buf)
+		n_word = ~0U;
 
-	for (i = 0; i < samples; i++) {
+	for (n = 0; n < n_word; ) {
 		int j;
 		unsigned long read_val;
 		char *end;
 
+		/* read 3 characters */
 		if (!fgets(tmp_str, sizeof(tmp_str), fp)) {
-			fprintf(stderr, "%s: %s: Error: The files does not contain enough data as given by the samples parameter.\n",
+			if (ferror(fp)) {
+				fprintf(stderr, "%s: %s: Error: File error indicator set.\n",
+					PROGRAM_NAME, file_name);
+				goto error;
+			}
+
+			if (!buf)  /* finished counting the sample */
+				break;
+
+			fprintf(stderr, "%s: %s: Error: The files does not contain enough data as given by the n_word parameter.\n",
 				PROGRAM_NAME, file_name);
 			goto error;
 		}
 
-		if (tmp_str[0] == '#' || tmp_str[0] == '\n') {
-			i--; /* a comment or empty line does not count as sample */
+		/* skip empty lines */
+		if (tmp_str[0] == '\n')
+			continue;
+
+		/* skip comment lines */
+		if (tmp_str[0] == '#') {
+			int c;
+			do {
+				c = fgetc(fp);
+			} while (c != '\n' && c != EOF);
 			continue;
 		}
 
+		/* check the string formation */
 		for (j = 0; j < 2; j++) {
 			if (!isxdigit(tmp_str[j])) {
-				fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected format is like: 12 AB 23 CD .. ..\n", PROGRAM_NAME,
-					file_name);
+				fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected format is like: 12 AB 23 CD .. ..\n",
+					PROGRAM_NAME, file_name);
 				goto error;
 			}
 		}
-
-		if (!(isspace(tmp_str[2]) || tmp_str[2] == '\n')) {
-			fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected format is: 12 AB 23 CD .. ..\n", PROGRAM_NAME, file_name);
-			goto error;
-		}
-
-		read_val = strtoul(tmp_str, &end, 16);
-
-		if (tmp_str == end || errno == ERANGE || read_val > UINT8_MAX) {
-			fprintf(stderr, "%s: %s: Error: The data can not be converted to integer.\n",
+		if (!isspace(tmp_str[2])) {
+			fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected format is like: 12 AB 23 CD .. ..\n",
 				PROGRAM_NAME, file_name);
 			goto error;
 		}
 
-		buffer[i] = (uint16_t)read_val;
-
-		if (verbose_en) {
-			if (i == 0)
-				printf("\n\n");
-
-			printf("%02X", buffer[i]);
-			if (i && !((i + 1) % 28))
-				printf("\n");
-			else
-				printf(" ");
+		/* convert data to integer and write it into the buffer */
+		if (buf) {
+			read_val = strtoul(tmp_str, &end, 16);
+			if (tmp_str == end || read_val > UINT8_MAX) {
+				fprintf(stderr, "%s: %s: Error: The data can not be converted to integer.\n",
+					PROGRAM_NAME, file_name);
+				goto error;
+			}
+			buf[n] = (uint8_t)read_val;
+
+			/* print data read in */;
+			if (verbose_en) {
+				if (n == 0)
+					printf("\n\n");
+				printf("%02X", buf[n]);
+				if (n && !((n + 1) % 32))
+					printf("\n");
+				else
+					printf(" ");
+			}
 		}
-	}
-	if (verbose_en)
-		printf("\n\n");
 
-	fgets(tmp_str, sizeof(tmp_str), fp);
-	if (!feof(fp) && tmp_str[0] == '\n') /* read last line break */
-		fgets(tmp_str, sizeof(tmp_str), fp);
+		n++;
+	}
 
-	if (!feof(fp)) {
-		fprintf(stderr, "%s: %s: Warning: The file may contain more data than specified by the samples parameter.\n",
-			PROGRAM_NAME, file_name);
+	if (buf) {
+		/* check if there is some additional stuff at the end of the file */
+		int c = getc(fp);
+		if (c != EOF)
+			if (c != '\n' && getc(fp) != EOF)
+				fprintf(stderr, "%s: %s: Warning: The file may contain more data than specified by the samples or cmp_size parameter.\n",
+					PROGRAM_NAME, file_name);
 	}
 
 	fclose(fp);
 
-	return buffer;
+	if (verbose_en && buf)
+		printf("\n\n");
+
+	return n;
 
-	error:
-		free(buffer);
-		fclose(fp);
-		return NULL;
+error:
+	fclose(fp);
+	return -1;
 }
 
 
 /**
- * @brief reads a hex encoded uint16_t data (or model) file, returns a buffer
- *	containing the read in data
+ * @brief reads the number of uint16_t samples of a hex-encoded data (or model)
+ *	file into a buffer
  *
- * @note data must be encode has 4 hex digits separated by a white space or new
- *	line character e.g. "ABCD 1234 AB12\n"
+ * @note data must be encode has 2 hex digits separated by a white space or new
+ *	line character e.g. "AB CD 12 34 AB 12\n"
  *
- * @param file_name	data file name
+ * @param file_name	data/model file name
+ * @param buf		buffer to write the file content (can be NULL)
  * @param samples	amount of uint16_t data samples to read in
  * @param verbose_en	print verbose output if not zero
  *
- * @returns address to the buffer containing the read in data, NULL on error
+ * @returns the size in bytes to store the file content; negative on error
  */
 
-uint16_t *read_file16(const char *file_name, uint32_t samples, int verbose_en)
+ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
+		    int verbose_en)
 {
-	size_t i;
-	uint16_t *buf = (uint16_t *)read_file8(file_name, samples*2, verbose_en);
+	ssize_t size = read_file8(file_name, (uint8_t *)buf,
+				  samples*sizeof(uint16_t), verbose_en);
 
-	if (!buf)
-		return NULL;
+	if (size < 0)
+		return size;
 
-	for (i=0; i < samples; i++)
-		be16_to_cpus(&buf[i]);
+	if (size & 0x1) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 2 hex words.\n",
+				PROGRAM_NAME, file_name);
+		return -1;
+	}
 
-	return buf;
+	if (buf) {
+		size_t i;
+		for (i = 0; i < samples; i++)
+			be16_to_cpus(&buf[i]);
+	}
+
+
+	return size;
 }
 
 
 /**
- * @brief reads a hex encoded uint32_t data file, returns a buffer containing
- *	the read in data
+ * @brief reads the number of uint32_t samples of a hex-encoded data (or model)
+ *	file into a buffer
  *
  * @note data must be encode has 2 hex digits separated by a white space or new
- *	line character e.g. AB CD 12 34
+ *	line character e.g. "AB CD 12 34 AB 12\n"
  *
- * @param file_name	data file name
- * @param buf_len	amount of uint32_t data samples to read in
+ * @param file_name	data/model file name
+ * @param buf		buffer to write the file content (can be NULL)
+ * @param samples	amount of uint32_t data samples to read in
  * @param verbose_en	print verbose output if not zero
  *
- * @returns address to the buffer containing the read in data, NULL on error
+ * @returns the size in bytes to store the file content; negative on error
  */
 
-uint32_t *read_file32(const char *file_name, uint32_t buf_len, int verbose_en)
+ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
+		    int verbose_en)
 {
-	size_t i;
+	ssize_t size = read_file8(file_name, (uint8_t *)buf,
+				  samples*sizeof(uint32_t), verbose_en);
 
-	uint32_t *buf = (uint32_t *)read_file8(file_name, buf_len*sizeof(uint32_t),
-					       verbose_en);
+	if (size < 0)
+		return -1;
 
-	if (!buf)
-		return NULL;
+	if (size & 0x3) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n",
+				PROGRAM_NAME, file_name);
+		return -1;
+	}
 
-	for (i=0; i < buf_len; i++)
-		be32_to_cpus(&buf[i]);
+	if (buf) {
+		size_t i;
+		for (i = 0; i < samples; i++)
+			be32_to_cpus(&buf[i]);
+	}
 
-	return buf;
+	return size;
 }
 
 
 /**
- * @brief prints config struct
+ * @brief write compression configuration to a stream
+ * @note internal use only!
  *
+ * @param fp		FILE pointer
  * @param cfg		configuration to print
  * @param rdcu_cfg	if set additional RDCU parameter are printed as well
  */
 
-void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg)
+static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg, int rdcu_cfg)
 {
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Default Configuration File\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Selected compression mode\n");
-	printf("# 0: raw mode\n");
-	printf("# 1: model mode with zero escape symbol mechanism\n");
-	printf("# 2: 1d differencing mode without input model with zero escape symbol mechanism\n");
-	printf("# 3: model mode with multi escape symbol mechanism\n");
-	printf("# 4: 1d differencing mode without input model multi escape symbol mechanism\n");
-	printf("\n");
-	printf("cmp_mode = %u\n", cfg->cmp_mode);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Number of samples (16 bit value) to compress, length of the data and model buffer\n");
-	printf("\n");
-	printf("samples = %u\n", cfg->samples);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Length of the compressed data buffer in number of samples (16 bit values)\n");
-	printf("\n");
-	printf("buffer_length = %u\n", cfg->buffer_length);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Golomb parameter for dictionary selection\n");
-	printf("\n");
-	printf("golomb_par = %u\n", cfg->golomb_par);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Spillover threshold for encoding outliers\n");
-	printf("\n");
-	printf("spill = %u\n", cfg->spill);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Model weighting parameter\n");
-	printf("\n");
-	printf("model_value = %u\n", cfg->model_value);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
-	printf("# Number of noise bits to be rounded\n");
-	printf("\n");
-	printf("round = %u\n", cfg->round);
-	printf("\n");
-	printf("#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Default Configuration File\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Selected compression mode\n");
+	fprintf(fp, "# 0: raw mode\n");
+	fprintf(fp, "# 1: model mode with zero escape symbol mechanism\n");
+	fprintf(fp, "# 2: 1d differencing mode without input model with zero escape symbol mechanism\n");
+	fprintf(fp, "# 3: model mode with multi escape symbol mechanism\n");
+	fprintf(fp, "# 4: 1d differencing mode without input model multi escape symbol mechanism\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "cmp_mode = %u\n", cfg->cmp_mode);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Number of samples (16 bit value) to compress, length of the data and model buffer\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "samples = %u\n", cfg->samples);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Length of the compressed data buffer in number of samples (16 bit values)\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "buffer_length = %u\n", cfg->buffer_length);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Golomb parameter for dictionary selection\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "golomb_par = %u\n", cfg->golomb_par);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Spillover threshold for encoding outliers\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "spill = %u\n", cfg->spill);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Model weighting parameter\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "model_value = %u\n", cfg->model_value);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Number of noise bits to be rounded\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "round = %u\n", cfg->round);
+	fprintf(fp, "\n");
+	fprintf(fp, "#-------------------------------------------------------------------------------\n");
 
 	if (rdcu_cfg) {
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# Hardware Compressor Settings (not need for SW compression)\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("\n");
-		printf("# Adaptive 1 Golomb parameter; HW only\n");
-		printf("\n");
-		printf("ap1_golomb_par = %u\n", cfg->ap1_golomb_par);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# Adaptive 1 spillover threshold; HW only\n");
-		printf("\n");
-		printf("ap1_spill = %u\n", cfg->ap1_spill);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# Adaptive 2 Golomb parameter; HW only\n");
-		printf("\n");
-		printf("ap2_golomb_par = %u\n", cfg->ap2_golomb_par);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# Adaptive 2 spillover threshold; HW only\n");
-		printf("\n");
-		printf("ap2_spill = %u\n", cfg->ap2_spill);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# RDCU data to compress start address, the first data address in the RDCU SRAM; HW only\n");
-		printf("\n");
-		printf("rdcu_data_adr = 0x%06X\n",
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# Hardware Compressor Settings (not need for SW compression)\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "# Adaptive 1 Golomb parameter; HW only\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "ap1_golomb_par = %u\n", cfg->ap1_golomb_par);
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# Adaptive 1 spillover threshold; HW only\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "ap1_spill = %u\n", cfg->ap1_spill);
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# Adaptive 2 Golomb parameter; HW only\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "ap2_golomb_par = %u\n", cfg->ap2_golomb_par);
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# Adaptive 2 spillover threshold; HW only\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "ap2_spill = %u\n", cfg->ap2_spill);
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# RDCU data to compress start address, the first data address in the RDCU SRAM; HW only\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "rdcu_data_adr = 0x%06X\n",
 		       cfg->rdcu_data_adr);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# RDCU model start address, the first model address in the RDCU SRAM\n");
-		printf("\n");
-		printf("rdcu_model_adr = 0x%06X\n",
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# RDCU model start address, the first model address in the RDCU SRAM\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "rdcu_model_adr = 0x%06X\n",
 		       cfg->rdcu_model_adr);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored\n");
-		printf("\n");
-		printf("rdcu_new_model_adr = 0x%06X\n",
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "rdcu_new_model_adr = 0x%06X\n",
 		       cfg->rdcu_new_model_adr);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
-		printf("# RDCU compressed data start address, the first output data address in the RDCU SRAM\n");
-		printf("\n");
-		printf("rdcu_buffer_adr = 0x%06X\n", cfg->rdcu_buffer_adr);
-		printf("\n");
-		printf("#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+		fprintf(fp, "# RDCU compressed data start address, the first output data address in the RDCU SRAM\n");
+		fprintf(fp, "\n");
+		fprintf(fp, "rdcu_buffer_adr = 0x%06X\n", cfg->rdcu_buffer_adr);
+		fprintf(fp, "\n");
+		fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	}
+}
+
+/**
+ * @brief prints config struct
+ *
+ * @param cfg		configuration to print
+ * @param rdcu_cfg	if set additional RDCU parameter are printed as well
+ */
+
+void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg)
+{
+	write_cfg_internal(stdout, cfg, rdcu_cfg);
+}
+
+/**
+ * @brief write compression configuration to a file
+ *
+ * @param cfg		configuration to print
+ * @param output_prefix prefix of the written file (.cfg is added to the prefix)
+ * @param rdcu_cfg	if non-zero additional RDCU parameter are printed as well
+ * @param verbose	print verbose output if not zero
+ *
+ * @returns 0 on success, error otherwise
+ */
+
+int write_cfg(const struct cmp_cfg *cfg, const char *output_prefix, int rdcu_cfg,
+	      int verbose)
+{
+	FILE *fp = open_file(output_prefix, ".cfg");
+
+	if (fp == NULL) {
+		fprintf(stderr, "%s: %s%s: %s\n", PROGRAM_NAME, output_prefix,
+			".cfg", strerror(errno));
+		return -1;
 	}
+
+	write_cfg_internal(fp, cfg, rdcu_cfg);
+
+	fclose(fp);
+
+	if (verbose)
+		print_cfg(cfg, rdcu_cfg);
+	return 0;
 }
 
+
 /**
  * @brief write a decompression information structure to a file
  *
  * @param info	 compressor information contains information of an executed
  *		 compression
  * @param output_prefix prefix of the written file (.info is added to the prefix)
- * @param machine_cfg - if set write additional RDCU parameter in the file
+ * @param rdcu_cfg - if non-zero write additional RDCU parameter in the file
  *
  * @returns 0 on success, error otherwise
  */
 
 int write_info(const struct cmp_info *info, const char *output_prefix,
-	       int machine_cfg)
+	       int rdcu_cfg)
 {
 	FILE *fp = open_file(output_prefix, ".info");
 
@@ -1157,7 +1295,7 @@ int write_info(const struct cmp_info *info, const char *output_prefix,
 	fprintf(fp, "\n");
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
 
-	if (machine_cfg) {
+	if (rdcu_cfg) {
 		fprintf(fp, "#-------------------------------------------------------------------------------\n");
 		fprintf(fp, "# Hardware Compressor Settings (not need for SW compression)\n");
 		fprintf(fp, "#-------------------------------------------------------------------------------\n");
diff --git a/lib/decmp.c b/lib/decmp.c
index 11387726ca69e7025afc56b63ef4cfb6e84bbc4a..e735c3db5fd85a9b054eb90ad48a5304e76023d2 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -57,7 +57,7 @@ static int de_raw_pre_process(uint8_t cmp_mode_used)
 /**
  * @brief model decompression pre-processing
  *
- * @note
+ * @note change the data_buf in-place
  *
  * @param data_buf	pointer to the data to process
  * @param model_buf	pointer to the model of the data to process
diff --git a/lib/rdcu_pkt_to_file.c b/lib/rdcu_pkt_to_file.c
index 24c213ee74134662530d113f80224d1151cf51c8..ea6ff5599a6682b853ce3576a0d9b25152ab7407 100644
--- a/lib/rdcu_pkt_to_file.c
+++ b/lib/rdcu_pkt_to_file.c
@@ -228,6 +228,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 			*p = '\0';
 		} else {
 			fprintf(stderr, "Error read in line to long.\n");
+			fclose(fp);
 			return -1;
 		}
 
@@ -241,6 +242,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 			    i > 0xFF) {
 				fprintf(stderr, "Error reading ICU_ADDR.\n");
 				errno = 0;
+				fclose(fp);
 				return -1;
 			}
 			*icu_addr = (uint8_t)i;
@@ -255,6 +257,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 			    || i > 0xFF) {
 				fprintf(stderr, "Error reading RDCU_ADDR.\n");
 				errno = 0;
+				fclose(fp);
 				return -1;
 			}
 			*rdcu_addr = (uint8_t)i;
@@ -269,6 +272,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 			    i > INT_MAX) {
 				fprintf(stderr, "Error reading MTU.\n");
 				errno = 0;
+				fclose(fp);
 				return -1;
 			}
 			*mtu = (int)i;
diff --git a/lib/rdcu_rmap.c b/lib/rdcu_rmap.c
index e25241c19e1e6c41034776ae24fa79576d1d99df..131cea07b0f4dee9f670be3dbb86a98bafdeeee6 100644
--- a/lib/rdcu_rmap.c
+++ b/lib/rdcu_rmap.c
@@ -261,7 +261,7 @@ static int rdcu_process_rx(void)
 
 		cnt++;
 
-		if (0)
+		if ((0))
 			rmap_parse_pkt(spw_pckt);
 
 		/* convert format */
@@ -353,7 +353,7 @@ int rdcu_submit_tx(const uint8_t *cmd,  int cmd_size,
 	if (!rmap_tx)
 		return -1;
 
-	if (0)
+	if ((0))
 		printf("Transmitting RMAP command\n");
 
 	if (rmap_tx(cmd, cmd_size, dpath_len, data, data_size)) {
@@ -530,8 +530,8 @@ int rdcu_sync_data(int (*fn)(uint16_t trans_id, uint8_t *cmd,
 
 	slot = trans_log_grab_slot(data);
 	if (slot < 0) {
-		if (0)
-		printf("Error: all slots busy!\n");
+		if ((0))
+			printf("Error: all slots busy!\n");
 		return 1;
 	}
 
@@ -792,10 +792,10 @@ void rdcu_rmap_reset_log(void)
  *
  * @param mtu the maximum data transfer size per unit
  *
- * @param rmap_tx a function pointer to transmit an rmap command
- * @param rmap_rx function pointer to receive an rmap command
+ * @param tx a function pointer to transmit an rmap command
+ * @param rx function pointer to receive an rmap command
  *
- * @note rmap_tx is expected to return 0 on success
+ * @note tx is expected to return 0 on success
  *	 rmap_rx is expected to return the number of packet bytes
  *
  * @returns 0 on success, otherwise error
diff --git a/test/cmp_tool/Makefile b/test/cmp_tool/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..543ea135a4f15e10d25440b3a7e17c9d3e1b41ff
--- /dev/null
+++ b/test/cmp_tool/Makefile
@@ -0,0 +1,25 @@
+CC               = gcc
+SOURCEDIR	 =
+INCLUDES         = -I../../include
+PATH            +=
+CFLAGS          := -O0 -W -Wall -Wextra -std=gnu99 -Werror -pedantic -g3\
+		-fprofile-arcs -ftest-coverage
+CPPFLAGS        := -D__MAIN__ $(INCLUDES) -I$(SOURCEDIR)
+LDFLAGS         := -lcunit
+SOURCES         := $(wildcard *.c) ../../lib/cmp_tool_lib.c ../../lib/cmp_guess.c\
+		../../lib/cmp_support.c ../../lib/cmp_icu.c ../../lib/cmp_data_types.c
+OBJECTS         := $(patsubst %.c, $(BUILDDIR)/%.o, $(subst $(SOURCEDIR)/,, $(SOURCES)))
+TARGET          := test_cmp_tool
+
+
+all: $(SOURCES)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $(TARGET)
+
+coverage: all
+	./$(TARGET)
+	lcov --rc lcov_branch_coverage=1 --capture --directory ./ --output-file coverage.info
+	genhtml --rc lcov_branch_coverage=1 --branch-coverage coverage.info --output-directory out
+	#firefox out/index.html
+
+clean:
+	rm -r $(TARGET) *.gcno *.gcda coverage.info out/ tmp_stderr.log
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..60e13cbb96b1a21734340f3157a0ee070976c4e0
--- /dev/null
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -0,0 +1,535 @@
+import subprocess
+import shlex
+import sys
+import os
+
+PATH_CMP_TOOL = "./cmp_tool"
+VERSION = "0.06"
+
+EXIT_FAILURE = 1
+EXIT_SUCCESS = 0
+
+
+def call_cmp_tool(args):
+    args = shlex.split(PATH_CMP_TOOL + " " + args)
+
+    try:
+        with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) as proc:
+            stdout, stderr = proc.communicate()
+            return (proc.returncode, stdout, stderr)
+    except:
+        print('Could not find the cmp_tool or has no execute rights!')
+        assert()
+
+
+def parse_key_value(str):
+    dir = {}
+    for line in str.splitlines():
+        if line == '':
+            continue
+        if line[0] == '#' or line[0] == '\n':
+            continue
+        name, var = line.partition(" = ")[::2]
+        dir[name.strip()] = var
+    return dir
+
+
+def del_file(filePath):
+    if os.path.exists(filePath):
+        os.remove(filePath)
+    else:
+        print("The file %s could not be deleted because it does not exist!" % (filePath))
+
+
+HELP_STRING = \
+"""usage: %s [options] [<argument>]
+General Options:
+  -h, --help               Print this help text and exit
+  -V, --version            Print program version and exit
+  -v, --verbose            Print various debugging information
+  -n, --model_cfg          Print a default model configuration and exit
+  --diff_cfg               Print a default 1d-differencing configuration and exit
+  -a, --rdcu_par           Add additional RDCU control parameters
+  -o <prefix>              Use the <prefix> for output files
+Compression Options:
+  -c <file>                File containing the compressing configuration
+  -d <file>                File containing the data to be compressed
+  -m <file>                File containing the model of the data to be compressed
+  --rdcu_pkt               Generate RMAP packets for an RDCU compression
+  --last_info <.info file> Generate RMAP packets for an RDCU compression with parallel read of the last results
+Decompression Options:
+  -i <file>                File containing the decompression information
+  -d <file>                File containing the compressed data
+  -m <file>                File containing the model of the compressed data
+Guessing Options:
+  --guess <mode>           Search for a good configuration for compression <mode>
+  -d <file>                File containing the data to be compressed
+  -m <file>                File containing the model of the data to be compressed
+  --guess_level <level>    Set guess level to <level> (optional)
+""" % (PATH_CMP_TOOL)
+
+
+CMP_START_STR = \
+"""#########################################################
+### PLATO Compression/Decompression Tool Version %s ###
+#########################################################
+
+""" % (VERSION)
+
+
+def test_no_option():
+    returncode, stdout, stderr = call_cmp_tool("")
+    assert(returncode == EXIT_FAILURE)
+    assert(stdout == HELP_STRING)
+    assert(stderr == "")
+
+
+def test_invalid_option():
+    args = ['-q', '--not_used']
+    for arg in args:
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(returncode == EXIT_FAILURE)
+        assert(stdout == HELP_STRING)
+        if arg == '-q':
+            if sys.platform == 'linux':
+                assert(stderr == "%s: invalid option -- 'q'\n" % (PATH_CMP_TOOL))
+            elif "win" in sys.platform:
+                assert(stderr == "%s: unknown option -- q\n" % (PATH_CMP_TOOL))
+            else:
+                assert(stderr == "cmp_tool: invalid option -- q\n")
+        else:
+            if sys.platform == 'linux':
+                assert(stderr == "%s: unrecognized option '--not_used'\n" % (PATH_CMP_TOOL))
+            elif "win" in sys.platform:
+                assert(stderr == "%s: unknown option -- not_used\n" % (PATH_CMP_TOOL))
+            else:
+                assert(stderr == "cmp_tool: unrecognized option `--not_used'\n")
+
+# def option requires an argument
+
+
+def test_help():
+    args = ['-h', '--help']
+    for arg in args:
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(returncode == EXIT_SUCCESS)
+        assert(stdout == HELP_STRING)
+        assert(stderr == "")
+
+
+def test_version():
+    args = ['-V', '--version']
+    for arg in args:
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(returncode == EXIT_SUCCESS)
+        assert(stdout == "cmp_tool version %s\n" % (VERSION))
+        assert(stderr == "")
+
+
+def test_print_diff_cfg():
+    # comments in the cfg file is not checked
+    args = ['--diff_cfg', '--diff_cfg -a', '--diff_cfg --rdcu_par']
+    for i, arg in enumerate(args):
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(returncode == EXIT_SUCCESS)
+        assert(stderr == "")
+
+        cfg = parse_key_value(stdout)
+        assert(cfg['cmp_mode'] == '2')
+        assert(cfg['samples'] == '0')
+        assert(cfg['buffer_length'] == '0')
+        assert(cfg['golomb_par'] == '7')
+        assert(cfg['spill'] == '60')
+        assert(cfg['model_value'] == '8')
+        assert(cfg['round'] == '0')
+        if i > 0:
+            assert(cfg['ap1_golomb_par'] == '6')
+            assert(cfg['ap1_spill'] == '48')
+            assert(cfg['ap2_golomb_par'] == '8')
+            assert(cfg['ap2_spill'] == '72')
+            assert(cfg['rdcu_data_adr'] == '0x000000')
+            assert(cfg['rdcu_model_adr'] == '0x000000')
+            assert(cfg['rdcu_new_model_adr'] == '0x000000')
+            assert(cfg['rdcu_buffer_adr'] == '0x600000')
+
+
+def test_print_model_cfg():
+    # comments in the cfg file is not checked
+    args = ['-n', '--model_cfg', '-na', '--model_cfg --rdcu_par']
+    for i, arg in enumerate(args):
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(returncode == EXIT_SUCCESS)
+        assert(stderr == "")
+
+        cfg = parse_key_value(stdout)
+        assert(cfg['cmp_mode'] == '3')
+        assert(cfg['samples'] == '0')
+        assert(cfg['buffer_length'] == '0')
+        assert(cfg['golomb_par'] == '4')
+        assert(cfg['spill'] == '48')
+        assert(cfg['model_value'] == '8')
+        assert(cfg['round'] == '0')
+        if i > 1:
+            assert(cfg['ap1_golomb_par'] == '3')
+            assert(cfg['ap1_spill'] == '35')
+            assert(cfg['ap2_golomb_par'] == '5')
+            assert(cfg['ap2_spill'] == '60')
+            assert(cfg['rdcu_data_adr'] == '0x000000')
+            assert(cfg['rdcu_model_adr'] == '0x200000')
+            assert(cfg['rdcu_new_model_adr'] == '0x400000')
+            assert(cfg['rdcu_buffer_adr'] == '0x600000')
+
+
+def test_no_data_file_name():
+    returncode, stdout, stderr = call_cmp_tool("-d no_data.data")
+    assert(returncode == EXIT_FAILURE)
+    assert(stdout == CMP_START_STR)
+    assert(stderr == "cmp_tool: No configuration file (-c option) or decompression information file (-i option) specified.\n")
+
+
+def test_no_c_or_i_file():
+    returncode, stdout, stderr = call_cmp_tool("-c no_cfg.cfg")
+    assert(returncode == EXIT_FAILURE)
+    assert(stdout == CMP_START_STR)
+    assert(stderr == "cmp_tool: No data file (-d option) specified.\n")
+
+
+def test_no_cfg_exist_test():
+    returncode, stdout, stderr = call_cmp_tool("-d no_data.dat -c no_cfg.cfg")
+    assert(returncode == EXIT_FAILURE)
+    assert(stdout == CMP_START_STR +
+           "Importing configuration file no_cfg.cfg ... FAILED\n")
+    assert(stderr == "cmp_tool: no_cfg.cfg: No such file or directory\n")
+
+
+def test_compression_diff():
+    # generate test data
+    data = '00 01 00 02 00 03 00 04 00 05 \n'
+    data_file_name = 'data.dat'
+    cfg_file_name = 'diff.cfg'
+    output_prefix = 'diff_cmp'
+    try:
+        with open(data_file_name, 'w', encoding='utf-8') as f:
+            f.write(data)
+
+        # generate test configuration
+        with open(cfg_file_name, 'w', encoding='utf-8') as f:
+            returncode, stdout, stderr = call_cmp_tool("--diff_cfg")
+            assert(returncode == EXIT_SUCCESS)
+            assert(stderr == "")
+            f.write(stdout)
+
+        # compression
+        returncode, stdout, stderr = call_cmp_tool(
+            " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix)
+
+        # check compression results
+        assert(returncode == EXIT_SUCCESS)
+        assert(stderr == "")
+        assert(stdout == CMP_START_STR +
+               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+               "Importing data file %s ... \n" % (data_file_name) +
+               "No samples parameter set. Use samples = 5.\n" +
+               "... DONE\n" +
+               "No buffer_length parameter set. Use buffer_length = 12 as compression buffer size.\n" +
+               "Compress data ... DONE\n" +
+               "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix) +
+               "Write decompression information to file %s.info ... DONE\n" % (output_prefix))
+        # check compressed data
+        with open(output_prefix+".cmp", encoding='utf-8') as f:
+            assert(f.read() == "44 44 40 00 \n")
+        # check info file
+        with open(output_prefix+".info", encoding='utf-8') as f:
+            info = parse_key_value(f.read())
+        assert(info['cmp_mode_used'] == '2')
+        # assert(info['model_value_used'] == '8')  # not needed for diff
+        assert(info['round_used'] == '0')
+        assert(info['spill_used'] == '60')
+        assert(info['golomb_par_used'] == '7')
+        assert(info['samples_used'] == '5')
+        assert(info['cmp_size'] == '20')
+        assert(info['cmp_err'] == '0')
+
+        # decompression
+        returncode, stdout, stderr = call_cmp_tool(
+            " -i "+output_prefix+".info -d "+output_prefix+".cmp -o "+output_prefix)
+
+        # check decompression
+        assert(returncode == EXIT_SUCCESS)
+        assert(stdout == CMP_START_STR +
+               "Importing decompression information file %s.info ... DONE\n" % (output_prefix) +
+               "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix) +
+               "Decompress data ... DONE\n" +
+               "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix))
+        assert(stderr == "")
+        with open(output_prefix+".dat", encoding='utf-8') as f:
+            assert(f.read() == data)  # decompressed data == input data
+
+    # clean up
+    finally:
+        del_file(data_file_name)
+        del_file(cfg_file_name)
+        del_file(output_prefix+'.cmp')
+        del_file(output_prefix+'.info')
+        del_file(output_prefix+'.dat')
+
+
+def test_model_compression():
+    # generate test data
+    data = '00 01 00 02 00 03 00 04 00 05 \n'
+    model = '00 00 00 01 00 02 00 03 00 04 \n'
+    data_file_name = 'data.dat'
+    model_file_name = 'model.dat'
+    cfg_file_name = 'model.cfg'
+    output_prefix1 = 'model_cmp'
+    output_prefix2 = 'model_decmp'
+    try:
+        with open(data_file_name, 'w', encoding='utf-8') as f:
+            f.write(data)
+        with open(model_file_name, 'w', encoding='utf-8') as f:
+            f.write(model)
+
+        # generate test configuration
+        with open(cfg_file_name, 'w', encoding='utf-8') as f:
+            returncode, stdout, stderr = call_cmp_tool("--model_cfg")
+            assert(returncode == EXIT_SUCCESS)
+            assert(stderr == "")
+            cfg = parse_key_value(stdout)
+            cfg['cmp_mode'] = 'MODE_MODEL_MULTI'
+            cfg["samples"] = '5'
+            cfg["buffer_length"] = '2'
+            for key, value in cfg.items():
+                f.write(key + ' = ' + str(value) + '\n')
+
+        # compression
+        returncode, stdout, stderr = call_cmp_tool(
+            " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix1)
+
+        # check compression results
+        assert(returncode == EXIT_SUCCESS)
+        assert(stderr == "")
+        assert(stdout == CMP_START_STR +
+               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+               "Importing data file %s ... DONE\n" % (data_file_name) +
+               "Importing model file %s ... DONE\n" % (model_file_name) +
+               "Compress data ... DONE\n" +
+               "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix1) +
+               "Write decompression information to file %s.info ... DONE\n" % (output_prefix1) +
+               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix1))
+        # check compressed data
+        with open(output_prefix1+".cmp", encoding='utf-8') as f:
+            assert(f.read() == "49 24 00 00 \n")
+        # check info file
+        with open(output_prefix1+".info", encoding='utf-8') as f:
+            info = parse_key_value(f.read())
+        assert(info['cmp_mode_used'] == '3')
+        assert(info['model_value_used'] == cfg['model_value'])
+        assert(info['round_used'] == cfg['round'])
+        assert(info['spill_used'] == cfg['spill'])
+        assert(info['golomb_par_used'] == cfg['golomb_par'])
+        assert(info['samples_used'] == cfg['samples'])
+        assert(info['cmp_size'] == '15')
+        assert(info['cmp_err'] == '0')
+
+        # decompression
+        returncode, stdout, stderr = call_cmp_tool(
+            " -i "+output_prefix1+".info -d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
+        assert(returncode == EXIT_SUCCESS)
+        assert(stdout == CMP_START_STR +
+               "Importing decompression information file %s.info ... DONE\n" % (output_prefix1) +
+               "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix1) +
+               "Importing model file %s ... DONE\n" % (model_file_name) +
+               "Decompress data ... DONE\n" +
+               "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix2) +
+               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix2))
+        assert(stderr == "")
+        # check compressed data
+
+        with open(output_prefix2+".dat", encoding='utf-8') as f:
+            assert(f.read() == data)
+
+        with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
+            with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
+                assert(f1.read() == f2.read() ==
+                       '00 00 00 01 00 02 00 03 00 04 \n')
+    # clean up
+    finally:
+        del_file(data_file_name)
+        del_file(model_file_name)
+        del_file(cfg_file_name)
+        del_file(output_prefix1+'.cmp')
+        del_file(output_prefix1+'.info')
+        del_file(output_prefix1+'_upmodel.dat')
+        del_file(output_prefix2+'.dat')
+        del_file(output_prefix2+'_upmodel.dat')
+
+
+def test_guess_option():
+    # generate test data
+    data = '00 01 00 01 00 01 00 01 00 01 \n'
+    model = '00 00 00 00 00 00 00 00 00 00 \n'
+    data_file_name = 'data.dat'
+    model_file_name = 'model.dat'
+    args = [
+        ['guess_RDCU_diff',  '--guess RDCU -d %s -o guess --rdcu_par' %
+            (data_file_name)],
+        ['guess_RDCU_model', '--guess RDCU -d %s -m %s -o guess --rdcu_par' %
+            (data_file_name, model_file_name)],
+        ['guess_level_3',    '--guess MODE_DIFF_MULTI --guess_level 3 -d %s -o guess' %
+            (data_file_name)],
+        ['cfg_folder_not_exist', '--guess RDCU -d ' +
+            data_file_name+' -o not_exist/guess'],
+        ['guess_level_10',    '--guess MODE_DIFF_MULTI --guess_level 10 -d %s -o guess' %
+            (data_file_name)],
+        ['guess_unknown_mode', '--guess MODE_UNKNOWN -d %s -o guess' %
+            (data_file_name)],
+        ['guess_model_mode_no_model ', '--guess 1 -d %s -o guess' %
+            (data_file_name)],
+    ]
+    try:
+        with open(data_file_name, 'w', encoding='utf-8') as f:
+            f.write(data)
+        with open(model_file_name, 'w', encoding='utf-8') as f:
+            f.write(model)
+
+        for sub_test, arg in args:
+            returncode, stdout, stderr = call_cmp_tool(arg)
+            if sub_test == 'guess_RDCU_diff' or sub_test == 'guess_RDCU_model' or sub_test == 'guess_level_3':
+                assert(stderr == "")
+                assert(returncode == EXIT_SUCCESS)
+
+                if sub_test == 'guess_RDCU_diff':
+                    exp_out = ('', '2', '', '7.27')
+                elif sub_test == 'guess_RDCU_model':
+                    exp_out = (
+                        'Importing model file model.dat ... DONE\n', '2', '', '5.33')
+                elif sub_test == 'guess_level_3':
+                    exp_out = (
+                        '', '3', ' 0%... 6%... 13%... 19%... 25%... 32%... 38%... 44%... 50%... 57%... 64%... 72%... 80%... 88%... 94%... 100%', '11.43')
+                else:
+                    exp_out = ('', '', '')
+
+                assert(stdout == CMP_START_STR +
+                       "Importing data file %s ... \n" % (data_file_name) +
+                       "No samples parameter set. Use samples = 5.\n"
+                       "... DONE\n"
+                       "%s"
+                       "Search for a good set of compression parameters (level: %s) ...%s DONE\n"
+                       "Write the guessed compression configuration to file guess.cfg ... DONE\n"
+                       "Guessed parameters can compress the data with a CR of %s.\n" % exp_out)
+
+                # check configuration file
+                with open('guess.cfg') as f:
+                    cfg = parse_key_value(f.read())
+                assert(cfg['samples'] == '5')
+                assert(cfg['buffer_length'] == '2')
+                assert(cfg['model_value'] == '11')
+                assert(cfg['round'] == '0')
+                if sub_test == 'guess_RDCU_diff':
+                    assert(cfg['cmp_mode'] == '2')
+                    assert(cfg['golomb_par'] == '2')
+                    assert(cfg['spill'] == '22')
+                    assert(cfg['ap1_golomb_par'] == '1')
+                    assert(cfg['ap1_spill'] == '8')
+                    assert(cfg['ap2_golomb_par'] == '3')
+                    assert(cfg['ap2_spill'] == '35')
+                    assert(cfg['rdcu_data_adr'] == '0x000000')
+                    assert(cfg['rdcu_model_adr'] == '0x000000')
+                    assert(cfg['rdcu_new_model_adr'] == '0x000000')
+                    assert(cfg['rdcu_buffer_adr'] == '0x600000')
+                elif sub_test == 'guess_RDCU_model':
+                    assert(cfg['cmp_mode'] == '3')
+                    assert(cfg['golomb_par'] == '1')
+                    assert(cfg['spill'] == '8')
+                    assert(cfg['ap1_golomb_par'] == '2')
+                    assert(cfg['ap1_spill'] == '16')
+                    assert(cfg['ap2_golomb_par'] == '3')
+                    assert(cfg['ap2_spill'] == '23')
+                    assert(cfg['rdcu_data_adr'] == '0x000000')
+                    assert(cfg['rdcu_model_adr'] == '0x200000')
+                    assert(cfg['rdcu_new_model_adr'] == '0x400000')
+                    assert(cfg['rdcu_buffer_adr'] == '0x600000')
+                else:
+                    assert(cfg['cmp_mode'] == '4')
+                    assert(cfg['golomb_par'] == '1')
+                    assert(cfg['spill'] == '3')
+            elif sub_test == 'cfg_folder_not_exist':
+                # error case cfg directory does not exit
+                assert(
+                    stderr == "cmp_tool: not_exist/guess.cfg: No such file or directory\n")
+                assert(returncode == EXIT_FAILURE)
+                assert(stdout == CMP_START_STR +
+                       "Importing data file %s ... \n" % (data_file_name) +
+                       "No samples parameter set. Use samples = 5.\n" +
+                       "... DONE\n"
+                       "Search for a good set of compression parameters (level: 2) ... DONE\n" +
+                       "Write the guessed compression configuration to file not_exist/guess.cfg ... FAILED\n")
+            elif sub_test == 'guess_level_10':
+                assert(stderr == "cmp_tool: guess level not supported!\n")
+                assert(returncode == EXIT_FAILURE)
+                assert(stdout == CMP_START_STR +
+                       "Importing data file %s ... \n" % (data_file_name) +
+                       "No samples parameter set. Use samples = 5.\n" +
+                       "... DONE\n"
+                       "Search for a good set of compression parameters (level: 10) ... FAILED\n")
+            elif sub_test == 'guess_unknown_mode':
+                assert(
+                    stderr == "cmp_tool: Error: unknown compression mode: MODE_UNKNOWN\n")
+                assert(returncode == EXIT_FAILURE)
+                assert(stdout == CMP_START_STR +
+                       "Importing data file %s ... \n" % (data_file_name) +
+                       "No samples parameter set. Use samples = 5.\n" +
+                       "... DONE\n"
+                       "Search for a good set of compression parameters (level: 2) ... FAILED\n")
+            else:
+                assert(
+                    stderr == "cmp_tool: Error: model mode needs model data (-m option)\n")
+                assert(returncode == EXIT_FAILURE)
+                assert(stdout == CMP_START_STR +
+                       "Importing data file %s ... \n" % (data_file_name) +
+                       "No samples parameter set. Use samples = 5.\n" +
+                       "... DONE\n"
+                       "Search for a good set of compression parameters (level: 2) ... FAILED\n")
+    # clean up
+    finally:
+        del_file(data_file_name)
+        del_file(model_file_name)
+        del_file('guess.cfg')
+
+
+def test_small_buf_err():
+    data = '00 01 0F 02 00 0C 00 42 00 23 \n'
+    data_file_name = 'small_buf.dat'
+    cfg_file_name = 'small_buf.cfg'
+    arg = '-c %s -d %s' % (cfg_file_name, data_file_name)
+
+    try:
+        with open(data_file_name, 'w') as f:
+            f.write(data)
+
+        # create a compression file
+        with open(cfg_file_name, 'w') as f:
+            returncode, stdout, stderr = call_cmp_tool("--diff_cfg")
+            assert(returncode == EXIT_SUCCESS)
+            assert(stderr == "")
+            cfg = parse_key_value(stdout)
+            cfg["samples"] = '5'
+            cfg["buffer_length"] = '2'
+            for key, value in cfg.items():
+                f.write(key + ' = ' + str(value) + '\n')
+
+        returncode, stdout, stderr = call_cmp_tool(arg)
+        assert(stdout == CMP_START_STR +
+               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+               "Importing data file %s ... DONE\n" % (data_file_name) +
+               "Compress data ... \n"
+               "Compression error 0x01\n"
+               "... FAILED\n")
+        assert(stderr == "cmp_tool: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n")
+        assert(returncode == EXIT_FAILURE)
+
+    finally:
+        del_file(data_file_name)
+        del_file(cfg_file_name)
+
+# TODO: random test
diff --git a/test/cmp_tool/cmp_tool_lib_test.c b/test/cmp_tool/cmp_tool_lib_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..d55a715acc64053c16c28d585b90cf9387b17375
--- /dev/null
+++ b/test/cmp_tool/cmp_tool_lib_test.c
@@ -0,0 +1,540 @@
+/**
+ * @file   test_cmp_tool_lib.c
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at)
+ * @date   2020
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief unit tests for cmp_tool_lib.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+#include <CUnit/Basic.h>
+#include <CUnit/Console.h>
+
+#include "../../include/cmp_tool_lib.h"
+#include "../../include/cmp_guess.h"
+
+#define PROGRAM_NAME "cmp_tool"
+
+/* used to redirect stdout to file */
+int fd;
+
+/* used to redirect stdout to file */
+fpos_t pos;
+
+/* @brief The init cmp_tool test suite cleanup functionr. Redirect stdout to
+ *	file
+ * @see: http://c-faq.com/stdio/undofreopen.html
+ * @returns zero on success, non-zero otherwise.
+ */
+static int init_cmp_tool(void)
+{
+	fflush(stderr);
+	fgetpos(stderr, &pos);
+	fd = dup(fileno(stderr));
+	if (freopen("tmp_stderr.log", "w", stderr) == NULL) {
+		perror("freopen() failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/* @brief The cmp_tool test suite cleanup function. Closes the temporary file
+ *	used by the tests.
+ * @returns zero on success, non-zero otherwise.
+ */
+static int clean_cmp_tool(void)
+{
+	fflush(stderr);
+	dup2(fd, fileno(stderr));
+	close(fd);
+	clearerr(stderr);
+	fsetpos(stderr, &pos);        /* for C9X */
+
+	return 0;
+}
+
+
+/* returnd memory must be freed after use */
+char *read_std_err_log(void)
+{
+	char *response = NULL;
+	size_t len = 0;
+	FILE *fp = fopen("tmp_stderr.log", "r");
+	static int n_lines_read =0;
+	int i;
+
+	if (!fp) {
+		puts("File opening failed");
+		abort();
+	}
+
+	fflush(stderr);
+	for (i=0; getline(&response, &len, fp) != -1; i++) {
+		if (i == n_lines_read) {
+			n_lines_read++;
+			/* printf("%zu %s\n",len, response); */
+			fclose(fp);
+			return response;
+		} else {
+			free(response);
+			response = NULL;
+		}
+	}
+	free(response);
+	response = malloc(1);
+	if (!response)
+		abort();
+	response[0] = '\0';
+
+	fclose(fp);
+	return response;
+}
+
+
+/* tests */
+
+/**
+ * @test cmp_tool
+ */
+
+void test_read_file8(void)
+{
+	void *file_name;
+	uint8_t *buf;
+	uint32_t n_word;
+	ssize_t i, size;
+	uint8_t array[33] = {0};
+	char *s;
+
+	/* read in a normal data file */
+	memset(array, 0, sizeof(array));
+	file_name = "test_read_file8_1.txt";
+	buf = array;
+	n_word = 33;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, 33);
+	/* no output on stderr */
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "");
+	free(s);
+
+	/* tests counting the size of a file */
+	file_name = "test_read_file8_2.txt";
+	buf = NULL;
+	n_word = 0;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, 33);
+	/* no output on stderr */
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "");
+	free(s);
+
+	/* test data read in counting comments */
+	file_name = "test_read_file8_2.txt";
+	buf = array;
+	n_word = size;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, 33);
+	for (i = 0; i < size; ++i) {
+		CU_ASSERT_EQUAL(buf[i], i);
+	}
+	/* no output on stderr */
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "");
+	free(s);
+
+	/* tests partially read in */
+	memset(array, 0, sizeof(array));
+	file_name = "test_read_file8_2.txt";
+	buf = array;
+	n_word = 32;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, 32);
+	for (i = 0; i < 33; ++i) {
+		if (i < 32) {
+			CU_ASSERT_EQUAL(buf[i], i);
+		} else {
+			CU_ASSERT_EQUAL(buf[i], 0);
+		}
+	}
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_2.txt: Warning: The file may contain more data than specified by the samples or cmp_size parameter.\n");
+	free(s);
+
+	/* tests read 0 words in */
+	memset(array, 0, sizeof(array));
+	file_name = "test_read_file8_2.txt";
+	buf = array;
+	n_word = 0;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, 0);
+	for (i = 0; i < 33; ++i) {
+		CU_ASSERT_EQUAL(buf[i], 0);
+	}
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_2.txt: Warning: The file may contain more data than specified by the samples or cmp_size parameter.\n");
+	free(s);
+
+	/* TODO; tests read in 0 empty file */
+
+	/* Error cases */
+	/***************/
+
+	/* file does not contain enough data */
+	memset(array, 0xFF, sizeof(array));
+	file_name = "test_read_file8_2.txt";
+	buf = array;
+	n_word = 34;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, -1);
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_2.txt: Error: The files does not contain enough data as given by the n_word parameter.\n");
+	free(s);
+	memset(array, 0xFF, sizeof(array));
+
+	/* no file_name */
+	file_name = NULL;
+	buf = array;
+	n_word = 33;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, -1);
+	/* no output on stderr */
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "");
+	free(s);
+
+	/* wrong file_name */
+	file_name = "file_not_exist.txt";
+	buf = array;
+	n_word = 33;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, -1);
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: file_not_exist.txt: No such file or directory\n");
+	free(s);
+
+	/* wrong data format part 1/2 */
+	file_name = "test_read_file8_3.txt";
+	buf = array;
+	n_word = 33;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, -1);
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_3.txt: Error: The data are not correct formatted. Expected format is like: 12 AB 23 CD .. ..\n");
+	free(s);
+
+	/* wrong data format part 2/2 */
+	file_name = "test_read_file8_4.txt";
+	buf = array;
+	n_word = 33;
+	size = read_file8(file_name, buf, n_word, 0);
+	CU_ASSERT_EQUAL(size, -1);
+	CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_4.txt: Error: The data are not correct formatted. Expected format is like: 12 AB 23 CD .. ..\n");
+	free(s);
+
+	/* file error */
+	/* TODO: how to trigger a file error indicator error */
+	if (1) {
+		/* static char fname[] = "test_read_file8_5.txt"; */
+		/* FILE *f = fopen(fname, "wb"); */
+		/* fputs("\xff\xff\n", f); // not a valid UTF-8 character sequence */
+		/* fclose(f); */
+		buf = array;
+		n_word = 33;
+		size = read_file8("test_read_file8_5.txt", buf, n_word, 0);
+		CU_ASSERT_EQUAL(size, -1);
+		CU_ASSERT_STRING_EQUAL(s=read_std_err_log(), "cmp_tool: test_read_file8_5.txt: Error: File error indicator set.\n");
+		free(s);
+	}
+}
+
+
+#define CMP_TEST_SAMPLES 5
+void test_cmp_guess(void)
+{
+	struct cmp_cfg cfg = {0};
+	uint16_t data[CMP_TEST_SAMPLES] = {2,4,6,8,10};
+	uint16_t data_exp[CMP_TEST_SAMPLES] = {2,4,6,8,10};
+	uint16_t model[CMP_TEST_SAMPLES] = {4,6,8,10,12};
+	uint16_t model_exp[CMP_TEST_SAMPLES] = {4,6,8,10,12};
+	uint32_t cmp_size;
+	int level;
+
+
+	/* test 1d-diff mode */
+	cfg.input_buf = data;
+	cfg.model_buf = NULL;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = MODE_DIFF_MULTI;
+	level = 2;
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_TRUE(cmp_size);
+
+	CU_ASSERT_EQUAL(cmp_size, 25);
+	CU_ASSERT_EQUAL(cfg.cmp_mode, MODE_DIFF_MULTI);
+	CU_ASSERT_EQUAL(cfg.golomb_par, 1);
+	CU_ASSERT_EQUAL(cfg.spill, 2);
+	/* CU_ASSERT_EQUAL(cfg.model_value, ); model_value is not needed */
+	CU_ASSERT_EQUAL(cfg.round, 0);
+	CU_ASSERT_EQUAL(cfg.ap1_golomb_par, 2);
+	CU_ASSERT_EQUAL(cfg.ap1_spill, 2);
+	CU_ASSERT_EQUAL(cfg.ap2_golomb_par, 3);
+	CU_ASSERT_EQUAL(cfg.ap2_spill, 2);
+	CU_ASSERT_NSTRING_EQUAL(cfg.input_buf, data_exp, CMP_TEST_SAMPLES);
+	/* CU_ASSERT_NSTRING_EQUAL(cfg.model_buf, model_exp, CMP_TEST_SAMPLES); model is
+	 * not used*/
+	CU_ASSERT_EQUAL(cfg.samples, CMP_TEST_SAMPLES);
+	CU_ASSERT_EQUAL(cfg.buffer_length, 2);
+
+
+	/* test model mode */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = MODE_MODEL_ZERO;
+	level =3;
+
+	cmp_guess_set_model_updates(12);
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_TRUE(cmp_size);
+
+	CU_ASSERT_EQUAL(cmp_size, 20);
+	CU_ASSERT_EQUAL(cfg.cmp_mode, 1);
+	CU_ASSERT_EQUAL(cfg.golomb_par, 2);
+	CU_ASSERT_EQUAL(cfg.spill, 22);
+	CU_ASSERT_EQUAL(cfg.model_value, 12);
+	CU_ASSERT_EQUAL(cfg.round, 0);
+	CU_ASSERT_EQUAL(cfg.ap1_golomb_par, 1);
+	CU_ASSERT_EQUAL(cfg.ap1_spill, 8);
+	CU_ASSERT_EQUAL(cfg.ap2_golomb_par, 3);
+	CU_ASSERT_EQUAL(cfg.ap2_spill, 35);
+	CU_ASSERT_NSTRING_EQUAL(cfg.input_buf, data_exp, CMP_TEST_SAMPLES);
+	CU_ASSERT_NSTRING_EQUAL(cfg.model_buf, model_exp, CMP_TEST_SAMPLES);
+	CU_ASSERT_EQUAL(cfg.samples, CMP_TEST_SAMPLES);
+	CU_ASSERT_EQUAL(cfg.buffer_length, 2);
+
+
+	/* test diff mode without model buffer*/
+	cmp_guess_set_model_updates(CMP_GUESS_N_MODEL_UPDATE_DEF);
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = MODE_DIFF_MULTI;
+	level = 3;
+
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_TRUE(cmp_size);
+
+	CU_ASSERT_EQUAL(cmp_size, 20);
+	CU_ASSERT_EQUAL(cfg.cmp_mode, MODE_DIFF_MULTI);
+	CU_ASSERT_EQUAL(cfg.golomb_par, 2);
+	CU_ASSERT_EQUAL(cfg.spill, 5);
+	CU_ASSERT_EQUAL(cfg.model_value, 11);
+	CU_ASSERT_EQUAL(cfg.round, 0);
+	CU_ASSERT_EQUAL(cfg.ap1_golomb_par, 1);
+	CU_ASSERT_EQUAL(cfg.ap1_spill, 2);
+	CU_ASSERT_EQUAL(cfg.ap2_golomb_par, 3);
+	CU_ASSERT_EQUAL(cfg.ap2_spill, 2);
+	CU_ASSERT_NSTRING_EQUAL(cfg.input_buf, data_exp, CMP_TEST_SAMPLES);
+	CU_ASSERT_NSTRING_EQUAL(cfg.model_buf, model_exp, CMP_TEST_SAMPLES);
+	CU_ASSERT_EQUAL(cfg.samples, CMP_TEST_SAMPLES);
+	CU_ASSERT_EQUAL(cfg.buffer_length, 2);
+
+
+	/* error test cfg = NULL */
+	level = 2;
+	cmp_size = cmp_guess(NULL, level);
+	CU_ASSERT_FALSE(cmp_size);
+
+
+	/* error test unknown guess_level */
+	level = 4;
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_FALSE(cmp_size);
+
+
+	/* error test model mode without model buffer*/
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = NULL;
+	cfg.model_buf = NULL;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = MODE_DIFF_MULTI;
+	level = 2;
+
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_FALSE(cmp_size);
+
+
+	/* error test model mode without model buffer*/
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = data;
+	cfg.model_buf = NULL;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = MODE_MODEL_MULTI;
+	level = 2;
+
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_FALSE(cmp_size);
+
+
+	/* error test not supported cmp_mode */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.samples = CMP_TEST_SAMPLES;
+	cfg.cmp_mode = 5;
+	level = 2;
+
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_FALSE(cmp_size);
+
+
+	/* error test samples = 0 */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.samples = 0;
+	cfg.cmp_mode = MODE_MODEL_MULTI;
+	level = 2;
+
+	cmp_size = cmp_guess(&cfg, level);
+	CU_ASSERT_FALSE(cmp_size);
+}
+
+void test_cmp_guess_model_value(void)
+{
+	uint16_t model_value;
+
+	model_value = cmp_guess_model_value(0);
+	CU_ASSERT_EQUAL(model_value, 8);
+	model_value = cmp_guess_model_value(1);
+	CU_ASSERT_EQUAL(model_value, 8);
+	model_value = cmp_guess_model_value(2);
+	CU_ASSERT_EQUAL(model_value, 8);
+	model_value = cmp_guess_model_value(3);
+	CU_ASSERT_EQUAL(model_value, 10);
+	model_value = cmp_guess_model_value(4);
+	CU_ASSERT_EQUAL(model_value, 10);
+	model_value = cmp_guess_model_value(5);
+	CU_ASSERT_EQUAL(model_value, 10);
+	model_value = cmp_guess_model_value(6);
+	CU_ASSERT_EQUAL(model_value, 11);
+	model_value = cmp_guess_model_value(10);
+	CU_ASSERT_EQUAL(model_value, 11);
+	model_value = cmp_guess_model_value(11);
+	CU_ASSERT_EQUAL(model_value, 11);
+	model_value = cmp_guess_model_value(12);
+	CU_ASSERT_EQUAL(model_value, 12);
+	model_value = cmp_guess_model_value(20);
+	CU_ASSERT_EQUAL(model_value, 12);
+	model_value = cmp_guess_model_value(21);
+	CU_ASSERT_EQUAL(model_value, 12);
+	model_value = cmp_guess_model_value(22);
+	CU_ASSERT_EQUAL(model_value, 13);
+}
+
+
+void test_cmp_mode_parse(void)
+{
+	uint32_t cmp_mode = ~0;
+	int err;
+
+	/* error cases */
+	err = cmp_mode_parse(NULL, NULL);
+	CU_ASSERT_TRUE(err);
+
+	err = cmp_mode_parse(NULL, &cmp_mode);
+	CU_ASSERT_TRUE(err);
+
+	err = cmp_mode_parse("MODE_RAW", NULL);
+	CU_ASSERT_TRUE(err);
+
+	err = cmp_mode_parse("UNKNOWN", &cmp_mode);
+	CU_ASSERT_TRUE(err);
+
+	err = cmp_mode_parse("9999999999999999999", &cmp_mode);
+	CU_ASSERT_TRUE(err);
+
+	/* mode not defined*/
+	err = cmp_mode_parse("424212", &cmp_mode);
+	CU_ASSERT_TRUE(err);
+
+	/* normal operation */
+	err = cmp_mode_parse("MODE_RAW", &cmp_mode);
+	CU_ASSERT_FALSE(err);
+	CU_ASSERT_EQUAL(cmp_mode, MODE_RAW);
+
+	err = cmp_mode_parse("0", &cmp_mode);
+	CU_ASSERT_FALSE(err);
+	CU_ASSERT_EQUAL(cmp_mode, MODE_RAW);
+
+	err = cmp_mode_parse("0 \n", &cmp_mode);
+	CU_ASSERT_FALSE(err);
+	CU_ASSERT_EQUAL(cmp_mode, MODE_RAW);
+
+	err = cmp_mode_parse(" 2 ", &cmp_mode);
+	CU_ASSERT_FALSE(err);
+	CU_ASSERT_EQUAL(cmp_mode, 2);
+
+	err = cmp_mode_parse("MODE_DIFF_MULTI", &cmp_mode);
+	CU_ASSERT_FALSE(err);
+	CU_ASSERT_EQUAL(cmp_mode, MODE_DIFF_MULTI);
+}
+
+CU_ErrorCode cmp_tool_add_tests(CU_pSuite suite)
+{
+	CU_pTest  __attribute__((unused)) test;
+
+	/* add a suite to the registry */
+	suite = CU_add_suite("cmp_tool", init_cmp_tool, clean_cmp_tool);
+	if (suite == NULL) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	/* add the tests to the suite */
+	if ((NULL == CU_add_test(suite, "test of read_file8()", test_read_file8)) ||
+	    (NULL == CU_add_test(suite, "test of cmp_mode_parse()", test_cmp_mode_parse))||
+	    (NULL == CU_add_test(suite, "test of cmp_guess_model_value()", test_cmp_guess_model_value))||
+	    (NULL == CU_add_test(suite, "test of cmp_guess()", test_cmp_guess))) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	return CUE_SUCCESS;
+}
+
+
+#if (__MAIN__)
+int main(void)
+{
+	CU_pSuite suite = NULL;
+
+	/* initialize the CUnit test registry */
+	if (CU_initialize_registry() != CUE_SUCCESS)
+		return CU_get_error();
+
+	cmp_tool_add_tests(suite);
+
+	CU_basic_set_mode(CU_BRM_VERBOSE);
+	CU_basic_run_tests();
+
+	printf("\n\n\n");
+
+	CU_basic_show_failures(CU_get_failure_list());
+
+	CU_cleanup_registry();
+
+	return CU_get_error();
+}
+#endif
diff --git a/test/cmp_tool/test_read_file8_1.txt b/test/cmp_tool/test_read_file8_1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c700aa60c35b1f2c5b7ca42082d62054511e025d
--- /dev/null
+++ b/test/cmp_tool/test_read_file8_1.txt
@@ -0,0 +1,2 @@
+00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
+11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
diff --git a/test/cmp_tool/test_read_file8_2.txt b/test/cmp_tool/test_read_file8_2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d8122a861aad099273fb76ab6a8e3d87ba8b80c5
--- /dev/null
+++ b/test/cmp_tool/test_read_file8_2.txt
@@ -0,0 +1,10 @@
+# test file to the read_file8 function
+00
+01	02
+03 04 05
+06 07 08 09
+
+0A 0B 0C 0D 0E
+0F 10 11 12 13 14
+# skip this line!
+15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 
diff --git a/test/cmp_tool/test_read_file8_3.txt b/test/cmp_tool/test_read_file8_3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..808a543aedc2ce35ebe1fa3726c5a582f1385431
--- /dev/null
+++ b/test/cmp_tool/test_read_file8_3.txt
@@ -0,0 +1,9 @@
+# 2nd test file to the read_file8 function
+# to test the error case when data are wrong encoded
+00 01 02 03 04 05
+06 07 08 09 0A 0B
+0C 0D 0E 0F 10 11
+12 13 14 15 16 17
+18 19 1A 1B 1C 1D
+1E1F 20
+#^ this is the wrong formating
diff --git a/test/cmp_tool/test_read_file8_4.txt b/test/cmp_tool/test_read_file8_4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8dcdd2a5818bafc3ffb5c8a93cb511b8920cde9a
--- /dev/null
+++ b/test/cmp_tool/test_read_file8_4.txt
@@ -0,0 +1,9 @@
+# 2nd test file to the read_file8 function
+# to test the error case when data are wrong encoded
+00 01 02 03 04 05
+06 07 08 09 0A 0B
+0C 0D 0E 0F 10 11
+12 13 14 15 16 17
+18 19 1A 1B 1C 1D
+1L  1F 20
+#^ this is the wrong formating
diff --git a/test/cmp_tool/test_read_file8_5.txt b/test/cmp_tool/test_read_file8_5.txt
new file mode 100644
index 0000000000000000000000000000000000000000..eac4d84af102ae56ad7c9d905f50db8f2fe5cc3a
--- /dev/null
+++ b/test/cmp_tool/test_read_file8_5.txt
@@ -0,0 +1 @@
+��