Fix ICC warnings
[alexxy/gromacs.git] / src / external / tng_io / src / lib / tng_io.c
index b6c6f22227e791677bc752ec05d48e5f88a5debe..7702d23846c5d12cd5aa2351c0a7a4fe2a4f193e 100644 (file)
@@ -1,9 +1,7 @@
 /* This code is part of the tng binary trajectory format.
- *
- *                      VERSION 1.5
  *
  * Written by Magnus Lundborg
- * Copyright (c) 2012-2013, The GROMACS development team.
+ * Copyright (c) 2012-2014, The GROMACS development team.
  * Check out http://www.gromacs.org for more information.
  *
  *
@@ -11,6 +9,14 @@
  * modify it under the terms of the Revised BSD License.
  */
 
+#define _FILE_OFFSET_BITS 64
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#define _LARGEFILE_SOURCE
+/* Define for large files, on AIX-style hosts. */
+#define _LARGE_FILES
+
+#include "tng/tng_io.h"
+
 #ifdef USE_STD_INTTYPES_H
 #include <inttypes.h>
 #endif
 #include <zlib.h>
 #endif
 
-#include "../../include/tng_io.h"
-#include "../../include/md5.h"
-#include "../../include/compression/tng_compress.h"
-
+#include "tng/md5.h"
+#include "compression/tng_compress.h"
+#include "tng/version.h"
+
+#if defined( _WIN32 ) || defined( _WIN64 )
+    #ifndef fseeko
+        #define fseeko _fseeki64
+    #endif
+    #ifndef ftello
+        #ifdef __MINGW32__
+            #define ftello ftello64
+        #else
+            #define ftello _ftelli64
+        #endif
+    #endif
+#endif
 
 struct tng_bond {
     /** One of the atoms of the bond */
@@ -190,6 +208,7 @@ struct tng_trajectory_frame_set {
 };
 
 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
+/* FIXME: Make only one data block struct */
 struct tng_particle_data {
     /** The block ID of the data block containing this particle data.
      *  This is used to determine the kind of data that is stored */
@@ -248,7 +267,7 @@ struct tng_non_particle_data {
     /** A 1-dimensional array of values of length
      *  [sizeof (datatype)] * n_frames * n_values_per_frame */
     void *values;
-    /** If storing character data store it in a 3-dimensional array */
+    /** If storing character data store it in a 2-dimensional array */
     char ***strings;
 };
 
@@ -260,7 +279,7 @@ struct tng_trajectory {
     /** A handle to the input file */
     FILE *input_file;
     /** The length of the input file */
-    long input_file_len;
+    int64_t input_file_len;
     /** The path of the output trajectory file */
     char *output_file_path;
     /** A handle to the output file */
@@ -345,16 +364,13 @@ struct tng_trajectory {
     /** The currently active frame set */
     struct tng_trajectory_frame_set current_trajectory_frame_set;
     /** The pos in the src file of the current frame set */
-    long current_trajectory_frame_set_input_file_pos;
+    int64_t current_trajectory_frame_set_input_file_pos;
     /** The pos in the dest file of the current frame set */
-    long current_trajectory_frame_set_output_file_pos;
+    int64_t current_trajectory_frame_set_output_file_pos;
     /** The number of frame sets in the trajectory N.B. Not saved in file and
      *  cannot be trusted to be up-to-date */
     int64_t n_trajectory_frame_sets;
 
-    /** The number of trajectory blocks in the file */
-    int64_t n_trajectory_blocks;
-
     /* These data blocks are non-trajectory data blocks */
     /** The number of non-frame dependent particle dependent data blocks */
     int n_particle_data_blocks;
@@ -735,7 +751,7 @@ static tng_function_status tng_block_init(struct tng_gen_block **block_p)
     *block_p = malloc(sizeof(struct tng_gen_block));
     if(!*block_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
                sizeof(struct tng_gen_block), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -746,7 +762,7 @@ static tng_function_status tng_block_init(struct tng_gen_block **block_p)
     /* Reset the md5_hash */
     memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
     block->name = 0;
-    block->block_version = TNG_VERSION;
+    block->block_version = TNG_API_VERSION;
     block->header_contents = 0;
     block->header_contents_size = 0;
     block->block_contents = 0;
@@ -797,13 +813,15 @@ static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
 /** Read the header of a data block, regardless of its type
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
+ * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
+ * error has occured (not able to read the header size, thus skipping
+ * the block) or TNG_CRITICAL (2) if a major error has occured.
  */
 static tng_function_status tng_block_header_read
                 (tng_trajectory_t tng_data, tng_gen_block_t block)
 {
-    int len, offset = 0;
+    int len;
+    int64_t offset = 0;
 
     TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
 
@@ -821,8 +839,14 @@ static tng_function_status tng_block_header_read
         return(TNG_CRITICAL);
     }
 
+    if(block->header_contents_size == 0)
+    {
+        block->id = -1;
+        return(TNG_FAILURE);
+    }
+
     /* If this was the size of the general info block check the endianness */
-    if(ftell(tng_data->input_file) < 9)
+    if(ftello(tng_data->input_file) < 9)
     {
         /* File is little endian */
         if ( *((const char*)&block->header_contents_size) != 0x00 &&
@@ -889,8 +913,8 @@ static tng_function_status tng_block_header_read
     }
 
     /* Move the reading position to the beginning of the header. */
-    fseek(tng_data->input_file, -(long)sizeof(block->header_contents_size),
-          SEEK_CUR);
+    fseeko(tng_data->input_file, -(int64_t)sizeof(block->header_contents_size),
+           SEEK_CUR);
 
     /* If there is already memory allocated for the contents free it (we do not
      * know if the size is correct). */
@@ -1030,56 +1054,64 @@ static tng_function_status tng_block_header_read
 // }
 */
 
-static tng_function_status tng_reread_frame_set_at_file_pos
-                (tng_trajectory_t tng_data,
-                 const int64_t pos)
+/** Update the md5 hash of a block already written to the file
+ * @param tng_data is a trajectory data container.
+ * @param block is the block, of which to update the md5 hash.
+ * @param header_start_pos is the file position where the block header starts.
+ * @param contents_start_pos is the file position where the block contents
+ * start.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
+                                               tng_gen_block_t block,
+                                               const int64_t header_start_pos,
+                                               const int64_t contents_start_pos)
 {
-    tng_gen_block_t block;
-    tng_function_status stat;
-
-    tng_block_init(&block);
+    if(block->block_contents)
+    {
+        free(block->block_contents);
+    }
 
-    fseek(tng_data->input_file, pos, SEEK_SET);
-    if(pos > 0)
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
     {
-        stat = tng_block_header_read(tng_data, block);
-        if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
-        {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
-                    __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_FAILURE);
-        }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-        if(tng_block_read_next(tng_data, block,
-                               TNG_SKIP_HASH) != TNG_SUCCESS)
-        {
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
+    fseeko(tng_data->output_file, contents_start_pos, SEEK_SET);
+    if(fread(block->block_contents, block->block_contents_size, 1,
+            tng_data->output_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    tng_block_destroy(&block);
+    tng_block_md5_hash_generate(block);
+
+    fseeko(tng_data->output_file, header_start_pos + 3 * sizeof(int64_t),
+          SEEK_SET);
+    fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
 
     return(TNG_SUCCESS);
 }
 
-/** Write the header of a data block, regardless of its type
+/** Update the frame set pointers in the file header (general info block),
+ * already written to disk
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @param hash_mode specifies whether to update the block md5 hash when
+ * updating the pointers.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_block_header_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 const char hash_mode)
+static tng_function_status tng_header_pointers_update
+                (tng_trajectory_t tng_data, const char hash_mode)
 {
-    int name_len, offset = 0;
-
-    TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
+    tng_gen_block_t block;
+    FILE *temp = tng_data->input_file;
+    int64_t output_file_pos, pos, contents_start_pos;
 
     if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
@@ -1088,101 +1120,54 @@ static tng_function_status tng_block_header_write
         return(TNG_CRITICAL);
     }
 
-    if(!block->name)
-    {
-        block->name = malloc(1);
-        if(!block->name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-        block->name[0] = 0;
-    }
+    tng_data->input_file = tng_data->output_file;
 
-    name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+    tng_block_init(&block);
 
-    if(hash_mode == TNG_USE_HASH)
+    output_file_pos = ftello(tng_data->output_file);
+    fseeko(tng_data->output_file, 0, SEEK_SET);
+
+    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
     {
-        tng_block_md5_hash_generate(block);
+        fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
+               __FILE__, __LINE__);
+        tng_data->input_file = temp;
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
 
-    /* Calculate the size of the header to write */
-    block->header_contents_size = sizeof(block->header_contents_size) +
-                                  sizeof(block->block_contents_size) +
-                                  sizeof(block->id) +
-                                  sizeof(block->block_version) +
-                                  TNG_MD5_HASH_LEN +
-                                  name_len;
+    contents_start_pos = ftello(tng_data->output_file);
 
-    if(block->header_contents)
-    {
-        free(block->header_contents);
-    }
+    fseeko(tng_data->output_file, block->block_contents_size - 5 *
+          sizeof(int64_t), SEEK_CUR);
 
-    block->header_contents = malloc(block->header_contents_size);
-    if(!block->header_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->header_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    tng_data->input_file = temp;
 
-    /* First copy all data into the header_contents block and finally write
-     * the whole block at once. */
-    memcpy(block->header_contents, &block->header_contents_size,
-           sizeof(block->header_contents_size));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(block->header_contents_size);
+    pos = tng_data->first_trajectory_frame_set_output_file_pos;
 
-    memcpy(block->header_contents+offset, &block->block_contents_size,
-           sizeof(block->block_contents_size));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_data->input_endianness_swap_func_64)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                    &pos)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(block->block_contents_size);
 
-    memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
-    if(tng_data->output_endianness_swap_func_64)
+    if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(block->id);
-
-    memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
-    offset += TNG_MD5_HASH_LEN;
 
-    strncpy(block->header_contents+offset, block->name, name_len);
-    offset += name_len;
+    pos = tng_data->last_trajectory_frame_set_output_file_pos;
 
-    memcpy(block->header_contents+offset, &block->block_version,
-           sizeof(block->block_version));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_data->input_endianness_swap_func_64)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                    &pos)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
@@ -1190,962 +1175,991 @@ static tng_function_status tng_block_header_write
         }
     }
 
-    if(fwrite(block->header_contents, block->header_contents_size,
-       1, tng_data->output_file) != 1)
+    if(fwrite(&pos,
+        sizeof(int64_t), 1, tng_data->output_file) != 1)
     {
-        fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
+    }
+
+    tng_block_destroy(&block);
+
+    fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
+
     return(TNG_SUCCESS);
 }
 
-/** Read a general info block. This is the first block of a TNG file.
- *  Populate the fields in tng_data.
+/** Update the frame set pointers in the current frame set block, already
+ * written to disk. It also updates the pointers of the blocks pointing to
+ * the current frame set block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
- * compared to the md5 hash of the read contents to ensure valid data.
+ * @param hash_mode specifies whether to update the block md5 hash when
+ * updating the pointers.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_general_info_block_read
-                (tng_trajectory_t tng_data, tng_gen_block_t block,
-                 const char hash_mode)
+static tng_function_status tng_frame_set_pointers_update
+                (tng_trajectory_t tng_data, const char hash_mode)
 {
-    int len, offset = 0;
-    tng_bool same_hash;
-
-    void *temp;
-
-    TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
+    tng_gen_block_t block;
+    tng_trajectory_frame_set_t frame_set;
+    FILE *temp = tng_data->input_file;
+    int64_t pos, output_file_pos, contents_start_pos;
 
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
+        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    temp = realloc(block->block_contents, block->block_contents_size);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        free(block->block_contents);
-        block->block_contents = 0;
-        return(TNG_CRITICAL);
-    }
-    block->block_contents = temp;
+    tng_block_init(&block);
+    output_file_pos = ftello(tng_data->output_file);
 
-    /* Read the whole block into block_contents to be able to write it to disk
-     * even if it cannot be interpreted. */
-    if(fread(block->block_contents, block->block_contents_size, 1,
-             tng_data->input_file) == 0)
-    {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    tng_data->input_file = tng_data->output_file;
 
-    /* FIXME: Does not check if the size of the contents matches the expected
-     * size or if the contents can be read. */
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-    if(hash_mode == TNG_USE_HASH)
+    pos = tng_data->current_trajectory_frame_set_output_file_pos;
+
+    /* Update next frame set */
+    if(frame_set->next_frame_set_file_pos > 0)
     {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
+        fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos,
+              SEEK_SET);
+
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
-                "%s: %d\n",
+            fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
                 __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
         }
-    }
 
-    len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_program_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_program_name);
-        tng_data->first_program_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->first_program_name = temp;
-    strncpy(tng_data->first_program_name, block->block_contents, len);
-    offset += len;
+        contents_start_pos = ftello(tng_data->output_file);
 
-    len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_program_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_program_name);
-        tng_data->last_program_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->last_program_name = temp;
-    strncpy(tng_data->last_program_name, block->block_contents + offset, len);
-    offset += len;
+        fseeko(tng_data->output_file, block->block_contents_size - (5 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_user_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_user_name);
-        tng_data->first_user_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->first_user_name = temp;
-    strncpy(tng_data->first_user_name, block->block_contents+offset, len);
-    offset += len;
+        if(tng_data->input_endianness_swap_func_64)
+        {
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                        &pos)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_user_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_user_name);
-        tng_data->last_user_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->last_user_name = temp;
-    strncpy(tng_data->last_user_name, block->block_contents+offset, len);
-    offset += len;
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_computer_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_computer_name);
-        tng_data->first_computer_name = 0;
-        return(TNG_CRITICAL);
+        if(hash_mode == TNG_USE_HASH)
+        {
+            tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
+                                contents_start_pos);
+        }
+        fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
     }
-    tng_data->first_computer_name = temp;
-    strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
-    offset += len;
-
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_computer_name, len);
-    if(!temp)
+    /* Update previous frame set */
+    if(frame_set->prev_frame_set_file_pos > 0)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_computer_name);
-        tng_data->last_computer_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->last_computer_name = temp;
-    strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
-    offset += len;
+        fseeko(tng_data->output_file, frame_set->prev_frame_set_file_pos,
+              SEEK_SET);
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_pgp_signature, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_pgp_signature);
-        tng_data->first_pgp_signature = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->first_pgp_signature = temp;
-    strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
-    offset += len;
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
+                __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_pgp_signature, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_pgp_signature);
-        tng_data->last_pgp_signature = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->last_pgp_signature = temp;
-    strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
-    offset += len;
+        contents_start_pos = ftello(tng_data->output_file);
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->forcefield_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->forcefield_name);
-        tng_data->forcefield_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->forcefield_name = temp;
-    strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
-    offset += len;
+        fseeko(tng_data->output_file, block->block_contents_size - (6 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
-    memcpy(&tng_data->time, block->block_contents+offset,
-           sizeof(tng_data->time));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &tng_data->time)
-            != TNG_SUCCESS)
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                        &pos)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(tng_data->time);
 
-    memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
-           sizeof(tng_data->var_num_atoms_flag));
-    offset += sizeof(tng_data->var_num_atoms_flag);
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
 
-    memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
-           sizeof(tng_data->frame_set_n_frames));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                 &tng_data->frame_set_n_frames)
-            != TNG_SUCCESS)
+        if(hash_mode == TNG_USE_HASH)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
+                                contents_start_pos);
         }
+        fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
     }
-    offset += sizeof(tng_data->frame_set_n_frames);
 
-    memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
-           block->block_contents+offset,
-           sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    /* Update the frame set one medium stride step after */
+    if(frame_set->medium_stride_next_frame_set_file_pos > 0)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                          &tng_data->first_trajectory_frame_set_input_file_pos)
-            != TNG_SUCCESS)
+        fseeko(tng_data->output_file,
+               frame_set->medium_stride_next_frame_set_file_pos,
+               SEEK_SET);
+
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
         }
-    }
-    offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
 
-    tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
-    tng_data->first_trajectory_frame_set_input_file_pos;
+        contents_start_pos = ftello(tng_data->output_file);
 
+        fseeko(tng_data->output_file, block->block_contents_size - (3 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
-    memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
-           block->block_contents+offset,
-           sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                          &tng_data->last_trajectory_frame_set_input_file_pos)
-            != TNG_SUCCESS)
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                        &pos)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
 
-    memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
-           sizeof(tng_data->medium_stride_length));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                               &tng_data->medium_stride_length)
-            != TNG_SUCCESS)
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
         }
-    }
-    offset += sizeof(tng_data->medium_stride_length);
 
-    memcpy(&tng_data->long_stride_length, block->block_contents+offset,
-           sizeof(tng_data->long_stride_length));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                 &tng_data->long_stride_length)
-            != TNG_SUCCESS)
+        if(hash_mode == TNG_USE_HASH)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            tng_md5_hash_update(tng_data, block,
+                                frame_set->medium_stride_next_frame_set_file_pos,
+                                contents_start_pos);
         }
     }
-    offset += sizeof(tng_data->long_stride_length);
-
-    if(block->block_version >= 3)
+    /* Update the frame set one medium stride step before */
+    if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
     {
-        memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
-            sizeof(tng_data->distance_unit_exponential));
+        fseeko(tng_data->output_file,
+               frame_set->medium_stride_prev_frame_set_file_pos,
+               SEEK_SET);
+
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+
+        contents_start_pos = ftello(tng_data->output_file);
+
+        fseeko(tng_data->output_file, block->block_contents_size - (4 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                          &tng_data->distance_unit_exponential)
+                                                        &pos)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
-    }
 
-    return(TNG_SUCCESS);
-}
-
-/** Write a general info block. This is the first block of a TNG file.
- * @param tng_data is a trajectory data container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_general_info_block_write
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int first_program_name_len, first_user_name_len;
-    int first_computer_name_len, first_pgp_signature_len;
-    int last_program_name_len, last_user_name_len;
-    int last_computer_name_len, last_pgp_signature_len;
-    int forcefield_name_len, name_len;
-    int offset = 0;
-    tng_gen_block_t block;
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
+        if(hash_mode == TNG_USE_HASH)
+        {
+            tng_md5_hash_update(tng_data, block,
+                                frame_set->medium_stride_prev_frame_set_file_pos,
+                                contents_start_pos);
+        }
     }
 
-    fseek(tng_data->output_file, 0, SEEK_SET);
-
-    /* If the strings are unallocated allocate memory for just string
-     * termination */
-    if(!tng_data->first_program_name)
+    /* Update the frame set one long stride step after */
+    if(frame_set->long_stride_next_frame_set_file_pos > 0)
     {
-        tng_data->first_program_name = malloc(1);
-        if(!tng_data->first_program_name)
+        fseeko(tng_data->output_file,
+               frame_set->long_stride_next_frame_set_file_pos,
+               SEEK_SET);
+
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
             return(TNG_CRITICAL);
         }
-        tng_data->first_program_name[0] = 0;
-    }
-    if(!tng_data->last_program_name)
-    {
-        tng_data->last_program_name = malloc(1);
-        if(!tng_data->last_program_name)
+
+        contents_start_pos = ftello(tng_data->output_file);
+
+        fseeko(tng_data->output_file, block->block_contents_size - (1 *
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                        &pos)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-        tng_data->last_program_name[0] = 0;
-    }
-    if(!tng_data->first_user_name)
-    {
-        tng_data->first_user_name = malloc(1);
-        if(!tng_data->first_user_name)
+
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
             return(TNG_CRITICAL);
         }
-        tng_data->first_user_name[0] = 0;
-    }
-    if(!tng_data->last_user_name)
-    {
-        tng_data->last_user_name = malloc(1);
-        if(!tng_data->last_user_name)
+
+        if(hash_mode == TNG_USE_HASH)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            tng_md5_hash_update(tng_data, block,
+                                frame_set->long_stride_next_frame_set_file_pos,
+                                contents_start_pos);
         }
-        tng_data->last_user_name[0] = 0;
     }
-    if(!tng_data->first_computer_name)
+    /* Update the frame set one long stride step before */
+    if(frame_set->long_stride_prev_frame_set_file_pos > 0)
     {
-        tng_data->first_computer_name = malloc(1);
-        if(!tng_data->first_computer_name)
+        fseeko(tng_data->output_file,
+               frame_set->long_stride_prev_frame_set_file_pos,
+               SEEK_SET);
+
+        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
             return(TNG_CRITICAL);
         }
-        tng_data->first_computer_name[0] = 0;
-    }
-    if(!tng_data->last_computer_name)
-    {
-        tng_data->last_computer_name = malloc(1);
-        if(!tng_data->last_computer_name)
+
+        contents_start_pos = ftello(tng_data->output_file);
+
+        fseeko(tng_data->output_file, block->block_contents_size - (2 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                        &pos)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-        tng_data->last_computer_name[0] = 0;
-    }
-    if(!tng_data->first_pgp_signature)
-    {
-        tng_data->first_pgp_signature = malloc(1);
-        if(!tng_data->first_pgp_signature)
+
+        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
             return(TNG_CRITICAL);
         }
-        tng_data->first_pgp_signature[0] = 0;
-    }
-    if(!tng_data->last_pgp_signature)
-    {
-        tng_data->last_pgp_signature = malloc(1);
-        if(!tng_data->last_pgp_signature)
+
+        if(hash_mode == TNG_USE_HASH)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            tng_md5_hash_update(tng_data, block,
+                                frame_set->long_stride_prev_frame_set_file_pos,
+                                contents_start_pos);
         }
-        tng_data->last_pgp_signature[0] = 0;
     }
-    if(!tng_data->forcefield_name)
+
+    fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
+
+    tng_data->input_file = temp;
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_reread_frame_set_at_file_pos
+                (tng_trajectory_t tng_data,
+                 const int64_t pos)
+{
+    tng_gen_block_t block;
+    tng_function_status stat;
+
+    tng_block_init(&block);
+
+    fseeko(tng_data->input_file, pos, SEEK_SET);
+    if(pos > 0)
     {
-        tng_data->forcefield_name = malloc(1);
-        if(!tng_data->forcefield_name)
+        stat = tng_block_header_read(tng_data, block);
+        if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
+                    __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            return(TNG_FAILURE);
+        }
+
+        if(tng_block_read_next(tng_data, block,
+                               TNG_SKIP_HASH) != TNG_SUCCESS)
+        {
+            tng_block_destroy(&block);
             return(TNG_CRITICAL);
         }
-        tng_data->forcefield_name[0] = 0;
     }
 
-    tng_block_init(&block);
+    tng_block_destroy(&block);
 
-    name_len = (int)strlen("GENERAL INFO");
+    return(TNG_SUCCESS);
+}
 
-    block->name = malloc(name_len + 1);
-    if(!block->name)
+static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
+                (tng_trajectory_t tng_data,
+                 int64_t *pos)
+{
+    int64_t orig_pos, curr_frame_set_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    orig_pos = ftello(tng_data->input_file);
+    curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
+
+    *pos = tng_data->first_trajectory_frame_set_input_file_pos;
+
+    if(*pos <= 0)
+    {
+        return(TNG_SUCCESS);
+    }
+
+    fseeko(tng_data->input_file, *pos, SEEK_SET);
+
+    tng_block_init(&block);
+    /* Read block headers first to see that a frame set block is found. */
+    stat = tng_block_header_read(tng_data, block);
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+    {
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
+                __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_FAILURE);
+    }
+
+    if(tng_block_read_next(tng_data, block,
+                           TNG_SKIP_HASH) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                name_len+1, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    strcpy(block->name, "GENERAL INFO");
-    block->id = TNG_GENERAL_INFO;
-
-    first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
-                           TNG_MAX_STR_LEN);
-    last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
-                           TNG_MAX_STR_LEN);
-    first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
-                        TNG_MAX_STR_LEN);
-    last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
-                        TNG_MAX_STR_LEN);
-    first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
-                            TNG_MAX_STR_LEN);
-    last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
-                            TNG_MAX_STR_LEN);
-    first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
-                            TNG_MAX_STR_LEN);
-    last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
-                            TNG_MAX_STR_LEN);
-    forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
-                              TNG_MAX_STR_LEN);
-
-    block->block_contents_size = sizeof(tng_data->time) +
-                sizeof(tng_data->var_num_atoms_flag) +
-                sizeof(tng_data->frame_set_n_frames) +
-                sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
-                sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
-                sizeof(tng_data->medium_stride_length) +
-                sizeof(tng_data->long_stride_length) +
-                sizeof(tng_data->distance_unit_exponential) +
-                first_program_name_len +
-                last_program_name_len +
-                first_user_name_len +
-                last_user_name_len +
-                first_computer_name_len +
-                last_computer_name_len +
-                first_pgp_signature_len +
-                last_pgp_signature_len +
-                forcefield_name_len;
-
-    if(block->block_contents)
+    /* Read all frame set blocks (not the blocks between them) */
+    while(frame_set->next_frame_set_file_pos > 0)
     {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
-    offset += first_program_name_len;
-
-    strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
-    offset += last_program_name_len;
+        fseeko(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
+        stat = tng_block_header_read(tng_data, block);
+        if(stat == TNG_CRITICAL)
+        {
+            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
+                    __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+        if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
+        {
+            return(TNG_FAILURE);
+        }
 
-    strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
-    offset += first_user_name_len;
+        stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
+        if(stat != TNG_SUCCESS)
+        {
+            tng_block_destroy(&block);
+            return(stat);
+        }
+        /* Update *pos if this is the earliest frame set so far (after orig_pos) */
+        if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
+           tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
+        {
+            *pos = tng_data->current_trajectory_frame_set_input_file_pos;
+        }
+    }
 
-    strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
-    offset += last_user_name_len;
+    /* Re-read the frame set that used to be the current one */
+    tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
 
-    strncpy(block->block_contents+offset, tng_data->first_computer_name,
-            first_computer_name_len);
-    offset += first_computer_name_len;
+    fseeko(tng_data->input_file, orig_pos, SEEK_SET);
 
-    strncpy(block->block_contents+offset, tng_data->last_computer_name,
-            last_computer_name_len);
-    offset += last_computer_name_len;
+    tng_block_destroy(&block);
 
-    strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
-            first_pgp_signature_len);
-    offset += first_pgp_signature_len;
+    return(TNG_SUCCESS);
+}
 
-    strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
-            last_pgp_signature_len);
-    offset += last_pgp_signature_len;
+static tng_function_status tng_frame_set_complete_migrate
+                (tng_trajectory_t tng_data,
+                 int64_t block_start_pos,
+                 int64_t block_len,
+                 int64_t new_pos)
+{
+    int64_t i;
+    tng_bool updated = TNG_FALSE;
 
-    strncpy(block->block_contents+offset, tng_data->forcefield_name,
-            forcefield_name_len);
-    offset += forcefield_name_len;
+    char *contents;
 
-    memcpy(block->block_contents+offset, &tng_data->time,
-           sizeof(tng_data->time));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->time);
 
-    memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
-           sizeof(tng_data->var_num_atoms_flag));
-    offset += sizeof(tng_data->var_num_atoms_flag);
+    fseeko(tng_data->input_file, block_start_pos, SEEK_SET);
 
-    memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
-           sizeof(tng_data->frame_set_n_frames));
-    if(tng_data->output_endianness_swap_func_64)
+    contents = malloc(block_len);
+    if(!contents)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                block_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->frame_set_n_frames);
 
-    memcpy(block->block_contents+offset,
-           &tng_data->first_trajectory_frame_set_input_file_pos,
-           sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(fread(contents, block_len, 1, tng_data->input_file) == 0)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
+               __FILE__, __LINE__);
+        free(contents);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
+    fseeko(tng_data->output_file, new_pos, SEEK_SET);
 
-    memcpy(block->block_contents+offset,
-           &tng_data->last_trajectory_frame_set_input_file_pos,
-           sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
+                __FILE__, __LINE__);
+        free(contents);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
 
-    memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
-           sizeof(tng_data->medium_stride_length));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(tng_data->medium_stride_length);
+    tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
 
-    memcpy(block->block_contents+offset, &tng_data->long_stride_length,
-           sizeof(tng_data->long_stride_length));
-    if(tng_data->output_endianness_swap_func_64)
+    tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
+
+    /* Update the general info block if needed */
+    if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
+        updated = TNG_TRUE;
     }
-    offset += sizeof(tng_data->long_stride_length);
-
-    memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
-           sizeof(tng_data->distance_unit_exponential));
-    if(tng_data->output_endianness_swap_func_64)
+    if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
+        updated = TNG_TRUE;
     }
-
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    if(updated)
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        tng_header_pointers_update(tng_data, TNG_USE_HASH);
     }
 
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-        tng_data->output_file) != 1)
+    /* Fill the block with NULL to avoid confusion. */
+    for(i = 0; i < block_len; i++)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        contents[i] = '\0';
     }
+    fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
 
-    tng_block_destroy(&block);
+    /* FIXME: casting block_len to size_t is dangerous */
+    fwrite(contents, 1, block_len, tng_data->output_file);
+
+    free(contents);
 
     return(TNG_SUCCESS);
 }
 
-/** Read the chain data of a molecules block.
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param chain is the chain data container.
- * @param offset is the offset of the block input and is updated when reading.
- * @return TNG_SUCCESS(0) is successful.
- */
-static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               tng_chain_t chain,
-                                               int *offset)
+static tng_function_status tng_length_of_current_frame_set_contents_get
+                (tng_trajectory_t tng_data,
+                 int64_t *len)
 {
-    int len;
+    int64_t orig_pos, pos, curr_frame_set_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    orig_pos = ftello(tng_data->input_file);
+    curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
 
-    memcpy(&chain->id, block->block_contents+*offset,
-            sizeof(chain->id));
-    if(tng_data->input_endianness_swap_func_64)
+    *len = 0;
+
+    fseeko(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
+
+    tng_block_init(&block);
+    /* Read block headers first to see that a frame set block is found. */
+    stat = tng_block_header_read(tng_data, block);
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &chain->id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+                curr_frame_set_pos, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_FAILURE);
     }
-    *offset += sizeof(chain->id);
-
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    chain->name = malloc(len);
-    strncpy(chain->name,
-            block->block_contents+*offset, len);
-    *offset += len;
 
-    memcpy(&chain->n_residues, block->block_contents+*offset,
-        sizeof(chain->n_residues));
-    if(tng_data->input_endianness_swap_func_64)
+    /* Read the headers of all blocks in the frame set (not the actual contents of them) */
+    while(stat == TNG_SUCCESS)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &chain->n_residues)
-            != TNG_SUCCESS)
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+        *len += block->header_contents_size + block->block_contents_size;
+        pos += block->header_contents_size + block->block_contents_size;
+        if(pos >= tng_data->input_file_len)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            break;
+        }
+        stat = tng_block_header_read(tng_data, block);
+        if(block->id == TNG_TRAJECTORY_FRAME_SET)
+        {
+            break;
         }
     }
-    *offset += sizeof(chain->n_residues);
+
+    /* Re-read the frame set that used to be the current one */
+    tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
+
+    fseeko(tng_data->input_file, orig_pos, SEEK_SET);
+
+    tng_block_destroy(&block);
 
     return(TNG_SUCCESS);
 }
 
-/** Write the chain data of a molecules block.
+/** Migrate blocks in the file to make room for new data in a block. This
+ * is required e.g. when adding data to a block or extending strings in a
+ * block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param chain is the chain data container.
- * @param offset is the offset of the block output and is updated when writing.
- * @return TNG_SUCCESS(0) is successful.
+ * @param start_pos is the position from which to start moving data, usually
+ * the byte after the end of the block to which data was added.
+ * @param offset is the number of bytes that were inserted.
+ * @details Trajectory blocks (frame sets and their related blocks) are moved
+ * to the end of the file (if needed) in order to make room for non-trajectory
+ * data.
  */
-static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
-                                                tng_gen_block_t block,
-                                                tng_chain_t chain,
-                                                int *offset)
+static tng_function_status tng_migrate_data_in_file
+                (tng_trajectory_t tng_data,
+                 int64_t start_pos,
+                 int64_t offset)
 {
-    int len;
+    int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
+    tng_gen_block_t block;
+    tng_function_status stat;
+    FILE *temp;
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    if(offset <= 0)
+    {
+        return(TNG_SUCCESS);
+    }
 
-    memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
-    if(tng_data->output_endianness_swap_func_64)
+    temp = tng_data->input_file;
+
+    stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
+    if(stat != TNG_SUCCESS)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                    (int64_t *)block->header_contents+*offset)
-            != TNG_SUCCESS)
+        tng_data->input_file = temp;
+        return(stat);
+    }
+
+    tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
+
+    empty_space = traj_start_pos - (start_pos - 1);
+
+    if(empty_space >= offset)
+    {
+        return(TNG_SUCCESS);
+    }
+
+    orig_file_pos = ftello(tng_data->input_file);
+    tng_block_init(&block);
+
+    while(empty_space < offset)
+    {
+        fseeko(tng_data->input_file, traj_start_pos, SEEK_SET);
+        stat = tng_block_header_read(tng_data, block);
+        if(stat == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
                     __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            tng_data->input_file = temp;
+            return(TNG_CRITICAL);
+        }
+        if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(TNG_FAILURE);
+        }
+        stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
+        if(stat != TNG_SUCCESS)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(stat);
+        }
+        stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
+                                              frame_set_length, tng_data->input_file_len);
+        if(stat != TNG_SUCCESS)
+        {
+            tng_data->input_file = temp;
+            tng_block_destroy(&block);
+            return(stat);
         }
+
+        empty_space += frame_set_length;
     }
-    *offset += sizeof(chain->id);
+    fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
+    tng_block_destroy(&block);
 
-    len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, chain->name, len);
-    *offset += len;
+    return(TNG_SUCCESS);
+}
 
-    memcpy(block->block_contents+*offset, &chain->n_residues,
-        sizeof(chain->n_residues));
-    if(tng_data->output_endianness_swap_func_64)
+static tng_function_status tng_block_header_len_calculate
+                (const tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 int64_t *len)
+{
+    int name_len;
+    (void)tng_data;
+
+    /* If the string is unallocated allocate memory for just string
+     * termination */
+    if(!block->name)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                    (int64_t *)block->header_contents+*offset)
-            != TNG_SUCCESS)
+        block->name = malloc(1);
+        if(!block->name)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
+        block->name[0] = 0;
     }
-    *offset += sizeof(chain->n_residues);
 
-    return(TNG_SUCCESS);
+    name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+
+    /* Calculate the size of the header to write */
+    *len = sizeof(block->header_contents_size) +
+                  sizeof(block->block_contents_size) +
+                  sizeof(block->id) +
+                  sizeof(block->block_version) +
+                  TNG_MD5_HASH_LEN +
+                  name_len;
+
+    return (TNG_SUCCESS);
 }
 
-/** Read the residue data of a molecules block.
+/** Write the header of a data block, regardless of its type
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
- * @param residue is the residue data container.
- * @param offset is the offset of the block input and is updated when reading.
- * @return TNG_SUCCESS(0) is successful.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
  */
-static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
-                                                 tng_gen_block_t block,
-                                                 tng_residue_t residue,
-                                                 int *offset)
+static tng_function_status tng_block_header_write
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const char hash_mode)
 {
-    int len;
+    int name_len, offset = 0;
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
 
-    memcpy(&residue->id, block->block_contents+*offset,
-        sizeof(residue->id));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &residue->id)
+        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
+        TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_block_md5_hash_generate(block);
+    }
+
+    if(block->header_contents)
+    {
+        free(block->header_contents);
+    }
+
+    block->header_contents = malloc(block->header_contents_size);
+    if(!block->header_contents)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->header_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+
+    /* First copy all data into the header_contents block and finally write
+     * the whole block at once. */
+    memcpy(block->header_contents, &block->header_contents_size,
+           sizeof(block->header_contents_size));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    *offset += sizeof(residue->id);
-
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    residue->name = malloc(len);
-    strncpy(residue->name,
-            block->block_contents+*offset, len);
-    *offset += len;
+    offset += sizeof(block->header_contents_size);
 
-    memcpy(&residue->n_atoms, block->block_contents+*offset,
-            sizeof(residue->n_atoms));
-    if(tng_data->input_endianness_swap_func_64)
+    memcpy(block->header_contents+offset, &block->block_contents_size,
+           sizeof(block->block_contents_size));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &residue->n_atoms)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    *offset += sizeof(residue->n_atoms);
-
-    return(TNG_SUCCESS);
-}
-
-/** Write the residue data of a molecules block.
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param residue is the residue data container.
- * @param offset is the offset of the block output and is updated when writing.
- * @return TNG_SUCCESS(0) is successful.
- */
-static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
-                                                  tng_gen_block_t block,
-                                                  tng_residue_t residue,
-                                                  int *offset)
-{
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    offset += sizeof(block->block_contents_size);
 
-    memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
+    memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
     if(tng_data->output_endianness_swap_func_64)
     {
         if(tng_data->output_endianness_swap_func_64(tng_data,
-                                    (int64_t *)block->header_contents+*offset)
+                                      (int64_t *)block->header_contents+offset)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    *offset += sizeof(residue->id);
+    offset += sizeof(block->id);
 
-    len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, residue->name, len);
-    *offset += len;
+    memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
+    offset += TNG_MD5_HASH_LEN;
 
-    memcpy(block->block_contents+*offset, &residue->n_atoms,
-        sizeof(residue->n_atoms));
+    strncpy(block->header_contents+offset, block->name, name_len);
+    offset += name_len;
+
+    memcpy(block->header_contents+offset, &block->block_version,
+           sizeof(block->block_version));
     if(tng_data->output_endianness_swap_func_64)
     {
         if(tng_data->output_endianness_swap_func_64(tng_data,
-                                    (int64_t *)block->header_contents+*offset)
+                                      (int64_t *)block->header_contents+offset)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    *offset += sizeof(residue->n_atoms);
 
+    if(fwrite(block->header_contents, block->header_contents_size,
+       1, tng_data->output_file) != 1)
+    {
+        fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
     return(TNG_SUCCESS);
 }
 
-/** Read the atom data of a molecules block.
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param atom is the atom data container.
- * @param offset is the offset of the block input and is updated when reading.
- * @return TNG_SUCCESS(0) is successful.
- */
-static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
-                                              tng_gen_block_t block,
-                                              tng_atom_t atom,
-                                              int *offset)
+static tng_function_status tng_general_info_block_len_calculate
+                (tng_trajectory_t tng_data,
+                 int64_t *len)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    int first_program_name_len, first_user_name_len;
+    int first_computer_name_len, first_pgp_signature_len;
+    int last_program_name_len, last_user_name_len;
+    int last_computer_name_len, last_pgp_signature_len;
+    int forcefield_name_len;
 
-    memcpy(&atom->id, block->block_contents+*offset,
-        sizeof(atom->id));
-    if(tng_data->input_endianness_swap_func_64)
+    /* If the strings are unallocated allocate memory for just string
+     * termination */
+    if(!tng_data->first_program_name)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                    &atom->id)
-            != TNG_SUCCESS)
+        tng_data->first_program_name = malloc(1);
+        if(!tng_data->first_program_name)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
+        tng_data->first_program_name[0] = 0;
     }
-    *offset += sizeof(atom->id);
-
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    atom->name = malloc(len);
-    strncpy(atom->name,
-            block->block_contents+*offset, len);
-    *offset += len;
-
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    atom->atom_type = malloc(len);
-    strncpy(atom->atom_type,
-            block->block_contents+*offset, len);
-    *offset += len;
-
-    return(TNG_SUCCESS);
-}
-
-/** Write the atom data of a molecules block.
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param atom is the atom data container.
- * @param offset is the offset of the block output and is updated when writing.
- * @return TNG_SUCCESS(0) is successful.
- */
-static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               tng_atom_t atom,
-                                               int *offset)
-{
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(block->block_contents+*offset, &atom->id,
-            sizeof(atom->id));
-    if(tng_data->output_endianness_swap_func_64)
+    if(!tng_data->last_program_name)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                    (int64_t *)block->header_contents+*offset)
-            != TNG_SUCCESS)
+        tng_data->last_program_name = malloc(1);
+        if(!tng_data->last_program_name)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
+        tng_data->last_program_name[0] = 0;
+    }
+    if(!tng_data->first_user_name)
+    {
+        tng_data->first_user_name = malloc(1);
+        if(!tng_data->first_user_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->first_user_name[0] = 0;
+    }
+    if(!tng_data->last_user_name)
+    {
+        tng_data->last_user_name = malloc(1);
+        if(!tng_data->last_user_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->last_user_name[0] = 0;
+    }
+    if(!tng_data->first_computer_name)
+    {
+        tng_data->first_computer_name = malloc(1);
+        if(!tng_data->first_computer_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->first_computer_name[0] = 0;
+    }
+    if(!tng_data->last_computer_name)
+    {
+        tng_data->last_computer_name = malloc(1);
+        if(!tng_data->last_computer_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->last_computer_name[0] = 0;
+    }
+    if(!tng_data->first_pgp_signature)
+    {
+        tng_data->first_pgp_signature = malloc(1);
+        if(!tng_data->first_pgp_signature)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->first_pgp_signature[0] = 0;
+    }
+    if(!tng_data->last_pgp_signature)
+    {
+        tng_data->last_pgp_signature = malloc(1);
+        if(!tng_data->last_pgp_signature)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->last_pgp_signature[0] = 0;
+    }
+    if(!tng_data->forcefield_name)
+    {
+        tng_data->forcefield_name = malloc(1);
+        if(!tng_data->forcefield_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        tng_data->forcefield_name[0] = 0;
     }
-    *offset += sizeof(atom->id);
 
-    len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, atom->name, len);
-    *offset += len;
+    first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
+                           TNG_MAX_STR_LEN);
+    last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
+                           TNG_MAX_STR_LEN);
+    first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
+                        TNG_MAX_STR_LEN);
+    last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
+                        TNG_MAX_STR_LEN);
+    first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
+                            TNG_MAX_STR_LEN);
+    last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
+                            TNG_MAX_STR_LEN);
+    first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
+                            TNG_MAX_STR_LEN);
+    last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
+                            TNG_MAX_STR_LEN);
+    forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
+                              TNG_MAX_STR_LEN);
 
-    len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, atom->atom_type, len);
-    *offset += len;
+    *len = sizeof(tng_data->time) +
+                  sizeof(tng_data->var_num_atoms_flag) +
+                  sizeof(tng_data->frame_set_n_frames) +
+                  sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
+                  sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
+                  sizeof(tng_data->medium_stride_length) +
+                  sizeof(tng_data->long_stride_length) +
+                  sizeof(tng_data->distance_unit_exponential) +
+                  first_program_name_len +
+                  last_program_name_len +
+                  first_user_name_len +
+                  last_user_name_len +
+                  first_computer_name_len +
+                  last_computer_name_len +
+                  first_pgp_signature_len +
+                  last_pgp_signature_len +
+                  forcefield_name_len;
 
     return(TNG_SUCCESS);
 }
 
-/** Read a molecules block. Contains chain, residue and atom data
+/** Read a general info block. This is the first block of a TNG file.
+ *  Populate the fields in tng_data.
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
@@ -2154,37 +2168,32 @@ static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_molecules_block_read
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
+static tng_function_status tng_general_info_block_read
+                (tng_trajectory_t tng_data, tng_gen_block_t block,
                  const char hash_mode)
 {
-    int64_t i, j, k, l;
     int len, offset = 0;
-    tng_molecule_t molecule;
-    tng_chain_t chain;
-    tng_residue_t residue;
-    tng_atom_t atom;
-    tng_bond_t bond;
     tng_bool same_hash;
 
+    void *temp;
+
+    TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
+
     if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
         return(TNG_CRITICAL);
     }
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    temp = realloc(block->block_contents, block->block_contents_size);
+    if(!temp)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
+        free(block->block_contents);
+        block->block_contents = 0;
         return(TNG_CRITICAL);
     }
+    block->block_contents = temp;
 
     /* Read the whole block into block_contents to be able to write it to disk
      * even if it cannot be interpreted. */
@@ -2192,6 +2201,7 @@ static tng_function_status tng_molecules_block_read
              tng_data->input_file) == 0)
     {
         fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
     /* FIXME: Does not check if the size of the contents matches the expected
@@ -2202,797 +2212,918 @@ static tng_function_status tng_molecules_block_read
         tng_md5_hash_match_verify(block, &same_hash);
         if(same_hash != TNG_TRUE)
         {
-            fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
+            fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
                 "%s: %d\n",
                 __FILE__, __LINE__);
+    /*         return(TNG_FAILURE); */
         }
     }
 
-    if(tng_data->molecules)
-    {
-        for(i=tng_data->n_molecules; i--;)
-        {
-            tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
-        }
-        free(tng_data->molecules);
-        tng_data->molecules = 0;
-        tng_data->n_molecules = 0;
-    }
-
-    memcpy(&tng_data->n_molecules, block->block_contents,
-           sizeof(tng_data->n_molecules));
-    if(tng_data->input_endianness_swap_func_64)
+    len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->first_program_name, len);
+    if(!temp)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &tng_data->n_molecules)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->first_program_name);
+        tng_data->first_program_name = 0;
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->n_molecules);
+    tng_data->first_program_name = temp;
+    strncpy(tng_data->first_program_name, block->block_contents, len);
+    offset += len;
 
-    if(tng_data->molecules)
+    len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->last_program_name, len);
+    if(!temp)
     {
-        free(tng_data->molecules);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->last_program_name);
+        tng_data->last_program_name = 0;
+        return(TNG_CRITICAL);
     }
+    tng_data->last_program_name = temp;
+    strncpy(tng_data->last_program_name, block->block_contents + offset, len);
+    offset += len;
 
-    tng_data->n_particles = 0;
-
-    tng_data->molecules = malloc(tng_data->n_molecules *
-                          sizeof(struct tng_molecule));
-    if(!tng_data->molecules)
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->first_user_name, len);
+    if(!temp)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               tng_data->n_molecules * sizeof(struct tng_molecule),
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
                __FILE__, __LINE__);
+        free(tng_data->first_user_name);
+        tng_data->first_user_name = 0;
         return(TNG_CRITICAL);
     }
+    tng_data->first_user_name = temp;
+    strncpy(tng_data->first_user_name, block->block_contents+offset, len);
+    offset += len;
 
-    if(!tng_data->var_num_atoms_flag)
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->last_user_name, len);
+    if(!temp)
     {
-        if(tng_data->molecule_cnt_list)
-        {
-            free(tng_data->molecule_cnt_list);
-        }
-        tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
-                                      tng_data->n_molecules);
-        if(!tng_data->molecule_cnt_list)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                   tng_data->n_molecules * sizeof(struct tng_molecule),
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->last_user_name);
+        tng_data->last_user_name = 0;
+        return(TNG_CRITICAL);
     }
+    tng_data->last_user_name = temp;
+    strncpy(tng_data->last_user_name, block->block_contents+offset, len);
+    offset += len;
 
-    /* Read each molecule from file */
-    for(i=0; i < tng_data->n_molecules; i++)
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->first_computer_name, len);
+    if(!temp)
     {
-        molecule = &tng_data->molecules[i];
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->first_computer_name);
+        tng_data->first_computer_name = 0;
+        return(TNG_CRITICAL);
+    }
+    tng_data->first_computer_name = temp;
+    strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
+    offset += len;
 
-        memcpy(&molecule->id, block->block_contents+offset,
-               sizeof(molecule->id));
-        if(tng_data->input_endianness_swap_func_64)
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->last_computer_name, len);
+    if(!temp)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->last_computer_name);
+        tng_data->last_computer_name = 0;
+        return(TNG_CRITICAL);
+    }
+    tng_data->last_computer_name = temp;
+    strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
+    offset += len;
+
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->first_pgp_signature, len);
+    if(!temp)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->first_pgp_signature);
+        tng_data->first_pgp_signature = 0;
+        return(TNG_CRITICAL);
+    }
+    tng_data->first_pgp_signature = temp;
+    strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
+    offset += len;
+
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->last_pgp_signature, len);
+    if(!temp)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->last_pgp_signature);
+        tng_data->last_pgp_signature = 0;
+        return(TNG_CRITICAL);
+    }
+    tng_data->last_pgp_signature = temp;
+    strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
+    offset += len;
+
+    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->forcefield_name, len);
+    if(!temp)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->forcefield_name);
+        tng_data->forcefield_name = 0;
+        return(TNG_CRITICAL);
+    }
+    tng_data->forcefield_name = temp;
+    strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
+    offset += len;
+
+    memcpy(&tng_data->time, block->block_contents+offset,
+           sizeof(tng_data->time));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &tng_data->time)
+            != TNG_SUCCESS)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->id)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->id);
+    }
+    offset += sizeof(tng_data->time);
 
-/*         fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
-        len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-        molecule->name = malloc(len);
-        strncpy(molecule->name, block->block_contents+offset, len);
-        offset += len;
+    memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
+           sizeof(tng_data->var_num_atoms_flag));
+    offset += sizeof(tng_data->var_num_atoms_flag);
 
-        memcpy(&molecule->quaternary_str, block->block_contents+offset,
-               sizeof(molecule->quaternary_str));
-        if(tng_data->input_endianness_swap_func_64)
+    memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
+           sizeof(tng_data->frame_set_n_frames));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                 &tng_data->frame_set_n_frames)
+            != TNG_SUCCESS)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                     &molecule->quaternary_str)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->quaternary_str);
+    }
+    offset += sizeof(tng_data->frame_set_n_frames);
 
-        if(!tng_data->var_num_atoms_flag)
+    memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
+           block->block_contents+offset,
+           sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                          &tng_data->first_trajectory_frame_set_input_file_pos)
+            != TNG_SUCCESS)
         {
-            memcpy(&tng_data->molecule_cnt_list[i],
-                   block->block_contents+offset,
-                   sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64)
-            {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                               &tng_data->molecule_cnt_list[i])
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
-            }
-            offset += sizeof(int64_t);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
+
+    tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
+    tng_data->first_trajectory_frame_set_input_file_pos;
 
 
-        memcpy(&molecule->n_chains, block->block_contents+offset,
-               sizeof(molecule->n_chains));
-        if(tng_data->input_endianness_swap_func_64)
+    memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
+           block->block_contents+offset,
+           sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                          &tng_data->last_trajectory_frame_set_input_file_pos)
+            != TNG_SUCCESS)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_chains)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_chains);
+    }
+    offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
 
-        memcpy(&molecule->n_residues, block->block_contents+offset,
-               sizeof(molecule->n_residues));
-        if(tng_data->input_endianness_swap_func_64)
+    memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
+           sizeof(tng_data->medium_stride_length));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                               &tng_data->medium_stride_length)
+            != TNG_SUCCESS)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_residues)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_residues);
+    }
+    offset += sizeof(tng_data->medium_stride_length);
 
-        memcpy(&molecule->n_atoms, block->block_contents+offset,
-               sizeof(molecule->n_atoms));
+    memcpy(&tng_data->long_stride_length, block->block_contents+offset,
+           sizeof(tng_data->long_stride_length));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &tng_data->long_stride_length)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(tng_data->long_stride_length);
+
+    if(block->block_version >= 3)
+    {
+        memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
+            sizeof(tng_data->distance_unit_exponential));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_atoms)
+                                          &tng_data->distance_unit_exponential)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
-        offset += sizeof(molecule->n_atoms);
+    }
 
-        tng_data->n_particles += molecule->n_atoms *
-                                 tng_data->molecule_cnt_list[i];
+    return(TNG_SUCCESS);
+}
 
-        if(molecule->n_chains > 0)
-        {
-            molecule->chains = malloc(molecule->n_chains *
-                                    sizeof(struct tng_chain));
-            if(!molecule->chains)
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                    molecule->n_chains * sizeof(struct tng_chain),
-                    __FILE__, __LINE__);
-                return(TNG_CRITICAL);
-            }
+/** Write a general info block. This is the first block of a TNG file.
+ * @param tng_data is a trajectory data container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_general_info_block_write
+                (tng_trajectory_t tng_data,
+                 const char hash_mode)
+{
+    int first_program_name_len, first_user_name_len;
+    int first_computer_name_len, first_pgp_signature_len;
+    int last_program_name_len, last_user_name_len;
+    int last_computer_name_len, last_pgp_signature_len;
+    int forcefield_name_len, name_len;
+    int offset = 0;
+    tng_gen_block_t block;
 
-            chain = molecule->chains;
-        }
-        else
-        {
-            chain = 0;
-        }
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
 
-        if(molecule->n_residues > 0)
-        {
-            molecule->residues = malloc(molecule->n_residues *
-                                sizeof(struct tng_residue));
-            if(!molecule->residues)
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                    molecule->n_residues * sizeof(struct tng_residue),
-                    __FILE__, __LINE__);
-                if(molecule->chains)
-                {
-                    free(molecule->chains);
-                    molecule->chains = 0;
-                }
-                return(TNG_CRITICAL);
-            }
+    fseeko(tng_data->output_file, 0, SEEK_SET);
 
-            residue = molecule->residues;
-        }
-        else
-        {
-            residue = 0;
-        }
+    tng_block_init(&block);
 
-        molecule->atoms = malloc(molecule->n_atoms *
-                                 sizeof(struct tng_atom));
-        if(!molecule->atoms)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                   molecule->n_atoms * sizeof(struct tng_atom),
-                   __FILE__, __LINE__);
-            if(molecule->chains)
-            {
-                free(molecule->chains);
-                molecule->chains = 0;
-            }
-            if(molecule->residues)
-            {
-                free(molecule->residues);
-                molecule->residues = 0;
-            }
-            return(TNG_CRITICAL);
-        }
+    name_len = (int)strlen("GENERAL INFO");
 
-        atom = molecule->atoms;
+    block->name = malloc(name_len + 1);
+    if(!block->name)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                name_len+1, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-        if(molecule->n_chains > 0)
-        {
-            /* Read the chains of the molecule */
-            for(j=molecule->n_chains; j--;)
-            {
-                chain->molecule = molecule;
+    strcpy(block->name, "GENERAL INFO");
+    block->id = TNG_GENERAL_INFO;
 
-                tng_chain_data_read(tng_data, block, chain, &offset);
+    if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
+        TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
+                __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-                chain->residues = molecule->residues;
-                residue = chain->residues;
+    first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
+                           TNG_MAX_STR_LEN);
+    last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
+                           TNG_MAX_STR_LEN);
+    first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
+                        TNG_MAX_STR_LEN);
+    last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
+                        TNG_MAX_STR_LEN);
+    first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
+                            TNG_MAX_STR_LEN);
+    last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
+                            TNG_MAX_STR_LEN);
+    first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
+                            TNG_MAX_STR_LEN);
+    last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
+                            TNG_MAX_STR_LEN);
+    forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
+                              TNG_MAX_STR_LEN);
 
-                /* Read the residues of the chain */
-                for(k=chain->n_residues; k--;)
-                {
-                    residue->chain = chain;
+    if(block->block_contents)
+    {
+        free(block->block_contents);
+    }
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-                    tng_residue_data_read(tng_data, block, residue, &offset);
+    strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
+    offset += first_program_name_len;
 
-                    residue->atoms_offset = atom - molecule->atoms;
-                    /* Read the atoms of the residue */
-                    for(l=residue->n_atoms; l--;)
-                    {
-                        atom->residue = residue;
+    strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
+    offset += last_program_name_len;
 
-                        tng_atom_data_read(tng_data, block, atom, &offset);
+    strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
+    offset += first_user_name_len;
 
-                        atom++;
-                    }
-                    residue++;
-                }
-                chain++;
-            }
-        }
-        else
-        {
-            if(molecule->n_residues > 0)
-            {
-                for(k=molecule->n_residues; k--;)
-                {
-                    residue->chain = 0;
+    strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
+    offset += last_user_name_len;
 
-                    tng_residue_data_read(tng_data, block, residue, &offset);
+    strncpy(block->block_contents+offset, tng_data->first_computer_name,
+            first_computer_name_len);
+    offset += first_computer_name_len;
 
-                    residue->atoms_offset = atom - molecule->atoms;
-                    /* Read the atoms of the residue */
-                    for(l=residue->n_atoms; l--;)
-                    {
-                        atom->residue = residue;
+    strncpy(block->block_contents+offset, tng_data->last_computer_name,
+            last_computer_name_len);
+    offset += last_computer_name_len;
 
-                        tng_atom_data_read(tng_data, block, atom, &offset);
+    strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
+            first_pgp_signature_len);
+    offset += first_pgp_signature_len;
 
-                        atom++;
-                    }
-                    residue++;
-                }
-            }
-            else
-            {
-                for(l=molecule->n_atoms; l--;)
-                {
-                    atom->residue = 0;
+    strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
+            last_pgp_signature_len);
+    offset += last_pgp_signature_len;
 
-                    tng_atom_data_read(tng_data, block, atom, &offset);
+    strncpy(block->block_contents+offset, tng_data->forcefield_name,
+            forcefield_name_len);
+    offset += forcefield_name_len;
 
-                    atom++;
-                }
-            }
+    memcpy(block->block_contents+offset, &tng_data->time,
+           sizeof(tng_data->time));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(tng_data->time);
 
-        memcpy(&molecule->n_bonds, block->block_contents+offset,
-               sizeof(molecule->n_bonds));
-        if(tng_data->input_endianness_swap_func_64)
+    memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
+           sizeof(tng_data->var_num_atoms_flag));
+    offset += sizeof(tng_data->var_num_atoms_flag);
+
+    memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
+           sizeof(tng_data->frame_set_n_frames));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_bonds)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_bonds);
+    }
+    offset += sizeof(tng_data->frame_set_n_frames);
 
-        if(molecule->n_bonds > 0)
+    memcpy(block->block_contents+offset,
+           &tng_data->first_trajectory_frame_set_output_file_pos,
+           sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
-                                           sizeof(struct tng_bond));
-            if(!molecule->bonds)
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                       molecule->n_bonds * sizeof(struct tng_bond),
-                       __FILE__, __LINE__);
-                if(molecule->chains)
-                {
-                    free(molecule->chains);
-                    molecule->chains = 0;
-                }
-                if(molecule->residues)
-                {
-                    free(molecule->residues);
-                    molecule->residues = 0;
-                }
-                if(molecule->atoms)
-                {
-                    free(molecule->atoms);
-                    molecule->atoms = 0;
-                }
-                return(TNG_CRITICAL);
-            }
-
-            bond = molecule->bonds;
-
-            for(j=molecule->n_bonds; j--;)
-            {
-                memcpy(&bond->from_atom_id, block->block_contents+offset,
-                    sizeof(bond->from_atom_id));
-                if(tng_data->input_endianness_swap_func_64)
-                {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                               &bond->from_atom_id)
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
-                }
-                offset += sizeof(bond->from_atom_id);
-
-                memcpy(&bond->to_atom_id, block->block_contents+offset,
-                    sizeof(bond->to_atom_id));
-                if(tng_data->input_endianness_swap_func_64)
-                {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                               &bond->to_atom_id)
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
-                }
-                offset += sizeof(bond->to_atom_id);
-
-                bond++;
-            }
-        }
-        else
-        {
-            molecule->bonds = 0;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
+    offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
 
-    return(TNG_SUCCESS);
-}
-
-/** Write a molecules block.
- * @param tng_data is a trajectory data container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_molecules_block_write
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int len = 0, name_len, offset = 0;
-    int64_t i, j, k, l;
-    tng_molecule_t molecule;
-    tng_chain_t chain;
-    tng_residue_t residue;
-    tng_atom_t atom;
-    tng_bond_t bond;
-    tng_gen_block_t block;
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    /* First predict the size of the block */
-    for(i = 0; i < tng_data->n_molecules; i++)
+    memcpy(block->block_contents+offset,
+           &tng_data->last_trajectory_frame_set_output_file_pos,
+           sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        molecule = &tng_data->molecules[i];
-        if(!molecule->name)
-        {
-            molecule->name = malloc(1);
-            if(!molecule->name)
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                       __FILE__, __LINE__);
-                return(TNG_CRITICAL);
-            }
-            molecule->name[0] = 0;
-        }
-        len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
-
-        chain = molecule->chains;
-        for(j = molecule->n_chains; j--;)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            len += sizeof(chain->id);
-
-            if(!chain->name)
-            {
-                chain->name = malloc(1);
-                if(!chain->name)
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                           __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                chain->name[0] = 0;
-            }
-            len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
-
-            len += sizeof(chain->n_residues);
-
-            chain++;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
 
-        residue = molecule->residues;
-        for(j = molecule->n_residues; j--;)
+    memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
+           sizeof(tng_data->medium_stride_length));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            len += sizeof(residue->id);
-
-            if(!residue->name)
-            {
-                residue->name = malloc(1);
-                if(!residue->name)
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                           __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                residue->name[0] = 0;
-            }
-            len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
-
-            len += sizeof(residue->n_atoms);
-
-            residue++;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(tng_data->medium_stride_length);
 
-        atom = molecule->atoms;
-        for(j = molecule->n_atoms; j--;)
+    memcpy(block->block_contents+offset, &tng_data->long_stride_length,
+           sizeof(tng_data->long_stride_length));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            len += sizeof(atom->id);
-            if(!atom->name)
-            {
-                atom->name = malloc(1);
-                if(!atom->name)
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                           __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                atom->name[0] = 0;
-            }
-            len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
-
-            if(!atom->atom_type)
-            {
-                atom->atom_type = malloc(1);
-                if(!atom->atom_type)
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                           __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                atom->atom_type[0] = 0;
-            }
-            len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
-
-            atom++;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(tng_data->long_stride_length);
 
-        for(j = molecule->n_bonds; j--;)
+    memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
+           sizeof(tng_data->distance_unit_exponential));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
 
-    tng_block_init(&block);
-
-    name_len = (int)strlen("MOLECULES");
-
-    block->name = malloc(name_len + 1);
-    if(!block->name)
+    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                name_len+1, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+               tng_data->output_file_path, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    strcpy(block->name, "MOLECULES");
-    block->id = TNG_MOLECULES;
-
-    block->block_contents_size = sizeof(tng_data->n_molecules) +
-                                 (sizeof(molecule->id) +
-                                 sizeof(molecule->quaternary_str) +
-                                 sizeof(molecule->n_chains) +
-                                 sizeof(molecule->n_residues) +
-                                 sizeof(molecule->n_atoms) +
-                                 sizeof(molecule->n_bonds)) *
-                                 tng_data->n_molecules +
-                                 len;
-
-    if(!tng_data->var_num_atoms_flag)
-    {
-        block->block_contents_size += tng_data->n_molecules * sizeof(int64_t);
-    }
-
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    if(fwrite(block->block_contents, block->block_contents_size, 1,
+        tng_data->output_file) != 1)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    memcpy(block->block_contents+offset, &tng_data->n_molecules,
-           sizeof(tng_data->n_molecules));
-    if(tng_data->output_endianness_swap_func_64)
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+/** Read the chain data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param chain is the chain data container.
+ * @param offset is the offset of the block input and is updated when reading.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
+                                               tng_gen_block_t block,
+                                               tng_chain_t chain,
+                                               int *offset)
+{
+    int len;
+
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(&chain->id, block->block_contents+*offset,
+            sizeof(chain->id));
+    if(tng_data->input_endianness_swap_func_64)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &chain->id)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(tng_data->n_molecules);
+    *offset += sizeof(chain->id);
 
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        molecule = &tng_data->molecules[i];
-        memcpy(block->block_contents+offset, &molecule->id,
-               sizeof(molecule->id));
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+            TNG_MAX_STR_LEN);
+    chain->name = malloc(len);
+    strncpy(chain->name,
+            block->block_contents+*offset, len);
+    *offset += len;
+
+    memcpy(&chain->n_residues, block->block_contents+*offset,
+        sizeof(chain->n_residues));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &chain->n_residues)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->id);
+    }
+    *offset += sizeof(chain->n_residues);
 
-/*         fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
-        len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
-        strncpy(block->block_contents + offset, molecule->name, len);
-        offset += len;
+    return(TNG_SUCCESS);
+}
 
-        memcpy(block->block_contents+offset, &molecule->quaternary_str,
-               sizeof(molecule->quaternary_str));
-        if(tng_data->output_endianness_swap_func_64)
+/** Write the chain data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param chain is the chain data container.
+ * @param offset is the offset of the block output and is updated when writing.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
+                                                tng_gen_block_t block,
+                                                tng_chain_t chain,
+                                                int *offset)
+{
+    int len;
+
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                    (int64_t *)block->header_contents+*offset)
+            != TNG_SUCCESS)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->quaternary_str);
+    }
+    *offset += sizeof(chain->id);
 
-        if(!tng_data->var_num_atoms_flag)
+    len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
+    strncpy(block->block_contents + *offset, chain->name, len);
+    *offset += len;
+
+    memcpy(block->block_contents+*offset, &chain->n_residues,
+        sizeof(chain->n_residues));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                    (int64_t *)block->header_contents+*offset)
+            != TNG_SUCCESS)
         {
-            memcpy(block->block_contents+offset,
-                   &tng_data->molecule_cnt_list[i], sizeof(int64_t));
-            if(tng_data->output_endianness_swap_func_64)
-            {
-                if(tng_data->output_endianness_swap_func_64(tng_data,
-                                            (int64_t *)block->header_contents+offset)
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
-            }
-            offset += sizeof(int64_t);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    *offset += sizeof(chain->n_residues);
 
-        memcpy(block->block_contents+offset, &molecule->n_chains,
-               sizeof(molecule->n_chains));
-        if(tng_data->output_endianness_swap_func_64)
+    return(TNG_SUCCESS);
+}
+
+/** Read the residue data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param residue is the residue data container.
+ * @param offset is the offset of the block input and is updated when reading.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
+                                                 tng_gen_block_t block,
+                                                 tng_residue_t residue,
+                                                 int *offset)
+{
+    int len;
+
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(&residue->id, block->block_contents+*offset,
+        sizeof(residue->id));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &residue->id)
+            != TNG_SUCCESS)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_chains);
+    }
+    *offset += sizeof(residue->id);
 
-        memcpy(block->block_contents+offset, &molecule->n_residues,
-               sizeof(molecule->n_residues));
-        if(tng_data->output_endianness_swap_func_64)
+    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+            TNG_MAX_STR_LEN);
+    residue->name = malloc(len);
+    strncpy(residue->name,
+            block->block_contents+*offset, len);
+    *offset += len;
+
+    memcpy(&residue->n_atoms, block->block_contents+*offset,
+            sizeof(residue->n_atoms));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &residue->n_atoms)
+            != TNG_SUCCESS)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_residues);
+    }
+    *offset += sizeof(residue->n_atoms);
 
-        memcpy(block->block_contents+offset, &molecule->n_atoms,
-               sizeof(molecule->n_atoms));
-        if(tng_data->output_endianness_swap_func_64)
+    return(TNG_SUCCESS);
+}
+
+/** Write the residue data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param residue is the residue data container.
+ * @param offset is the offset of the block output and is updated when writing.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
+                                                  tng_gen_block_t block,
+                                                  tng_residue_t residue,
+                                                  int *offset)
+{
+    int len;
+
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                    (int64_t *)block->header_contents+*offset)
+            != TNG_SUCCESS)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        offset += sizeof(molecule->n_atoms);
+    }
+    *offset += sizeof(residue->id);
 
-        if(molecule->n_chains > 0)
+    len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
+    strncpy(block->block_contents + *offset, residue->name, len);
+    *offset += len;
+
+    memcpy(block->block_contents+*offset, &residue->n_atoms,
+        sizeof(residue->n_atoms));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                    (int64_t *)block->header_contents+*offset)
+            != TNG_SUCCESS)
         {
-            chain = molecule->chains;
-            for(j = molecule->n_chains; j--;)
-            {
-                tng_chain_data_write(tng_data, block, chain, &offset);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    *offset += sizeof(residue->n_atoms);
 
-                residue = chain->residues;
-                for(k = chain->n_residues; k--;)
-                {
-                    tng_residue_data_write(tng_data, block, residue, &offset);
+    return(TNG_SUCCESS);
+}
 
-                    atom = molecule->atoms + residue->atoms_offset;
-                    for(l = residue->n_atoms; l--;)
-                    {
-                        tng_atom_data_write(tng_data, block, atom, &offset);
+/** Read the atom data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param atom is the atom data container.
+ * @param offset is the offset of the block input and is updated when reading.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
+                                              tng_gen_block_t block,
+                                              tng_atom_t atom,
+                                              int *offset)
+{
+    int len;
 
-                        atom++;
-                    }
-                    residue++;
-                }
-                chain++;
-            }
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(&atom->id, block->block_contents+*offset,
+        sizeof(atom->id));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                    &atom->id)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        else
+    }
+    *offset += sizeof(atom->id);
+
+    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+            TNG_MAX_STR_LEN);
+    atom->name = malloc(len);
+    strncpy(atom->name,
+            block->block_contents+*offset, len);
+    *offset += len;
+
+    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+            TNG_MAX_STR_LEN);
+    atom->atom_type = malloc(len);
+    strncpy(atom->atom_type,
+            block->block_contents+*offset, len);
+    *offset += len;
+
+    return(TNG_SUCCESS);
+}
+
+/** Write the atom data of a molecules block.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param atom is the atom data container.
+ * @param offset is the offset of the block output and is updated when writing.
+ * @return TNG_SUCCESS(0) is successful.
+ */
+static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
+                                               tng_gen_block_t block,
+                                               tng_atom_t atom,
+                                               int *offset)
+{
+    int len;
+
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+    memcpy(block->block_contents+*offset, &atom->id,
+            sizeof(atom->id));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                    (int64_t *)block->header_contents+*offset)
+            != TNG_SUCCESS)
         {
-            if(molecule->n_residues > 0)
-            {
-                residue = molecule->residues;
-                for(k = molecule->n_residues; k--;)
-                {
-                    tng_residue_data_write(tng_data, block, residue, &offset);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    *offset += sizeof(atom->id);
 
-                    atom = molecule->atoms + residue->atoms_offset;
-                    for(l = residue->n_atoms; l--;)
-                    {
-                        tng_atom_data_write(tng_data, block, atom, &offset);
+    len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
+    strncpy(block->block_contents + *offset, atom->name, len);
+    *offset += len;
 
-                        atom++;
-                    }
-                    residue++;
-                }
+    len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
+    strncpy(block->block_contents + *offset, atom->atom_type, len);
+    *offset += len;
+
+    return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_molecules_block_len_calculate
+                (const tng_trajectory_t tng_data,
+                 int64_t *len)
+{
+    int64_t i, j;
+    tng_molecule_t molecule;
+    tng_chain_t chain;
+    tng_residue_t residue;
+    tng_atom_t atom;
+    tng_bond_t bond;
+
+    *len = 0;
+
+    for(i = 0; i < tng_data->n_molecules; i++)
+    {
+        molecule = &tng_data->molecules[i];
+        if(!molecule->name)
+        {
+            molecule->name = malloc(1);
+            if(!molecule->name)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                       __FILE__, __LINE__);
+                return(TNG_CRITICAL);
             }
-            else
+            molecule->name[0] = 0;
+        }
+        *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
+
+        chain = molecule->chains;
+        for(j = 0; j < molecule->n_chains; j++)
+        {
+            *len += sizeof(chain->id);
+
+            if(!chain->name)
             {
-                atom = molecule->atoms;
-                for(l = molecule->n_atoms; l--;)
+                chain->name = malloc(1);
+                if(!chain->name)
                 {
-                    tng_atom_data_write(tng_data, block, atom, &offset);
-
-                    atom++;
+                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                           __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
                 }
+                chain->name[0] = 0;
             }
+            *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
+
+            *len += sizeof(chain->n_residues);
+
+            chain++;
         }
 
-        memcpy(block->block_contents+offset, &molecule->n_bonds,
-               sizeof(molecule->n_bonds));
-        if(tng_data->output_endianness_swap_func_64)
+        residue = molecule->residues;
+        for(j = 0; j < molecule->n_residues; j++)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
+            *len += sizeof(residue->id);
+
+            if(!residue->name)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                residue->name = malloc(1);
+                if(!residue->name)
+                {
+                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                           __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
+                }
+                residue->name[0] = 0;
             }
+            *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
+
+            *len += sizeof(residue->n_atoms);
+
+            residue++;
         }
-        offset += sizeof(molecule->n_bonds);
 
-        bond = molecule->bonds;
-        for(j = molecule->n_bonds; j--;)
+        atom = molecule->atoms;
+        for(j = 0; j < molecule->n_atoms; j++)
         {
-            memcpy(block->block_contents+offset, &bond->from_atom_id,
-                   sizeof(bond->from_atom_id));
-            if(tng_data->output_endianness_swap_func_64)
+            *len += sizeof(atom->id);
+            if(!atom->name)
             {
-                if(tng_data->output_endianness_swap_func_64(tng_data,
-                                            (int64_t *)block->header_contents+offset)
-                    != TNG_SUCCESS)
+                atom->name = malloc(1);
+                if(!atom->name)
                 {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
+                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                           __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
                 }
+                atom->name[0] = 0;
             }
-            offset += sizeof(bond->from_atom_id);
+            *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
 
-            memcpy(block->block_contents+offset, &bond->to_atom_id,
-                   sizeof(bond->to_atom_id));
-            if(tng_data->output_endianness_swap_func_64)
+            if(!atom->atom_type)
             {
-                if(tng_data->output_endianness_swap_func_64(tng_data,
-                                            (int64_t *)block->header_contents+offset)
-                    != TNG_SUCCESS)
+                atom->atom_type = malloc(1);
+                if(!atom->atom_type)
                 {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
+                    fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                           __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
                 }
+                atom->atom_type[0] = 0;
             }
-            offset += sizeof(bond->to_atom_id);
+            *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
 
-            bond++;
+            atom++;
         }
-    }
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        for(j = 0; j < molecule->n_bonds; j++)
+        {
+            *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
+        }
     }
+    *len += sizeof(tng_data->n_molecules) +
+            (sizeof(molecule->id) +
+            sizeof(molecule->quaternary_str) +
+            sizeof(molecule->n_chains) +
+            sizeof(molecule->n_residues) +
+            sizeof(molecule->n_atoms) +
+            sizeof(molecule->n_bonds)) *
+            tng_data->n_molecules;
 
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
+    if(!tng_data->var_num_atoms_flag)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
-               __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        *len += tng_data->n_molecules * sizeof(int64_t);
     }
 
-    tng_block_destroy(&block);
-
     return(TNG_SUCCESS);
 }
 
-/** Read a frame set block. Update tng_data->current_trajectory_frame_set
+/** Read a molecules block. Contains chain, residue and atom data
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
@@ -3001,17 +3132,19 @@ static tng_function_status tng_molecules_block_write
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_frame_set_block_read
+static tng_function_status tng_molecules_block_read
                 (tng_trajectory_t tng_data,
                  tng_gen_block_t block,
                  const char hash_mode)
 {
-    long file_pos;
-    int offset = 0;
-    int64_t i, prev_n_particles;
+    int64_t i, j, k, l;
+    int len, offset = 0;
+    tng_molecule_t molecule;
+    tng_chain_t chain;
+    tng_residue_t residue;
+    tng_atom_t atom;
+    tng_bond_t bond;
     tng_bool same_hash;
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
 
     if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
@@ -3031,748 +3164,637 @@ static tng_function_status tng_frame_set_block_read
         return(TNG_CRITICAL);
     }
 
-    /* Read the whole block into block_contents to be able to write it to
-     * disk even if it cannot be interpreted. */
+    /* Read the whole block into block_contents to be able to write it to disk
+     * even if it cannot be interpreted. */
     if(fread(block->block_contents, block->block_contents_size, 1,
              tng_data->input_file) == 0)
     {
         fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
     }
 
     /* FIXME: Does not check if the size of the contents matches the expected
      * size or if the contents can be read. */
 
-    file_pos = (int64_t)ftell(tng_data->input_file) -
-               (long)(block->block_contents_size + block->header_contents_size);
-
     if(hash_mode == TNG_USE_HASH)
     {
         tng_md5_hash_match_verify(block, &same_hash);
         if(same_hash != TNG_TRUE)
         {
-            fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %ld Hashes do not match. "
+            fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
                 "%s: %d\n",
-                file_pos, __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
+                __FILE__, __LINE__);
         }
     }
 
-    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
-
-    tng_frame_set_particle_mapping_free(tng_data);
-
-    if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
-    {
-        tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
-    }
-    /* FIXME: Should check the frame number instead of the file_pos, in case
-     * frame sets are not in order */
-    if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
-    {
-        tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
-    }
-
-    memcpy(&frame_set->first_frame, block->block_contents,
-           sizeof(frame_set->first_frame));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_data->molecules)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &frame_set->first_frame)
-            != TNG_SUCCESS)
+        for(i=0; i<tng_data->n_molecules; i++)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
         }
+        free(tng_data->molecules);
+        tng_data->molecules = 0;
+        tng_data->n_molecules = 0;
     }
-    offset += sizeof(frame_set->first_frame);
 
-    memcpy(&frame_set->n_frames, block->block_contents + offset,
-           sizeof(frame_set->n_frames));
+    memcpy(&tng_data->n_molecules, block->block_contents,
+           sizeof(tng_data->n_molecules));
     if(tng_data->input_endianness_swap_func_64)
     {
         if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &frame_set->n_frames)
+                                                   &tng_data->n_molecules)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(frame_set->n_frames);
+    offset += sizeof(tng_data->n_molecules);
 
-    if(tng_data->var_num_atoms_flag)
+    if(tng_data->molecules)
     {
-        prev_n_particles = frame_set->n_particles;
-        frame_set->n_particles = 0;
-        /* If the list of molecule counts has already been created assume that
-         * it is of correct size. */
-        if(!frame_set->molecule_cnt_list)
-        {
-                frame_set->molecule_cnt_list =
-                malloc(sizeof(int64_t) * tng_data->n_molecules);
-
-                if(!frame_set->molecule_cnt_list)
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                           sizeof(int64_t) * tng_data->n_molecules,
-                           __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-        }
-        for(i = 0; i < tng_data->n_molecules; i++)
-        {
-            memcpy(&frame_set->molecule_cnt_list[i],
-                   block->block_contents + offset,
-                   sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64)
-            {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                              &frame_set->molecule_cnt_list[i])
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
-            }
-            offset += sizeof(int64_t);
-            frame_set->n_particles += tng_data->molecules[i].n_atoms *
-                                      frame_set->molecule_cnt_list[i];
-        }
-        if(prev_n_particles && frame_set->n_particles != prev_n_particles)
-        {
-            /* FIXME: Particle dependent data memory management */
-        }
+        free(tng_data->molecules);
     }
 
-    memcpy(&frame_set->next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    tng_data->n_particles = 0;
+
+    tng_data->molecules = malloc(tng_data->n_molecules *
+                          sizeof(struct tng_molecule));
+    if(!tng_data->molecules)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                           &frame_set->next_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               tng_data->n_molecules * sizeof(struct tng_molecule),
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-    memcpy(&frame_set->prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(!tng_data->var_num_atoms_flag)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                           &frame_set->prev_frame_set_file_pos)
-            != TNG_SUCCESS)
+        if(tng_data->molecule_cnt_list)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            free(tng_data->molecule_cnt_list);
+        }
+        tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
+                                      tng_data->n_molecules);
+        if(!tng_data->molecule_cnt_list)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                   tng_data->n_molecules * sizeof(struct tng_molecule),
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    offset += sizeof(frame_set->prev_frame_set_file_pos);
 
-    memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    /* Read each molecule from file */
+    for(i=0; i < tng_data->n_molecules; i++)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                             &frame_set->medium_stride_next_frame_set_file_pos)
-            != TNG_SUCCESS)
+        molecule = &tng_data->molecules[i];
+
+        memcpy(&molecule->id, block->block_contents+offset,
+               sizeof(molecule->id));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                       &molecule->id)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
+        offset += sizeof(molecule->id);
 
-    memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                             &frame_set->medium_stride_prev_frame_set_file_pos)
-            != TNG_SUCCESS)
+/*         fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
+        len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
+        molecule->name = malloc(len);
+        strncpy(molecule->name, block->block_contents+offset, len);
+        offset += len;
+
+        memcpy(&molecule->quaternary_str, block->block_contents+offset,
+               sizeof(molecule->quaternary_str));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                     &molecule->quaternary_str)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
+        offset += sizeof(molecule->quaternary_str);
 
-    memcpy(&frame_set->long_stride_next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->long_stride_next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                               &frame_set->long_stride_next_frame_set_file_pos)
-            != TNG_SUCCESS)
+        if(!tng_data->var_num_atoms_flag)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            memcpy(&tng_data->molecule_cnt_list[i],
+                   block->block_contents+offset,
+                   sizeof(int64_t));
+            if(tng_data->input_endianness_swap_func_64)
+            {
+                if(tng_data->input_endianness_swap_func_64(tng_data,
+                                               &tng_data->molecule_cnt_list[i])
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            offset += sizeof(int64_t);
         }
-    }
-    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
 
-    memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                               &frame_set->long_stride_prev_frame_set_file_pos)
-            != TNG_SUCCESS)
+
+        memcpy(&molecule->n_chains, block->block_contents+offset,
+               sizeof(molecule->n_chains));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                       &molecule->n_chains)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
+        offset += sizeof(molecule->n_chains);
 
-    if(block->block_version >= 3)
-    {
-        memcpy(&frame_set->first_frame_time,
-            block->block_contents + offset,
-            sizeof(frame_set->first_frame_time));
+        memcpy(&molecule->n_residues, block->block_contents+offset,
+               sizeof(molecule->n_residues));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                (int64_t *)&frame_set->first_frame_time)
+                                                       &molecule->n_residues)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
-        offset += sizeof(frame_set->first_frame_time);
+        offset += sizeof(molecule->n_residues);
 
-        memcpy(&tng_data->time_per_frame,
-            block->block_contents + offset,
-            sizeof(tng_data->time_per_frame));
+        memcpy(&molecule->n_atoms, block->block_contents+offset,
+               sizeof(molecule->n_atoms));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                (int64_t *)&tng_data->time_per_frame)
+                                                       &molecule->n_atoms)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
-    }
-    else
-    {
-        frame_set->first_frame_time = -1;
-        tng_data->time_per_frame = -1;
-    }
+        offset += sizeof(molecule->n_atoms);
 
-    frame_set->n_written_frames = frame_set->n_frames;
+        tng_data->n_particles += molecule->n_atoms *
+                                 tng_data->molecule_cnt_list[i];
 
-    return(TNG_SUCCESS);
-}
+        if(molecule->n_chains > 0)
+        {
+            molecule->chains = malloc(molecule->n_chains *
+                                    sizeof(struct tng_chain));
+            if(!molecule->chains)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                    molecule->n_chains * sizeof(struct tng_chain),
+                    __FILE__, __LINE__);
+                return(TNG_CRITICAL);
+            }
 
-/** Write tng_data->current_trajectory_frame_set to file
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_frame_set_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 const char hash_mode)
-{
-    char *temp_name;
-    int64_t i;
-    int offset = 0;
-    unsigned int name_len;
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
+            chain = molecule->chains;
+        }
+        else
+        {
+            chain = 0;
+        }
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
+        if(molecule->n_residues > 0)
+        {
+            molecule->residues = malloc(molecule->n_residues *
+                                sizeof(struct tng_residue));
+            if(!molecule->residues)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                    molecule->n_residues * sizeof(struct tng_residue),
+                    __FILE__, __LINE__);
+                if(molecule->chains)
+                {
+                    free(molecule->chains);
+                    molecule->chains = 0;
+                }
+                return(TNG_CRITICAL);
+            }
 
-    name_len = (int)strlen("TRAJECTORY FRAME SET");
+            residue = molecule->residues;
+        }
+        else
+        {
+            residue = 0;
+        }
 
-    if(!block->name || strlen(block->name) < name_len)
-    {
-        temp_name = realloc(block->name, name_len + 1);
-        if(!temp_name)
+        molecule->atoms = malloc(molecule->n_atoms *
+                                 sizeof(struct tng_atom));
+        if(!molecule->atoms)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   name_len+1, __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                   molecule->n_atoms * sizeof(struct tng_atom),
+                   __FILE__, __LINE__);
+            if(molecule->chains)
+            {
+                free(molecule->chains);
+                molecule->chains = 0;
+            }
+            if(molecule->residues)
+            {
+                free(molecule->residues);
+                molecule->residues = 0;
+            }
             return(TNG_CRITICAL);
         }
-        block->name = temp_name;
-    }
-    strcpy(block->name, "TRAJECTORY FRAME SET");
-    block->id = TNG_TRAJECTORY_FRAME_SET;
 
-    block->block_contents_size = sizeof(int64_t) * 8;
-    block->block_contents_size += sizeof(double) * 2;
+        atom = molecule->atoms;
 
-    if(tng_data->var_num_atoms_flag)
-    {
-        block->block_contents_size += sizeof(int64_t) * tng_data->n_molecules;
-    }
+        if(molecule->n_chains > 0)
+        {
+            /* Read the chains of the molecule */
+            for(j=0; j<molecule->n_chains; j++)
+            {
+                chain->molecule = molecule;
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+                tng_chain_data_read(tng_data, block, chain, &offset);
 
-    memcpy(block->block_contents, &frame_set->first_frame,
-           sizeof(frame_set->first_frame));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->first_frame);
+                chain->residues = molecule->residues;
+                residue = chain->residues;
 
-    memcpy(block->block_contents+offset, &frame_set->n_frames,
-           sizeof(frame_set->n_frames));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->n_frames);
+                /* Read the residues of the chain */
+                for(k=0; k<chain->n_residues; k++)
+                {
+                    residue->chain = chain;
+
+                    tng_residue_data_read(tng_data, block, residue, &offset);
 
-    if(tng_data->var_num_atoms_flag)
-    {
-        for(i = 0; i < tng_data->n_molecules; i++)
+                    residue->atoms_offset = atom - molecule->atoms;
+                    /* Read the atoms of the residue */
+                    for(l=0; l<residue->n_atoms; l++)
+                    {
+                        atom->residue = residue;
+
+                        tng_atom_data_read(tng_data, block, atom, &offset);
+
+                        atom++;
+                    }
+                    residue++;
+                }
+                chain++;
+            }
+        }
+        else
         {
-            memcpy(block->block_contents+offset,
-                   &frame_set->molecule_cnt_list[i],
-                   sizeof(int64_t));
-            if(tng_data->output_endianness_swap_func_64)
+            if(molecule->n_residues > 0)
             {
-                if(tng_data->output_endianness_swap_func_64(tng_data,
-                                            (int64_t *)block->header_contents+offset)
-                    != TNG_SUCCESS)
+                for(k=0; k<molecule->n_residues; k++)
                 {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
+                    residue->chain = 0;
+
+                    tng_residue_data_read(tng_data, block, residue, &offset);
+
+                    residue->atoms_offset = atom - molecule->atoms;
+                    /* Read the atoms of the residue */
+                    for(l=0; l<residue->n_atoms; l++)
+                    {
+                        atom->residue = residue;
+
+                        tng_atom_data_read(tng_data, block, atom, &offset);
+
+                        atom++;
+                    }
+                    residue++;
                 }
             }
-            offset += sizeof(int64_t);
-        }
-    }
+            else
+            {
+                for(l=0; l<molecule->n_atoms; l++)
+                {
+                    atom->residue = 0;
 
+                    tng_atom_data_read(tng_data, block, atom, &offset);
 
-    memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
-           sizeof(frame_set->next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+                    atom++;
+                }
+            }
         }
-    }
-    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
-           sizeof(frame_set->prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        memcpy(&molecule->n_bonds, block->block_contents+offset,
+               sizeof(molecule->n_bonds));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                       &molecule->n_bonds)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(frame_set->prev_frame_set_file_pos);
+        offset += sizeof(molecule->n_bonds);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->medium_stride_next_frame_set_file_pos,
-           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        if(molecule->n_bonds > 0)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
+            tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
+                                           sizeof(struct tng_bond));
+            if(!molecule->bonds)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                       molecule->n_bonds * sizeof(struct tng_bond),
+                       __FILE__, __LINE__);
+                if(molecule->chains)
+                {
+                    free(molecule->chains);
+                    molecule->chains = 0;
+                }
+                if(molecule->residues)
+                {
+                    free(molecule->residues);
+                    molecule->residues = 0;
+                }
+                if(molecule->atoms)
+                {
+                    free(molecule->atoms);
+                    molecule->atoms = 0;
+                }
+                return(TNG_CRITICAL);
+            }
 
-    memcpy(block->block_contents+offset,
-           &frame_set->medium_stride_prev_frame_set_file_pos,
-           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
+            bond = molecule->bonds;
 
-    memcpy(block->block_contents+offset,
-           &frame_set->long_stride_next_frame_set_file_pos,
-           sizeof(frame_set->long_stride_next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
+            for(j=0; j<molecule->n_bonds; j++)
+            {
+                memcpy(&bond->from_atom_id, block->block_contents+offset,
+                    sizeof(bond->from_atom_id));
+                if(tng_data->input_endianness_swap_func_64)
+                {
+                    if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                               &bond->from_atom_id)
+                        != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
+                    }
+                }
+                offset += sizeof(bond->from_atom_id);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->long_stride_prev_frame_set_file_pos,
-           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
+                memcpy(&bond->to_atom_id, block->block_contents+offset,
+                    sizeof(bond->to_atom_id));
+                if(tng_data->input_endianness_swap_func_64)
+                {
+                    if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                               &bond->to_atom_id)
+                        != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
+                    }
+                }
+                offset += sizeof(bond->to_atom_id);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->first_frame_time,
-           sizeof(frame_set->first_frame_time));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+                bond++;
+            }
         }
-    }
-    offset += sizeof(frame_set->first_frame_time);
-
-    memcpy(block->block_contents+offset,
-           &tng_data->time_per_frame,
-           sizeof(tng_data->time_per_frame));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        else
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            molecule->bonds = 0;
         }
     }
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
-    {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
     return(TNG_SUCCESS);
 }
 
-
-/** Read an atom mappings block (translating between real atom indexes and how
- *  the atom info is written in this frame set).
+/** Write a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
- * compared to the md5 hash of the read contents to ensure valid data.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_trajectory_mapping_block_read
+static tng_function_status tng_molecules_block_write
                 (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
                  const char hash_mode)
 {
-    int64_t i;
-    int offset = 0;
-    tng_bool same_hash;
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
-
-    tng_particle_mapping_t mapping, mappings;
+    int len = 0, name_len, offset = 0;
+    int64_t i, j, k, l;
+    tng_molecule_t molecule;
+    tng_chain_t chain;
+    tng_residue_t residue;
+    tng_atom_t atom;
+    tng_bond_t bond;
+    tng_gen_block_t block;
 
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
         return(TNG_CRITICAL);
     }
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
+    tng_block_init(&block);
 
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    name_len = (int)strlen("MOLECULES");
 
-    /* Read the whole block into block_contents to be able to write it to disk
-     *  even if it cannot be interpreted. */
-    if(fread(block->block_contents, block->block_contents_size, 1,
-        tng_data->input_file) == 0)
+    block->name = malloc(name_len + 1);
+    if(!block->name)
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                name_len+1, __FILE__, __LINE__);
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    /* FIXME: Does not check if the size of the contents matches the expected
-     * size or if the contents can be read. */
+    strcpy(block->name, "MOLECULES");
+    block->id = TNG_MOLECULES;
 
-    if(hash_mode == TNG_USE_HASH)
+    if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
+        TNG_SUCCESS)
     {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
-        {
-            fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
-                "%s: %d\n",
+        fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
                 __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
-        }
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
 
-    frame_set->n_mapping_blocks++;
-    mappings = realloc(frame_set->mappings,
-                       sizeof(struct tng_particle_mapping) *
-                       frame_set->n_mapping_blocks);
-    if(!mappings)
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
-        free(frame_set->mappings);
-        frame_set->mappings = 0;
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
-    frame_set->mappings = mappings;
-    mapping = &mappings[frame_set->n_mapping_blocks - 1];
 
-
-    memcpy(&mapping->num_first_particle, block->block_contents+offset,
-           sizeof(mapping->num_first_particle));
-    if(tng_data->input_endianness_swap_func_64)
+    memcpy(block->block_contents+offset, &tng_data->n_molecules,
+           sizeof(tng_data->n_molecules));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &mapping->num_first_particle)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(mapping->num_first_particle);
+    offset += sizeof(tng_data->n_molecules);
 
-    memcpy(&mapping->n_particles, block->block_contents+offset,
-           sizeof(mapping->n_particles));
-    if(tng_data->input_endianness_swap_func_64)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &mapping->n_particles)
-            != TNG_SUCCESS)
+        molecule = &tng_data->molecules[i];
+        memcpy(block->block_contents+offset, &molecule->id,
+               sizeof(molecule->id));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
-    }
-    offset += sizeof(mapping->n_particles);
+        offset += sizeof(molecule->id);
 
-    mapping->real_particle_numbers = malloc(mapping->n_particles *
-                                            sizeof(int64_t));
-    if(!mapping->real_particle_numbers)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+/*         fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
+        len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
+        strncpy(block->block_contents + offset, molecule->name, len);
+        offset += len;
 
-    /* If the byte order needs to be swapped the data must be read one value at
-     * a time and swapped */
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        for(i = 0; i < mapping->n_particles; i++)
+        memcpy(block->block_contents+offset, &molecule->quaternary_str,
+               sizeof(molecule->quaternary_str));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            memcpy(&mapping->real_particle_numbers[i],
-                    block->block_contents + offset,
-                    sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                            &mapping->real_particle_numbers[i])
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
+        }
+        offset += sizeof(molecule->quaternary_str);
+
+        if(!tng_data->var_num_atoms_flag)
+        {
+            memcpy(block->block_contents+offset,
+                   &tng_data->molecule_cnt_list[i], sizeof(int64_t));
+            if(tng_data->output_endianness_swap_func_64)
+            {
+                if(tng_data->output_endianness_swap_func_64(tng_data,
+                                            (int64_t *)block->header_contents+offset)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
             offset += sizeof(int64_t);
         }
-    }
-    /* Otherwise the data can be read all at once */
-    else
-    {
-        memcpy(mapping->real_particle_numbers, block->block_contents + offset,
-               mapping->n_particles * sizeof(int64_t));
-    }
 
+        memcpy(block->block_contents+offset, &molecule->n_chains,
+               sizeof(molecule->n_chains));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(molecule->n_chains);
 
-    return(TNG_SUCCESS);
-}
+        memcpy(block->block_contents+offset, &molecule->n_residues,
+               sizeof(molecule->n_residues));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(molecule->n_residues);
 
-/** Write the atom mappings of the current trajectory frame set
- * @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param mapping_block_nr is the index of the mapping block to write.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
- * has occurred or TNG_CRITICAL (2) if a major error has occured.
- */
-static tng_function_status tng_trajectory_mapping_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 int mapping_block_nr,
-                 const char hash_mode)
-{
-    char *temp_name;
-    int i, offset = 0;
-    unsigned int name_len;
-    tng_particle_mapping_t mapping =
-    &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
+        memcpy(block->block_contents+offset, &molecule->n_atoms,
+               sizeof(molecule->n_atoms));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(molecule->n_atoms);
 
-    if(mapping_block_nr >=
-       tng_data->current_trajectory_frame_set.n_mapping_blocks)
-    {
-        fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_FAILURE);
-    }
+        if(molecule->n_chains > 0)
+        {
+            chain = molecule->chains;
+            for(j = 0; j < molecule->n_chains; j++)
+            {
+                tng_chain_data_write(tng_data, block, chain, &offset);
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
+                residue = chain->residues;
+                for(k = 0; k < chain->n_residues; k++)
+                {
+                    tng_residue_data_write(tng_data, block, residue, &offset);
 
-    name_len = (int)strlen("PARTICLE MAPPING");
+                    atom = molecule->atoms + residue->atoms_offset;
+                    for(l = 0; l < residue->n_atoms; l++)
+                    {
+                        tng_atom_data_write(tng_data, block, atom, &offset);
 
-    if(!block->name || strlen(block->name) < name_len)
-    {
-        temp_name = realloc(block->name, name_len + 1);
-        if(!temp_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   name_len+1, __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
-            return(TNG_CRITICAL);
+                        atom++;
+                    }
+                    residue++;
+                }
+                chain++;
+            }
         }
-        block->name = temp_name;
-    }
-    strcpy(block->name, "PARTICLE MAPPING");
-    block->id = TNG_PARTICLE_MAPPING;
-
-    block->block_contents_size = sizeof(int64_t) * (2 + mapping->n_particles);
+        else
+        {
+            if(molecule->n_residues > 0)
+            {
+                residue = molecule->residues;
+                for(k = 0; k < molecule->n_residues; k++)
+                {
+                    tng_residue_data_write(tng_data, block, residue, &offset);
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+                    atom = molecule->atoms + residue->atoms_offset;
+                    for(l = 0; l < residue->n_atoms; l++)
+                    {
+                        tng_atom_data_write(tng_data, block, atom, &offset);
 
-    memcpy(block->block_contents, &mapping->num_first_particle,
-           sizeof(mapping->num_first_particle));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(mapping->num_first_particle);
+                        atom++;
+                    }
+                    residue++;
+                }
+            }
+            else
+            {
+                atom = molecule->atoms;
+                for(l = 0; l < molecule->n_atoms; l++)
+                {
+                    tng_atom_data_write(tng_data, block, atom, &offset);
 
-    memcpy(block->block_contents+offset, &mapping->n_particles,
-           sizeof(mapping->n_particles));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+                    atom++;
+                }
+            }
         }
-    }
-    offset += sizeof(mapping->n_particles);
 
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        for(i = 0; i < mapping->n_particles; i++)
+        memcpy(block->block_contents+offset, &molecule->n_bonds,
+               sizeof(molecule->n_bonds));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
-                sizeof(int64_t));
             if(tng_data->output_endianness_swap_func_64(tng_data,
                                         (int64_t *)block->header_contents+offset)
                 != TNG_SUCCESS)
@@ -3780,1802 +3802,1844 @@ static tng_function_status tng_trajectory_mapping_block_write
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
-            offset += sizeof(int64_t);
         }
-    }
-    else
-    {
-        memcpy(block->block_contents+offset, mapping->real_particle_numbers,
-               mapping->n_particles * sizeof(int64_t));
-    }
+        offset += sizeof(molecule->n_bonds);
+
+        bond = molecule->bonds;
+        for(j = 0; j < molecule->n_bonds; j++)
+        {
+            memcpy(block->block_contents+offset, &bond->from_atom_id,
+                   sizeof(bond->from_atom_id));
+            if(tng_data->output_endianness_swap_func_64)
+            {
+                if(tng_data->output_endianness_swap_func_64(tng_data,
+                                            (int64_t *)block->header_contents+offset)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            offset += sizeof(bond->from_atom_id);
+
+            memcpy(block->block_contents+offset, &bond->to_atom_id,
+                   sizeof(bond->to_atom_id));
+            if(tng_data->output_endianness_swap_func_64)
+            {
+                if(tng_data->output_endianness_swap_func_64(tng_data,
+                                            (int64_t *)block->header_contents+offset)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            offset += sizeof(bond->to_atom_id);
 
+            bond++;
+        }
+    }
 
     if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
     {
         fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
                tng_data->output_file_path, __FILE__, __LINE__);
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
     if(fwrite(block->block_contents, block->block_contents_size, 1,
               tng_data->output_file) != 1)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
+               __FILE__, __LINE__);
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
+    tng_block_destroy(&block);
+
     return(TNG_SUCCESS);
 }
 
-/** Prepare a block for storing particle data
+static tng_function_status tng_frame_set_block_len_calculate
+                (const tng_trajectory_t tng_data,
+                 int64_t *len)
+{
+    *len = sizeof(int64_t) * 8;
+    *len += sizeof(double) * 2;
+
+    if(tng_data->var_num_atoms_flag)
+    {
+        *len += sizeof(int64_t) * tng_data->n_molecules;
+    }
+    return(TNG_SUCCESS);
+}
+
+/** Read a frame set block. Update tng_data->current_trajectory_frame_set
  * @param tng_data is a trajectory data container.
- * @param block_type_flag specifies if this is a trajectory block or a
- * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
+ * @param block is a general block container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
+ * compared to the md5 hash of the read contents to ensure valid data.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_particle_data_block_create
+static tng_function_status tng_frame_set_block_read
                 (tng_trajectory_t tng_data,
-                 const char block_type_flag)
+                 tng_gen_block_t block,
+                 const char hash_mode)
 {
+    int offset = 0;
+    int64_t file_pos, i, prev_n_particles;
+    tng_bool same_hash;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
 
-    tng_particle_data_t data;
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    if(block->block_contents)
     {
-        frame_set->n_particle_data_blocks++;
-        data = realloc(frame_set->tr_particle_data,
-                    sizeof(struct tng_particle_data) *
-                    frame_set->n_particle_data_blocks);
-        if(!data)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                sizeof(struct tng_particle_data) *
-                frame_set->n_particle_data_blocks,
-                __FILE__, __LINE__);
-            free(frame_set->tr_particle_data);
-            frame_set->tr_particle_data = 0;
-            return(TNG_CRITICAL);
-        }
-        frame_set->tr_particle_data = data;
+        free(block->block_contents);
     }
-    else
+
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
     {
-        tng_data->n_particle_data_blocks++;
-        data = realloc(tng_data->non_tr_particle_data,
-                        sizeof(struct tng_particle_data) *
-                        tng_data->n_particle_data_blocks);
-        if(!data)
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    /* Read the whole block into block_contents to be able to write it to
+     * disk even if it cannot be interpreted. */
+    if(fread(block->block_contents, block->block_contents_size, 1,
+             tng_data->input_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    /* FIXME: Does not check if the size of the contents matches the expected
+     * size or if the contents can be read. */
+
+    file_pos = (int64_t)ftello(tng_data->input_file) -
+               (block->block_contents_size + block->header_contents_size);
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_md5_hash_match_verify(block, &same_hash);
+        if(same_hash != TNG_TRUE)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                    sizeof(struct tng_particle_data) *
-                    tng_data->n_particle_data_blocks,
-                    __FILE__, __LINE__);
-            free(tng_data->non_tr_particle_data);
-            tng_data->non_tr_particle_data = 0;
-            return(TNG_CRITICAL);
+            fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %"PRId64" Hashes do not match. "
+                "%s: %d\n",
+                file_pos, __FILE__, __LINE__);
+    /*         return(TNG_FAILURE); */
         }
-        tng_data->non_tr_particle_data = data;
     }
 
-    return(TNG_SUCCESS);
-}
+    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
 
-static tng_function_status tng_compress(tng_trajectory_t tng_data,
-                                        tng_gen_block_t block,
-                                        const int64_t n_frames,
-                                        const int64_t n_particles,
-                                        const char type,
-                                        void *start_pos)
-{
-    int nalgo;
-    int new_len;
-    int *alt_algo = 0;
-    char *dest, *temp;
-    int64_t algo_find_n_frames;
-    unsigned long offset;
-    float f_precision;
-    double d_precision;
+    tng_frame_set_particle_mapping_free(tng_data);
 
-    if(block->id != TNG_TRAJ_POSITIONS &&
-       block->id != TNG_TRAJ_VELOCITIES)
+    if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
     {
-        fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
-               "TNG method. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
+        tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
     }
-    if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
+    /* FIXME: Should check the frame number instead of the file_pos, in case
+     * frame sets are not in order */
+    if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
     {
-        fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
+        tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
     }
 
-    if(n_frames <= 0 || n_particles <= 0)
+    memcpy(&frame_set->first_frame, block->block_contents,
+           sizeof(frame_set->first_frame));
+    if(tng_data->input_endianness_swap_func_64)
     {
-        fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
-               "with the TNG method. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &frame_set->first_frame)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(frame_set->first_frame);
+
+    memcpy(&frame_set->n_frames, block->block_contents + offset,
+           sizeof(frame_set->n_frames));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &frame_set->n_frames)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(frame_set->n_frames);
 
-    f_precision = 1/(float)tng_data->compression_precision;
-    d_precision = 1/tng_data->compression_precision;
-
-    if(block->id == TNG_TRAJ_POSITIONS)
+    if(tng_data->var_num_atoms_flag)
     {
-        /* If there is only one frame in this frame set and there might be more
-         * do not store the algorithm as the compression algorithm, but find
-         * the best one without storing it */
-        if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
-        {
-            nalgo = tng_compress_nalgo();
-            alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
-            if(type == TNG_FLOAT_DATA)
-            {
-                dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
-                                                        (int)n_frames,
-                                                        f_precision,
-                                                        0, alt_algo,
-                                                        &new_len);
-
-            }
-            else
-            {
-                dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
-                                           (int)n_frames,
-                                           d_precision,
-                                           0, alt_algo,
-                                           &new_len);
-            }
-        }
-        else if(!tng_data->compress_algo_pos)
+        prev_n_particles = frame_set->n_particles;
+        frame_set->n_particles = 0;
+        /* If the list of molecule counts has already been created assume that
+         * it is of correct size. */
+        if(!frame_set->molecule_cnt_list)
         {
-            if(n_frames > 10)
-            {
-                algo_find_n_frames = 5;
-            }
-            else
-            {
-                algo_find_n_frames = n_frames;
-            }
-
-            nalgo = tng_compress_nalgo();
-            tng_data->compress_algo_pos=malloc(nalgo *
-                                           sizeof *tng_data->compress_algo_pos);
-            if(type == TNG_FLOAT_DATA)
-            {
-                dest = tng_compress_pos_float_find_algo(start_pos, (int)n_particles,
-                                                        (int)algo_find_n_frames,
-                                                        f_precision,
-                                                        0, tng_data->
-                                                        compress_algo_pos,
-                                                        &new_len);
+                frame_set->molecule_cnt_list =
+                malloc(sizeof(int64_t) * tng_data->n_molecules);
 
-                if(algo_find_n_frames < n_frames)
+                if(!frame_set->molecule_cnt_list)
                 {
-                    dest = tng_compress_pos_float(start_pos, (int)n_particles,
-                                                  (int)n_frames,
-                                                  f_precision,
-                                                  0, tng_data->compress_algo_pos,
-                                                  &new_len);
+                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                           sizeof(int64_t) * tng_data->n_molecules,
+                           __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
                 }
-            }
-            else
+        }
+        for(i = 0; i < tng_data->n_molecules; i++)
+        {
+            memcpy(&frame_set->molecule_cnt_list[i],
+                   block->block_contents + offset,
+                   sizeof(int64_t));
+            if(tng_data->input_endianness_swap_func_64)
             {
-                dest = tng_compress_pos_find_algo(start_pos, (int)n_particles,
-                                           (int)algo_find_n_frames,
-                                           d_precision,
-                                           0, tng_data->
-                                           compress_algo_pos,
-                                           &new_len);
-
-                if(algo_find_n_frames < n_frames)
+                if(tng_data->input_endianness_swap_func_64(tng_data,
+                                              &frame_set->molecule_cnt_list[i])
+                    != TNG_SUCCESS)
                 {
-                    dest = tng_compress_pos(start_pos, (int)n_particles,
-                                            (int)n_frames,
-                                            d_precision, 0,
-                                            tng_data->compress_algo_pos,
-                                            &new_len);
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
                 }
             }
+            offset += sizeof(int64_t);
+            frame_set->n_particles += tng_data->molecules[i].n_atoms *
+                                      frame_set->molecule_cnt_list[i];
         }
-        else
+        if(prev_n_particles && frame_set->n_particles != prev_n_particles)
         {
-            if(type == TNG_FLOAT_DATA)
-            {
-                dest = tng_compress_pos_float(start_pos, (int)n_particles,
-                                              (int)n_frames,
-                                              f_precision, 0,
-                                              tng_data->compress_algo_pos, &new_len);
-            }
-            else
-            {
-                dest = tng_compress_pos(start_pos, (int)n_particles,
-                                        (int)n_frames,
-                                        d_precision, 0,
-                                        tng_data->compress_algo_pos,
-                                        &new_len);
-            }
+            /* FIXME: Particle dependent data memory management */
         }
     }
-    else if(block->id == TNG_TRAJ_VELOCITIES)
+
+    memcpy(&frame_set->next_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->next_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
     {
-        /* If there is only one frame in this frame set and there might be more
-         * do not store the algorithm as the compression algorithm, but find
-         * the best one without storing it */
-        if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                           &frame_set->next_frame_set_file_pos)
+            != TNG_SUCCESS)
         {
-            nalgo = tng_compress_nalgo();
-            alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
-            if(type == TNG_FLOAT_DATA)
-            {
-                dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
-                                                        (int)n_frames,
-                                                        f_precision,
-                                                        0, alt_algo,
-                                                        &new_len);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-            }
-            else
-            {
-                dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
-                                                  (int)n_frames,
-                                                  d_precision,
-                                                  0, alt_algo,
-                                                  &new_len);
-            }
+    memcpy(&frame_set->prev_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->prev_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                           &frame_set->prev_frame_set_file_pos)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        else if(!tng_data->compress_algo_vel)
+    }
+    offset += sizeof(frame_set->prev_frame_set_file_pos);
+
+    memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                             &frame_set->medium_stride_next_frame_set_file_pos)
+            != TNG_SUCCESS)
         {
-            if(n_frames > 10)
-            {
-                algo_find_n_frames = 5;
-            }
-            else
-            {
-                algo_find_n_frames = n_frames;
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
 
-            nalgo = tng_compress_nalgo();
-            tng_data->compress_algo_vel=malloc(nalgo *
-                                           sizeof *tng_data->compress_algo_vel);
+    memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                             &frame_set->medium_stride_prev_frame_set_file_pos)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
 
-            if(type == TNG_FLOAT_DATA)
-            {
-                dest = tng_compress_vel_float_find_algo(start_pos, (int)n_particles,
-                                                        (int)algo_find_n_frames,
-                                                        f_precision,
-                                                        0, tng_data->
-                                                        compress_algo_vel,
-                                                        &new_len);
-                if(algo_find_n_frames < n_frames)
-                {
-                    dest = tng_compress_vel_float(start_pos, (int)n_particles,
-                                                  (int)n_frames,
-                                                  f_precision,
-                                                  0, tng_data->compress_algo_vel,
-                                                  &new_len);
-                }
-            }
-            else
-            {
-                dest = tng_compress_vel_find_algo(start_pos, (int)n_particles,
-                                                  (int)algo_find_n_frames,
-                                                  d_precision,
-                                                  0, tng_data->
-                                                  compress_algo_vel,
-                                                  &new_len);
-                if(algo_find_n_frames < n_frames)
-                {
-                    dest = tng_compress_vel(start_pos, (int)n_particles,
-                                            (int)n_frames,
-                                            d_precision,
-                                            0, tng_data->compress_algo_vel,
-                                            &new_len);
-                }
-            }
+    memcpy(&frame_set->long_stride_next_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->long_stride_next_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                               &frame_set->long_stride_next_frame_set_file_pos)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        else
+    }
+    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
+
+    memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
+           block->block_contents + offset,
+           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                               &frame_set->long_stride_prev_frame_set_file_pos)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
+
+    if(block->block_version >= 3)
+    {
+        memcpy(&frame_set->first_frame_time,
+            block->block_contents + offset,
+            sizeof(frame_set->first_frame_time));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            if(type == TNG_FLOAT_DATA)
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                (int64_t *)&frame_set->first_frame_time)
+                != TNG_SUCCESS)
             {
-                dest = tng_compress_vel_float(start_pos, (int)n_particles,
-                                              (int)n_frames,
-                                              f_precision,
-                                              0, tng_data->
-                                              compress_algo_vel,
-                                              &new_len);
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
-            else
+        }
+        offset += sizeof(frame_set->first_frame_time);
+
+        memcpy(&tng_data->time_per_frame,
+            block->block_contents + offset,
+            sizeof(tng_data->time_per_frame));
+        if(tng_data->input_endianness_swap_func_64)
+        {
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                (int64_t *)&tng_data->time_per_frame)
+                != TNG_SUCCESS)
             {
-                dest = tng_compress_vel(start_pos, (int)n_particles,
-                                        (int)n_frames,
-                                        d_precision,
-                                        0, tng_data->
-                                        compress_algo_vel,
-                                        &new_len);
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
         }
     }
     else
     {
-        fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
-        return(TNG_FAILURE);
+        frame_set->first_frame_time = -1;
+        tng_data->time_per_frame = -1;
     }
 
-    offset = (unsigned long)((char *)start_pos - block->block_contents);
+    /* If the output file and the input files are the same the number of
+     * frames in the file are the same number as has just been read.
+     * This is updated here to later on see if there have been new frames
+     * added and thereby the frame set needs to be rewritten. */
+    if(tng_data->output_file == tng_data->input_file)
+    {
+        frame_set->n_written_frames = frame_set->n_frames;
+    }
 
-    if(alt_algo)
+    return(TNG_SUCCESS);
+}
+
+/** Write tng_data->current_trajectory_frame_set to file
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_frame_set_block_write
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const char hash_mode)
+{
+    char *temp_name;
+    int64_t i;
+    int offset = 0;
+    unsigned int name_len;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        free(alt_algo);
+        return(TNG_CRITICAL);
     }
 
-    block->block_contents_size = new_len + offset;
+    name_len = (int)strlen("TRAJECTORY FRAME SET");
 
-    temp = realloc(block->block_contents, block->block_contents_size);
-    if(!temp)
+    if(!block->name || strlen(block->name) < name_len)
+    {
+        temp_name = realloc(block->name, name_len + 1);
+        if(!temp_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
+                   name_len+1, __FILE__, __LINE__);
+            free(block->name);
+            block->name = 0;
+            return(TNG_CRITICAL);
+        }
+        block->name = temp_name;
+    }
+    strcpy(block->name, "TRAJECTORY FRAME SET");
+    block->id = TNG_TRAJECTORY_FRAME_SET;
+
+    if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
+        TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(block->block_contents)
     {
         free(block->block_contents);
-        block->block_contents = 0;
+    }
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
+    {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
-    block->block_contents = temp;
-    if(dest)
+
+    memcpy(block->block_contents, &frame_set->first_frame,
+           sizeof(frame_set->first_frame));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        memcpy(temp + offset, dest, new_len);
-        free(dest);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
-    else
+    offset += sizeof(frame_set->first_frame);
+
+    memcpy(block->block_contents+offset, &frame_set->n_frames,
+           sizeof(frame_set->n_frames));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(frame_set->n_frames);
 
-    return(TNG_SUCCESS);
-}
-
-static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
-                                          tng_gen_block_t block,
-                                          const char type,
-                                          void *start_pos,
-                                          const unsigned long uncompressed_len)
-{
-    char *temp;
-    double *d_dest = 0;
-    float *f_dest = 0;
-    unsigned long offset;
-    int result;
-    (void)tng_data;
-
-    TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
-
-    if(block->id != TNG_TRAJ_POSITIONS &&
-       block->id != TNG_TRAJ_VELOCITIES)
+    if(tng_data->var_num_atoms_flag)
     {
-        fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
-               "TNG method.\n");
-        return(TNG_FAILURE);
+        for(i = 0; i < tng_data->n_molecules; i++)
+        {
+            memcpy(block->block_contents+offset,
+                   &frame_set->molecule_cnt_list[i],
+                   sizeof(int64_t));
+            if(tng_data->output_endianness_swap_func_64)
+            {
+                if(tng_data->output_endianness_swap_func_64(tng_data,
+                                            (int64_t *)block->header_contents+offset)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            offset += sizeof(int64_t);
+        }
     }
-    if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
+
+
+    memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
+           sizeof(frame_set->next_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        fprintf(stderr, "TNG library: Data type not supported.\n");
-        return(TNG_FAILURE);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-    if(type == TNG_FLOAT_DATA)
+    memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
+           sizeof(frame_set->prev_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        f_dest = malloc(uncompressed_len);
-        if(!f_dest)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                uncompressed_len, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        result = tng_compress_uncompress_float(start_pos, f_dest);
     }
-    else
+    offset += sizeof(frame_set->prev_frame_set_file_pos);
+
+    memcpy(block->block_contents+offset,
+           &frame_set->medium_stride_next_frame_set_file_pos,
+           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        d_dest = malloc(uncompressed_len);
-        if(!d_dest)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                uncompressed_len, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        result = tng_compress_uncompress(start_pos, d_dest);
     }
+    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
 
-    if(result == 1)
+    memcpy(block->block_contents+offset,
+           &frame_set->medium_stride_prev_frame_set_file_pos,
+           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
-        return(TNG_FAILURE);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
 
-    offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
-
-    block->block_contents_size = (int64_t)(uncompressed_len + offset);
-
-    temp = realloc(block->block_contents, uncompressed_len + offset);
-    if(!temp)
+    memcpy(block->block_contents+offset,
+           &frame_set->long_stride_next_frame_set_file_pos,
+           sizeof(frame_set->long_stride_next_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        free(block->block_contents);
-        block->block_contents = 0;
-        if(d_dest)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            free(d_dest);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        if(f_dest)
+    }
+    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
+
+    memcpy(block->block_contents+offset,
+           &frame_set->long_stride_prev_frame_set_file_pos,
+           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            free(f_dest);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
     }
+    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
 
-    if(type == TNG_FLOAT_DATA)
+    memcpy(block->block_contents+offset,
+           &frame_set->first_frame_time,
+           sizeof(frame_set->first_frame_time));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        memcpy(temp + offset, f_dest, uncompressed_len);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
-    else
+    offset += sizeof(frame_set->first_frame_time);
+
+    memcpy(block->block_contents+offset,
+           &tng_data->time_per_frame,
+           sizeof(tng_data->time_per_frame));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        memcpy(temp + offset, d_dest, uncompressed_len);
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
 
-    block->block_contents = temp;
-
-    if(d_dest)
+    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
     {
-        free(d_dest);
+        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+               tng_data->output_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    if(f_dest)
+
+    if(fwrite(block->block_contents, block->block_contents_size, 1,
+              tng_data->output_file) != 1)
     {
-        free(f_dest);
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
+
     return(TNG_SUCCESS);
 }
 
-#ifdef USE_ZLIB
-static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
-                                             tng_gen_block_t block,
-                                             void *start_pos, const int len)
+static tng_function_status tng_trajectory_mapping_block_len_calculate
+                (const tng_trajectory_t tng_data,
+                 const int64_t n_particles,
+                 int64_t *len)
 {
-    Bytef *dest;
-    char *temp;
-    unsigned long max_len, stat, offset;
     (void)tng_data;
+    *len = sizeof(int64_t) * (2 + n_particles);
 
-    max_len = compressBound(len);
-    dest = malloc(max_len);
-    if(!dest)
+    return(TNG_SUCCESS);
+}
+
+/** Read an atom mappings block (translating between real atom indexes and how
+ *  the atom info is written in this frame set).
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
+ * compared to the md5 hash of the read contents to ensure valid data.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_trajectory_mapping_block_read
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const char hash_mode)
+{
+    int64_t i;
+    int offset = 0;
+    tng_bool same_hash;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    tng_particle_mapping_t mapping, mappings;
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%ld bytes). %s: %d\n",
-               max_len, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    stat = compress(dest, &max_len, start_pos, len);
-    if(stat != (unsigned long)Z_OK)
+    if(block->block_contents)
     {
-        free(dest);
-        if(stat == (unsigned long)Z_MEM_ERROR)
-        {
-            fprintf(stderr, "TNG library: Not enough memory. ");
-        }
-        else if(stat == (unsigned long)Z_BUF_ERROR)
-        {
-            fprintf(stderr, "TNG library: Destination buffer too small. ");
-        }
-        fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
+        free(block->block_contents);
     }
 
-    offset = (char *)start_pos - block->block_contents;
-
-    block->block_contents_size = max_len + offset;
-
-    temp = realloc(block->block_contents, block->block_contents_size);
-    if(!temp)
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
     {
-        free(block->block_contents);
-        free(dest);
-        block->block_contents = 0;
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    block->block_contents = temp;
-
-    memcpy(temp + offset, dest, max_len);
-
-    free(dest);
-
-    return(TNG_SUCCESS);
-}
-
-static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               void *start_pos,
-                                               unsigned long uncompressed_len)
-{
-    Bytef *dest;
-    char *temp;
-    unsigned long stat;
-    int offset;
-    (void)tng_data;
-
-    offset = (char *)start_pos - (char *)block->block_contents;
-
-    dest = malloc(uncompressed_len);
-    if(!dest)
+    /* Read the whole block into block_contents to be able to write it to disk
+     *  even if it cannot be interpreted. */
+    if(fread(block->block_contents, block->block_contents_size, 1,
+        tng_data->input_file) == 0)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
-               uncompressed_len, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
-                      block->block_contents_size - offset);
+    /* FIXME: Does not check if the size of the contents matches the expected
+     * size or if the contents can be read. */
 
-    if(stat != Z_OK)
+    if(hash_mode == TNG_USE_HASH)
     {
-        free(dest);
-        if(stat == (unsigned long)Z_MEM_ERROR)
-        {
-            fprintf(stderr, "TNG library: Not enough memory. ");
-        }
-        else if(stat == (unsigned long)Z_BUF_ERROR)
-        {
-            fprintf(stderr, "TNG library: Destination buffer too small. ");
-        }
-        else if(stat == (unsigned long)Z_DATA_ERROR)
+        tng_md5_hash_match_verify(block, &same_hash);
+        if(same_hash != TNG_TRUE)
         {
-            fprintf(stderr, "TNG library: Data corrupt. ");
+            fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
+                "%s: %d\n",
+                __FILE__, __LINE__);
+    /*         return(TNG_FAILURE); */
         }
-        fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
-               __LINE__);
-        return(TNG_FAILURE);
     }
 
-
-    block->block_contents_size = uncompressed_len + offset;
-
-    temp = realloc(block->block_contents, uncompressed_len + offset);
-    if(!temp)
+    frame_set->n_mapping_blocks++;
+    mappings = realloc(frame_set->mappings,
+                       sizeof(struct tng_particle_mapping) *
+                       frame_set->n_mapping_blocks);
+    if(!mappings)
     {
-        free(block->block_contents);
-        block->block_contents = 0;
-        free(dest);
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
+        free(frame_set->mappings);
+        frame_set->mappings = 0;
         return(TNG_CRITICAL);
     }
+    frame_set->mappings = mappings;
+    mapping = &mappings[frame_set->n_mapping_blocks - 1];
 
-    memcpy(temp + offset, dest, uncompressed_len);
-
-    block->block_contents = temp;
-
-    free(dest);
-    return(TNG_SUCCESS);
-}
-#endif
 
-/** Allocate memory for storing particle data.
- * The allocated block will be refered to by data->values.
- * @param tng_data is a trajectory data container.
- * @param data is the data struct, which will contain the allocated memory in
- * data->values.
- * @param n_frames is the number of frames of data to store.
- * @param n_particles is the number of particles with data.
- * @param n_values_per_frame is the number of data values per particle and
- * frame.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_allocate_particle_data_mem
-                (tng_trajectory_t tng_data,
-                 tng_particle_data_t data,
-                 int64_t n_frames,
-                 int64_t stride_length,
-                 const int64_t n_particles,
-                 const int64_t n_values_per_frame)
-{
-    void ***values;
-    int64_t i, j, k, size, frame_alloc;
-    (void)tng_data;
+    memcpy(&mapping->num_first_particle, block->block_contents+offset,
+           sizeof(mapping->num_first_particle));
+    if(tng_data->input_endianness_swap_func_64)
+    {
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &mapping->num_first_particle)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(mapping->num_first_particle);
 
-    if(n_particles == 0 || n_values_per_frame == 0)
+    memcpy(&mapping->n_particles, block->block_contents+offset,
+           sizeof(mapping->n_particles));
+    if(tng_data->input_endianness_swap_func_64)
     {
-        return(TNG_FAILURE);
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   &mapping->n_particles)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(mapping->n_particles);
 
-    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    mapping->real_particle_numbers = malloc(mapping->n_particles *
+                                            sizeof(int64_t));
+    if(!mapping->real_particle_numbers)
     {
-        for(i = data->n_frames; i--;)
-        {
-            for(j = n_particles; j--;)
-            {
-                for(k = data->n_values_per_frame; k--;)
-                {
-                    if(data->strings[i][j][k])
-                    {
-                        free(data->strings[i][j][k]);
-                    }
-                }
-                free(data->strings[i][j]);
-            }
-            free(data->strings[i]);
-        }
-        free(data->strings);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    data->n_frames = n_frames;
-    n_frames = tng_max_i64(1, n_frames);
-    data->stride_length = tng_max_i64(1, stride_length);
-    data->n_values_per_frame = n_values_per_frame;
-    frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
-    if(data->datatype == TNG_CHAR_DATA)
+    /* If the byte order needs to be swapped the data must be read one value at
+     * a time and swapped */
+    if(tng_data->input_endianness_swap_func_64)
     {
-        data->strings = malloc(sizeof(char ***) * frame_alloc);
-        for(i = frame_alloc; i-- ;)
+        for(i = 0; i < mapping->n_particles; i++)
         {
-            data->strings[i] = malloc(sizeof(char **) *
-                                    n_particles);
-            if(!data->strings[i])
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                    sizeof(union data_values *) * n_particles,
-                    __FILE__, __LINE__);
-                return(TNG_CRITICAL);
-            }
-            for(j = n_particles; j--;)
+            memcpy(&mapping->real_particle_numbers[i],
+                    block->block_contents + offset,
+                    sizeof(int64_t));
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                            &mapping->real_particle_numbers[i])
+                != TNG_SUCCESS)
             {
-                data->strings[i][j] = malloc(sizeof(char *) *
-                                            n_values_per_frame);
-                if(!data->strings[i][j])
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                        sizeof(union data_values) * n_values_per_frame,
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                for(k = n_values_per_frame; k--;)
-                {
-                    data->strings[i][j][k] = 0;
-                }
             }
+            offset += sizeof(int64_t);
         }
     }
+    /* Otherwise the data can be read all at once */
     else
     {
-        switch(data->datatype)
-        {
-        case TNG_INT_DATA:
-            size = sizeof(int64_t);
-            break;
-        case TNG_FLOAT_DATA:
-            size = sizeof(float);
-            break;
-        case TNG_DOUBLE_DATA:
-        default:
-            size = sizeof(double);
-        }
-
-        values = realloc(data->values,
-                         size * frame_alloc *
-                         n_particles * n_values_per_frame);
-        if(!values)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                   size * frame_alloc *
-                   n_particles * n_values_per_frame,
-                   __FILE__, __LINE__);
-            free(data->values);
-            data->values = 0;
-            return(TNG_CRITICAL);
-        }
-        data->values = values;
+        memcpy(mapping->real_particle_numbers, block->block_contents + offset,
+               mapping->n_particles * sizeof(int64_t));
     }
+
+
     return(TNG_SUCCESS);
 }
 
-static tng_function_status tng_particle_data_find
+/** Write the atom mappings of the current trajectory frame set
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param mapping_block_nr is the index of the mapping block to write.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
+ * has occurred or TNG_CRITICAL (2) if a major error has occured.
+ */
+static tng_function_status tng_trajectory_mapping_block_write
                 (tng_trajectory_t tng_data,
-                 const int64_t id,
-                 tng_particle_data_t *data)
+                 tng_gen_block_t block,
+                 int mapping_block_nr,
+                 const char hash_mode)
 {
-    int64_t block_index, i;
-    tng_trajectory_frame_set_t frame_set = &tng_data->
-                                           current_trajectory_frame_set;
-    char block_type_flag;
+    char *temp_name;
+    int i, offset = 0;
+    unsigned int name_len;
+    tng_particle_mapping_t mapping =
+    &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
 
-    if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
-       tng_data->current_trajectory_frame_set_output_file_pos > 0)
-    {
-        block_type_flag = TNG_TRAJECTORY_BLOCK;
-    }
-    else
+    if(mapping_block_nr >=
+       tng_data->current_trajectory_frame_set.n_mapping_blocks)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    block_index = -1;
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        for(i = frame_set->n_particle_data_blocks; i-- ;)
-        {
-            *data = &frame_set->tr_particle_data[i];
-            if((*data)->block_id == id)
-            {
-                block_index = i;
-                break;
-            }
-        }
+        return(TNG_CRITICAL);
     }
-    else
+
+    name_len = (int)strlen("PARTICLE MAPPING");
+
+    if(!block->name || strlen(block->name) < name_len)
     {
-        for(i = tng_data->n_particle_data_blocks; i-- ;)
+        temp_name = realloc(block->name, name_len + 1);
+        if(!temp_name)
         {
-            *data = &tng_data->non_tr_particle_data[i];
-            if((*data)->block_id == id)
-            {
-                block_index = i;
-                break;
-            }
+            fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
+                   name_len+1, __FILE__, __LINE__);
+            free(block->name);
+            block->name = 0;
+            return(TNG_CRITICAL);
         }
+        block->name = temp_name;
     }
-    if(block_index == -1)
+    strcpy(block->name, "PARTICLE MAPPING");
+    block->id = TNG_PARTICLE_MAPPING;
+
+    if(tng_trajectory_mapping_block_len_calculate(tng_data,
+                                                  mapping->n_particles,
+                                                  &block->block_contents_size) !=
+        TNG_SUCCESS)
     {
-        return(TNG_FAILURE);
+        fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    return(TNG_SUCCESS);
-}
-
-static tng_function_status tng_data_find
-                (tng_trajectory_t tng_data,
-                 const int64_t id,
-                 tng_non_particle_data_t *data)
-{
-    int64_t block_index, i;
-    tng_trajectory_frame_set_t frame_set = &tng_data->
-                                           current_trajectory_frame_set;
-    char block_type_flag;
 
-    if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
-       tng_data->current_trajectory_frame_set_output_file_pos > 0)
+    if(block->block_contents)
     {
-        block_type_flag = TNG_TRAJECTORY_BLOCK;
+        free(block->block_contents);
     }
-    else
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    block_index = -1;
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    memcpy(block->block_contents, &mapping->num_first_particle,
+           sizeof(mapping->num_first_particle));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        for(i = frame_set->n_data_blocks; i-- ;)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            *data = &frame_set->tr_data[i];
-            if((*data)->block_id == id)
-            {
-                block_index = i;
-                break;
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        if(block_index == -1)
+    }
+    offset += sizeof(mapping->num_first_particle);
+
+    memcpy(block->block_contents+offset, &mapping->n_particles,
+           sizeof(mapping->n_particles));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+                                      (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            for(i = tng_data->n_data_blocks; i-- ;)
-            {
-                *data = &tng_data->non_tr_data[i];
-                if((*data)->block_id == id)
-                {
-                    block_index = i;
-                    break;
-                }
-            }
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
-    else
+    offset += sizeof(mapping->n_particles);
+
+    if(tng_data->output_endianness_swap_func_64)
     {
-        for(i = tng_data->n_data_blocks; i-- ;)
+        for(i = 0; i < mapping->n_particles; i++)
         {
-            *data = &tng_data->non_tr_data[i];
-            if((*data)->block_id == id)
+            memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
+                sizeof(int64_t));
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                                        (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
             {
-                block_index = i;
-                break;
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
+            offset += sizeof(int64_t);
         }
     }
-    if(block_index == -1)
+    else
+    {
+        memcpy(block->block_contents+offset, mapping->real_particle_numbers,
+               mapping->n_particles * sizeof(int64_t));
+    }
+
+
+    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+               tng_data->output_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(fwrite(block->block_contents, block->block_contents_size, 1,
+              tng_data->output_file) != 1)
     {
-        return(TNG_FAILURE);
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
+
     return(TNG_SUCCESS);
 }
 
-/** Read the values of a particle data block
+/** Prepare a block for storing particle data
  * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param offset is the reading offset to point at the place where the actual
- * values are stored, starting from the beginning of the block_contents. The
- * offset is changed during the reading.
- * @param datatype is the type of data of the data block (char, int, float or
- * double).
- * @param num_first_particle is the number of the first particle in the data
- * block. This should be the same as in the corresponding particle mapping
- * block.
- * @param n_particles is the number of particles in the data block. This should
- * be the same as in the corresponding particle mapping block.
- * @param first_frame_with_data is the frame number of the first frame with data
- * in this data block.
- * @param stride_length is the number of frames between each data entry.
- * @param n_frames is the number of frames in this data block.
- * @param n_values is the number of values per particle and frame stored in this
- * data block.
- * @param codec_id is the ID of the codec to compress the data.
- * @param multiplier is the multiplication factor applied to each data value
- * before compression. This factor is applied since some compression algorithms
- * work only on integers.
+ * @param block_type_flag specifies if this is a trajectory block or a
+ * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_particle_data_read
+static tng_function_status tng_particle_data_block_create
                 (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 int *offset,
-                 const char datatype,
-                 const int64_t num_first_particle,
-                 const int64_t n_particles,
-                 const int64_t first_frame_with_data,
-                 const int64_t stride_length,
-                 int64_t n_frames,
-                 const int64_t n_values,
-                 const int64_t codec_id,
-                 const double multiplier)
+                 const char block_type_flag)
 {
-    int64_t i, j, k, tot_n_particles, n_frames_div;
-    int size, len;
-    unsigned long data_size;
-    char ***first_dim_values, **second_dim_values;
-    tng_particle_data_t data;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
-    char block_type_flag;
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    switch(datatype)
-    {
-    case TNG_CHAR_DATA:
-        size = 1;
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int64_t);
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-    }
+    tng_particle_data_t data;
 
-    /* If the block does not exist, create it */
-    if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
-        {
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
-        }
-        else
-        {
-            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
-        }
-
-        if(tng_particle_data_block_create(tng_data, block_type_flag) !=
-           TNG_SUCCESS)
+        frame_set->n_particle_data_blocks++;
+        data = realloc(frame_set->tr_particle_data,
+                    sizeof(struct tng_particle_data) *
+                    frame_set->n_particle_data_blocks);
+        if(!data)
         {
-            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
-                   __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+                sizeof(struct tng_particle_data) *
+                frame_set->n_particle_data_blocks,
+                __FILE__, __LINE__);
+            free(frame_set->tr_particle_data);
+            frame_set->tr_particle_data = 0;
             return(TNG_CRITICAL);
         }
-        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
-        {
-            data = &frame_set->tr_particle_data[frame_set->
-                                                n_particle_data_blocks - 1];
-        }
-        else
-        {
-            data = &tng_data->non_tr_particle_data[tng_data->
-                                                   n_particle_data_blocks - 1];
-        }
-        data->block_id = block->id;
-
-        data->block_name = malloc(strlen(block->name) + 1);
-        if(!data->block_name)
+        frame_set->tr_particle_data = data;
+    }
+    else
+    {
+        tng_data->n_particle_data_blocks++;
+        data = realloc(tng_data->non_tr_particle_data,
+                        sizeof(struct tng_particle_data) *
+                        tng_data->n_particle_data_blocks);
+        if(!data)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block->name)+1, __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+                    sizeof(struct tng_particle_data) *
+                    tng_data->n_particle_data_blocks,
+                    __FILE__, __LINE__);
+            free(tng_data->non_tr_particle_data);
+            tng_data->non_tr_particle_data = 0;
             return(TNG_CRITICAL);
         }
-        strcpy(data->block_name, block->name);
+        tng_data->non_tr_particle_data = data;
+    }
 
-        data->datatype = datatype;
+    return(TNG_SUCCESS);
+}
 
-        data->values = 0;
-        /* FIXME: Memory leak from strings. */
-        data->strings = 0;
-        data->n_frames = 0;
-        data->codec_id = codec_id;
-        data->compression_multiplier = multiplier;
-        data->last_retrieved_frame = -1;
+static tng_function_status tng_compress(tng_trajectory_t tng_data,
+                                        tng_gen_block_t block,
+                                        const int64_t n_frames,
+                                        const int64_t n_particles,
+                                        const char type,
+                                        void *start_pos)
+{
+    int nalgo;
+    int new_len;
+    int *alt_algo = 0;
+    char *dest, *temp, *temp_data_contents;
+    int64_t algo_find_n_frames, compressed_len, offset;
+    float f_precision;
+    double d_precision;
+
+    if(block->id != TNG_TRAJ_POSITIONS &&
+       block->id != TNG_TRAJ_VELOCITIES)
+    {
+        fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
+               "TNG method. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
+    {
+        fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
-       tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
-       tng_data->var_num_atoms_flag)
+    if(n_frames <= 0 || n_particles <= 0)
     {
-        tot_n_particles = frame_set->n_particles;
+        fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
+               "with the TNG method. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
-    else
+
+    f_precision = 1/(float)tng_data->compression_precision;
+    d_precision = 1/tng_data->compression_precision;
+
+    compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
+    temp_data_contents = malloc(compressed_len);
+    if(!temp_data_contents)
     {
-        tot_n_particles = tng_data->n_particles;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                compressed_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+    memcpy(temp_data_contents, (char *)start_pos, compressed_len);
 
-    if(codec_id != TNG_UNCOMPRESSED)
+    if(block->id == TNG_TRAJ_POSITIONS)
     {
-        data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
-        switch(codec_id)
+        /* If there is only one frame in this frame set and there might be more
+         * do not store the algorithm as the compression algorithm, but find
+         * the best one without storing it */
+        if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
         {
-        case TNG_XTC_COMPRESSION:
-            fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
-            break;
-        case TNG_TNG_COMPRESSION:
-/*            fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
-            if(tng_uncompress(tng_data, block, datatype,
-                              block->block_contents + *offset,
-                              data_size) != TNG_SUCCESS)
+            nalgo = tng_compress_nalgo();
+            alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
+            if(type == TNG_FLOAT_DATA)
+            {
+                dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
+                                                        (int)n_frames,
+                                                        f_precision,
+                                                        0, alt_algo,
+                                                        &new_len);
+
+            }
+            else
+            {
+                dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
+                                           (int)n_frames,
+                                           d_precision,
+                                           0, alt_algo,
+                                           &new_len);
+            }
+        }
+        else if(!tng_data->compress_algo_pos)
+        {
+            if(n_frames > 10)
+            {
+                algo_find_n_frames = 5;
+            }
+            else
+            {
+                algo_find_n_frames = n_frames;
+            }
+
+            nalgo = tng_compress_nalgo();
+            tng_data->compress_algo_pos=malloc(nalgo *
+                                           sizeof *tng_data->compress_algo_pos);
+            if(type == TNG_FLOAT_DATA)
+            {
+                dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
+                                                        (int)algo_find_n_frames,
+                                                        f_precision,
+                                                        0, tng_data->
+                                                        compress_algo_pos,
+                                                        &new_len);
+
+                if(algo_find_n_frames < n_frames)
+                {
+                    dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
+                                                  (int)n_frames,
+                                                  f_precision,
+                                                  0, tng_data->compress_algo_pos,
+                                                  &new_len);
+                }
+            }
+            else
+            {
+                dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
+                                           (int)algo_find_n_frames,
+                                           d_precision,
+                                           0, tng_data->
+                                           compress_algo_pos,
+                                           &new_len);
+
+                if(algo_find_n_frames < n_frames)
+                {
+                    dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
+                                            (int)n_frames,
+                                            d_precision, 0,
+                                            tng_data->compress_algo_pos,
+                                            &new_len);
+                }
+            }
+        }
+        else
+        {
+            if(type == TNG_FLOAT_DATA)
             {
-                fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
-                       __FILE__, __LINE__);
-                return(TNG_CRITICAL);
+                dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
+                                              (int)n_frames,
+                                              f_precision, 0,
+                                              tng_data->compress_algo_pos, &new_len);
             }
-/*            fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
-            break;
-#ifdef USE_ZLIB
-        case TNG_GZIP_COMPRESSION:
-/*            fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
-            if(tng_gzip_uncompress(tng_data, block,
-                                   block->block_contents + *offset,
-                                   data_size) != TNG_SUCCESS)
+            else
             {
-                fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
-                    __LINE__);
-                return(TNG_CRITICAL);
+                dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
+                                        (int)n_frames,
+                                        d_precision, 0,
+                                        tng_data->compress_algo_pos,
+                                        &new_len);
             }
-/*            fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
-            break;
-#endif
         }
     }
-    /* Allocate memory */
-    if(!data->values || data->n_frames != n_frames ||
-       data->n_values_per_frame != n_values)
+    else if(block->id == TNG_TRAJ_VELOCITIES)
     {
-        if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
-                                          stride_length,
-                                          tot_n_particles, n_values) !=
-           TNG_SUCCESS)
+        /* If there is only one frame in this frame set and there might be more
+         * do not store the algorithm as the compression algorithm, but find
+         * the best one without storing it */
+        if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
-
-    data->first_frame_with_data = first_frame_with_data;
+            nalgo = tng_compress_nalgo();
+            alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_vel);
+            if(type == TNG_FLOAT_DATA)
+            {
+                dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
+                                                        (int)n_frames,
+                                                        f_precision,
+                                                        0, alt_algo,
+                                                        &new_len);
 
-    if(datatype == TNG_CHAR_DATA)
-    {
-        for(i = 0; i < n_frames_div; i++)
-        {
-            first_dim_values = data->strings[i];
-            for(j = num_first_particle; j < num_first_particle + n_particles;
-                j++)
+            }
+            else
             {
-                second_dim_values = first_dim_values[j];
-                for(k = 0; k < n_values; k++)
-                {
-                    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-                              TNG_MAX_STR_LEN);
-                    if(second_dim_values[k])
-                    {
-                        free(second_dim_values[k]);
-                    }
-                    second_dim_values[k] = malloc(len);
-                    if(!second_dim_values[k])
-                    {
-                        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                            len, __FILE__, __LINE__);
-                        return(TNG_CRITICAL);
-                    }
-                    strncpy(second_dim_values[k],
-                            block->block_contents+*offset, len);
-                    *offset += len;
-                }
+                dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
+                                                  (int)n_frames,
+                                                  d_precision,
+                                                  0, alt_algo,
+                                                  &new_len);
             }
         }
-    }
-    else
-    {
-        memcpy((char *)data->values + n_frames_div * size * n_values *
-               num_first_particle,
-               block->block_contents + *offset,
-               block->block_contents_size - *offset);
-        switch(datatype)
+        else if(!tng_data->compress_algo_vel)
         {
-        case TNG_FLOAT_DATA:
-            if(tng_data->input_endianness_swap_func_32)
+            if(n_frames > 10)
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+                algo_find_n_frames = 5;
+            }
+            else
+            {
+                algo_find_n_frames = n_frames;
+            }
+
+            nalgo = tng_compress_nalgo();
+            tng_data->compress_algo_vel=malloc(nalgo *
+                                           sizeof *tng_data->compress_algo_vel);
+
+            if(type == TNG_FLOAT_DATA)
+            {
+                dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
+                                                        (int)algo_find_n_frames,
+                                                        f_precision,
+                                                        0, tng_data->
+                                                        compress_algo_vel,
+                                                        &new_len);
+                if(algo_find_n_frames < n_frames)
                 {
-                    if(tng_data->input_endianness_swap_func_32(tng_data,
-                        (int32_t *)((char *)data->values + i))
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
+                    dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
+                                                  (int)n_frames,
+                                                  f_precision,
+                                                  0, tng_data->compress_algo_vel,
+                                                  &new_len);
                 }
             }
-            break;
-        case TNG_INT_DATA:
-        case TNG_DOUBLE_DATA:
-            if(tng_data->input_endianness_swap_func_64)
+            else
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+                dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
+                                                  (int)algo_find_n_frames,
+                                                  d_precision,
+                                                  0, tng_data->
+                                                  compress_algo_vel,
+                                                  &new_len);
+                if(algo_find_n_frames < n_frames)
                 {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                        (int64_t *)((char *)data->values + i))
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
+                    dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
+                                            (int)n_frames,
+                                            d_precision,
+                                            0, tng_data->compress_algo_vel,
+                                            &new_len);
                 }
             }
-            break;
-        case TNG_CHAR_DATA:
-            break;
         }
+        else
+        {
+            if(type == TNG_FLOAT_DATA)
+            {
+                dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
+                                              (int)n_frames,
+                                              f_precision,
+                                              0, tng_data->
+                                              compress_algo_vel,
+                                              &new_len);
+            }
+            else
+            {
+                dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
+                                        (int)n_frames,
+                                        d_precision,
+                                        0, tng_data->
+                                        compress_algo_vel,
+                                        &new_len);
+            }
+        }
+    }
+    else
+    {
+        fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
+        free(temp_data_contents);
+        return(TNG_FAILURE);
+    }
+
+    offset = (unsigned long)((char *)start_pos - block->block_contents);
+
+    if(alt_algo)
+    {
+        free(alt_algo);
     }
+
+    block->block_contents_size = new_len + offset;
+
+    free(temp_data_contents);
+
+    temp = realloc(block->block_contents, block->block_contents_size);
+    if(!temp)
+    {
+        free(block->block_contents);
+        block->block_contents = 0;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+    block->block_contents = temp;
+    if(dest)
+    {
+        memcpy(temp + offset, dest, new_len);
+        free(dest);
+    }
+    else
+    {
+        fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
     return(TNG_SUCCESS);
 }
 
-/** Write a particle data block
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param block_index is the index number of the data block in the frame set.
- * @param mapping is the particle mapping that is relevant for the data block.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_particle_data_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 const int64_t block_index,
-                 const tng_particle_mapping_t mapping,
-                 const char hash_mode)
+static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
+                                          tng_gen_block_t block,
+                                          const char type,
+                                          void *start_pos,
+                                          const int64_t uncompressed_len)
 {
-    int64_t n_particles, num_first_particle, n_frames, stride_length;
-    int64_t frame_step, data_start_pos;
-    int64_t i, j, k;
-    int size;
-    size_t len, offset = 0;
-    char dependency, temp, *temp_name;
-    double multiplier;
-    char ***first_dim_values, **second_dim_values;
-    tng_trajectory_frame_set_t frame_set;
-    tng_function_status stat;
-
-    tng_particle_data_t data;
-    char block_type_flag;
+    char *temp, *temp_data_contents;
+    int64_t compressed_len;
+    double *d_dest = 0;
+    float *f_dest = 0;
+    int64_t offset;
+    int result;
+    (void)tng_data;
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
 
-    /* If we have already started writing frame sets it is too late to write
-     * non-trajectory data blocks */
-    if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
+    if(block->id != TNG_TRAJ_POSITIONS &&
+       block->id != TNG_TRAJ_VELOCITIES)
     {
-        block_type_flag = TNG_TRAJECTORY_BLOCK;
+        fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
+               "TNG method.\n");
+        return(TNG_FAILURE);
     }
-    else
+    if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        fprintf(stderr, "TNG library: Data type not supported.\n");
+        return(TNG_FAILURE);
     }
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
+    temp_data_contents = malloc(compressed_len);
+    if(!temp_data_contents)
     {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                uncompressed_len, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
-    {
-        data = &frame_set->tr_particle_data[block_index];
+    memcpy(temp_data_contents, (char *)start_pos, compressed_len);
 
-        /* If this data block has not had any data added in this frame set
-         * do not write it. */
-        if(data->first_frame_with_data < frame_set->first_frame)
+    if(type == TNG_FLOAT_DATA)
+    {
+        f_dest = malloc(uncompressed_len);
+        if(!f_dest)
         {
-            return(TNG_SUCCESS);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                uncompressed_len, __FILE__, __LINE__);
+            free(temp_data_contents);
+            return(TNG_CRITICAL);
         }
-
-        stride_length = tng_max_i64(1, data->stride_length);
+        result = tng_compress_uncompress_float(temp_data_contents, f_dest);
     }
     else
     {
-        data = &tng_data->non_tr_particle_data[block_index];
-        stride_length = 1;
-    }
-
-    switch(data->datatype)
-    {
-    case TNG_CHAR_DATA:
-        size = 1;
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int64_t);
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-    }
-
-    len = strlen(data->block_name) + 1;
-
-    if(!block->name || strlen(block->name) < len)
-    {
-        temp_name = realloc(block->name, len);
-        if(!temp_name)
+        d_dest = malloc(uncompressed_len);
+        if(!d_dest)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                uncompressed_len, __FILE__, __LINE__);
+            free(temp_data_contents);
             return(TNG_CRITICAL);
         }
-        block->name = temp_name;
+        result = tng_compress_uncompress(temp_data_contents, d_dest);
     }
-    strncpy(block->name, data->block_name, len);
-    block->id = data->block_id;
-
-    /* If writing frame independent data data->n_frames is 0, but n_frames
-       is used for the loop writing the data (and reserving memory) and needs
-       to be at least 1 */
-    n_frames = tng_max_i64(1, data->n_frames);
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    if(result == 1)
     {
-        /* If the frame set is finished before writing the full number of frames
-           make sure the data block is not longer than the frame set. */
-        n_frames = tng_min_i64(n_frames, frame_set->n_frames);
-
-        n_frames -= (data->first_frame_with_data - frame_set->first_frame);
+        fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
+        free(temp_data_contents);
+        return(TNG_FAILURE);
     }
 
-    frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
-                 n_frames / stride_length;
+    offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
 
-    /* TNG compression will use compression precision to get integers from
-     * floating point data. The compression multiplier stores that information
-     * to be able to return the precision of the compressed data. */
-    if(data->codec_id == TNG_TNG_COMPRESSION)
-    {
-        data->compression_multiplier = tng_data->compression_precision;
-    }
-    /* Uncompressed data blocks do not use compression multipliers at all.
-     * GZip compression does not need it either. */
-    else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
-    {
-        data->compression_multiplier = 1.0;
-    }
+    block->block_contents_size = (int64_t)(uncompressed_len + offset);
 
-    if(mapping && mapping->n_particles != 0)
-    {
-        n_particles = mapping->n_particles;
-        num_first_particle = mapping->num_first_particle;
-    }
-    else
+    temp = realloc(block->block_contents, uncompressed_len + offset);
+    if(!temp)
     {
-        num_first_particle = 0;
-        if(tng_data->var_num_atoms_flag)
+        free(block->block_contents);
+        block->block_contents = 0;
+        if(d_dest)
         {
-            n_particles = frame_set->n_particles;
+            free(d_dest);
         }
-        else
+        if(f_dest)
         {
-            n_particles = tng_data->n_particles;
+            free(f_dest);
         }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        free(temp_data_contents);
+        return(TNG_CRITICAL);
     }
 
-    block->block_contents_size = sizeof(char) * 2 +
-                                 sizeof(data->n_values_per_frame) +
-                                 sizeof(data->codec_id) +
-                                 sizeof(num_first_particle) +
-                                 sizeof(n_particles);
-
-    if(stride_length > 1)
+    if(type == TNG_FLOAT_DATA)
     {
-        block->block_contents_size += sizeof(data->first_frame_with_data) +
-                                      sizeof(data->stride_length);
+        memcpy(temp + offset, f_dest, uncompressed_len);
     }
-
-    if(data->codec_id != TNG_UNCOMPRESSED)
+    else
     {
-        block->block_contents_size += sizeof(data->compression_multiplier);
+        memcpy(temp + offset, d_dest, uncompressed_len);
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+    block->block_contents = temp;
+
+    free(temp_data_contents);
+    if(d_dest)
     {
-        dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
+        free(d_dest);
     }
-    else
+    if(f_dest)
     {
-        dependency = TNG_PARTICLE_DEPENDENT;
+        free(f_dest);
     }
-    if(dependency & TNG_FRAME_DEPENDENT)
+    return(TNG_SUCCESS);
+}
+
+#ifdef USE_ZLIB
+static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
+                                             tng_gen_block_t block,
+                                             void *start_pos, const int len)
+{
+    Bytef *dest;
+    char *temp;
+    unsigned long max_len, stat, offset;
+    (void)tng_data;
+
+    max_len = compressBound(len);
+    dest = malloc(max_len);
+    if(!dest)
     {
-        block->block_contents_size += sizeof(char);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+               max_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    data_start_pos = block->block_contents_size;
-
-    if(data->datatype == TNG_CHAR_DATA)
+    stat = compress(dest, &max_len, start_pos, len);
+    if(stat != (unsigned long)Z_OK)
     {
-        for(i = n_frames; i--;)
+        free(dest);
+        if(stat == (unsigned long)Z_MEM_ERROR)
         {
-            first_dim_values = data->strings[i];
-            for(j = num_first_particle; j < num_first_particle + n_particles;
-                j++)
-            {
-                second_dim_values = first_dim_values[j];
-                for(k = data->n_values_per_frame; k--;)
-                {
-                    block->block_contents_size +=
-                    strlen(second_dim_values[k]) + 1;
-                }
-            }
+            fprintf(stderr, "TNG library: Not enough memory. ");
         }
-    }
-    else
-    {
-        block->block_contents_size += size * frame_step *
-                                      n_particles * data->n_values_per_frame;
+        else if(stat == (unsigned long)Z_BUF_ERROR)
+        {
+            fprintf(stderr, "TNG library: Destination buffer too small. ");
+        }
+        fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    if(block->block_contents)
+    offset = (char *)start_pos - block->block_contents;
+
+    block->block_contents_size = max_len + offset;
+
+    temp = realloc(block->block_contents, block->block_contents_size);
+    if(!temp)
     {
         free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
-    {
+        free(dest);
+        block->block_contents = 0;
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                block->block_contents_size, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
+    block->block_contents = temp;
 
-    memcpy(block->block_contents, &data->datatype, sizeof(char));
-    offset += sizeof(char);
-
-    memcpy(block->block_contents+offset, &dependency, sizeof(char));
-    offset += sizeof(char);
+    memcpy(temp + offset, dest, max_len);
 
-    if(dependency & TNG_FRAME_DEPENDENT)
-    {
-        if(stride_length > 1)
-        {
-            temp = 1;
-        }
-        else
-        {
-            temp = 0;
-        }
-        memcpy(block->block_contents+offset, &temp, sizeof(char));
-        offset += sizeof(char);
-    }
+    free(dest);
 
-    memcpy(block->block_contents+offset, &data->n_values_per_frame,
-           sizeof(data->n_values_per_frame));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(data->n_values_per_frame);
+    return(TNG_SUCCESS);
+}
 
-    memcpy(block->block_contents+offset, &data->codec_id,
-           sizeof(data->codec_id));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(data->codec_id);
+static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
+                                               tng_gen_block_t block,
+                                               void *start_pos,
+                                               unsigned long uncompressed_len)
+{
+    Bytef *dest;
+    char *temp;
+    unsigned long stat;
+    int offset;
+    (void)tng_data;
 
-    if(data->codec_id != TNG_UNCOMPRESSED)
+    offset = (char *)start_pos - (char *)block->block_contents;
+
+    dest = malloc(uncompressed_len);
+    if(!dest)
     {
-        memcpy(block->block_contents+offset, &data->compression_multiplier,
-               sizeof(data->compression_multiplier));
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-               (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        offset += sizeof(data->compression_multiplier);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
+               uncompressed_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    if(data->n_frames > 0 && stride_length > 1)
+    stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
+                      block->block_contents_size - offset);
+
+    if(stat != Z_OK)
     {
-        /* FIXME: first_frame_with_data is not reliably set */
-        if(data->first_frame_with_data == 0)
+        free(dest);
+        if(stat == (unsigned long)Z_MEM_ERROR)
         {
-            data->first_frame_with_data = frame_set->first_frame;
+            fprintf(stderr, "TNG library: Not enough memory. ");
         }
-        memcpy(block->block_contents+offset, &data->first_frame_with_data,
-               sizeof(data->first_frame_with_data));
-        if(tng_data->output_endianness_swap_func_64)
+        else if(stat == (unsigned long)Z_BUF_ERROR)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-               (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Destination buffer too small. ");
         }
-        offset += sizeof(data->first_frame_with_data);
-
-        memcpy(block->block_contents+offset, &stride_length,
-               sizeof(stride_length));
-        if(tng_data->output_endianness_swap_func_64)
+        else if(stat == (unsigned long)Z_DATA_ERROR)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-               (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Data corrupt. ");
         }
-        offset += sizeof(stride_length);
+        fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
+               __LINE__);
+        return(TNG_FAILURE);
     }
 
 
-    memcpy(block->block_contents+offset, &num_first_particle,
-           sizeof(num_first_particle));
-    if(tng_data->output_endianness_swap_func_64)
+    block->block_contents_size = uncompressed_len + offset;
+
+    temp = realloc(block->block_contents, uncompressed_len + offset);
+    if(!temp)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        free(block->block_contents);
+        block->block_contents = 0;
+        free(dest);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(num_first_particle);
 
-    memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
-    if(tng_data->output_endianness_swap_func_64)
+    memcpy(temp + offset, dest, uncompressed_len);
+
+    block->block_contents = temp;
+
+    free(dest);
+    return(TNG_SUCCESS);
+}
+#endif
+
+/** Allocate memory for storing particle data.
+ * The allocated block will be refered to by data->values.
+ * @param tng_data is a trajectory data container.
+ * @param data is the data struct, which will contain the allocated memory in
+ * data->values.
+ * @param n_frames is the number of frames of data to store.
+ * @param n_particles is the number of particles with data.
+ * @param n_values_per_frame is the number of data values per particle and
+ * frame.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_allocate_particle_data_mem
+                (tng_trajectory_t tng_data,
+                 tng_particle_data_t data,
+                 int64_t n_frames,
+                 int64_t stride_length,
+                 const int64_t n_particles,
+                 const int64_t n_values_per_frame)
+{
+    void ***values;
+    int64_t i, j, k, size, frame_alloc;
+    (void)tng_data;
+
+    if(n_particles == 0 || n_values_per_frame == 0)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_FAILURE);
     }
-    offset += sizeof(n_particles);
 
-    if(data->datatype == TNG_CHAR_DATA)
+    if(data->strings && data->datatype == TNG_CHAR_DATA)
     {
-        if(data->strings)
+        for(i = 0; i < data->n_frames; i++)
         {
-            for(i = 0; i < frame_step; i++)
+            for(j = 0; j < n_particles; j++)
             {
-                first_dim_values = data->strings[i];
-                for(j = num_first_particle; j < num_first_particle + n_particles;
-                    j++)
+                for(k = 0; k < data->n_values_per_frame; k++)
                 {
-                    second_dim_values = first_dim_values[j];
-                    for(k = 0; k < data->n_values_per_frame; k++)
+                    if(data->strings[i][j][k])
                     {
-                        len = (unsigned int)strlen(second_dim_values[k]) + 1;
-                        strncpy(block->block_contents+offset,
-                                second_dim_values[k], len);
-                        offset += len;
+                        free(data->strings[i][j][k]);
                     }
                 }
+                free(data->strings[i][j]);
             }
+            free(data->strings[i]);
         }
+        free(data->strings);
     }
-    else if(data->values)
-    {
-        memcpy(block->block_contents + offset, data->values,
-               block->block_contents_size - offset);
+    data->n_frames = n_frames;
+    n_frames = tng_max_i64(1, n_frames);
+    data->stride_length = tng_max_i64(1, stride_length);
+    data->n_values_per_frame = n_values_per_frame;
+    frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
-        switch(data->datatype)
+    if(data->datatype == TNG_CHAR_DATA)
+    {
+        data->strings = malloc(sizeof(char ***) * frame_alloc);
+        for(i = 0; i < frame_alloc; i++)
         {
-        case TNG_FLOAT_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
-            {
-                if(tng_data->input_endianness_swap_func_32)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        if(tng_data->input_endianness_swap_func_32(tng_data,
-                           (int32_t *)(block->block_contents + i))
-                           != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_32)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        *(float *)(block->block_contents + i) *= (float)multiplier;
-                        if(tng_data->input_endianness_swap_func_32 &&
-                        tng_data->input_endianness_swap_func_32(tng_data,
-                        (int32_t *)(block->block_contents + i))
-                        != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            break;
-        case TNG_INT_DATA:
-            if(tng_data->input_endianness_swap_func_64)
-            {
-                for(i = offset; i < block->block_contents_size; i+=size)
-                {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                       (int64_t *)(block->block_contents + i))
-                       != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
-                }
-            }
-            break;
-        case TNG_DOUBLE_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
+            data->strings[i] = malloc(sizeof(char **) *
+                                    n_particles);
+            if(!data->strings[i])
             {
-                if(tng_data->input_endianness_swap_func_64)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        if(tng_data->input_endianness_swap_func_64(tng_data,
-                           (int64_t *)(block->block_contents + i))
-                           != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                    sizeof(union data_values *) * n_particles,
+                    __FILE__, __LINE__);
+                return(TNG_CRITICAL);
             }
-            else
+            for(j = 0; j < n_particles; j++)
             {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_64)
+                data->strings[i][j] = malloc(sizeof(char *) *
+                                            n_values_per_frame);
+                if(!data->strings[i][j])
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        *(double *)(block->block_contents + i) *= multiplier;
-                        if(tng_data->input_endianness_swap_func_64 &&
-                        tng_data->input_endianness_swap_func_64(tng_data,
-                        (int64_t *)(block->block_contents + i))
-                        != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
+                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                        sizeof(union data_values) * n_values_per_frame,
+                        __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
+                }
+                for(k = 0; k < n_values_per_frame; k++)
+                {
+                    data->strings[i][j][k] = 0;
                 }
             }
+        }
+    }
+    else
+    {
+        switch(data->datatype)
+        {
+        case TNG_INT_DATA:
+            size = sizeof(int64_t);
             break;
-        case TNG_CHAR_DATA:
+        case TNG_FLOAT_DATA:
+            size = sizeof(float);
             break;
+        case TNG_DOUBLE_DATA:
+        default:
+            size = sizeof(double);
+        }
+
+        values = realloc(data->values,
+                         size * frame_alloc *
+                         n_particles * n_values_per_frame);
+        if(!values)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                   size * frame_alloc *
+                   n_particles * n_values_per_frame,
+                   __FILE__, __LINE__);
+            free(data->values);
+            data->values = 0;
+            return(TNG_CRITICAL);
         }
+        data->values = values;
+    }
+    return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_particle_data_find
+                (tng_trajectory_t tng_data,
+                 const int64_t id,
+                 tng_particle_data_t *data)
+{
+    int64_t block_index, i;
+    tng_trajectory_frame_set_t frame_set = &tng_data->
+                                           current_trajectory_frame_set;
+    char block_type_flag;
+
+    if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
+       tng_data->current_trajectory_frame_set_output_file_pos > 0)
+    {
+        block_type_flag = TNG_TRAJECTORY_BLOCK;
     }
     else
     {
-        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
+        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
     }
 
-    frame_set->n_written_frames += frame_set->n_unwritten_frames;
-    frame_set->n_unwritten_frames = 0;
-
-    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
+    block_index = -1;
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        switch(data->codec_id)
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
-        case TNG_XTC_COMPRESSION:
-            fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
-            data->codec_id = TNG_UNCOMPRESSED;
-            break;
-        case TNG_TNG_COMPRESSION:
-            stat = tng_compress(tng_data, block, frame_step,
-                                n_particles, data->datatype,
-                                block->block_contents + data_start_pos);
-            if(stat != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
-                    __FILE__, __LINE__);
-                if(stat == TNG_CRITICAL)
-                {
-                    return(TNG_CRITICAL);
-                }
-                /* Set the data again, but with no compression (to write only
-                 * the relevant data) */
-                data->codec_id = TNG_UNCOMPRESSED;
-                stat = tng_particle_data_block_write(tng_data, block,
-                                                     block_index, mapping,
-                                                     hash_mode);
-                return(stat);
-            }
-            break;
-#ifdef USE_ZLIB
-        case TNG_GZIP_COMPRESSION:
-    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
-            stat = tng_gzip_compress(tng_data, block,
-                                     block->block_contents + data_start_pos,
-                                     block->block_contents_size - data_start_pos);
-            if(stat != TNG_SUCCESS)
+            *data = &frame_set->tr_particle_data[i];
+            if((*data)->block_id == id)
             {
-                fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
-                    __LINE__);
-                if(stat == TNG_CRITICAL)
-                {
-                    return(TNG_CRITICAL);
-                }
-                /* Set the data again, but with no compression (to write only
-                 * the relevant data) */
-                data->codec_id = TNG_UNCOMPRESSED;
-                stat = tng_particle_data_block_write(tng_data, block,
-                                                     block_index, mapping,
-                                                     hash_mode);
-                return(stat);
+                block_index = i;
+                break;
             }
-    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
-            break;
-#endif
         }
     }
-
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    else
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
+        {
+            *data = &tng_data->non_tr_particle_data[i];
+            if((*data)->block_id == id)
+            {
+                block_index = i;
+                break;
+            }
+        }
     }
-
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-        tng_data->output_file) != 1)
+    if(block_index == -1)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
-                __LINE__);
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
-
     return(TNG_SUCCESS);
 }
 
-/* TEST: */
-/** Create a non-particle data block
- * @param tng_data is a trajectory data container.
- * @param block_type_flag specifies if this is a trajectory block or a
- * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_data_block_create
+static tng_function_status tng_data_find
                 (tng_trajectory_t tng_data,
-                 const char block_type_flag)
+                 const int64_t id,
+                 tng_non_particle_data_t *data)
 {
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
+    int64_t block_index, i;
+    tng_trajectory_frame_set_t frame_set = &tng_data->
+                                           current_trajectory_frame_set;
+    char block_type_flag;
 
-    tng_non_particle_data_t data;
+    if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
+       tng_data->current_trajectory_frame_set_output_file_pos > 0)
+    {
+        block_type_flag = TNG_TRAJECTORY_BLOCK;
+    }
+    else
+    {
+        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+    }
 
+    block_index = -1;
     if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        frame_set->n_data_blocks++;
-        data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
-                       frame_set->n_data_blocks);
-        if(!data)
+        for(i = 0; i < frame_set->n_data_blocks; i++)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
-                __FILE__, __LINE__);
-            free(frame_set->tr_data);
-            frame_set->tr_data = 0;
-            return(TNG_CRITICAL);
+            *data = &frame_set->tr_data[i];
+            if((*data)->block_id == id)
+            {
+                block_index = i;
+                break;
+            }
+        }
+        if(block_index == -1)
+        {
+            for(i = 0; i < tng_data->n_data_blocks; i++)
+            {
+                *data = &tng_data->non_tr_data[i];
+                if((*data)->block_id == id)
+                {
+                    block_index = i;
+                    break;
+                }
+            }
         }
-        frame_set->tr_data = data;
     }
     else
     {
-        tng_data->n_data_blocks++;
-        data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
-                        tng_data->n_data_blocks);
-        if(!data)
+        for(i = 0; i < tng_data->n_data_blocks; i++)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
-                sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
-                __FILE__, __LINE__);
-            free(tng_data->non_tr_data);
-            tng_data->non_tr_data = 0;
-            return(TNG_CRITICAL);
+            *data = &tng_data->non_tr_data[i];
+            if((*data)->block_id == id)
+            {
+                block_index = i;
+                break;
+            }
         }
-        tng_data->non_tr_data = data;
     }
-
+    if(block_index == -1)
+    {
+        return(TNG_FAILURE);
+    }
     return(TNG_SUCCESS);
 }
 
-/* TEST: */
-/** Allocate memory for storing non-particle data.
- * The allocated block will be refered to by data->values.
- * @param tng_data is a trajectory data container.
- * @param data is the data struct, which will contain the allocated memory in
- * data->values.
- * @param n_frames is the number of frames of data to store.
- * @param n_values_per_frame is the number of data values per frame.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_allocate_data_mem
-                (tng_trajectory_t tng_data,
-                 tng_non_particle_data_t data,
-                 int64_t n_frames,
-                 int64_t stride_length,
-                 const int64_t n_values_per_frame)
-{
-    void **values;
-    int64_t i, j, size, frame_alloc;
-    (void)tng_data;
+static tng_function_status tng_data_block_len_calculate
+                (const tng_trajectory_t tng_data,
+                 const tng_particle_data_t data,
+                 const tng_bool is_particle_data,
+                 const int64_t n_frames,
+                 const int64_t frame_step,
+                 const int64_t stride_length,
+                 const int64_t num_first_particle,
+                 const int64_t n_particles,
+                 const char dependency,
+                 int64_t *data_start_pos,
+                 int64_t *len)
+{
+    int size;
+    int64_t i, j, k;
+    char ***first_dim_values, **second_dim_values;
+    (void)tng_data;
+
+    if(data == 0)
+    {
+        return(TNG_SUCCESS);
+    }
+
+    switch(data->datatype)
+    {
+    case TNG_CHAR_DATA:
+        size = 1;
+        break;
+    case TNG_INT_DATA:
+        size = sizeof(int64_t);
+        break;
+    case TNG_FLOAT_DATA:
+        size = sizeof(float);
+        break;
+    case TNG_DOUBLE_DATA:
+    default:
+        size = sizeof(double);
+    }
+
+    *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
+           sizeof(data->codec_id);
+    if(is_particle_data)
+    {
+        *len += sizeof(num_first_particle) + sizeof(n_particles);
+    }
+
+    if(stride_length > 1)
+    {
+        *len += sizeof(data->first_frame_with_data) +
+                sizeof(data->stride_length);
+    }
+
+    if(data->codec_id != TNG_UNCOMPRESSED)
+    {
+        *len += sizeof(data->compression_multiplier);
+    }
 
-    if(n_values_per_frame == 0)
+    if(dependency & TNG_FRAME_DEPENDENT)
     {
-        return(TNG_FAILURE);
+        *len += sizeof(char);
     }
 
-    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    *data_start_pos = *len;
+
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        for(i = data->n_frames; i--;)
+        if(is_particle_data)
         {
-            for(j = data->n_values_per_frame; j--;)
+            for(i = 0; i < n_frames; i++)
             {
-                if(data->strings[i][j])
+                first_dim_values = data->strings[i];
+                for(j = num_first_particle; j < num_first_particle + n_particles;
+                    j++)
                 {
-                    free(data->strings[i][j]);
-                    data->strings[i][j] = 0;
+                    second_dim_values = first_dim_values[j];
+                    for(k = 0; k < data->n_values_per_frame; k++)
+                    {
+                        *len += strlen(second_dim_values[k]) + 1;
+                    }
                 }
             }
-            free(data->strings[i]);
-            data->strings[i] = 0;
         }
-        free(data->strings);
-    }
-    data->n_frames = n_frames;
-    data->stride_length = tng_max_i64(1, stride_length);
-    n_frames = tng_max_i64(1, n_frames);
-    data->n_values_per_frame = n_values_per_frame;
-    frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
-
-    if(data->datatype == TNG_CHAR_DATA)
-    {
-        data->strings = malloc(sizeof(char **) * frame_alloc);
-        for(i = frame_alloc; i-- ;)
+        else
         {
-            data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
-            if(!data->strings[i])
+            for(i = 0; i < n_frames; i++)
             {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                       n_values_per_frame,
-                       __FILE__, __LINE__);
-                return(TNG_CRITICAL);
-            }
-            for(j = n_values_per_frame; j--;)
-            {
-                data->strings[i][j] = 0;
+                second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
+                for(j = 0; j < data->n_values_per_frame; j++)
+                {
+                    *len += strlen(second_dim_values[j]) + 1;
+                }
             }
         }
     }
     else
     {
-        switch(data->datatype)
-        {
-        case TNG_INT_DATA:
-            size = sizeof(int64_t);
-            break;
-        case TNG_FLOAT_DATA:
-            size = sizeof(float);
-            break;
-        case TNG_DOUBLE_DATA:
-        default:
-            size = sizeof(double);
-        }
-
-        values = realloc(data->values,
-                         size * frame_alloc *
-                         n_values_per_frame);
-        if(!values)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                   size * frame_alloc *
-                   n_values_per_frame,
-                   __FILE__, __LINE__);
-            free(data->values);
-            data->values = 0;
-            return(TNG_CRITICAL);
-        }
-        data->values = values;
+        *len += size * frame_step * n_particles * data->n_values_per_frame;
     }
 
     return(TNG_SUCCESS);
 }
 
-/** Read the values of a non-particle data block
+/** Read the values of a particle data block
  * @param tng_data is a trajectory data container.
  * @param block is the block to store the data (should already contain
  * the block headers and the block contents).
@@ -5584,11 +5648,17 @@ static tng_function_status tng_allocate_data_mem
  * offset is changed during the reading.
  * @param datatype is the type of data of the data block (char, int, float or
  * double).
+ * @param num_first_particle is the number of the first particle in the data
+ * block. This should be the same as in the corresponding particle mapping
+ * block.
+ * @param n_particles is the number of particles in the data block. This should
+ * be the same as in the corresponding particle mapping block.
  * @param first_frame_with_data is the frame number of the first frame with data
  * in this data block.
  * @param stride_length is the number of frames between each data entry.
  * @param n_frames is the number of frames in this data block.
- * @param n_values is the number of values per frame stored in this data block.
+ * @param n_values is the number of values per particle and frame stored in this
+ * data block.
  * @param codec_id is the ID of the codec to compress the data.
  * @param multiplier is the multiplication factor applied to each data value
  * before compression. This factor is applied since some compression algorithms
@@ -5596,30 +5666,40 @@ static tng_function_status tng_allocate_data_mem
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_data_read(tng_trajectory_t tng_data,
-                                         tng_gen_block_t block,
-                                         int *offset,
-                                         const char datatype,
-                                         const int64_t first_frame_with_data,
-                                         const int64_t stride_length,
-                                         int64_t n_frames,
-                                         const int64_t n_values,
-                                         const int64_t codec_id,
-                                         const double multiplier)
+static tng_function_status tng_particle_data_read
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 int *offset,
+                 const char datatype,
+                 const int64_t num_first_particle,
+                 const int64_t n_particles,
+                 const int64_t first_frame_with_data,
+                 const int64_t stride_length,
+                 int64_t n_frames,
+                 const int64_t n_values,
+                 const int64_t codec_id,
+                 const double multiplier)
 {
-    int64_t i, j, n_frames_div;
+    int64_t i, j, k, tot_n_particles, n_frames_div;
     int size, len;
-#ifdef USE_ZLIB
-    unsigned long data_size;
-#endif
-    tng_non_particle_data_t data;
+    int64_t data_size;
+    char ***first_dim_values, **second_dim_values;
+    tng_particle_data_t data;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
     char block_type_flag;
 
     TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
 
-/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
+    /* This must be caught early to avoid creating a data block if not necessary. */
+#ifndef USE_ZLIB
+    if(codec_id == TNG_GZIP_COMPRESSION)
+    {
+        fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
+                __LINE__);
+        return(TNG_FAILURE);
+    }
+#endif
 
     switch(datatype)
     {
@@ -5638,7 +5718,7 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
     }
 
     /* If the block does not exist, create it */
-    if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
     {
         if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
         {
@@ -5649,8 +5729,8 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
             block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
         }
 
-        if(tng_data_block_create(tng_data, block_type_flag) !=
-            TNG_SUCCESS)
+        if(tng_particle_data_block_create(tng_data, block_type_flag) !=
+           TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
                    __FILE__, __LINE__);
@@ -5658,11 +5738,13 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
         }
         if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+            data = &frame_set->tr_particle_data[frame_set->
+                                                n_particle_data_blocks - 1];
         }
         else
         {
-            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
+            data = &tng_data->non_tr_particle_data[tng_data->
+                                                   n_particle_data_blocks - 1];
         }
         data->block_id = block->id;
 
@@ -5686,16 +5768,42 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
         data->last_retrieved_frame = -1;
     }
 
+    if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
+       tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
+       tng_data->var_num_atoms_flag)
+    {
+        tot_n_particles = frame_set->n_particles;
+    }
+    else
+    {
+        tot_n_particles = tng_data->n_particles;
+    }
+
     n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
     if(codec_id != TNG_UNCOMPRESSED)
     {
+        data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
         switch(codec_id)
         {
+        case TNG_XTC_COMPRESSION:
+            fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
+            break;
+        case TNG_TNG_COMPRESSION:
+/*            fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
+            if(tng_uncompress(tng_data, block, datatype,
+                              block->block_contents + *offset,
+                              data_size) != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(TNG_CRITICAL);
+            }
+/*            fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
+            break;
 #ifdef USE_ZLIB
         case TNG_GZIP_COMPRESSION:
-            data_size = n_frames_div * size * n_values;
-    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+/*            fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
             if(tng_gzip_uncompress(tng_data, block,
                                    block->block_contents + *offset,
                                    data_size) != TNG_SUCCESS)
@@ -5704,21 +5812,21 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
                     __LINE__);
                 return(TNG_CRITICAL);
             }
-    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
+/*            fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
             break;
 #endif
         }
     }
-
     /* Allocate memory */
     if(!data->values || data->n_frames != n_frames ||
        data->n_values_per_frame != n_values)
     {
-        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
-                                 n_values) !=
+        if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
+                                          stride_length,
+                                          tot_n_particles, n_values) !=
            TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
                    __FILE__, __LINE__);
             return(TNG_CRITICAL);
         }
@@ -5730,30 +5838,38 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
     {
         for(i = 0; i < n_frames_div; i++)
         {
-            for(j = 0; j < n_values; j++)
+            first_dim_values = data->strings[i];
+            for(j = num_first_particle; j < num_first_particle + n_particles;
+                j++)
             {
-                len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-                              TNG_MAX_STR_LEN);
-                if(data->strings[i][j])
-                {
-                    free(data->strings[i][j]);
-                }
-                data->strings[i][j] = malloc(len);
-                if(!data->strings[i][j])
+                second_dim_values = first_dim_values[j];
+                for(k = 0; k < n_values; k++)
                 {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                           len, __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
+                    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+                              TNG_MAX_STR_LEN);
+                    if(second_dim_values[k])
+                    {
+                        free(second_dim_values[k]);
+                    }
+                    second_dim_values[k] = malloc(len);
+                    if(!second_dim_values[k])
+                    {
+                        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                            len, __FILE__, __LINE__);
+                        return(TNG_CRITICAL);
+                    }
+                    strncpy(second_dim_values[k],
+                            block->block_contents+*offset, len);
+                    *offset += len;
                 }
-                strncpy(data->strings[i][j], block->block_contents+*offset,
-                        len);
-                *offset += len;
             }
         }
     }
     else
     {
-        memcpy(data->values, block->block_contents + *offset,
+        memcpy((char *)data->values + n_frames_div * size * n_values *
+               num_first_particle,
+               block->block_contents + *offset,
                block->block_contents_size - *offset);
         switch(datatype)
         {
@@ -5795,37 +5911,40 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
     return(TNG_SUCCESS);
 }
 
-/** Write a non-particle data block
+/** Write a particle data block
  * @param tng_data is a trajectory data container.
  * @param block is the block to store the data (should already contain
  * the block headers and the block contents).
  * @param block_index is the index number of the data block in the frame set.
+ * @param mapping is the particle mapping that is relevant for the data block.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
  * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
-                                                tng_gen_block_t block,
-                                                const int64_t block_index,
-                                                const char hash_mode)
+static tng_function_status tng_particle_data_block_write
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const int64_t block_index,
+                 const tng_particle_mapping_t mapping,
+                 const char hash_mode)
 {
-    int64_t n_frames, stride_length, frame_step;
-    int64_t i, j;
-    int offset = 0, size;
-    unsigned int len;
-#ifdef USE_ZLIB
-    int data_start_pos;
-    tng_function_status stat;
-#endif
-    char temp, dependency, *temp_name;
+    int64_t n_particles, num_first_particle, n_frames, stride_length;
+    int64_t frame_step, data_start_pos;
+    int64_t i, j, k;
+    int size;
+    size_t len, offset = 0;
+    char dependency, temp, *temp_name;
     double multiplier;
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
+    char ***first_dim_values, **second_dim_values;
+    tng_trajectory_frame_set_t frame_set;
+    tng_function_status stat;
 
-    tng_non_particle_data_t data;
+    tng_particle_data_t data;
     char block_type_flag;
 
+    frame_set = &tng_data->current_trajectory_frame_set;
+
     /* If we have already started writing frame sets it is too late to write
      * non-trajectory data blocks */
     if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
@@ -5844,7 +5963,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
 
     if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        data = &frame_set->tr_data[block_index];
+        data = &frame_set->tr_particle_data[block_index];
 
         /* If this data block has not had any data added in this frame set
          * do not write it. */
@@ -5857,7 +5976,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
     }
     else
     {
-        data = &tng_data->non_tr_data[block_index];
+        data = &tng_data->non_tr_particle_data[block_index];
         stride_length = 1;
     }
 
@@ -5877,14 +5996,14 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         size = sizeof(double);
     }
 
-    len = (unsigned int)strlen(data->block_name) + 1;
+    len = strlen(data->block_name) + 1;
 
     if(!block->name || strlen(block->name) < len)
     {
         temp_name = realloc(block->name, len);
         if(!temp_name)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
             free(block->name);
             block->name = 0;
@@ -5926,52 +6045,41 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         data->compression_multiplier = 1.0;
     }
 
-    block->block_contents_size = sizeof(char) * 2 +
-                                 sizeof(data->n_values_per_frame) +
-                                 sizeof(data->codec_id);
-
-    if(stride_length > 1)
+    if(mapping && mapping->n_particles != 0)
     {
-        block->block_contents_size += sizeof(data->first_frame_with_data) +
-                                      sizeof(data->stride_length);
+        n_particles = mapping->n_particles;
+        num_first_particle = mapping->num_first_particle;
     }
-
-    if(data->codec_id != TNG_UNCOMPRESSED)
+    else
     {
-        block->block_contents_size += sizeof(data->compression_multiplier);
+        num_first_particle = 0;
+        if(tng_data->var_num_atoms_flag)
+        {
+            n_particles = frame_set->n_particles;
+        }
+        else
+        {
+            n_particles = tng_data->n_particles;
+        }
     }
 
     if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
     {
-        dependency = TNG_FRAME_DEPENDENT;
+        dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
     }
     else
     {
-        dependency = 0;
-    }
-    if(dependency & TNG_FRAME_DEPENDENT)
-    {
-        block->block_contents_size += sizeof(char);
+        dependency = TNG_PARTICLE_DEPENDENT;
     }
 
-#ifdef USE_ZLIB
-    data_start_pos = block->block_contents_size;
-#endif
-
-    if(data->datatype == TNG_CHAR_DATA)
-    {
-        for(i = n_frames; i--;)
-        {
-            for(j = data->n_values_per_frame; j--;)
-            {
-                block->block_contents_size += strlen(data->strings[i][j]) + 1;
-            }
-        }
-    }
-    else
+    if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
+                                    frame_step, stride_length, num_first_particle,
+                                    n_particles, dependency, &data_start_pos,
+                                    &block->block_contents_size) != TNG_SUCCESS)
     {
-        block->block_contents_size += size * frame_step *
-        data->n_values_per_frame;
+        fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
     if(block->block_contents)
@@ -6042,7 +6150,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         if(tng_data->output_endianness_swap_func_64)
         {
             if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
+               (int64_t *)block->header_contents+offset)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
@@ -6064,7 +6172,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         if(tng_data->output_endianness_swap_func_64)
         {
             if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
+               (int64_t *)block->header_contents+offset)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
@@ -6074,19 +6182,47 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         offset += sizeof(data->first_frame_with_data);
 
         memcpy(block->block_contents+offset, &stride_length,
-               sizeof(data->stride_length));
+               sizeof(stride_length));
         if(tng_data->output_endianness_swap_func_64)
         {
             if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
+               (int64_t *)block->header_contents+offset)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
-        offset += sizeof(data->stride_length);
+        offset += sizeof(stride_length);
+    }
+
+
+    memcpy(block->block_contents+offset, &num_first_particle,
+           sizeof(num_first_particle));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(num_first_particle);
+
+    memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
     }
+    offset += sizeof(n_particles);
 
     if(data->datatype == TNG_CHAR_DATA)
     {
@@ -6094,12 +6230,18 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
         {
             for(i = 0; i < frame_step; i++)
             {
-                for(j = 0; j < data->n_values_per_frame; j++)
+                first_dim_values = data->strings[i];
+                for(j = num_first_particle; j < num_first_particle + n_particles;
+                    j++)
                 {
-                    len = (unsigned int)strlen(data->strings[i][j]) + 1;
-                    strncpy(block->block_contents+offset, data->strings[i][j],
-                            len);
-                    offset += len;
+                    second_dim_values = first_dim_values[j];
+                    for(k = 0; k < data->n_values_per_frame; k++)
+                    {
+                        len = (unsigned int)strlen(second_dim_values[k]) + 1;
+                        strncpy(block->block_contents+offset,
+                                second_dim_values[k], len);
+                        offset += len;
+                    }
                 }
             }
         }
@@ -6108,6 +6250,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
     {
         memcpy(block->block_contents + offset, data->values,
                block->block_contents_size - offset);
+
         switch(data->datatype)
         {
         case TNG_FLOAT_DATA:
@@ -6134,7 +6277,7 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
                 if(fabs(multiplier - 1.0) > 0.00001 ||
                    tng_data->input_endianness_swap_func_32)
                 {
-                    for(i = offset; block->block_contents_size; i+=size)
+                    for(i = offset; i < block->block_contents_size; i+=size)
                     {
                         *(float *)(block->block_contents + i) *= (float)multiplier;
                         if(tng_data->input_endianness_swap_func_32 &&
@@ -6219,9 +6362,34 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
     {
         switch(data->codec_id)
         {
+        case TNG_XTC_COMPRESSION:
+            fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
+            data->codec_id = TNG_UNCOMPRESSED;
+            break;
+        case TNG_TNG_COMPRESSION:
+            stat = tng_compress(tng_data, block, frame_step,
+                                n_particles, data->datatype,
+                                block->block_contents + data_start_pos);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
+                    __FILE__, __LINE__);
+                if(stat == TNG_CRITICAL)
+                {
+                    return(TNG_CRITICAL);
+                }
+                /* Set the data again, but with no compression (to write only
+                 * the relevant data) */
+                data->codec_id = TNG_UNCOMPRESSED;
+                stat = tng_particle_data_block_write(tng_data, block,
+                                                     block_index, mapping,
+                                                     hash_mode);
+                return(stat);
+            }
+            break;
 #ifdef USE_ZLIB
         case TNG_GZIP_COMPRESSION:
-    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
             stat = tng_gzip_compress(tng_data, block,
                                      block->block_contents + data_start_pos,
                                      block->block_contents_size - data_start_pos);
@@ -6233,255 +6401,570 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
                 {
                     return(TNG_CRITICAL);
                 }
-                data->codec_id = TNG_UNCOMPRESSED;
+                /* Set the data again, but with no compression (to write only
+                 * the relevant data) */
+                data->codec_id = TNG_UNCOMPRESSED;
+                stat = tng_particle_data_block_write(tng_data, block,
+                                                     block_index, mapping,
+                                                     hash_mode);
+                return(stat);
+            }
+    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
+            break;
+#endif
+        }
+    }
+
+    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+               tng_data->output_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(fwrite(block->block_contents, block->block_contents_size, 1,
+        tng_data->output_file) != 1)
+    {
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
+                __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/* TEST: */
+/** Create a non-particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block_type_flag specifies if this is a trajectory block or a
+ * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_create
+                (tng_trajectory_t tng_data,
+                 const char block_type_flag)
+{
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    tng_non_particle_data_t data;
+
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        frame_set->n_data_blocks++;
+        data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
+                       frame_set->n_data_blocks);
+        if(!data)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+                sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
+                __FILE__, __LINE__);
+            free(frame_set->tr_data);
+            frame_set->tr_data = 0;
+            return(TNG_CRITICAL);
+        }
+        frame_set->tr_data = data;
+    }
+    else
+    {
+        tng_data->n_data_blocks++;
+        data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
+                        tng_data->n_data_blocks);
+        if(!data)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+                sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
+                __FILE__, __LINE__);
+            free(tng_data->non_tr_data);
+            tng_data->non_tr_data = 0;
+            return(TNG_CRITICAL);
+        }
+        tng_data->non_tr_data = data;
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/* TEST: */
+/** Allocate memory for storing non-particle data.
+ * The allocated block will be refered to by data->values.
+ * @param tng_data is a trajectory data container.
+ * @param data is the data struct, which will contain the allocated memory in
+ * data->values.
+ * @param n_frames is the number of frames of data to store.
+ * @param n_values_per_frame is the number of data values per frame.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_allocate_data_mem
+                (tng_trajectory_t tng_data,
+                 tng_non_particle_data_t data,
+                 int64_t n_frames,
+                 int64_t stride_length,
+                 const int64_t n_values_per_frame)
+{
+    void **values;
+    int64_t i, j, size, frame_alloc;
+    (void)tng_data;
+
+    if(n_values_per_frame == 0)
+    {
+        return(TNG_FAILURE);
+    }
+
+    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    {
+        for(i = 0; i < data->n_frames; i++)
+        {
+            for(j = 0; j < data->n_values_per_frame; j++)
+            {
+                if(data->strings[i][j])
+                {
+                    free(data->strings[i][j]);
+                    data->strings[i][j] = 0;
+                }
             }
-    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
-            break;
-#endif
+            free(data->strings[i]);
+            data->strings[i] = 0;
         }
+        free(data->strings);
     }
+    data->n_frames = n_frames;
+    data->stride_length = tng_max_i64(1, stride_length);
+    n_frames = tng_max_i64(1, n_frames);
+    data->n_values_per_frame = n_values_per_frame;
+    frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        data->strings = malloc(sizeof(char **) * frame_alloc);
+        for(i = 0; i < frame_alloc; i++)
+        {
+            data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
+            if(!data->strings[i])
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                       n_values_per_frame,
+                       __FILE__, __LINE__);
+                return(TNG_CRITICAL);
+            }
+            for(j = 0; j < n_values_per_frame; j++)
+            {
+                data->strings[i][j] = 0;
+            }
+        }
     }
-
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
+    else
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        switch(data->datatype)
+        {
+        case TNG_INT_DATA:
+            size = sizeof(int64_t);
+            break;
+        case TNG_FLOAT_DATA:
+            size = sizeof(float);
+            break;
+        case TNG_DOUBLE_DATA:
+        default:
+            size = sizeof(double);
+        }
+
+        values = realloc(data->values,
+                         size * frame_alloc *
+                         n_values_per_frame);
+        if(!values)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                   size * frame_alloc *
+                   n_values_per_frame,
+                   __FILE__, __LINE__);
+            free(data->values);
+            data->values = 0;
+            return(TNG_CRITICAL);
+        }
+        data->values = values;
     }
 
     return(TNG_SUCCESS);
 }
 
-/** Read the meta information of a data block (particle or non-particle data).
+/** Read the values of a non-particle data block
  * @param tng_data is a trajectory data container.
  * @param block is the block to store the data (should already contain
- * the block headers).
+ * the block headers and the block contents).
+ * @param offset is the reading offset to point at the place where the actual
+ * values are stored, starting from the beginning of the block_contents. The
+ * offset is changed during the reading.
+ * @param datatype is the type of data of the data block (char, int, float or
+ * double).
+ * @param first_frame_with_data is the frame number of the first frame with data
+ * in this data block.
+ * @param stride_length is the number of frames between each data entry.
+ * @param n_frames is the number of frames in this data block.
+ * @param n_values is the number of values per frame stored in this data block.
+ * @param codec_id is the ID of the codec to compress the data.
+ * @param multiplier is the multiplication factor applied to each data value
+ * before compression. This factor is applied since some compression algorithms
+ * work only on integers.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_data_block_meta_information_read
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 int *offset,
-                 char *datatype,
-                 char *dependency,
-                 char *sparse_data,
-                 int64_t *n_values,
-                 int64_t *codec_id,
-                 int64_t *first_frame_with_data,
-                 int64_t *stride_length,
-                 int64_t *n_frames,
-                 int64_t *num_first_particle,
-                 int64_t *block_n_particles,
-                 double *multiplier)
+static tng_function_status tng_data_read(tng_trajectory_t tng_data,
+                                         tng_gen_block_t block,
+                                         int *offset,
+                                         const char datatype,
+                                         const int64_t first_frame_with_data,
+                                         const int64_t stride_length,
+                                         int64_t n_frames,
+                                         const int64_t n_values,
+                                         const int64_t codec_id,
+                                         const double multiplier)
 {
-    int meta_size;
-    char *contents;
+    int64_t i, j, n_frames_div;
+    int size, len;
+#ifdef USE_ZLIB
+    int64_t data_size;
+#endif
+    tng_non_particle_data_t data;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+    char block_type_flag;
 
-    if(block->block_contents)
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
+
+    /* This must be caught early to avoid creating a data block if not necessary. */
+#ifndef USE_ZLIB
+    if(codec_id == TNG_GZIP_COMPRESSION)
     {
-        contents = block->block_contents;
+        fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
+                __LINE__);
+        return(TNG_FAILURE);
     }
-    else
+#endif
+
+    switch(datatype)
     {
-        meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
-        contents = malloc(meta_size);
-        if(!contents)
+    case TNG_CHAR_DATA:
+        size = 1;
+        break;
+    case TNG_INT_DATA:
+        size = sizeof(int64_t);
+        break;
+    case TNG_FLOAT_DATA:
+        size = sizeof(float);
+        break;
+    case TNG_DOUBLE_DATA:
+    default:
+        size = sizeof(double);
+    }
+
+    /* If the block does not exist, create it */
+    if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    {
+        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-               meta_size, __FILE__, __LINE__);
+            block_type_flag = TNG_TRAJECTORY_BLOCK;
+        }
+        else
+        {
+            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
         }
 
-        if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
+        if(tng_data_block_create(tng_data, block_type_flag) !=
+            TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
-            free(contents);
+            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+                   __FILE__, __LINE__);
             return(TNG_CRITICAL);
         }
-    }
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+        {
+            data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+        }
+        else
+        {
+            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
+        }
+        data->block_id = block->id;
 
-    memcpy(datatype, contents+*offset,
-           sizeof(*datatype));
-    *offset += sizeof(*datatype);
+        data->block_name = malloc(strlen(block->name) + 1);
+        if(!data->block_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                   (int)strlen(block->name)+1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        strcpy(data->block_name, block->name);
 
-    memcpy(dependency, contents+*offset,
-           sizeof(*dependency));
-    *offset += sizeof(*dependency);
+        data->datatype = datatype;
 
-    if(*dependency & TNG_FRAME_DEPENDENT)
-    {
-        memcpy(sparse_data, contents+*offset,
-               sizeof(*sparse_data));
-        *offset += sizeof(*sparse_data);
+        data->values = 0;
+        /* FIXME: Memory leak from strings. */
+        data->strings = 0;
+        data->n_frames = 0;
+        data->codec_id = codec_id;
+        data->compression_multiplier = multiplier;
+        data->last_retrieved_frame = -1;
     }
 
-    memcpy(n_values, contents+*offset,
-        sizeof(*n_values));
-    if(tng_data->input_endianness_swap_func_64)
+    n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+
+    if(codec_id != TNG_UNCOMPRESSED)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   n_values)
-            != TNG_SUCCESS)
+        switch(codec_id)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+#ifdef USE_ZLIB
+        case TNG_GZIP_COMPRESSION:
+            data_size = n_frames_div * size * n_values;
+    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+            if(tng_gzip_uncompress(tng_data, block,
+                                   block->block_contents + *offset,
+                                   data_size) != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
+                    __LINE__);
+                return(TNG_CRITICAL);
+            }
+    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
+            break;
+#endif
         }
     }
-    *offset += sizeof(*n_values);
 
-    memcpy(codec_id, contents+*offset,
-        sizeof(*codec_id));
-    if(tng_data->input_endianness_swap_func_64)
+    /* Allocate memory */
+    if(!data->values || data->n_frames != n_frames ||
+       data->n_values_per_frame != n_values)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   codec_id)
-            != TNG_SUCCESS)
+        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
+                                 n_values) !=
+           TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    *offset += sizeof(*codec_id);
 
-    if(*codec_id != TNG_UNCOMPRESSED)
-    {
-        memcpy(multiplier, contents+*offset,
-            sizeof(*multiplier));
-        if(tng_data->input_endianness_swap_func_64)
+    data->first_frame_with_data = first_frame_with_data;
+
+    if(datatype == TNG_CHAR_DATA)
+    {
+        for(i = 0; i < n_frames_div; i++)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       (int64_t *) multiplier)
-                != TNG_SUCCESS)
+            for(j = 0; j < n_values; j++)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+                              TNG_MAX_STR_LEN);
+                if(data->strings[i][j])
+                {
+                    free(data->strings[i][j]);
+                }
+                data->strings[i][j] = malloc(len);
+                if(!data->strings[i][j])
+                {
+                    fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                           len, __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
+                }
+                strncpy(data->strings[i][j], block->block_contents+*offset,
+                        len);
+                *offset += len;
             }
         }
-        *offset += sizeof(*multiplier);
     }
     else
     {
-        *multiplier = 1;
-    }
-
-    if(*dependency & TNG_FRAME_DEPENDENT)
-    {
-        if(*sparse_data)
+        memcpy(data->values, block->block_contents + *offset,
+               block->block_contents_size - *offset);
+        switch(datatype)
         {
-            memcpy(first_frame_with_data, contents+*offset,
-                sizeof(*first_frame_with_data));
-            if(tng_data->input_endianness_swap_func_64)
+        case TNG_FLOAT_DATA:
+            if(tng_data->input_endianness_swap_func_32)
             {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                           first_frame_with_data)
-                    != TNG_SUCCESS)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
+                    if(tng_data->input_endianness_swap_func_32(tng_data,
+                        (int32_t *)((char *)data->values + i))
+                        != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
+                    }
                 }
             }
-            *offset += sizeof(*first_frame_with_data);
-
-            memcpy(stride_length, contents+*offset,
-                sizeof(*stride_length));
+            break;
+        case TNG_INT_DATA:
+        case TNG_DOUBLE_DATA:
             if(tng_data->input_endianness_swap_func_64)
             {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                           stride_length)
-                    != TNG_SUCCESS)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
+                    if(tng_data->input_endianness_swap_func_64(tng_data,
+                        (int64_t *)((char *)data->values + i))
+                        != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
+                    }
                 }
             }
-            *offset += sizeof(*stride_length);
-            *n_frames = tng_data->current_trajectory_frame_set.n_frames -
-                        (*first_frame_with_data -
-                        tng_data->current_trajectory_frame_set.first_frame);
-        }
-        else
-        {
-            *first_frame_with_data = 0;
-            *stride_length = 1;
-            *n_frames = tng_data->current_trajectory_frame_set.n_frames;
+            break;
+        case TNG_CHAR_DATA:
+            break;
         }
     }
+    return(TNG_SUCCESS);
+}
+
+/** Write a non-particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers and the block contents).
+ * @param block_index is the index number of the data block in the frame set.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
+                                                tng_gen_block_t block,
+                                                const int64_t block_index,
+                                                const char hash_mode)
+{
+    int64_t n_frames, stride_length, frame_step, data_start_pos;
+    int64_t i, j;
+    int offset = 0, size;
+    unsigned int len;
+#ifdef USE_ZLIB
+    tng_function_status stat;
+#endif
+    char temp, dependency, *temp_name;
+    double multiplier;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    tng_non_particle_data_t data;
+    char block_type_flag;
+
+    /* If we have already started writing frame sets it is too late to write
+     * non-trajectory data blocks */
+    if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
+    {
+        block_type_flag = TNG_TRAJECTORY_BLOCK;
+    }
     else
     {
-        *first_frame_with_data = 0;
-        *stride_length = 1;
-        *n_frames = 1;
+        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
     }
 
-    if (*dependency & TNG_PARTICLE_DEPENDENT)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        memcpy(num_first_particle, contents+*offset,
-               sizeof(*num_first_particle));
-        if(tng_data->input_endianness_swap_func_64)
+        return(TNG_CRITICAL);
+    }
+
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        data = &frame_set->tr_data[block_index];
+
+        /* If this data block has not had any data added in this frame set
+         * do not write it. */
+        if(data->first_frame_with_data < frame_set->first_frame)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       num_first_particle)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_SUCCESS);
         }
-        *offset += sizeof(*num_first_particle);
 
-        memcpy(block_n_particles, contents+*offset,
-            sizeof(*block_n_particles));
-        if(tng_data->input_endianness_swap_func_64)
+        stride_length = tng_max_i64(1, data->stride_length);
+    }
+    else
+    {
+        data = &tng_data->non_tr_data[block_index];
+        stride_length = 1;
+    }
+
+    switch(data->datatype)
+    {
+    case TNG_CHAR_DATA:
+        size = 1;
+        break;
+    case TNG_INT_DATA:
+        size = sizeof(int64_t);
+        break;
+    case TNG_FLOAT_DATA:
+        size = sizeof(float);
+        break;
+    case TNG_DOUBLE_DATA:
+    default:
+        size = sizeof(double);
+    }
+
+    len = (unsigned int)strlen(data->block_name) + 1;
+
+    if(!block->name || strlen(block->name) < len)
+    {
+        temp_name = realloc(block->name, len);
+        if(!temp_name)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       block_n_particles)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n", len+1,
+                   __FILE__, __LINE__);
+            free(block->name);
+            block->name = 0;
+            return(TNG_CRITICAL);
         }
-        *offset += sizeof(*block_n_particles);
+        block->name = temp_name;
     }
+    strncpy(block->name, data->block_name, len);
+    block->id = data->block_id;
 
-    if(!block->block_contents)
+    /* If writing frame independent data data->n_frames is 0, but n_frames
+       is used for the loop writing the data (and reserving memory) and needs
+       to be at least 1 */
+    n_frames = tng_max_i64(1, data->n_frames);
+
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        free(contents);
+        /* If the frame set is finished before writing the full number of frames
+           make sure the data block is not longer than the frame set. */
+        n_frames = tng_min_i64(n_frames, frame_set->n_frames);
+
+        n_frames -= (data->first_frame_with_data - frame_set->first_frame);
     }
-    return(TNG_SUCCESS);
-}
 
-/** Read the contents of a data block (particle or non-particle data).
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers).
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
- * compared to the md5 hash of the read contents to ensure valid data.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_data_block_contents_read
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 const char hash_mode)
-{
-    int64_t n_values, codec_id, n_frames, first_frame_with_data;
-    int64_t stride_length, block_n_particles, num_first_particle;
-    double multiplier;
-    char datatype, dependency, sparse_data;
-    int offset = 0;
-    tng_bool same_hash;
+    frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
+                 n_frames / stride_length;
+
+    /* TNG compression will use compression precision to get integers from
+     * floating point data. The compression multiplier stores that information
+     * to be able to return the precision of the compressed data. */
+    if(data->codec_id == TNG_TNG_COMPRESSION)
+    {
+        data->compression_multiplier = tng_data->compression_precision;
+    }
+    /* Uncompressed data blocks do not use compression multipliers at all.
+     * GZip compression does not need it either. */
+    else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
+    {
+        data->compression_multiplier = 1.0;
+    }
+
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+    {
+        dependency = TNG_FRAME_DEPENDENT;
+    }
+    else
+    {
+        dependency = 0;
+    }
 
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
+                                    frame_step, stride_length, 0,
+                                    1, dependency, &data_start_pos,
+                                    &block->block_contents_size) != TNG_SUCCESS)
     {
+        fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
+                __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
@@ -6489,7 +6972,6 @@ static tng_function_status tng_data_block_contents_read
     {
         free(block->block_contents);
     }
-
     block->block_contents = malloc(block->block_contents_size);
     if(!block->block_contents)
     {
@@ -6498,396 +6980,578 @@ static tng_function_status tng_data_block_contents_read
         return(TNG_CRITICAL);
     }
 
-    /* Read the whole block into block_contents to be able to write it to
-     * disk even if it cannot be interpreted. */
-    if(fread(block->block_contents, block->block_contents_size, 1,
-             tng_data->input_file) == 0)
+
+    memcpy(block->block_contents, &data->datatype, sizeof(char));
+    offset += sizeof(char);
+
+    memcpy(block->block_contents+offset, &dependency, sizeof(char));
+    offset += sizeof(char);
+
+    if(dependency & TNG_FRAME_DEPENDENT)
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        if(stride_length > 1)
+        {
+            temp = 1;
+        }
+        else
+        {
+            temp = 0;
+        }
+        memcpy(block->block_contents+offset, &temp, sizeof(char));
+        offset += sizeof(char);
     }
 
-    /* FIXME: Does not check if the size of the contents matches the expected
-     * size or if the contents can be read. */
+    memcpy(block->block_contents+offset, &data->n_values_per_frame,
+           sizeof(data->n_values_per_frame));
+    if(tng_data->output_endianness_swap_func_64)
+    {
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    offset += sizeof(data->n_values_per_frame);
 
-    if(hash_mode == TNG_USE_HASH)
+    memcpy(block->block_contents+offset, &data->codec_id,
+           sizeof(data->codec_id));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
-                block->name, __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
+    offset += sizeof(data->codec_id);
 
-    if(tng_data_block_meta_information_read(tng_data, block,
-                                            &offset, &datatype,
-                                            &dependency, &sparse_data,
-                                            &n_values, &codec_id,
-                                            &first_frame_with_data,
-                                            &stride_length, &n_frames,
-                                            &num_first_particle,
-                                            &block_n_particles,
-                                            &multiplier) == TNG_CRITICAL)
+    if(data->codec_id != TNG_UNCOMPRESSED)
     {
-        fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
-            block->name, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        memcpy(block->block_contents+offset, &data->compression_multiplier,
+               sizeof(data->compression_multiplier));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+            (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(data->compression_multiplier);
     }
 
-    if (dependency & TNG_PARTICLE_DEPENDENT)
+    if(data->n_frames > 0 && stride_length > 1)
     {
-        return(tng_particle_data_read(tng_data, block,
-                                      &offset, datatype,
-                                      num_first_particle,
-                                      block_n_particles,
-                                      first_frame_with_data,
-                                      stride_length,
-                                      n_frames, n_values,
-                                      codec_id, multiplier));
+        /* FIXME: first_frame_with_data is not reliably set */
+        if(data->first_frame_with_data == 0)
+        {
+            data->first_frame_with_data = frame_set->first_frame;
+        }
+        memcpy(block->block_contents+offset, &data->first_frame_with_data,
+               sizeof(data->first_frame_with_data));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+            (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(data->first_frame_with_data);
+
+        memcpy(block->block_contents+offset, &stride_length,
+               sizeof(data->stride_length));
+        if(tng_data->output_endianness_swap_func_64)
+        {
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+            (int64_t *)block->header_contents+offset)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
+        }
+        offset += sizeof(data->stride_length);
+    }
+
+    if(data->datatype == TNG_CHAR_DATA)
+    {
+        if(data->strings)
+        {
+            for(i = 0; i < frame_step; i++)
+            {
+                for(j = 0; j < data->n_values_per_frame; j++)
+                {
+                    len = (unsigned int)strlen(data->strings[i][j]) + 1;
+                    strncpy(block->block_contents+offset, data->strings[i][j],
+                            len);
+                    offset += len;
+                }
+            }
+        }
+    }
+    else if(data->values)
+    {
+        memcpy(block->block_contents + offset, data->values,
+               block->block_contents_size - offset);
+        switch(data->datatype)
+        {
+        case TNG_FLOAT_DATA:
+            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+               data->codec_id == TNG_TNG_COMPRESSION)
+            {
+                if(tng_data->input_endianness_swap_func_32)
+                {
+                    for(i = offset; i < block->block_contents_size; i+=size)
+                    {
+                        if(tng_data->input_endianness_swap_func_32(tng_data,
+                           (int32_t *)(block->block_contents + i))
+                           != TNG_SUCCESS)
+                        {
+                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                    __FILE__, __LINE__);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                multiplier = data->compression_multiplier;
+                if(fabs(multiplier - 1.0) > 0.00001 ||
+                   tng_data->input_endianness_swap_func_32)
+                {
+                    for(i = offset; block->block_contents_size; i+=size)
+                    {
+                        *(float *)(block->block_contents + i) *= (float)multiplier;
+                        if(tng_data->input_endianness_swap_func_32 &&
+                        tng_data->input_endianness_swap_func_32(tng_data,
+                        (int32_t *)(block->block_contents + i))
+                        != TNG_SUCCESS)
+                        {
+                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                    __FILE__, __LINE__);
+                        }
+                    }
+                }
+            }
+            break;
+        case TNG_INT_DATA:
+            if(tng_data->input_endianness_swap_func_64)
+            {
+                for(i = offset; i < block->block_contents_size; i+=size)
+                {
+                    if(tng_data->input_endianness_swap_func_64(tng_data,
+                       (int64_t *)(block->block_contents + i))
+                       != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
+                    }
+                }
+            }
+            break;
+        case TNG_DOUBLE_DATA:
+            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+               data->codec_id == TNG_TNG_COMPRESSION)
+            {
+                if(tng_data->input_endianness_swap_func_64)
+                {
+                    for(i = offset; i < block->block_contents_size; i+=size)
+                    {
+                        if(tng_data->input_endianness_swap_func_64(tng_data,
+                           (int64_t *)(block->block_contents + i))
+                           != TNG_SUCCESS)
+                        {
+                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                    __FILE__, __LINE__);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                multiplier = data->compression_multiplier;
+                if(fabs(multiplier - 1.0) > 0.00001 ||
+                   tng_data->input_endianness_swap_func_64)
+                {
+                    for(i = offset; i < block->block_contents_size; i+=size)
+                    {
+                        *(double *)(block->block_contents + i) *= multiplier;
+                        if(tng_data->input_endianness_swap_func_64 &&
+                        tng_data->input_endianness_swap_func_64(tng_data,
+                        (int64_t *)(block->block_contents + i))
+                        != TNG_SUCCESS)
+                        {
+                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                    __FILE__, __LINE__);
+                        }
+                    }
+                }
+            }
+            break;
+        case TNG_CHAR_DATA:
+            break;
+        }
     }
     else
     {
-        return(tng_data_read(tng_data, block,
-                             &offset, datatype,
-                             first_frame_with_data,
-                             stride_length,
-                             n_frames, n_values,
-                             codec_id, multiplier));
+        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
     }
-}
 
-/** Update the md5 hash of a block already written to the file
- * @param tng_data is a trajectory data container.
- * @param block is the block, of which to update the md5 hash.
- * @param header_start_pos is the file position where the block header starts.
- * @param contents_start_pos is the file position where the block contents
- * start.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               const int64_t header_start_pos,
-                                               const int64_t contents_start_pos)
-{
-    if(block->block_contents)
+    frame_set->n_written_frames += frame_set->n_unwritten_frames;
+    frame_set->n_unwritten_frames = 0;
+
+    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
     {
-        free(block->block_contents);
+        switch(data->codec_id)
+        {
+#ifdef USE_ZLIB
+        case TNG_GZIP_COMPRESSION:
+    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+            stat = tng_gzip_compress(tng_data, block,
+                                     block->block_contents + data_start_pos,
+                                     block->block_contents_size - data_start_pos);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
+                    __LINE__);
+                if(stat == TNG_CRITICAL)
+                {
+                    return(TNG_CRITICAL);
+                }
+                data->codec_id = TNG_UNCOMPRESSED;
+            }
+    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
+            break;
+#endif
+        }
     }
 
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+               tng_data->output_file_path, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
-    if(fread(block->block_contents, block->block_contents_size, 1,
-            tng_data->output_file) == 0)
+    if(fwrite(block->block_contents, block->block_contents_size, 1,
+              tng_data->output_file) != 1)
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    tng_block_md5_hash_generate(block);
-
-    fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
-          SEEK_SET);
-    fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
-
     return(TNG_SUCCESS);
 }
 
-/** Update the frame set pointers in the file header (general info block),
- * already written to disk
+/** Read the meta information of a data block (particle or non-particle data).
  * @param tng_data is a trajectory data container.
- * @param hash_mode specifies whether to update the block md5 hash when
- * updating the pointers.
+ * @param block is the block to store the data (should already contain
+ * the block headers).
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_header_pointers_update
-                (tng_trajectory_t tng_data, const char hash_mode)
+static tng_function_status tng_data_block_meta_information_read
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 int *offset,
+                 char *datatype,
+                 char *dependency,
+                 char *sparse_data,
+                 int64_t *n_values,
+                 int64_t *codec_id,
+                 int64_t *first_frame_with_data,
+                 int64_t *stride_length,
+                 int64_t *n_frames,
+                 int64_t *num_first_particle,
+                 int64_t *block_n_particles,
+                 double *multiplier)
 {
-    tng_gen_block_t block;
-    FILE *temp = tng_data->input_file;
-    int64_t output_file_pos, pos, contents_start_pos;
+    int meta_size;
+    char *contents;
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    if(block->block_contents)
     {
-        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        contents = block->block_contents;
     }
-
-    tng_data->input_file = tng_data->output_file;
-
-    tng_block_init(&block);
-
-    output_file_pos = ftell(tng_data->output_file);
-    fseek(tng_data->output_file, 0, SEEK_SET);
-
-    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+    else
     {
-        fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
-               __FILE__, __LINE__);
-        tng_data->input_file = temp;
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    contents_start_pos = ftell(tng_data->output_file);
-
-    fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
-          sizeof(int64_t), SEEK_CUR);
-
-    tng_data->input_file = temp;
-
-    pos = tng_data->first_trajectory_frame_set_output_file_pos;
+        meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
+        contents = malloc(meta_size);
+        if(!contents)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+               meta_size, __FILE__, __LINE__);
+        }
 
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                    &pos)
-            != TNG_SUCCESS)
+        if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
+            free(contents);
+            return(TNG_CRITICAL);
         }
     }
 
-    if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+    memcpy(datatype, contents+*offset,
+           sizeof(*datatype));
+    *offset += sizeof(*datatype);
+
+    memcpy(dependency, contents+*offset,
+           sizeof(*dependency));
+    *offset += sizeof(*dependency);
+
+    if(*dependency & TNG_FRAME_DEPENDENT)
     {
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        memcpy(sparse_data, contents+*offset,
+               sizeof(*sparse_data));
+        *offset += sizeof(*sparse_data);
     }
 
-    pos = tng_data->last_trajectory_frame_set_output_file_pos;
-
+    memcpy(n_values, contents+*offset,
+        sizeof(*n_values));
     if(tng_data->input_endianness_swap_func_64)
     {
         if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                    &pos)
+                                                   n_values)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
+    *offset += sizeof(*n_values);
 
-    if(fwrite(&pos,
-        sizeof(int64_t), 1, tng_data->output_file) != 1)
-    {
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    if(hash_mode == TNG_USE_HASH)
-    {
-        tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
-    }
-
-    tng_block_destroy(&block);
-
-    fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
-
-    return(TNG_SUCCESS);
-}
-
-/** Update the frame set pointers in the current frame set block, already
- * written to disk. It also updates the pointers of the blocks pointing to
- * the current frame set block.
- * @param tng_data is a trajectory data container.
- * @param hash_mode specifies whether to update the block md5 hash when
- * updating the pointers.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_frame_set_pointers_update
-                (tng_trajectory_t tng_data, const char hash_mode)
-{
-    tng_gen_block_t block;
-    tng_trajectory_frame_set_t frame_set;
-    FILE *temp = tng_data->input_file;
-    int64_t pos, output_file_pos, header_start_pos, contents_start_pos;
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    tng_block_init(&block);
-    output_file_pos = ftell(tng_data->output_file);
-
-    tng_data->input_file = tng_data->output_file;
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    /* Update previous frame set */
-    if(frame_set->prev_frame_set_file_pos != -1 &&
-       frame_set->prev_frame_set_file_pos != 0)
-    {
-        fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
-              SEEK_SET);
-
-        header_start_pos = frame_set->prev_frame_set_file_pos;
-
-        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
-                __FILE__, __LINE__);
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
-
-        contents_start_pos = ftell(tng_data->output_file);
-
-        fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
-        pos = tng_data->current_trajectory_frame_set_output_file_pos;
-
-        if(tng_data->input_endianness_swap_func_64)
-        {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                        &pos)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-
-        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
-        {
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
-
-        if(hash_mode == TNG_USE_HASH)
-        {
-            tng_md5_hash_update(tng_data, block, header_start_pos,
-                                contents_start_pos);
-        }
-        fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
-    }
-
-    /* Update the frame set one medium stride step before */
-    if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
-       frame_set->medium_stride_prev_frame_set_file_pos != 0)
+    memcpy(codec_id, contents+*offset,
+        sizeof(*codec_id));
+    if(tng_data->input_endianness_swap_func_64)
     {
-        fseek(tng_data->output_file,
-              (long)frame_set->medium_stride_prev_frame_set_file_pos,
-              SEEK_SET);
-
-        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+        if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                   codec_id)
+            != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
-                __FILE__, __LINE__);
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    *offset += sizeof(*codec_id);
 
-        contents_start_pos = ftell(tng_data->output_file);
-
-        fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
-        pos = tng_data->current_trajectory_frame_set_output_file_pos;
-
+    if(*codec_id != TNG_UNCOMPRESSED)
+    {
+        memcpy(multiplier, contents+*offset,
+            sizeof(*multiplier));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                        &pos)
+                                                       (int64_t *) multiplier)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
+        *offset += sizeof(*multiplier);
+    }
+    else
+    {
+        *multiplier = 1;
+    }
 
-        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+    if(*dependency & TNG_FRAME_DEPENDENT)
+    {
+        if(*sparse_data)
         {
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
+            memcpy(first_frame_with_data, contents+*offset,
+                sizeof(*first_frame_with_data));
+            if(tng_data->input_endianness_swap_func_64)
+            {
+                if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                           first_frame_with_data)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            *offset += sizeof(*first_frame_with_data);
 
-        if(hash_mode == TNG_USE_HASH)
+            memcpy(stride_length, contents+*offset,
+                sizeof(*stride_length));
+            if(tng_data->input_endianness_swap_func_64)
+            {
+                if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                           stride_length)
+                    != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
+                }
+            }
+            *offset += sizeof(*stride_length);
+            *n_frames = tng_data->current_trajectory_frame_set.n_frames -
+                        (*first_frame_with_data -
+                        tng_data->current_trajectory_frame_set.first_frame);
+        }
+        else
         {
-            tng_md5_hash_update(tng_data, block,
-                                frame_set->medium_stride_prev_frame_set_file_pos,
-                                contents_start_pos);
+            *first_frame_with_data = 0;
+            *stride_length = 1;
+            *n_frames = tng_data->current_trajectory_frame_set.n_frames;
         }
     }
-
-    /* Update the frame set one long stride step before */
-    if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
-       frame_set->long_stride_prev_frame_set_file_pos != 0)
+    else
     {
-        fseek(tng_data->output_file,
-              (long)frame_set->long_stride_prev_frame_set_file_pos,
-              SEEK_SET);
+        *first_frame_with_data = 0;
+        *stride_length = 1;
+        *n_frames = 1;
+    }
 
-        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+    if (*dependency & TNG_PARTICLE_DEPENDENT)
+    {
+        memcpy(num_first_particle, contents+*offset,
+               sizeof(*num_first_particle));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
-                __FILE__, __LINE__);
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
+            if(tng_data->input_endianness_swap_func_64(tng_data,
+                                                       num_first_particle)
+                != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
+            }
         }
+        *offset += sizeof(*num_first_particle);
 
-        contents_start_pos = ftell(tng_data->output_file);
-
-        fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
-        pos = tng_data->current_trajectory_frame_set_output_file_pos;
-
+        memcpy(block_n_particles, contents+*offset,
+            sizeof(*block_n_particles));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                        &pos)
+                                                       block_n_particles)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
+        *offset += sizeof(*block_n_particles);
+    }
 
-        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
-        {
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
+    if(!block->block_contents)
+    {
+        free(contents);
+    }
+    return(TNG_SUCCESS);
+}
 
-        if(hash_mode == TNG_USE_HASH)
-        {
-            tng_md5_hash_update(tng_data, block,
-                                frame_set->long_stride_prev_frame_set_file_pos,
-                                contents_start_pos);
-        }
+/** Read the contents of a data block (particle or non-particle data).
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers).
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
+ * compared to the md5 hash of the read contents to ensure valid data.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_contents_read
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const char hash_mode)
+{
+    int64_t n_values, codec_id, n_frames, first_frame_with_data;
+    int64_t stride_length, block_n_particles, num_first_particle;
+    double multiplier;
+    char datatype, dependency, sparse_data;
+    int offset = 0;
+    tng_bool same_hash;
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
     }
 
-    fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+    if(block->block_contents)
+    {
+        free(block->block_contents);
+    }
 
-    tng_data->input_file = temp;
+    block->block_contents = malloc(block->block_contents_size);
+    if(!block->block_contents)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+               block->block_contents_size, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-    tng_block_destroy(&block);
+    /* Read the whole block into block_contents to be able to write it to
+     * disk even if it cannot be interpreted. */
+    if(fread(block->block_contents, block->block_contents_size, 1,
+             tng_data->input_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-    return(TNG_SUCCESS);
+    /* FIXME: Does not check if the size of the contents matches the expected
+     * size or if the contents can be read. */
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_md5_hash_match_verify(block, &same_hash);
+        if(same_hash != TNG_TRUE)
+        {
+            fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
+                block->name, __FILE__, __LINE__);
+    /*         return(TNG_FAILURE); */
+        }
+    }
+
+    if(tng_data_block_meta_information_read(tng_data, block,
+                                            &offset, &datatype,
+                                            &dependency, &sparse_data,
+                                            &n_values, &codec_id,
+                                            &first_frame_with_data,
+                                            &stride_length, &n_frames,
+                                            &num_first_particle,
+                                            &block_n_particles,
+                                            &multiplier) == TNG_CRITICAL)
+    {
+        fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
+            block->name, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if (dependency & TNG_PARTICLE_DEPENDENT)
+    {
+        return(tng_particle_data_read(tng_data, block,
+                                      &offset, datatype,
+                                      num_first_particle,
+                                      block_n_particles,
+                                      first_frame_with_data,
+                                      stride_length,
+                                      n_frames, n_values,
+                                      codec_id, multiplier));
+    }
+    else
+    {
+        return(tng_data_read(tng_data, block,
+                             &offset, datatype,
+                             first_frame_with_data,
+                             stride_length,
+                             n_frames, n_values,
+                             codec_id, multiplier));
+    }
 }
+
 /*
 // ** Move the blocks in a frame set so that there is no unused space between
 //  * them. This can only be done on the last frame set in the file and should
@@ -6926,13 +7590,13 @@ static tng_function_status tng_frame_set_pointers_update
 //     }
 //
 //     tng_block_init(&block);
-// //     output_file_pos = ftell(tng_data->output_file);
+// //     output_file_pos = ftello(tng_data->output_file);
 //
 //     tng_data->input_file = tng_data->output_file;
 //
 //     pos = tng_data->current_trajectory_frame_set_output_file_pos;
 //
-//     fseek(tng_data->output_file, pos, SEEK_SET);
+//     fseeko(tng_data->output_file, pos, SEEK_SET);
 //     if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
 //     {
 //         fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
@@ -6942,12 +7606,12 @@ static tng_function_status tng_frame_set_pointers_update
 //         return(TNG_CRITICAL);
 //     }
 //
-//     contents_start_pos = ftell(tng_data->output_file);
+//     contents_start_pos = ftello(tng_data->output_file);
 //
-//     fseek(tng_data->output_file, 0, SEEK_END);
-//     output_file_len = ftell(tng_data->output_file);
+//     fseeko(tng_data->output_file, 0, SEEK_END);
+//     output_file_len = ftello(tng_data->output_file);
 //     pos = contents_start_pos + block->block_contents_size;
-//     fseek(tng_data->output_file, pos,
+//     fseeko(tng_data->output_file, pos,
 //           SEEK_SET);
 //
 //     while(pos < output_file_len)
@@ -6961,7 +7625,7 @@ static tng_function_status tng_frame_set_pointers_update
 //             return(TNG_CRITICAL);
 //         }
 //         pos += block->header_contents_size + block->block_contents_size;
-//         fseek(tng_data->output_file, pos, SEEK_SET);
+//         fseeko(tng_data->output_file, pos, SEEK_SET);
 //     }
 //
 //     return(TNG_SUCCESS);
@@ -6999,13 +7663,13 @@ static tng_function_status tng_frame_set_finalize
     }
 
     tng_block_init(&block);
-/*     output_file_pos = ftell(tng_data->output_file); */
+/*     output_file_pos = ftello(tng_data->output_file); */
 
     tng_data->input_file = tng_data->output_file;
 
     pos = tng_data->current_trajectory_frame_set_output_file_pos;
 
-    fseek(tng_data->output_file, (long)pos, SEEK_SET);
+    fseeko(tng_data->output_file, pos, SEEK_SET);
 
     if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
     {
@@ -7016,9 +7680,9 @@ static tng_function_status tng_frame_set_finalize
         return(TNG_CRITICAL);
     }
 
-    contents_start_pos = ftell(tng_data->output_file);
+    contents_start_pos = ftello(tng_data->output_file);
 
-    fseek(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
+    fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
     if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
               1, tng_data->output_file) != 1)
     {
@@ -7034,10 +7698,10 @@ static tng_function_status tng_frame_set_finalize
                             pos + block->header_contents_size);
     }
 
-    fseek(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftell(tng_data->output_file);
+    fseeko(tng_data->output_file, 0, SEEK_END);
+    output_file_len = ftello(tng_data->output_file);
     pos = contents_start_pos + block->block_contents_size;
-    fseek(tng_data->output_file, (long)pos, SEEK_SET);
+    fseeko(tng_data->output_file, pos, SEEK_SET);
 
     while(pos < output_file_len)
     {
@@ -7056,7 +7720,7 @@ static tng_function_status tng_frame_set_finalize
                                 pos + block->header_contents_size);
         }
         pos += block->header_contents_size + block->block_contents_size;
-        fseek(tng_data->output_file, (long)pos, SEEK_SET);
+        fseeko(tng_data->output_file, pos, SEEK_SET);
     }
 
     tng_data->input_file = temp;
@@ -7257,34 +7921,70 @@ static tng_function_status tng_atom_destroy(tng_atom_t atom)
     return(TNG_SUCCESS);
 }
 
+tng_function_status DECLSPECDLLEXPORT tng_version_major
+                (const tng_trajectory_t tng_data,
+                 int *version)
+{
+    (void)tng_data;
+
+    *version = TNG_VERSION_MAJOR;
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_version_minor
+                (const tng_trajectory_t tng_data,
+                 int *version)
+{
+    (void)tng_data;
+
+    *version = TNG_VERSION_MINOR;
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
+                (const tng_trajectory_t tng_data,
+                 int *patch_level)
+{
+    (void)tng_data;
+
+    *patch_level = TNG_VERSION_PATCHLEVEL;
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_version
+                (const tng_trajectory_t tng_data,
+                 char *version,
+                 const int max_len)
+{
+    (void)tng_data;
+    TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
+
+    TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
+
+    return(TNG_SUCCESS);
+}
+
 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
                 (tng_trajectory_t tng_data,
                  const char *name,
                  tng_molecule_t *molecule)
 {
-    int64_t id, i;
-    tng_bool found_id = TNG_TRUE;
+    int64_t id;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    /* Find an unused ID */
-    id = 0;
-    while(found_id)
+    /* Set ID to the ID of the last molecule + 1 */
+    if(tng_data->n_molecules)
     {
-        found_id = TNG_FALSE;
-        for(i = tng_data->n_molecules; i--;)
-        {
-            if(tng_data->molecules[i].id == id)
-            {
-                found_id = TNG_TRUE;
-                i = 0;
-            }
-        }
-        if(found_id)
-        {
-            id++;
-        }
+        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
+    }
+    else
+    {
+        id = 1;
     }
 
     return(tng_molecule_w_id_add(tng_data, name, id, molecule));
@@ -7297,7 +7997,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
                  tng_molecule_t *molecule)
 {
     tng_molecule_t new_molecules;
-    int64_t *new_molecule_cnt_list, i;
+    int64_t *new_molecule_cnt_list;
     tng_function_status stat = TNG_SUCCESS;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -7309,7 +8009,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
 
     if(!new_molecules)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
                __FILE__, __LINE__);
         free(tng_data->molecules);
@@ -7323,7 +8023,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
 
     if(!new_molecule_cnt_list)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * (tng_data->n_molecules + 1),
                __FILE__, __LINE__);
         free(tng_data->molecule_cnt_list);
@@ -7343,17 +8043,6 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
     /* FIXME: Should this be a function argument instead? */
     tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
 
-    for(i = tng_data->n_molecules; i--;)
-    {
-        if(tng_data->molecules[i].id == id)
-        {
-            stat = TNG_FAILURE;
-            fprintf(stderr, "TNG library: Molecule ID %"PRId64" already in use. %s: %d\n", id,
-                   __FILE__, __LINE__);
-            break;
-        }
-    }
-
     (*molecule)->id = id;
 
     tng_data->n_molecules++;
@@ -7365,29 +8054,19 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
                 (tng_trajectory_t tng_data,
                  tng_molecule_t *molecule_p)
 {
-    tng_bool found_id = TNG_TRUE;
+    int64_t *new_molecule_cnt_list, id;
     tng_molecule_t new_molecules, molecule;
-    int64_t *new_molecule_cnt_list, i, id;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-    /* Find an unused ID */
-    id = 0;
-    while(found_id)
+    /* Set ID to the ID of the last molecule + 1 */
+    if(tng_data->n_molecules)
     {
-        found_id = TNG_FALSE;
-        for(i = tng_data->n_molecules; i--;)
-        {
-            if(tng_data->molecules[i].id == id)
-            {
-                found_id = TNG_TRUE;
-                i = 0;
-            }
-        }
-        if(found_id)
-        {
-            id++;
-        }
+        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
+    }
+    else
+    {
+        id = 1;
     }
 
     new_molecules = realloc(tng_data->molecules,
@@ -7396,7 +8075,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
 
     if(!new_molecules)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
                __FILE__, __LINE__);
         free(tng_data->molecules);
@@ -7410,7 +8089,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
 
     if(!new_molecule_cnt_list)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * (tng_data->n_molecules + 1),
                __FILE__, __LINE__);
         free(tng_data->molecule_cnt_list);
@@ -7506,12 +8185,12 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
 
-    for(i = tng_data->n_molecules; i--;)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
         if(&tng_data->molecules[i] == molecule)
         {
             index = i;
-            i = 0;
+            break;
         }
     }
     if(index == -1)
@@ -7532,12 +8211,12 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-    for(i = tng_data->n_molecules; i--;)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
         if(&tng_data->molecules[i] == molecule)
         {
             index = i;
-            i = 0;
+            break;
         }
     }
     if(index == -1)
@@ -7580,7 +8259,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_find
 
     n_molecules = tng_data->n_molecules;
 
-    for(i = 0; i < n_molecules; i++)
+    for(i = n_molecules - 1; i >= 0; i--)
     {
         *molecule = &tng_data->molecules[i];
         if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
@@ -7641,7 +8320,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t
                     sizeof(struct tng_molecule) * tng_data_src->n_molecules);
     if(!molecule_temp)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_molecule) * tng_data_src->n_molecules,
                __FILE__, __LINE__);
         free(tng_data_dest->molecules);
@@ -7652,7 +8331,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t
                                      sizeof(int64_t) * tng_data_src->n_molecules);
     if(!list_temp)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * tng_data_src->n_molecules,
                __FILE__, __LINE__);
         free(tng_data_dest->molecule_cnt_list);
@@ -7716,21 +8395,24 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t
             }
         }
         molecule_temp->n_bonds = molecule->n_bonds;
-        bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
-                            molecule->n_bonds);
-        if(!bond_temp)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                   sizeof(struct tng_bond) * molecule->n_bonds,
-                   __FILE__, __LINE__);
-            free(molecule_temp->bonds);
-            molecule_temp->n_bonds = 0;
-            return(TNG_CRITICAL);
-        }
-        molecule_temp->bonds = bond_temp;
-        for(j = 0; j < molecule->n_bonds; j++)
+        if(molecule->n_bonds > 0)
         {
-            molecule_temp->bonds[j] = molecule->bonds[j];
+            bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
+                                molecule->n_bonds);
+            if(!bond_temp)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                       sizeof(struct tng_bond) * molecule->n_bonds,
+                       __FILE__, __LINE__);
+                free(molecule_temp->bonds);
+                molecule_temp->n_bonds = 0;
+                return(TNG_CRITICAL);
+            }
+            molecule_temp->bonds = bond_temp;
+            for(j = 0; j < molecule->n_bonds; j++)
+            {
+                molecule_temp->bonds[j] = molecule->bonds[j];
+            }
         }
         stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
                                     tng_data_src->molecule_cnt_list[i]);
@@ -7858,7 +8540,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
 
     n_chains = molecule->n_chains;
 
-    for(i = 0; i < n_chains; i++)
+    for(i = n_chains - 1; i >= 0; i--)
     {
         *chain = &molecule->chains[i];
         if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
@@ -7881,11 +8563,23 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
                  const char *name,
                  tng_chain_t *chain)
 {
+    int64_t id;
+
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
+    /* Set ID to the ID of the last chain + 1 */
+    if(molecule->n_chains)
+    {
+        id = molecule->chains[molecule->n_chains-1].id + 1;
+    }
+    else
+    {
+        id = 1;
+    }
+
     return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
-                                       molecule->n_chains + 1, chain));
+                                       id, chain));
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
@@ -7895,7 +8589,6 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
                  const int64_t id,
                  tng_chain_t *chain)
 {
-    int64_t i;
     tng_chain_t new_chains;
     tng_function_status stat = TNG_SUCCESS;
 
@@ -7908,7 +8601,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
 
     if(!new_chains)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_chain) * (molecule->n_chains + 1),
                __FILE__, __LINE__);
         free(molecule->chains);
@@ -7926,16 +8619,6 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
     (*chain)->molecule = molecule;
     (*chain)->n_residues = 0;
 
-    for(i = molecule->n_chains; i--;)
-    {
-        if(molecule->chains[i].id == id)
-        {
-            stat = TNG_FAILURE;
-            fprintf(stderr, "TNG library: Chain ID already in use. %s: %d\n", __FILE__, __LINE__);
-            break;
-        }
-    }
-
     molecule->n_chains++;
 
     (*chain)->id = id;
@@ -7950,28 +8633,16 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
                  const int64_t to_atom_id,
                  tng_bond_t *bond)
 {
-    int64_t i;
     tng_bond_t new_bonds;
     (void)tng_data;
 
-    for(i = 0; i < molecule->n_bonds; i++)
-    {
-        *bond = &molecule->bonds[i];
-        /* Check if the bond already exists */
-        if(((*bond)->from_atom_id == from_atom_id && (*bond)->to_atom_id == to_atom_id) ||
-           ((*bond)->to_atom_id == from_atom_id && (*bond)->from_atom_id == to_atom_id))
-        {
-            return(TNG_SUCCESS);
-        }
-    }
-
     new_bonds = realloc(molecule->bonds,
                         sizeof(struct tng_bond) *
                         (molecule->n_bonds + 1));
 
     if(!new_bonds)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_bond) * (molecule->n_bonds + 1),
                __FILE__, __LINE__);
         *bond = 0;
@@ -8006,7 +8677,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
 
     n_atoms = molecule->n_atoms;
 
-    for(i = 0; i < n_atoms; i++)
+    for(i = n_atoms - 1; i >= 0; i--)
     {
         *atom = &molecule->atoms[i];
         if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
@@ -8124,7 +8795,7 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
 
     n_residues = chain->n_residues;
 
-    for(i = 0; i < n_residues; i++)
+    for(i = n_residues - 1; i >= 0; i--)
     {
         *residue = &chain->residues[i];
         if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
@@ -8147,11 +8818,23 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
                  const char *name,
                  tng_residue_t *residue)
 {
+    int64_t id;
+
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
+    /* Set ID to the ID of the last residue + 1 */
+    if(chain->n_residues)
+    {
+        id = chain->residues[chain->n_residues-1].id + 1;
+    }
+    else
+    {
+        id = 0;
+    }
+
     return(tng_chain_residue_w_id_add(tng_data, chain, name,
-                                      chain->n_residues + 1, residue));
+                                      id, residue));
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
@@ -8161,7 +8844,7 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
                  const int64_t id,
                  tng_residue_t *residue)
 {
-    int64_t i, curr_index;
+    int64_t curr_index;
     tng_residue_t new_residues, temp_residue, last_residue;
     tng_molecule_t molecule = chain->molecule;
     tng_function_status stat = TNG_SUCCESS;
@@ -8184,7 +8867,7 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
 
     if(!new_residues)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_residue) * (molecule->n_residues + 1),
                __FILE__, __LINE__);
         free(molecule->residues);
@@ -8223,6 +8906,10 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
     {
         chain->residues = *residue;
     }
+    else
+    {
+        chain->residues = &molecule->residues[curr_index];
+    }
 
     (*residue)->name = 0;
     tng_residue_name_set(tng_data, *residue, name);
@@ -8231,16 +8918,6 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
     (*residue)->n_atoms = 0;
     (*residue)->atoms_offset = 0;
 
-    for(i = chain->n_residues; i--;)
-    {
-        if(chain->residues[i].id == id)
-        {
-            stat = TNG_FAILURE;
-            fprintf(stderr, "TNG library: Residue ID already in use. %s: %d\n", __FILE__, __LINE__);
-            break;
-        }
-    }
-
     chain->n_residues++;
     molecule->n_residues++;
 
@@ -8355,13 +9032,24 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
                  const char *atom_type,
                  tng_atom_t *atom)
 {
+    int64_t id;
+
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
     TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
 
+    /* Set ID to the ID of the last atom + 1 */
+    if(residue->chain->molecule->n_atoms)
+    {
+        id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
+    }
+    else
+    {
+        id = 0;
+    }
+
     return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
-                                     residue->chain->molecule->n_atoms + 1,
-                                     atom));
+                                     id, atom));
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
@@ -8372,7 +9060,6 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
                  const int64_t id,
                  tng_atom_t *atom)
 {
-    int64_t i;
     tng_atom_t new_atoms;
     tng_molecule_t molecule = residue->chain->molecule;
     tng_function_status stat = TNG_SUCCESS;
@@ -8392,7 +9079,7 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
 
     if(!new_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_atom) * (molecule->n_atoms + 1),
                __FILE__, __LINE__);
         free(molecule->atoms);
@@ -8410,16 +9097,6 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
 
     (*atom)->residue = residue;
 
-    for(i = molecule->n_atoms; i--;)
-    {
-        if(molecule->atoms[i].id == id)
-        {
-            stat = TNG_FAILURE;
-            fprintf(stderr, "TNG library: Atom ID %"PRId64" already in use. %s: %d\n", id, __FILE__, __LINE__);
-            break;
-        }
-    }
-
     residue->n_atoms++;
     molecule->n_atoms++;
 
@@ -8434,7 +9111,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t
     *molecule_p = malloc(sizeof(struct tng_molecule));
     if(!*molecule_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
                sizeof(struct tng_molecule), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -8492,7 +9169,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_
 
     if(molecule->chains)
     {
-        for(i = molecule->n_chains; i--;)
+        for(i = 0; i < molecule->n_chains; i++)
         {
             if(molecule->chains[i].name)
             {
@@ -8507,7 +9184,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_
 
     if(molecule->residues)
     {
-        for(i = molecule->n_residues; i--;)
+        for(i = 0; i < molecule->n_residues; i++)
         {
             if(molecule->residues[i].name)
             {
@@ -8522,7 +9199,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_
 
     if(molecule->atoms)
     {
-        for(i = molecule->n_atoms; i--;)
+        for(i = 0; i < molecule->n_atoms; i++)
         {
             tng_atom_destroy(&molecule->atoms[i]);
         }
@@ -8666,14 +9343,14 @@ tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
     *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
     if(!*from_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
     *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
     if(!*to_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
         free(*from_atoms);
         *from_atoms = 0;
@@ -9055,7 +9732,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
 
     if(!mapping)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
                __FILE__, __LINE__);
         free(frame_set->mappings);
@@ -9070,7 +9747,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
     frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
     if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(int64_t) * n_particles, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -9095,7 +9772,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_tr
 
     if(frame_set->n_mapping_blocks && frame_set->mappings)
     {
-        for(i = frame_set->n_mapping_blocks; i--;)
+        for(i = 0; i < frame_set->n_mapping_blocks; i++)
         {
             mapping = &frame_set->mappings[i];
             if(mapping->real_particle_numbers)
@@ -9121,7 +9798,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_
     *tng_data_p = malloc(sizeof(struct tng_trajectory));
     if(!*tng_data_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
                sizeof(struct tng_trajectory), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -9165,7 +9842,6 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_
     tng_data->current_trajectory_frame_set_output_file_pos = -1;
     tng_data->frame_set_n_frames = 100;
     tng_data->n_trajectory_frame_sets = 0;
-    tng_data->n_trajectory_blocks = 0;
     tng_data->medium_stride_length = 100;
     tng_data->long_stride_length = 10000;
 
@@ -9303,6 +9979,11 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(tng_data->input_file)
     {
+        if(tng_data->output_file == tng_data->input_file)
+        {
+            tng_frame_set_finalize(tng_data, TNG_USE_HASH);
+            tng_data->output_file = 0;
+        }
         fclose(tng_data->input_file);
         tng_data->input_file = 0;
     }
@@ -9394,7 +10075,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(tng_data->non_tr_particle_data)
     {
-        for(i = tng_data->n_particle_data_blocks; i--; )
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
         {
             if(tng_data->non_tr_particle_data[i].values)
             {
@@ -9408,11 +10089,11 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
                                      n_values_per_frame;
                 if(tng_data->non_tr_particle_data[i].strings[0])
                 {
-                    for(j = n_particles; j--;)
+                    for(j = 0; j < n_particles; j++)
                     {
                         if(tng_data->non_tr_particle_data[i].strings[0][j])
                         {
-                            for(k = n_values_per_frame; k--;)
+                            for(k = 0; k < n_values_per_frame; k++)
                             {
                                 if(tng_data->non_tr_particle_data[i].
                                    strings[0][j][k])
@@ -9447,7 +10128,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(tng_data->non_tr_data)
     {
-        for(i = tng_data->n_data_blocks; i--;)
+        for(i = 0; i < tng_data->n_data_blocks; i++)
         {
             if(tng_data->non_tr_data[i].values)
             {
@@ -9461,7 +10142,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
                                      n_values_per_frame;
                 if(tng_data->non_tr_data[i].strings[0])
                 {
-                    for(j = n_values_per_frame; j--;)
+                    for(j = 0; j < n_values_per_frame; j++)
                     {
                         if(tng_data->non_tr_data[i].strings[0][j])
                         {
@@ -9502,7 +10183,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(frame_set->tr_particle_data)
     {
-        for(i = frame_set->n_particle_data_blocks; i--; )
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
             if(frame_set->tr_particle_data[i].values)
             {
@@ -9514,16 +10195,16 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
             {
                 n_values_per_frame = frame_set->tr_particle_data[i].
                                      n_values_per_frame;
-                for(j = frame_set->tr_particle_data[i].n_frames; j--;)
+                for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
                 {
                     if(frame_set->tr_particle_data[i].strings[j])
                     {
-                        for(k = n_particles; k--;)
+                        for(k = 0; k < n_particles; k++)
                         {
                             if(frame_set->tr_particle_data[i].
                                 strings[j][k])
                             {
-                                for(l = n_values_per_frame; l--;)
+                                for(l = 0; l < n_values_per_frame; l++)
                                 {
                                     if(frame_set->tr_particle_data[i].
                                         strings[j][k][l])
@@ -9560,7 +10241,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(frame_set->tr_data)
     {
-        for(i = frame_set->n_data_blocks; i--;)
+        for(i = 0; i < frame_set->n_data_blocks; i++)
         {
             if(frame_set->tr_data[i].values)
             {
@@ -9572,11 +10253,11 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
             {
                 n_values_per_frame = frame_set->tr_data[i].
                                      n_values_per_frame;
-                for(j = frame_set->tr_data[i].n_frames; j--;)
+                for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
                 {
                     if(frame_set->tr_data[i].strings[j])
                     {
-                        for(k = n_values_per_frame; k--;)
+                        for(k = 0; k < n_values_per_frame; k++)
                         {
                             if(frame_set->tr_data[i].strings[j][k])
                             {
@@ -9607,7 +10288,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *t
 
     if(tng_data->molecules)
     {
-        for(i=tng_data->n_molecules; i--;)
+        for(i = 0; i < tng_data->n_molecules; i++)
         {
             tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
         }
@@ -9638,7 +10319,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajector
     *dest_p = malloc(sizeof(struct tng_trajectory));
     if(!*dest_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
                sizeof(struct tng_trajectory), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -9692,7 +10373,6 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajector
     src->current_trajectory_frame_set_output_file_pos;
     dest->frame_set_n_frames = src->frame_set_n_frames;
     dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
-    dest->n_trajectory_blocks = src->n_trajectory_blocks;
     dest->medium_stride_length = src->medium_stride_length;
     dest->long_stride_length = src->long_stride_length;
 
@@ -9896,6 +10576,7 @@ tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
                 tng_data->output_file_path, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
+    tng_data->input_file = tng_data->output_file;
 
     return(TNG_SUCCESS);
 }
@@ -9985,7 +10666,7 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
 
     /* Tne endianness cannot be changed if the data has already been written
      * to the output file. */
-    if(ftell(tng_data->output_file) > 0)
+    if(ftello(tng_data->output_file) > 0)
     {
         return(TNG_FAILURE);
     }
@@ -10609,14 +11290,13 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
 {
     tng_gen_block_t block;
     tng_function_status stat;
-    long file_pos;
-    int64_t last_file_pos, first_frame, n_frames;
+    int64_t file_pos, last_file_pos, first_frame, n_frames;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
     TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
 
-    file_pos = ftell(tng_data->input_file);
+    file_pos = ftello(tng_data->input_file);
     last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
 
     if(last_file_pos <= 0)
@@ -10625,9 +11305,9 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
     }
 
     tng_block_init(&block);
-    fseek(tng_data->input_file,
-          (long)last_file_pos,
-          SEEK_SET);
+    fseeko(tng_data->input_file,
+           last_file_pos,
+           SEEK_SET);
     /* Read block headers first to see that a frame set block is found. */
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -10651,7 +11331,7 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
                __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
-    fseek(tng_data->input_file, file_pos, SEEK_SET);
+    fseeko(tng_data->input_file, file_pos, SEEK_SET);
 
     *n = first_frame + n_frames;
 
@@ -10831,7 +11511,7 @@ tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
         return(TNG_FAILURE);
     }
 
-    for(i = tng_data->n_molecules; i --;)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
         cnt += cnt_list[i];
     }
@@ -10914,9 +11594,9 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
                  int64_t *n)
 {
     int64_t long_stride_length, medium_stride_length;
-    long file_pos, orig_frame_set_file_pos;
+    int64_t file_pos, orig_frame_set_file_pos;
     tng_trajectory_frame_set_t frame_set;
-    struct tng_trajectory_frame_set   orig_frame_set;
+    struct tng_trajectory_frame_set orig_frame_set;
     tng_gen_block_t block;
     tng_function_status stat;
     int64_t cnt = 0;
@@ -10929,10 +11609,16 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
     frame_set = &tng_data->current_trajectory_frame_set;
 
     orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
-    file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+    file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
+
+    if(file_pos < 0)
+    {
+        *n = tng_data->n_trajectory_frame_sets = cnt;
+        return(TNG_SUCCESS);
+    }
 
     tng_block_init(&block);
-    fseek(tng_data->input_file,
+    fseeko(tng_data->input_file,
           file_pos,
           SEEK_SET);
     tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
@@ -10940,7 +11626,7 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n", file_pos,
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
                 __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
@@ -10960,18 +11646,18 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
 
     /* Take long steps forward until a long step forward would be too long or
      * the last frame set is found */
-    file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
+    file_pos = frame_set->long_stride_next_frame_set_file_pos;
     while(file_pos > 0)
     {
         if(file_pos > 0)
         {
             cnt += long_stride_length;
-            fseek(tng_data->input_file, file_pos, SEEK_SET);
+            fseeko(tng_data->input_file, file_pos, SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
             {
-                fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+                fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                        file_pos, __FILE__, __LINE__);
                 tng_block_destroy(&block);
                 return(TNG_CRITICAL);
@@ -10984,25 +11670,25 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
                 return(TNG_CRITICAL);
             }
         }
-        file_pos = (long)frame_set->long_stride_next_frame_set_file_pos;
+        file_pos = frame_set->long_stride_next_frame_set_file_pos;
     }
 
     /* Take medium steps forward until a medium step forward would be too long
      * or the last frame set is found */
-    file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
+    file_pos = frame_set->medium_stride_next_frame_set_file_pos;
     while(file_pos > 0)
     {
         if(file_pos > 0)
         {
             cnt += medium_stride_length;
-            fseek(tng_data->input_file,
+            fseeko(tng_data->input_file,
                   file_pos,
                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
             {
-                fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+                fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                        file_pos, __FILE__, __LINE__);
                 tng_block_destroy(&block);
                 return(TNG_CRITICAL);
@@ -11015,24 +11701,24 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
                 return(TNG_CRITICAL);
             }
         }
-        file_pos = (long)frame_set->medium_stride_next_frame_set_file_pos;
+        file_pos = frame_set->medium_stride_next_frame_set_file_pos;
     }
 
     /* Take one step forward until the last frame set is found */
-    file_pos = (long)frame_set->next_frame_set_file_pos;
+    file_pos = frame_set->next_frame_set_file_pos;
     while(file_pos > 0)
     {
         if(file_pos > 0)
         {
             ++cnt;
-            fseek(tng_data->input_file,
+            fseeko(tng_data->input_file,
                   file_pos,
                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
             {
-                fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+                fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                        file_pos, __FILE__, __LINE__);
                 tng_block_destroy(&block);
                 return(TNG_CRITICAL);
@@ -11045,7 +11731,7 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
                 return(TNG_CRITICAL);
             }
         }
-        file_pos = (long)frame_set->next_frame_set_file_pos;
+        file_pos = frame_set->next_frame_set_file_pos;
     }
 
     tng_block_destroy(&block);
@@ -11053,10 +11739,14 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
     *n = tng_data->n_trajectory_frame_sets = cnt;
 
     *frame_set = orig_frame_set;
+    /* The mapping block in the original frame set has been freed when reading
+     * other frame sets. */
+    frame_set->mappings = 0;
+    frame_set->n_mapping_blocks = 0;
 
-    fseek(tng_data->input_file,
-          (long)tng_data->first_trajectory_frame_set_input_file_pos,
-          SEEK_SET);
+    fseeko(tng_data->input_file,
+           tng_data->first_trajectory_frame_set_input_file_pos,
+           SEEK_SET);
 
     tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
 
@@ -11123,10 +11813,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
     }
 
     tng_block_init(&block);
-    fseek(tng_data->input_file,
-          (long)file_pos,
-          SEEK_SET);
-    tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
+    fseeko(tng_data->input_file,
+           file_pos,
+           SEEK_SET);
+    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
     /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11160,7 +11850,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             curr_nr += long_stride_length;
-            fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
+            fseeko(tng_data->input_file, file_pos, SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11172,7 +11862,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
             }
 
             if(tng_block_read_next(tng_data, block,
-                                TNG_SKIP_HASH) != TNG_SUCCESS)
+                                   TNG_SKIP_HASH) != TNG_SUCCESS)
             {
                 tng_block_destroy(&block);
                 return(TNG_CRITICAL);
@@ -11193,9 +11883,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             curr_nr += medium_stride_length;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11228,9 +11918,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             ++curr_nr;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11263,9 +11953,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             curr_nr -= long_stride_length;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11298,9 +11988,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             curr_nr -= medium_stride_length;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11332,9 +12022,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             --curr_nr;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11367,9 +12057,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
         if(file_pos > 0)
         {
             ++curr_nr;
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11419,10 +12109,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
     if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
     {
         file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
-        fseek(tng_data->input_file,
-                (long)file_pos,
-                SEEK_SET);
-        tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
+        fseeko(tng_data->input_file,
+               file_pos,
+               SEEK_SET);
+        tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
         /* Read block headers first to see what block is found. */
         stat = tng_block_header_read(tng_data, block);
         if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11502,10 +12192,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
 
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
-            tng_data->current_trajectory_frame_set_input_file_pos = (long)file_pos;
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
+            tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11544,7 +12234,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->long_stride_next_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file, (long)file_pos, SEEK_SET);
+            fseeko(tng_data->input_file, file_pos, SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11579,9 +12269,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->medium_stride_next_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11614,9 +12304,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->next_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11651,9 +12341,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->long_stride_prev_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11688,9 +12378,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11723,9 +12413,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->prev_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11759,9 +12449,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
         file_pos = frame_set->next_frame_set_file_pos;
         if(file_pos > 0)
         {
-            fseek(tng_data->input_file,
-                  (long)file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11912,11 +12602,55 @@ static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
 }
 */
 
+static tng_function_status tng_file_headers_len_get
+                (tng_trajectory_t tng_data,
+                 int64_t *len)
+{
+    int64_t orig_pos;
+    tng_gen_block_t block;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
+
+    *len = 0;
+
+    orig_pos = ftello(tng_data->input_file);
+
+    if(!tng_data->input_file_len)
+    {
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
+    }
+    fseeko(tng_data->input_file, 0, SEEK_SET);
+
+    tng_block_init(&block);
+    /* Read through the headers of non-trajectory blocks (they come before the
+     * trajectory blocks in the file) */
+    while (*len < tng_data->input_file_len &&
+           tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
+           block->id != -1 &&
+           block->id != TNG_TRAJECTORY_FRAME_SET)
+    {
+        *len += block->header_contents_size + block->block_contents_size;
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+    }
+
+    fseeko(tng_data->input_file, orig_pos, SEEK_SET);
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
                 (tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    int cnt = 0, prev_pos = 0;
+    int64_t prev_pos = 0;
     tng_gen_block_t block;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -11930,10 +12664,10 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
 
     if(!tng_data->input_file_len)
     {
-        fseek(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftell(tng_data->input_file);
-        fseek(tng_data->input_file, 0, SEEK_SET);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
     }
+    fseeko(tng_data->input_file, 0, SEEK_SET);
 
     tng_block_init(&block);
     /* Non trajectory blocks (they come before the trajectory
@@ -11943,18 +12677,14 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
            block->id != -1 &&
            block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        if(tng_block_read_next(tng_data, block,
-                               hash_mode) == TNG_SUCCESS)
-        {
-            cnt++;
-        }
-        prev_pos = ftell(tng_data->input_file);
+        tng_block_read_next(tng_data, block, hash_mode);
+        prev_pos = ftello(tng_data->input_file);
     }
 
     /* Go back if a trajectory block was encountered */
     if(block->id == TNG_TRAJECTORY_FRAME_SET)
     {
-        fseek(tng_data->input_file, prev_pos, SEEK_SET);
+        fseeko(tng_data->input_file, prev_pos, SEEK_SET);
     }
 
     tng_block_destroy(&block);
@@ -11967,7 +12697,9 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
                  const char hash_mode)
 {
     int i;
-    tng_gen_block_t data_block;
+    int64_t len, orig_len, tot_len = 0, data_start_pos;
+    tng_function_status stat;
+    tng_gen_block_t block;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
@@ -11976,6 +12708,69 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
         return(TNG_CRITICAL);
     }
 
+    if(tng_data->n_trajectory_frame_sets > 0)
+    {
+        stat = tng_file_headers_len_get(tng_data, &orig_len);
+        if(stat != TNG_SUCCESS)
+        {
+            return(stat);
+        }
+
+        tng_block_init(&block);
+        block->name = malloc(TNG_MAX_STR_LEN);
+        if(!block->name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                    TNG_MAX_STR_LEN, __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+        strcpy(block->name, "GENERAL INFO");
+        tng_block_header_len_calculate(tng_data, block, &len);
+        tot_len += len;
+        tng_general_info_block_len_calculate(tng_data, &len);
+        tot_len += len;
+        strcpy(block->name, "MOLECULES");
+        tng_block_header_len_calculate(tng_data, block, &len);
+        tot_len += len;
+        tng_molecules_block_len_calculate(tng_data, &len);
+        tot_len += len;
+
+        for(i = 0; i < tng_data->n_data_blocks; i++)
+        {
+            strcpy(block->name, tng_data->non_tr_data[i].block_name);
+            tng_block_header_len_calculate(tng_data, block, &len);
+            tot_len += len;
+            tng_data_block_len_calculate(tng_data,
+                                        (tng_particle_data_t)&tng_data->non_tr_data[i],
+                                        TNG_FALSE, 1, 1, 1, 0,
+                                        1, 0, &data_start_pos,
+                                        &len);
+            tot_len += len;
+        }
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
+        {
+            strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
+            tng_block_header_len_calculate(tng_data, block, &len);
+            tot_len += len;
+            tng_data_block_len_calculate(tng_data,
+                                        &tng_data->non_tr_particle_data[i],
+                                        TNG_TRUE, 1, 1, 1, 0,
+                                        tng_data->n_particles, TNG_PARTICLE_DEPENDENT,
+                                        &data_start_pos,
+                                        &len);
+            tot_len += len;
+        }
+        tng_block_destroy(&block);
+
+        if(tot_len > orig_len)
+        {
+            tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len);
+        }
+
+        tng_data->current_trajectory_frame_set_output_file_pos = -1;
+    }
+
     /* TODO: If there is already frame set data written to this file (e.g. when
      * appending to an already existing file we might need to move frame sets to
      * the end of the file. */
@@ -11998,22 +12793,22 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
 
     /* FIXME: Currently writing non-trajectory data blocks here.
      * Should perhaps be moved. */
-    tng_block_init(&data_block);
+    tng_block_init(&block);
     for(i = 0; i < tng_data->n_data_blocks; i++)
     {
-        data_block->id = tng_data->non_tr_data[i].block_id;
-        tng_data_block_write(tng_data, data_block,
+        block->id = tng_data->non_tr_data[i].block_id;
+        tng_data_block_write(tng_data, block,
                              i, hash_mode);
     }
 
     for(i = 0; i < tng_data->n_particle_data_blocks; i++)
     {
-        data_block->id = tng_data->non_tr_particle_data[i].block_id;
-        tng_particle_data_block_write(tng_data, data_block,
+        block->id = tng_data->non_tr_particle_data[i].block_id;
+        tng_particle_data_block_write(tng_data, block,
                                       i, 0, hash_mode);
     }
 
-    tng_block_destroy(&data_block);
+    tng_block_destroy(&block);
 
     return(TNG_SUCCESS);
 }
@@ -12043,7 +12838,7 @@ tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_d
         else
         {
             /* Skip to the next block */
-            fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
             return(TNG_FAILURE);
         }
     }
@@ -12053,7 +12848,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
                 (tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    long file_pos;
+    int64_t file_pos;
     tng_gen_block_t block;
     tng_function_status stat;
 
@@ -12064,22 +12859,23 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
         return(TNG_CRITICAL);
     }
 
-    file_pos = ftell(tng_data->input_file);
+    file_pos = ftello(tng_data->input_file);
 
     tng_block_init(&block);
 
     if(!tng_data->input_file_len)
     {
-        fseek(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftell(tng_data->input_file);
-        fseek(tng_data->input_file, file_pos, SEEK_SET);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
     }
 
     /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
+       block->id == -1)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
@@ -12091,18 +12887,19 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
                            hash_mode) == TNG_SUCCESS)
     {
         tng_data->n_trajectory_frame_sets++;
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
               stat != TNG_CRITICAL &&
-              block->id != TNG_TRAJECTORY_FRAME_SET)
+              block->id != TNG_TRAJECTORY_FRAME_SET &&
+              block->id != -1)
         {
             stat = tng_block_read_next(tng_data, block,
                                        hash_mode);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -12111,7 +12908,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
         }
         if(stat == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                    file_pos, __FILE__, __LINE__);
             tng_block_destroy(&block);
             return(stat);
@@ -12119,7 +12916,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
 
         if(block->id == TNG_TRAJECTORY_FRAME_SET)
         {
-            fseek(tng_data->input_file, file_pos, SEEK_SET);
+            fseeko(tng_data->input_file, file_pos, SEEK_SET);
         }
     }
 
@@ -12134,7 +12931,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
                  const char hash_mode,
                  const int64_t block_id)
 {
-    long file_pos;
+    int64_t file_pos;
     tng_gen_block_t block;
     tng_function_status stat;
     int found_flag = 1;
@@ -12146,19 +12943,19 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
         return(TNG_CRITICAL);
     }
 
-    file_pos = (long)tng_data->current_trajectory_frame_set_input_file_pos;
+    file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
 
     if(file_pos < 0)
     {
         /* No current frame set. This means that the first frame set must be
          * read */
         found_flag = 0;
-        file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
 
     if(file_pos > 0)
     {
-        fseek(tng_data->input_file,
+        fseeko(tng_data->input_file,
               file_pos,
               SEEK_SET);
     }
@@ -12171,16 +12968,16 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
 
     if(!tng_data->input_file_len)
     {
-        fseek(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftell(tng_data->input_file);
-        fseek(tng_data->input_file, file_pos, SEEK_SET);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
     }
 
     /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
@@ -12188,7 +12985,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
     /* If the current frame set had already been read skip its block contents */
     if(found_flag)
     {
-        fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
     }
     /* Otherwiese read the frame set block */
     else
@@ -12202,7 +12999,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
             return(stat);
         }
     }
-    file_pos = ftell(tng_data->input_file);
+    file_pos = ftello(tng_data->input_file);
 
     found_flag = 0;
 
@@ -12211,7 +13008,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
     stat = tng_block_header_read(tng_data, block);
     while(file_pos < tng_data->input_file_len &&
             stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
     {
         if(block->id == block_id)
         {
@@ -12219,7 +13017,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
                                        hash_mode);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 found_flag = 1;
                 if(file_pos < tng_data->input_file_len)
                 {
@@ -12229,8 +13027,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
         }
         else
         {
-            file_pos += (long)(block->block_contents_size + block->header_contents_size);
-            fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+            file_pos += (block->block_contents_size + block->header_contents_size);
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
             if(file_pos < tng_data->input_file_len)
             {
                 stat = tng_block_header_read(tng_data, block);
@@ -12239,7 +13037,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
     }
     if(stat == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                 file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(stat);
@@ -12247,7 +13045,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
 
     if(block->id == TNG_TRAJECTORY_FRAME_SET)
     {
-        fseek(tng_data->input_file, file_pos, SEEK_SET);
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
     }
 
     tng_block_destroy(&block);
@@ -12266,7 +13064,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
                 (tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    long file_pos;
+    int64_t file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
@@ -12275,16 +13073,16 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
         return(TNG_CRITICAL);
     }
 
-    file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
+    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
 
     if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
 
     if(file_pos > 0)
     {
-        fseek(tng_data->input_file,
+        fseeko(tng_data->input_file,
               file_pos,
               SEEK_SET);
     }
@@ -12301,7 +13099,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_blo
                  const char hash_mode,
                  const int64_t block_id)
 {
-    long file_pos;
+    int64_t file_pos;
     tng_gen_block_t block;
     tng_function_status stat;
 
@@ -12312,16 +13110,16 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_blo
         return(TNG_CRITICAL);
     }
 
-    file_pos = (long)tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
+    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
 
     if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
 
     if(file_pos > 0)
     {
-        fseek(tng_data->input_file,
+        fseeko(tng_data->input_file,
               file_pos,
               SEEK_SET);
     }
@@ -12334,16 +13132,16 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_blo
 
     if(!tng_data->input_file_len)
     {
-        fseek(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftell(tng_data->input_file);
-        fseek(tng_data->input_file, file_pos, SEEK_SET);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
     }
 
     /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
@@ -12380,7 +13178,7 @@ tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
     }
 
     tng_data->current_trajectory_frame_set_output_file_pos =
-    ftell(tng_data->output_file);
+    ftello(tng_data->output_file);
     tng_data->last_trajectory_frame_set_output_file_pos =
     tng_data->current_trajectory_frame_set_output_file_pos;
 
@@ -12491,7 +13289,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
 
     frame_set = &tng_data->current_trajectory_frame_set;
 
-    curr_pos = ftell(tng_data->output_file);
+    curr_pos = ftello(tng_data->output_file);
 
     if(curr_pos <= 10)
     {
@@ -12509,7 +13307,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
     }
 
     tng_data->current_trajectory_frame_set_output_file_pos =
-    ftell(tng_data->output_file);
+    ftello(tng_data->output_file);
 
     tng_data->n_trajectory_frame_sets++;
 
@@ -12529,10 +13327,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
             tng_block_init(&block);
             tng_data->input_file = tng_data->output_file;
 
-            curr_pos = ftell(tng_data->output_file);
-            fseek(tng_data->output_file,
-                  (long)frame_set->medium_stride_prev_frame_set_file_pos,
-                  SEEK_SET);
+            curr_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file,
+                   frame_set->medium_stride_prev_frame_set_file_pos,
+                   SEEK_SET);
 
             if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
             {
@@ -12545,8 +13343,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
 
             /* Read the next frame set from the previous frame set and one
              * medium stride step back */
-            fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
-                sizeof(int64_t), SEEK_CUR);
+            fseeko(tng_data->output_file, block->block_contents_size - (6 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
             if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
                sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
                1, tng_data->output_file) == 0)
@@ -12586,9 +13384,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
                     tng_block_init(&block);
                     tng_data->input_file = tng_data->output_file;
 
-                    fseek(tng_data->output_file,
-                          (long)frame_set->long_stride_prev_frame_set_file_pos,
-                          SEEK_SET);
+                    fseeko(tng_data->output_file,
+                           frame_set->long_stride_prev_frame_set_file_pos,
+                           SEEK_SET);
 
                     if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
                     {
@@ -12601,8 +13399,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
 
                     /* Read the next frame set from the previous frame set and one
                     * long stride step back */
-                    fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
-                          sizeof(int64_t), SEEK_CUR);
+                    fseeko(tng_data->output_file, block->block_contents_size - (6 *
+                          sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
                     tng_block_destroy(&block);
 
@@ -12630,7 +13428,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
             }
 
             tng_data->input_file = temp;
-            fseek(tng_data->output_file, (long)curr_pos, SEEK_SET);
+            fseeko(tng_data->output_file, curr_pos, SEEK_SET);
         }
     }
 
@@ -12700,7 +13498,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
                 (const tng_trajectory_t tng_data,
                  int64_t *frame)
 {
-    long file_pos, next_frame_set_file_pos;
+    int64_t file_pos, next_frame_set_file_pos;
     tng_gen_block_t block;
     tng_function_status stat;
 
@@ -12710,16 +13508,16 @@ tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
     TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
     TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
 
-    file_pos = ftell(tng_data->input_file);
+    file_pos = ftello(tng_data->input_file);
 
     if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        next_frame_set_file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
+        next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
     else
     {
         frame_set = &tng_data->current_trajectory_frame_set;
-        next_frame_set_file_pos = (long)frame_set->next_frame_set_file_pos;
+        next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
     }
 
     if(next_frame_set_file_pos <= 0)
@@ -12727,13 +13525,13 @@ tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
         return(TNG_FAILURE);
     }
 
-    fseek(tng_data->input_file, (long)next_frame_set_file_pos, SEEK_SET);
+    fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
     /* Read block headers first to see that a frame set block is found. */
     tng_block_init(&block);
     stat = tng_block_header_read(tng_data, block);
     if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                file_pos, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -12749,7 +13547,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
                __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
-    fseek(tng_data->input_file, file_pos, SEEK_SET);
+    fseeko(tng_data->input_file, file_pos, SEEK_SET);
 
     return(TNG_SUCCESS);
 }
@@ -13329,8 +14127,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
     int64_t header_pos, file_pos;
     int64_t output_file_len, n_values_per_frame, size, contents_size;
     int64_t header_size, temp_first, temp_last;
-    int64_t i, last_frame;
-    long temp_current;
+    int64_t i, last_frame, temp_current;
     tng_gen_block_t block;
     tng_trajectory_frame_set_t frame_set;
     FILE *temp = tng_data->input_file;
@@ -13385,10 +14182,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
             tng_frame_set_new(tng_data,
                               last_frame+1,
                               tng_data->frame_set_n_frames);
-            file_pos = ftell(tng_data->output_file);
-            fseek(tng_data->output_file, 0, SEEK_END);
-            output_file_len = ftell(tng_data->output_file);
-            fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
+            file_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, 0, SEEK_END);
+            output_file_len = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
             /* Read mapping blocks from the last frame set */
             tng_block_init(&block);
@@ -13396,7 +14193,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
             stat = tng_block_header_read(tng_data, block);
             while(file_pos < output_file_len &&
                   stat != TNG_CRITICAL &&
-                  block->id != TNG_TRAJECTORY_FRAME_SET)
+                  block->id != TNG_TRAJECTORY_FRAME_SET &&
+                  block->id != -1)
             {
                 if(block->id == TNG_PARTICLE_MAPPING)
                 {
@@ -13405,10 +14203,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
                 }
                 else
                 {
-                    fseek(tng_data->output_file, (long)block->block_contents_size,
-                        SEEK_CUR);
+                    fseeko(tng_data->output_file, block->block_contents_size,
+                           SEEK_CUR);
                 }
-                file_pos = ftell(tng_data->output_file);
+                file_pos = ftello(tng_data->output_file);
                 if(file_pos < output_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -13437,9 +14235,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
 
     file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
 
-    fseek(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftell(tng_data->output_file);
-    fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
+    fseeko(tng_data->output_file, 0, SEEK_END);
+    output_file_len = ftello(tng_data->output_file);
+    fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
     /* Read past the frame set block first */
     stat = tng_block_header_read(tng_data, block);
@@ -13455,8 +14253,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
         tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
         return(stat);
     }
-    fseek(tng_data->output_file, (long)block->block_contents_size,
-            SEEK_CUR);
+    fseeko(tng_data->output_file, block->block_contents_size,
+           SEEK_CUR);
 
     /* Read all block headers until next frame set block or
      * until the wanted block id is found */
@@ -13464,10 +14262,11 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
     while(file_pos < output_file_len &&
             stat != TNG_CRITICAL &&
             block->id != block_id &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
     {
-        fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
-        file_pos = ftell(tng_data->output_file);
+        fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
+        file_pos = ftello(tng_data->output_file);
         if(file_pos < output_file_len)
         {
             stat = tng_block_header_read(tng_data, block);
@@ -13488,7 +14287,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
     contents_size = block->block_contents_size;
     header_size = block->header_contents_size;
 
-    header_pos = ftell(tng_data->output_file) - header_size;
+    header_pos = ftello(tng_data->output_file) - header_size;
     frame_set = &tng_data->current_trajectory_frame_set;
 
     if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
@@ -13670,7 +14469,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
         return(TNG_FAILURE);
     }
 
-    fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
+    fseeko(tng_data->output_file, file_pos, SEEK_CUR);
 
     /* If the endianness is not big endian the data needs to be swapped */
     if((data.datatype == TNG_INT_DATA ||
@@ -13753,8 +14552,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
     int64_t output_file_len, n_values_per_frame, size, contents_size;
     int64_t header_size, temp_first, temp_last;
     int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
-    int64_t i, last_frame;
-    long temp_current;
+    int64_t i, last_frame, temp_current;
     tng_gen_block_t block;
     tng_trajectory_frame_set_t frame_set;
     FILE *temp = tng_data->input_file;
@@ -13813,10 +14611,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
                               last_frame+1,
                               tng_data->frame_set_n_frames);
 
-            file_pos = ftell(tng_data->output_file);
-            fseek(tng_data->output_file, 0, SEEK_END);
-            output_file_len = ftell(tng_data->output_file);
-            fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
+            file_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, 0, SEEK_END);
+            output_file_len = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
             /* Read mapping blocks from the last frame set */
             tng_block_init(&block);
@@ -13824,7 +14622,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
             stat = tng_block_header_read(tng_data, block);
             while(file_pos < output_file_len &&
                   stat != TNG_CRITICAL &&
-                  block->id != TNG_TRAJECTORY_FRAME_SET)
+                  block->id != TNG_TRAJECTORY_FRAME_SET &&
+                  block->id != -1)
             {
                 if(block->id == TNG_PARTICLE_MAPPING)
                 {
@@ -13833,10 +14632,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
                 }
                 else
                 {
-                    fseek(tng_data->output_file, (long)block->block_contents_size,
+                    fseeko(tng_data->output_file, block->block_contents_size,
                         SEEK_CUR);
                 }
-                file_pos = ftell(tng_data->output_file);
+                file_pos = ftello(tng_data->output_file);
                 if(file_pos < output_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -13866,9 +14665,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
 
     file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
 
-    fseek(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftell(tng_data->output_file);
-    fseek(tng_data->output_file, (long)file_pos, SEEK_SET);
+    fseeko(tng_data->output_file, 0, SEEK_END);
+    output_file_len = ftello(tng_data->output_file);
+    fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
     /* Read past the frame set block first */
     stat = tng_block_header_read(tng_data, block);
@@ -13884,7 +14683,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
         tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
         return(stat);
     }
-    fseek(tng_data->output_file, (long)block->block_contents_size,
+    fseeko(tng_data->output_file, block->block_contents_size,
             SEEK_CUR);
 
     if(tng_data->var_num_atoms_flag)
@@ -13903,7 +14702,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < output_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             if(block->id == TNG_PARTICLE_MAPPING)
             {
@@ -13911,10 +14711,10 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
             }
             else
             {
-                fseek(tng_data->output_file, (long)block->block_contents_size,
+                fseeko(tng_data->output_file, block->block_contents_size,
                       SEEK_CUR);
             }
-            file_pos = ftell(tng_data->output_file);
+            file_pos = ftello(tng_data->output_file);
             if(block->id == TNG_PARTICLE_MAPPING)
             {
                 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
@@ -13954,7 +14754,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
             tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
             return(TNG_FAILURE);
         }
-        fseek(tng_data->output_file, (long)mapping_block_end_pos, SEEK_SET);
+        fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
     }
 
     /* Read all block headers until next frame set block or
@@ -13964,10 +14764,11 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
             stat != TNG_CRITICAL &&
             block->id != block_id &&
             block->id != TNG_PARTICLE_MAPPING &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
     {
-        fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
-        file_pos = ftell(tng_data->output_file);
+        fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
+        file_pos = ftello(tng_data->output_file);
         if(file_pos < output_file_len)
         {
             stat = tng_block_header_read(tng_data, block);
@@ -13989,7 +14790,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
     contents_size = block->block_contents_size;
     header_size = block->header_contents_size;
 
-    header_pos = ftell(tng_data->output_file) - header_size;
+    header_pos = ftello(tng_data->output_file) - header_size;
     frame_set = &tng_data->current_trajectory_frame_set;
 
     if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
@@ -14213,7 +15014,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
         return(TNG_FAILURE);
     }
 
-    fseek(tng_data->output_file, (long)file_pos, SEEK_CUR);
+    fseeko(tng_data->output_file, file_pos, SEEK_CUR);
 
     /* If the endianness is not big endian the data needs to be swapped */
     if((data.datatype == TNG_INT_DATA ||
@@ -14312,20 +15113,20 @@ static tng_function_status tng_data_values_alloc
     *values = malloc(sizeof(union data_values *) * n_frames);
     if(!*values)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(union data_values **) * n_frames,
                __FILE__, __LINE__);
         return(TNG_CRITICAL);
 
     }
 
-    for(i = n_frames; i--;)
+    for(i = 0; i < n_frames; i++)
     {
         (*values)[i] = malloc(sizeof(union data_values) *
                            n_values_per_frame);
         if(!(*values)[i])
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                    sizeof(union data_values) * n_values_per_frame,
                    __FILE__, __LINE__);
             free(values);
@@ -14355,7 +15156,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_values_free
             {
                 if(type == TNG_CHAR_DATA)
                 {
-                    for(j = n_values_per_frame; j--;)
+                    for(j = 0; j < n_values_per_frame; j++)
                     {
                         if(values[i][j].c)
                         {
@@ -14406,33 +15207,33 @@ static tng_function_status tng_particle_data_values_alloc
     *values = malloc(sizeof(union data_values **) * n_frames);
     if(!*values)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                sizeof(union data_values **) * n_frames,
                __FILE__, __LINE__);
         return(TNG_CRITICAL);
 
     }
 
-    for(i = n_frames; i--;)
+    for(i = 0; i < n_frames; i++)
     {
         (*values)[i] = malloc(sizeof(union data_values *) *
                            n_particles);
         if(!(*values)[i])
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                    sizeof(union data_values *) * n_particles,
                    __FILE__, __LINE__);
             free(*values);
             *values = 0;
             return(TNG_CRITICAL);
         }
-        for(j = n_particles; j--;)
+        for(j = 0; j < n_particles; j++)
         {
             (*values)[i][j] = malloc(sizeof(union data_values) *
                                   n_values_per_frame);
             if(!(*values)[i][j])
             {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                     sizeof(union data_values *) * n_particles,
                     __FILE__, __LINE__);
                 tng_particle_data_values_free(tng_data, *values, n_frames,
@@ -14468,7 +15269,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
                 {
                     if(type == TNG_CHAR_DATA)
                     {
-                        for(k = n_values_per_frame; k--;)
+                        for(k = 0; k < n_values_per_frame; k++)
                         {
                             if(values[i][j][k].c)
                             {
@@ -14521,19 +15322,20 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
     if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
     {
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             /* Use hash by default */
             stat = tng_block_read_next(tng_data, block,
                                     TNG_USE_HASH);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -14548,7 +15350,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
             return(stat);
         }
 
-        for(i = frame_set->n_data_blocks; i-- ;)
+        for(i = 0; i < frame_set->n_data_blocks; i++)
         {
             data = &frame_set->tr_data[i];
             if(data->block_id == block_id)
@@ -14581,9 +15383,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
     switch(*type)
     {
     case TNG_CHAR_DATA:
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 len = strlen(data->strings[i][j]) + 1;
                 (*values)[i][j].c = malloc(len);
@@ -14593,9 +15395,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
         break;
     case TNG_INT_DATA:
         size = sizeof(int);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].i = *(int *)((char *)data->values + size *
                                              (i*(*n_values_per_frame) + j));
@@ -14604,9 +15406,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
         break;
     case TNG_FLOAT_DATA:
         size = sizeof(float);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].f = *(float *)((char *)data->values + size *
                                                (i*(*n_values_per_frame) + j));
@@ -14616,9 +15418,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
     case TNG_DOUBLE_DATA:
     default:
         size = sizeof(double);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].d = *(double *)((char *)data->values + size *
                                                 (i*(*n_values_per_frame) + j));
@@ -14661,19 +15463,20 @@ tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
     if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
     {
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             /* Use hash by default */
             stat = tng_block_read_next(tng_data, block,
                                     TNG_USE_HASH);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -14688,7 +15491,7 @@ tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
             return(stat);
         }
 
-        for(i = frame_set->n_data_blocks; i-- ;)
+        for(i = 0; i < frame_set->n_data_blocks; i++)
         {
             data = &frame_set->tr_data[i];
             if(data->block_id == block_id)
@@ -14789,18 +15592,19 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
        frame_set->n_data_blocks <= 0)
     {
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
             stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
         {
             stat = tng_block_read_next(tng_data, block,
                                     hash_mode);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -14819,7 +15623,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
 
     /* See if there is a data block of this ID.
      * Start checking the last read frame set */
-    for(i = frame_set->n_data_blocks; i-- ;)
+    for(i = 0; i < frame_set->n_data_blocks; i++)
     {
         data = &frame_set->tr_data[i];
         if(data->block_id == block_id)
@@ -14868,7 +15672,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 len = strlen(data->strings[current_frame_pos][j]) + 1;
                 (*values)[i][j].c = malloc(len);
@@ -14890,7 +15694,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].i = *(int *)((char *)data->values + size *
                                             (current_frame_pos *
@@ -14912,7 +15716,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].f = *(float *)((char *)data->values + size *
                                                (current_frame_pos *
@@ -14935,7 +15739,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_values_per_frame; j--;)
+            for(j = 0; j < *n_values_per_frame; j++)
             {
                 (*values)[i][j].d = *(double *)((char *)data->values + size *
                                                 (current_frame_pos *
@@ -14995,9 +15799,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
         tng_block_init(&block);
         if(stat != TNG_SUCCESS)
         {
-            fseek(tng_data->input_file,
-                  (long)tng_data->current_trajectory_frame_set_input_file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   tng_data->current_trajectory_frame_set_input_file_pos,
+                   SEEK_SET);
             stat = tng_block_header_read(tng_data, block);
             if(stat != TNG_SUCCESS)
             {
@@ -15006,14 +15810,15 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
                 return(stat);
             }
 
-            fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
         }
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
             stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
         {
             if(block->id == block_id)
             {
@@ -15021,7 +15826,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
                                         hash_mode);
                 if(stat != TNG_CRITICAL)
                 {
-                    file_pos = ftell(tng_data->input_file);
+                    file_pos = ftello(tng_data->input_file);
                     if(file_pos < tng_data->input_file_len)
                     {
                         stat = tng_block_header_read(tng_data, block);
@@ -15031,7 +15836,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
             else
             {
                 file_pos += block->block_contents_size + block->header_contents_size;
-                fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+                fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -15231,19 +16036,20 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
         }
 
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             /* Use hash by default */
             stat = tng_block_read_next(tng_data, block,
                                     TNG_USE_HASH);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -15258,7 +16064,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
             return(stat);
         }
 
-        for(i = frame_set->n_particle_data_blocks; i-- ;)
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
             data = &frame_set->tr_particle_data[i];
             if(data->block_id == block_id)
@@ -15316,12 +16122,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     switch(*type)
     {
     case TNG_CHAR_DATA:
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     len = strlen(data->strings[i][j][k]) + 1;
                     (*values)[i][mapping][k].c = malloc(len);
@@ -15334,12 +16140,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     case TNG_INT_DATA:
         size = sizeof(int);
         i_step = (*n_particles) * (*n_values_per_frame);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].i = *(int *)
                                                  ((char *)data->values + size *
@@ -15352,12 +16158,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     case TNG_FLOAT_DATA:
         size = sizeof(float);
         i_step = (*n_particles) * (*n_values_per_frame);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].f = *(float *)
                                                  ((char *)data->values + size *
@@ -15371,12 +16177,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     default:
         size = sizeof(double);
         i_step = (*n_particles) * (*n_values_per_frame);
-        for(i=*n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].d = *(double *)
                                                  ((char *)data->values + size *
@@ -15426,19 +16232,20 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
     if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
     {
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             /* Use hash by default */
             stat = tng_block_read_next(tng_data, block,
                                     TNG_USE_HASH);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -15453,7 +16260,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
             return(stat);
         }
 
-        for(i = frame_set->n_particle_data_blocks; i-- ;)
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
             data = &frame_set->tr_particle_data[i];
             if(data->block_id == block_id)
@@ -15534,9 +16341,9 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
     else
     {
         i_step = (*n_particles) * (*n_values_per_frame);
-        for(i = *n_frames; i--;)
+        for(i = 0; i < *n_frames; i++)
         {
-            for(j = *n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
                 memcpy(((char *)*values) + size * (i * i_step + mapping *
@@ -15596,18 +16403,19 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
        frame_set->n_particle_data_blocks <= 0)
     {
         tng_block_init(&block);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
         {
             stat = tng_block_read_next(tng_data, block,
                                     hash_mode);
             if(stat != TNG_CRITICAL)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -15686,10 +16494,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     len = strlen(data->strings[current_frame_pos][j][k]) + 1;
                     (*values)[i][mapping][k].c = malloc(len);
@@ -15713,10 +16521,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_particles; j--;)
+            for(j = 0; j < *n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k = 0; k < *n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].i = *(int *)
                                                  ((char *)data->values + size *
@@ -15742,10 +16550,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_particles; j--;)
+            for(j=0; j<*n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k=0; k<*n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].f = *(float *)
                                                  ((char *)data->values + size *
@@ -15772,10 +16580,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=*n_particles; j--;)
+            for(j=0; j<*n_particles; j++)
             {
                 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=*n_values_per_frame; k--;)
+                for(k=0; k<*n_values_per_frame; k++)
                 {
                     (*values)[i][mapping][k].d = *(double *)
                                                  ((char *)data->values + size *
@@ -15839,9 +16647,9 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
         tng_block_init(&block);
         if(stat != TNG_SUCCESS)
         {
-            fseek(tng_data->input_file,
-                  (long)tng_data->current_trajectory_frame_set_input_file_pos,
-                  SEEK_SET);
+            fseeko(tng_data->input_file,
+                   tng_data->current_trajectory_frame_set_input_file_pos,
+                   SEEK_SET);
             stat = tng_block_header_read(tng_data, block);
             if(stat != TNG_SUCCESS)
             {
@@ -15850,14 +16658,15 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
                 return(stat);
             }
 
-            fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
         }
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         /* Read until next frame set block */
         stat = tng_block_header_read(tng_data, block);
         while(file_pos < tng_data->input_file_len &&
             stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
         {
             if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
             {
@@ -15865,7 +16674,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
                                         hash_mode);
                 if(stat != TNG_CRITICAL)
                 {
-                    file_pos = ftell(tng_data->input_file);
+                    file_pos = ftello(tng_data->input_file);
                     if(file_pos < tng_data->input_file_len)
                     {
                         stat = tng_block_header_read(tng_data, block);
@@ -15875,7 +16684,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
             else
             {
                 file_pos += block->block_contents_size + block->header_contents_size;
-                fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+                fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
                 if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
@@ -16042,7 +16851,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
     tng_function_status stat;
     tng_non_particle_data_t np_data;
     tng_particle_data_t p_data;
-    long orig_file_pos, file_pos;
+    int64_t orig_file_pos, file_pos;
     int is_particle_data;
 
     if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
@@ -16069,11 +16878,11 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
             /* If no specific frame was required read until this data block is found */
             if(frame < 0)
             {
-                file_pos = ftell(tng_data->input_file);
+                file_pos = ftello(tng_data->input_file);
                 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
                 {
                     stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-                    file_pos = ftell(tng_data->input_file);
+                    file_pos = ftello(tng_data->input_file);
                 }
             }
             if(stat != TNG_SUCCESS)
@@ -16173,7 +16982,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         /* Read the file headers */
         tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
 
-        tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+        stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+
+        if(stat != TNG_SUCCESS)
+        {
+            return(stat);
+        }
     }
 
     if(mode == 'w')
@@ -16182,9 +16996,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
     }
     else if(mode == 'a')
     {
-        fseek((*tng_data_p)->input_file,
-                (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
-                SEEK_SET);
+        if((*tng_data_p)->output_file)
+        {
+            fclose((*tng_data_p)->output_file);
+        }
+        (*tng_data_p)->output_file = (*tng_data_p)->input_file;
+        fseeko((*tng_data_p)->input_file,
+               (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
+               SEEK_SET);
 
         stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
@@ -16192,6 +17011,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
             fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
                    __FILE__, __LINE__);
         }
+        (*tng_data_p)->output_file = 0;
 
         (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
         (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
@@ -16199,9 +17019,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
         (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
         (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
-        (*tng_data_p)->first_trajectory_frame_set_input_file_pos = -1;
-        (*tng_data_p)->last_trajectory_frame_set_input_file_pos = -1;
-        (*tng_data_p)->current_trajectory_frame_set_input_file_pos = -1;
         if((*tng_data_p)->input_file)
         {
             fclose((*tng_data_p)->input_file);
@@ -16214,7 +17031,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         }
         tng_output_append_file_set(*tng_data_p, filename);
 
-        fseek((*tng_data_p)->output_file, 0, SEEK_END);
+        fseeko((*tng_data_p)->output_file, 0, SEEK_END);
     }
 
     return(TNG_SUCCESS);
@@ -16562,9 +17379,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     tng_particle_data_t data = 0;
     tng_function_status stat;
     int size;
-    int64_t i, data_size, n_particles;
+    int64_t i, data_size, n_particles, file_pos;
     void *temp;
-    long file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
@@ -16578,11 +17394,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     if(stat != TNG_SUCCESS)
     {
         stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
         {
             stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-            file_pos = ftell(tng_data->input_file);
+            file_pos = ftello(tng_data->input_file);
         }
         if(stat != TNG_SUCCESS)
         {
@@ -16596,9 +17412,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     }
     if(data->last_retrieved_frame < 0)
     {
-        fseek(tng_data->input_file,
-              (long)tng_data->first_trajectory_frame_set_input_file_pos,
-              SEEK_SET);
+        fseeko(tng_data->input_file,
+               tng_data->first_trajectory_frame_set_input_file_pos,
+               SEEK_SET);
         stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
         {
@@ -16635,6 +17451,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
                 {
                     return(stat);
                 }
+                if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+                {
+                    return(TNG_FAILURE);
+                }
                 i = frame_set->first_frame;
             }
         }
@@ -16722,9 +17542,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     tng_non_particle_data_t data = 0;
     tng_function_status stat;
     int size;
-    int64_t i, data_size;
+    int64_t i, data_size, file_pos;
     void *temp;
-    long file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
@@ -16738,11 +17557,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     if(stat != TNG_SUCCESS)
     {
         stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-        file_pos = ftell(tng_data->input_file);
+        file_pos = ftello(tng_data->input_file);
         while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
         {
             stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-            file_pos = ftell(tng_data->input_file);
+            file_pos = ftello(tng_data->input_file);
         }
         if(stat != TNG_SUCCESS)
         {
@@ -16756,9 +17575,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     }
     if(data->last_retrieved_frame < 0)
     {
-        fseek(tng_data->input_file,
-                (long)tng_data->first_trajectory_frame_set_input_file_pos,
-                SEEK_SET);
+        fseeko(tng_data->input_file,
+               tng_data->first_trajectory_frame_set_input_file_pos,
+               SEEK_SET);
         stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
         {
@@ -16795,6 +17614,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
                 {
                     return(stat);
                 }
+                if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+                {
+                    return(TNG_FAILURE);
+                }
                 i = frame_set->first_frame;
             }
         }
@@ -18202,7 +19025,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
                 (tng_trajectory_t tng_data,
                  const int64_t block_id,
                  int64_t *codec_id,
-                 float *factor)
+                 double *factor)
 {
     tng_trajectory_frame_set_t frame_set;
     tng_particle_data_t p_data = 0;
@@ -18299,12 +19122,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
     if(block_type == TNG_PARTICLE_BLOCK_DATA)
     {
         *codec_id = p_data->codec_id;
-        *factor   = (float)p_data->compression_multiplier;
+        *factor   = p_data->compression_multiplier;
     }
     else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
     {
         *codec_id = np_data->codec_id;
-        *factor   = (float)np_data->compression_multiplier;
+        *factor   = np_data->compression_multiplier;
     }
     return(TNG_SUCCESS);
 }
@@ -18325,9 +19148,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
     tng_gen_block_t block;
     int64_t i, j, block_id, *temp;
     int64_t data_frame, frame_diff, min_diff;
-    int64_t size, frame_set_file_pos;
+    int64_t size, frame_set_file_pos, file_pos;
     int found, read_all = 0;
-    long file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
@@ -18341,7 +19163,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
         temp = realloc(*data_block_ids_in_next_frame, size);
         if(!temp)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                     sizeof(int64_t) * (*n_data_blocks_in_next_frame),
                     __FILE__, __LINE__);
             free(*data_block_ids_in_next_frame);
@@ -18375,25 +19197,24 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
         }
     }
 
-    /* If no data blocks have been found in the frame set check what data blocks
-     * are present. If they have already been found do not read them again. */
+    /* Check for data blocks only if they have not already been found. */
     if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
     {
-        file_pos = ftell(tng_data->input_file);
-        /* Read all blocks until next frame set block */
+        file_pos = ftello(tng_data->input_file);
         if(file_pos < tng_data->input_file_len)
         {
             tng_block_init(&block);
             stat = tng_block_header_read(tng_data, block);
             while(file_pos < tng_data->input_file_len &&
                 stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET)
+                block->id != TNG_TRAJECTORY_FRAME_SET &&
+                block->id != -1)
             {
                 stat = tng_block_read_next(tng_data, block,
                                         TNG_USE_HASH);
                 if(stat != TNG_CRITICAL)
                 {
-                    file_pos = ftell(tng_data->input_file);
+                    file_pos = ftello(tng_data->input_file);
                     if(file_pos < tng_data->input_file_len)
                     {
                         stat = tng_block_header_read(tng_data, block);
@@ -18403,7 +19224,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
             tng_block_destroy(&block);
             if(stat == TNG_CRITICAL)
             {
-                fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+                fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                         file_pos, __FILE__, __LINE__);
                 return(stat);
             }
@@ -18484,7 +19305,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
                 temp = realloc(*data_block_ids_in_next_frame, size);
                 if(!temp)
                 {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                            sizeof(int64_t) * (*n_data_blocks_in_next_frame),
                            __FILE__, __LINE__);
                     free(*data_block_ids_in_next_frame);
@@ -18571,7 +19392,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
                 temp = realloc(*data_block_ids_in_next_frame, size);
                 if(!temp)
                 {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                    fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
                            sizeof(int64_t) * (*n_data_blocks_in_next_frame),
                            __FILE__, __LINE__);
                     free(*data_block_ids_in_next_frame);
@@ -18611,7 +19432,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
                  char **compressions)
 {
     tng_gen_block_t block;
-    long orig_file_pos, file_pos;
+    int64_t orig_file_pos, file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
@@ -18619,15 +19440,15 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
     TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
     TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
 
-    orig_file_pos = ftell(tng_data->input_file);
+    orig_file_pos = ftello(tng_data->input_file);
 
     if(!tng_data->input_file_len)
     {
-        fseek(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftell(tng_data->input_file);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
     }
 
-    fseek(tng_data->input_file, 0, SEEK_SET);
+    fseeko(tng_data->input_file, 0, SEEK_SET);
     file_pos = 0;
 
     *n_data_blocks = 0;
@@ -18641,11 +19462,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
         {
 
         }
-        file_pos += (long)(block->block_contents_size + block->header_contents_size);
-        fseek(tng_data->input_file, (long)block->block_contents_size, SEEK_CUR);
+        file_pos += (block->block_contents_size + block->header_contents_size);
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
     }
 
-    fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
+    fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
 
     return(TNG_SUCCESS);
 }