Bumped the TNG library to the latest version.
authorMagnus Lundborg <lundborg.magnus@gmail.com>
Mon, 16 Jun 2014 15:15:08 +0000 (17:15 +0200)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 19 Jun 2014 10:01:08 +0000 (12:01 +0200)
This is commit f7083045c6f7d23bac47b8302e413becd53fc030
in the TNG repository.

Change-Id: I1f5a9edbaf1588b6d1cee6cf86a7ea254aad23a1

15 files changed:
src/external/tng_io/CMakeLists.txt
src/external/tng_io/include/tng_io.h
src/external/tng_io/include/tng_io.hpp
src/external/tng_io/include/tng_io_fwd.h
src/external/tng_io/include/version.h.in [new file with mode: 0644]
src/external/tng_io/src/compression/CMakeLists.txt
src/external/tng_io/src/lib/CMakeLists.txt
src/external/tng_io/src/lib/tng_io.c
src/external/tng_io/src/lib/tng_io_fortran.c
src/external/tng_io/src/tests/md_openmp.c
src/external/tng_io/src/tests/md_openmp_util.c
src/external/tng_io/src/tests/tng_io_read_pos.c
src/external/tng_io/src/tests/tng_io_read_pos_util.c
src/external/tng_io/src/tests/tng_io_testing.c
src/external/tng_io/src/tests/tng_parallel_read.c

index 41eb1551de31a517b20ef93754da53f256b2f4f0..06f3f7d53b91a187fc0f6d85490d751f3a960f30 100644 (file)
@@ -1,7 +1,12 @@
 cmake_minimum_required(VERSION 2.8)
 
 project(TNG_IO)
-set(PROJECT_VERSION "1.0")
+set(PROJECT_VERSION "1.5")
+set(API_VERSION "5")
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in
+                ${CMAKE_BINARY_DIR}/include/version.h )
+include_directories(${CMAKE_BINARY_DIR}/include)
 
 if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
     set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall")
@@ -47,5 +52,8 @@ if(TNG_BUILD_DOCUMENTATION)
                                         SOURCES ${PROJECT_BINARY_DIR}/Doxyfile)
   # IF you do NOT want the documentation to be generated EVERY time you build the project
   # then leave out the 'ALL' keyword from the above command.
+
+  install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Documentation/
+      DESTINATION share/tng/doc)
 endif()
 
index 45cb1d8d2d17d6df92a7c0c8835b9c96ec7ce7bb..5b89cd6357255fad170d502a0d2044cdeb39fa1b 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.
  *
  *
@@ -343,10 +341,6 @@ typedef unsigned __int64 uint64_t;
 #endif /* USE_WINDOWS */
 #endif /* DECLSPECDLLEXPORT */
 
-
-/** The version of this TNG build */
-#define TNG_VERSION 5 /* TNG_VERSION 4 => Api version 1.5 */
-
 /** Flag to indicate frame dependent data. */
 #define TNG_FRAME_DEPENDENT 1
 /** Flag to indicate particle dependent data. */
@@ -419,6 +413,7 @@ typedef enum {TNG_NON_TRAJECTORY_BLOCK, TNG_TRAJECTORY_BLOCK} tng_block_type;
 #define TNG_TRAJ_B_FACTORS              0x0000000010000006LL
 #define TNG_TRAJ_ANISOTROPIC_B_FACTORS  0x0000000010000007LL
 #define TNG_TRAJ_OCCUPANCY              0x0000000010000008LL
+#define TNG_TRAJ_GENERAL_COMMENTS       0x0000000010000009LL
 /** @} */
 
 
index f3bc32abea9803cf15657eb180ed09a8c8fa5bea..12172e5515c7c9119a0b999b7cb65bb7a0104131 100644 (file)
@@ -1,6 +1,4 @@
 /* This code is part of the tng binary trajectory format.
- *
- *                      VERSION 1.5
  *
  * Written by Anders Gärdenäs
  * Copyright (c) 2012-2013, The GROMACS development team.
index 34ddd87bad3d9233b6c5fc0e2d2a5b50ab5f1814..8b63a9a55ee4deb4c9881715955fc40b7dddaf2a 100644 (file)
@@ -1,6 +1,4 @@
 /* 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.
diff --git a/src/external/tng_io/include/version.h.in b/src/external/tng_io/include/version.h.in
new file mode 100644 (file)
index 0000000..840e454
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef VERSION_CONFIG_H
+#define VERSION_CONFIG_H
+
+/* define the API version */
+#define TNG_API_VERSION @API_VERSION@
+
+#endif
index 267a45a8acb31086c4bbd8b902c9424465380535..3efd6bbf4d68d84c1b14569037a4c6c9c2a0f8a5 100644 (file)
@@ -1,11 +1,12 @@
-add_library(tng_compress bwlzh.c bwt.c coder.c dict.c fixpoint.c huffman.c huffmem.c lz77.c merge_sort.c mtf.c rle.c tng_compress.c vals16.c warnmalloc.c widemuldiv.c xtc2.c xtc3.c)
+set(source_files bwlzh.c bwt.c coder.c dict.c fixpoint.c huffman.c huffmem.c lz77.c merge_sort.c mtf.c rle.c tng_compress.c vals16.c warnmalloc.c widemuldiv.c xtc2.c xtc3.c)
+
+add_library(tng_compress ${source_files})
+
+# Append the required library dependencies
 if(UNIX)
-target_link_libraries(tng_compress m)
+  target_link_libraries(tng_compress m)
 endif()
 
-set_property(TARGET tng_compress PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
-set_property(TARGET tng_compress PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
-
 install(TARGETS tng_compress
         LIBRARY DESTINATION lib
         ARCHIVE DESTINATION lib)
index c760f57539435f13fe50c1ec36e9a87f51b84f64..81b5843e876755b4537f7bc164a01a5a7bcde6a7 100644 (file)
@@ -1,18 +1,18 @@
+set(source_files tng_io.c md5.c)
 if(TNG_BUILD_FORTRAN)
-  add_library(tng_io tng_io.c md5.c tng_io_fortran.c)
-else()
-  add_library(tng_io tng_io.c md5.c)
+  list(APPEND source_files tng_io_fortran.c)
 endif()
 
-set_property(TARGET tng_io PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
-set_property(TARGET tng_io PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+add_library(tng_io ${source_files})
 
-install(TARGETS tng_io
-        LIBRARY DESTINATION lib
-        ARCHIVE DESTINATION lib)
+# Now add source-file compilation properties to the source-file
+# targets
 
 if(HAVE_INTTYPES_H)
-  set_property(TARGET tng_io APPEND PROPERTY COMPILE_DEFINITIONS USE_STD_INTTYPES_H)
+  set_property(SOURCE tng_io.c APPEND PROPERTY COMPILE_DEFINITIONS USE_STD_INTTYPES_H)
+endif()
+if(TNG_BUILD_WITH_ZLIB)
+  set_property(SOURCE tng_io.c APPEND PROPERTY COMPILE_DEFINITIONS USE_ZLIB)
 endif()
 
 # This test is for md5. The TNG library itself determines the actual byte order -
@@ -20,12 +20,15 @@ endif()
 include(TestBigEndian)
 test_big_endian(TNG_INTEGER_BIG_ENDIAN)
 if(TNG_INTEGER_BIG_ENDIAN)
-  set_property(TARGET tng_io APPEND PROPERTY COMPILE_DEFINITIONS TNG_INTEGER_BIG_ENDIAN)
+  set_property(SOURCE md5.c APPEND PROPERTY COMPILE_DEFINITIONS TNG_INTEGER_BIG_ENDIAN)
 endif()
 
+# Append the required library dependencies
+target_link_libraries(tng_io tng_compress)
 if(TNG_BUILD_WITH_ZLIB)
-  set_property(TARGET tng_io APPEND PROPERTY COMPILE_DEFINITIONS USE_ZLIB)
-  target_link_libraries(tng_io tng_compress ${ZLIB_LIBRARIES})
-else()
-  target_link_libraries(tng_io tng_compress)
+  target_link_libraries(tng_io ${ZLIB_LIBRARIES})
 endif()
+
+install(TARGETS tng_io
+        LIBRARY DESTINATION lib
+        ARCHIVE DESTINATION lib)
index b6c6f22227e791677bc752ec05d48e5f88a5debe..252cbb2901d5e393393af90a6a1ede600b303f7f 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.
  *
  *
@@ -27,6 +25,7 @@
 #include "../../include/tng_io.h"
 #include "../../include/md5.h"
 #include "../../include/compression/tng_compress.h"
+#include "../include/version.h"
 
 
 struct tng_bond {
@@ -190,6 +189,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 +248,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;
 };
 
@@ -352,9 +352,6 @@ struct tng_trajectory {
      *  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;
@@ -746,7 +743,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,8 +794,9 @@ 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)
@@ -821,6 +819,12 @@ 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)
     {
@@ -1030,56 +1034,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);
-        }
+    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)
+    {
+        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);
+
+    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);
 }
 
-/** 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 +1100,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 = ftell(tng_data->output_file);
+    fseek(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 = ftell(tng_data->output_file);
 
-    if(block->header_contents)
-    {
-        free(block->header_contents);
-    }
+    fseek(tng_data->output_file, (long)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,70 +1155,1044 @@ 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);
+
+    fseek(tng_data->output_file, (long)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 = ftell(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)
-        {
-            fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
+        fseek(tng_data->output_file, (long)frame_set->next_frame_set_file_pos,
+              SEEK_SET);
+
+        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 - (5 *
+            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,
+                                                        &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, frame_set->next_frame_set_file_pos,
+                                contents_start_pos);
+        }
+        fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+    }
+    /* Update previous frame set */
+    if(frame_set->prev_frame_set_file_pos > 0)
+    {
+        fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
+              SEEK_SET);
+
+        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);
+
+        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, frame_set->prev_frame_set_file_pos,
+                                contents_start_pos);
+        }
+        fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+    }
+
+    /* Update the frame set one medium stride step after */
+    if(frame_set->medium_stride_next_frame_set_file_pos > 0)
+    {
+        fseek(tng_data->output_file,
+              (long)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 read frame set 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 - (3 *
+            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,
+                                                        &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,
+                                frame_set->medium_stride_next_frame_set_file_pos,
+                                contents_start_pos);
+        }
+    }
+    /* Update the frame set one medium stride step before */
+    if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
+    {
+        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)
+        {
+            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 = ftell(tng_data->output_file);
+
+        fseek(tng_data->output_file, (long)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,
+                                                        &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,
+                                frame_set->medium_stride_prev_frame_set_file_pos,
+                                contents_start_pos);
+        }
+    }
+
+    /* Update the frame set one long stride step after */
+    if(frame_set->long_stride_next_frame_set_file_pos > 0)
+    {
+        fseek(tng_data->output_file,
+              (long)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 read frame set 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 - (1 *
+            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,
+                                                        &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,
+                                frame_set->long_stride_next_frame_set_file_pos,
+                                contents_start_pos);
+        }
+    }
+    /* Update the frame set one long stride step before */
+    if(frame_set->long_stride_prev_frame_set_file_pos > 0)
+    {
+        fseek(tng_data->output_file,
+              (long)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 read frame set 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 - (2 *
+            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,
+                                                        &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,
+                                frame_set->long_stride_prev_frame_set_file_pos,
+                                contents_start_pos);
+        }
+    }
+
+    fseek(tng_data->output_file, (long)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);
+
+    fseek(tng_data->input_file, pos, SEEK_SET);
+    if(pos > 0)
+    {
+        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)
+        {
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+    }
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+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 = ftell(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);
+    }
+
+    fseek(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)
+    {
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
+
+    /* Read all frame set blocks (not the blocks between them) */
+    while(frame_set->next_frame_set_file_pos > 0)
+    {
+        fseek(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);
+        }
+
+        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;
+        }
+    }
+
+    /* 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);
+
+    fseek(tng_data->input_file, orig_pos, SEEK_SET);
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+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;
+
+    char *contents;
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
+
+    fseek(tng_data->input_file, block_start_pos, SEEK_SET);
+
+    contents = malloc(block_len);
+    if(!contents)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                block_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(fread(contents, block_len, 1, tng_data->input_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
+               __FILE__, __LINE__);
+        free(contents);
+        return(TNG_CRITICAL);
+    }
+    fseek(tng_data->output_file, new_pos, SEEK_SET);
+
+    if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
+    {
+        fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
+                __FILE__, __LINE__);
+        free(contents);
+        return(TNG_CRITICAL);
+    }
+
+    tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
+
+    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)
+    {
+        tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
+        updated = TNG_TRUE;
+    }
+    if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
+    {
+        tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
+        updated = TNG_TRUE;
+    }
+    if(updated)
+    {
+        tng_header_pointers_update(tng_data, TNG_USE_HASH);
+    }
+
+    /* Fill the block with NULL to avoid confusion. */
+    for(i = 0; i < block_len; i++)
+    {
+        contents[i] = '\0';
+    }
+    fseek(tng_data->output_file, block_start_pos, SEEK_SET);
+
+    /* FIXME: casting block_len to size_t is dangerous */
+    fwrite(contents, 1, block_len, tng_data->output_file);
+
+    free(contents);
+
+    return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_length_of_current_frame_set_contents_get
+                (tng_trajectory_t tng_data,
+                 int64_t *len)
+{
+    int64_t orig_pos, pos, curr_frame_set_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
+
+    orig_pos = ftell(tng_data->input_file);
+    curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
+
+    *len = 0;
+
+    fseek(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)
+    {
+        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);
+    }
+
+    /* Read the headers of all blocks in the frame set (not the actual contents of them) */
+    while(stat == TNG_SUCCESS)
+    {
+        fseek(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)
+        {
+            break;
+        }
+        stat = tng_block_header_read(tng_data, block);
+        if(block->id == TNG_TRAJECTORY_FRAME_SET)
+        {
+            break;
+        }
+    }
+
+    /* 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);
+
+    fseek(tng_data->input_file, orig_pos, SEEK_SET);
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+/** 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 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_migrate_data_in_file
+                (tng_trajectory_t tng_data,
+                 int64_t start_pos,
+                 int64_t offset)
+{
+    int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
+    tng_gen_block_t block;
+    tng_function_status stat;
+    FILE *temp;
+
+    if(offset <= 0)
+    {
+        return(TNG_SUCCESS);
+    }
+
+    temp = tng_data->input_file;
+
+    stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
+    if(stat != 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 = ftell(tng_data->input_file);
+    tng_block_init(&block);
+
+    while(empty_space < offset)
+    {
+        fseek(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 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;
+    }
+    fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
+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)
+    {
+        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;
+    }
+
+    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);
+}
+
+/** 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 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_block_header_write
+                (tng_trajectory_t tng_data,
+                 tng_gen_block_t block,
+                 const char hash_mode)
+{
+    int name_len, offset = 0;
+
+    TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
+
+    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);
+    }
+
+    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(block->header_contents_size);
+
+    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->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->block_contents_size);
+
+    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)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+    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;
+
+    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)
+            != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
+        }
+    }
+
+    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);
+}
+
+static tng_function_status tng_general_info_block_len_calculate
+                (tng_trajectory_t tng_data,
+                 int64_t *len)
+{
+    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;
+
+    /* If the strings are unallocated allocate memory for just string
+     * termination */
+    if(!tng_data->first_program_name)
+    {
+        tng_data->first_program_name = malloc(1);
+        if(!tng_data->first_program_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+                   __FILE__, __LINE__);
+            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)
+        {
+            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;
+    }
+
+    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 = 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 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.
+ * 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_general_info_block_read
+                (tng_trajectory_t tng_data, tng_gen_block_t block,
+                 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)");
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        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;
+
+    /* 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. */
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_md5_hash_match_verify(block, &same_hash);
+        if(same_hash != TNG_TRUE)
+        {
+            fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
                 "%s: %d\n",
                 __FILE__, __LINE__);
     /*         return(TNG_FAILURE); */
@@ -1502,131 +2441,29 @@ static tng_function_status tng_general_info_block_read
 /** 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(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    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)
-    {
-        tng_data->first_program_name = malloc(1);
-        if(!tng_data->first_program_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
-                   __FILE__, __LINE__);
-            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)
-        {
-            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)
+ * 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(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        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;
+        return(TNG_CRITICAL);
     }
 
+    fseek(tng_data->output_file, 0, SEEK_SET);
+
     tng_block_init(&block);
 
     name_len = (int)strlen("GENERAL INFO");
@@ -1643,6 +2480,15 @@ static tng_function_status tng_general_info_block_write
     strcpy(block->name, "GENERAL INFO");
     block->id = TNG_GENERAL_INFO;
 
+    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);
+    }
+
     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,
@@ -1662,24 +2508,6 @@ static tng_function_status tng_general_info_block_write
     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)
     {
         free(block->block_contents);
@@ -1758,8 +2586,8 @@ static tng_function_status tng_general_info_block_write
     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));
+           &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,
@@ -1770,11 +2598,11 @@ static tng_function_status tng_general_info_block_write
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
+    offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
 
     memcpy(block->block_contents+offset,
-           &tng_data->last_trajectory_frame_set_input_file_pos,
-           sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
+           &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)
     {
         if(tng_data->output_endianness_swap_func_64(tng_data,
@@ -1785,7 +2613,7 @@ static tng_function_status tng_general_info_block_write
                     __FILE__, __LINE__);
         }
     }
-    offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
+    offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
 
     memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
            sizeof(tng_data->medium_stride_length));
@@ -2145,6 +2973,136 @@ static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
     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);
+            }
+            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)
+            {
+                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++;
+        }
+
+        residue = molecule->residues;
+        for(j = 0; j < molecule->n_residues; j++)
+        {
+            *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++;
+        }
+
+        atom = molecule->atoms;
+        for(j = 0; j < molecule->n_atoms; j++)
+        {
+            *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++;
+        }
+
+        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(!tng_data->var_num_atoms_flag)
+    {
+        *len += tng_data->n_molecules * sizeof(int64_t);
+    }
+
+    return(TNG_SUCCESS);
+}
+
 /** 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.
@@ -2210,7 +3168,7 @@ static tng_function_status tng_molecules_block_read
 
     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]);
         }
@@ -2438,7 +3396,7 @@ static tng_function_status tng_molecules_block_read
         if(molecule->n_chains > 0)
         {
             /* Read the chains of the molecule */
-            for(j=molecule->n_chains; j--;)
+            for(j=0; j<molecule->n_chains; j++)
             {
                 chain->molecule = molecule;
 
@@ -2448,7 +3406,7 @@ static tng_function_status tng_molecules_block_read
                 residue = chain->residues;
 
                 /* Read the residues of the chain */
-                for(k=chain->n_residues; k--;)
+                for(k=0; k<chain->n_residues; k++)
                 {
                     residue->chain = chain;
 
@@ -2456,7 +3414,7 @@ static tng_function_status tng_molecules_block_read
 
                     residue->atoms_offset = atom - molecule->atoms;
                     /* Read the atoms of the residue */
-                    for(l=residue->n_atoms; l--;)
+                    for(l=0; l<residue->n_atoms; l++)
                     {
                         atom->residue = residue;
 
@@ -2473,7 +3431,7 @@ static tng_function_status tng_molecules_block_read
         {
             if(molecule->n_residues > 0)
             {
-                for(k=molecule->n_residues; k--;)
+                for(k=0; k<molecule->n_residues; k++)
                 {
                     residue->chain = 0;
 
@@ -2481,7 +3439,7 @@ static tng_function_status tng_molecules_block_read
 
                     residue->atoms_offset = atom - molecule->atoms;
                     /* Read the atoms of the residue */
-                    for(l=residue->n_atoms; l--;)
+                    for(l=0; l<residue->n_atoms; l++)
                     {
                         atom->residue = residue;
 
@@ -2494,7 +3452,7 @@ static tng_function_status tng_molecules_block_read
             }
             else
             {
-                for(l=molecule->n_atoms; l--;)
+                for(l=0; l<molecule->n_atoms; l++)
                 {
                     atom->residue = 0;
 
@@ -2548,7 +3506,7 @@ static tng_function_status tng_molecules_block_read
 
             bond = molecule->bonds;
 
-            for(j=molecule->n_bonds; j--;)
+            for(j=0; j<molecule->n_bonds; j++)
             {
                 memcpy(&bond->from_atom_id, block->block_contents+offset,
                     sizeof(bond->from_atom_id));
@@ -2615,108 +3573,6 @@ static tng_function_status tng_molecules_block_write
         return(TNG_CRITICAL);
     }
 
-    /* First predict the size of the block */
-    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);
-            }
-            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--;)
-        {
-            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++;
-        }
-
-        residue = molecule->residues;
-        for(j = molecule->n_residues; j--;)
-        {
-            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++;
-        }
-
-        atom = molecule->atoms;
-        for(j = molecule->n_atoms; j--;)
-        {
-            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++;
-        }
-
-        for(j = molecule->n_bonds; j--;)
-        {
-            len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
-        }
-    }
-
     tng_block_init(&block);
 
     name_len = (int)strlen("MOLECULES");
@@ -2733,19 +3589,13 @@ static tng_function_status tng_molecules_block_write
     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)
+    if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
+        TNG_SUCCESS)
     {
-        block->block_contents_size += tng_data->n_molecules * sizeof(int64_t);
+        fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
+                __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
 
     block->block_contents = malloc(block->block_contents_size);
@@ -2869,17 +3719,17 @@ static tng_function_status tng_molecules_block_write
         if(molecule->n_chains > 0)
         {
             chain = molecule->chains;
-            for(j = molecule->n_chains; j--;)
+            for(j = 0; j < molecule->n_chains; j++)
             {
                 tng_chain_data_write(tng_data, block, chain, &offset);
 
                 residue = chain->residues;
-                for(k = chain->n_residues; k--;)
+                for(k = 0; k < chain->n_residues; k++)
                 {
                     tng_residue_data_write(tng_data, block, residue, &offset);
 
                     atom = molecule->atoms + residue->atoms_offset;
-                    for(l = residue->n_atoms; l--;)
+                    for(l = 0; l < residue->n_atoms; l++)
                     {
                         tng_atom_data_write(tng_data, block, atom, &offset);
 
@@ -2895,12 +3745,12 @@ static tng_function_status tng_molecules_block_write
             if(molecule->n_residues > 0)
             {
                 residue = molecule->residues;
-                for(k = molecule->n_residues; k--;)
+                for(k = 0; k < molecule->n_residues; k++)
                 {
                     tng_residue_data_write(tng_data, block, residue, &offset);
 
                     atom = molecule->atoms + residue->atoms_offset;
-                    for(l = residue->n_atoms; l--;)
+                    for(l = 0; l < residue->n_atoms; l++)
                     {
                         tng_atom_data_write(tng_data, block, atom, &offset);
 
@@ -2912,7 +3762,7 @@ static tng_function_status tng_molecules_block_write
             else
             {
                 atom = molecule->atoms;
-                for(l = molecule->n_atoms; l--;)
+                for(l = 0; l < molecule->n_atoms; l++)
                 {
                     tng_atom_data_write(tng_data, block, atom, &offset);
 
@@ -2936,7 +3786,7 @@ static tng_function_status tng_molecules_block_write
         offset += sizeof(molecule->n_bonds);
 
         bond = molecule->bonds;
-        for(j = molecule->n_bonds; j--;)
+        for(j = 0; j < molecule->n_bonds; j++)
         {
             memcpy(block->block_contents+offset, &bond->from_atom_id,
                    sizeof(bond->from_atom_id));
@@ -2992,6 +3842,20 @@ static tng_function_status tng_molecules_block_write
     return(TNG_SUCCESS);
 }
 
+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 is a general block container.
@@ -3272,7 +4136,14 @@ static tng_function_status tng_frame_set_block_read
         tng_data->time_per_frame = -1;
     }
 
-    frame_set->n_written_frames = frame_set->n_frames;
+    /* 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;
+    }
 
     return(TNG_SUCCESS);
 }
@@ -3320,12 +4191,12 @@ static tng_function_status tng_frame_set_block_write
     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;
-
-    if(tng_data->var_num_atoms_flag)
+    if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
+        TNG_SUCCESS)
     {
-        block->block_contents_size += sizeof(int64_t) * tng_data->n_molecules;
+        fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
     if(block->block_contents)
@@ -3524,6 +4395,16 @@ static tng_function_status tng_frame_set_block_write
     return(TNG_SUCCESS);
 }
 
+static tng_function_status tng_trajectory_mapping_block_len_calculate
+                (const tng_trajectory_t tng_data,
+                 const int64_t n_particles,
+                 int64_t *len)
+{
+    (void)tng_data;
+    *len = sizeof(int64_t) * (2 + n_particles);
+
+    return(TNG_SUCCESS);
+}
 
 /** Read an atom mappings block (translating between real atom indexes and how
  *  the atom info is written in this frame set).
@@ -3725,7 +4606,15 @@ static tng_function_status tng_trajectory_mapping_block_write
     strcpy(block->name, "PARTICLE MAPPING");
     block->id = TNG_PARTICLE_MAPPING;
 
-    block->block_contents_size = sizeof(int64_t) * (2 + mapping->n_particles);
+    if(tng_trajectory_mapping_block_len_calculate(tng_data,
+                                                  mapping->n_particles,
+                                                  &block->block_contents_size) !=
+        TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
     if(block->block_contents)
     {
@@ -4280,624 +5169,273 @@ static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
     temp = realloc(block->block_contents, block->block_contents_size);
     if(!temp)
     {
-        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)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
-               uncompressed_len, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
-                      block->block_contents_size - offset);
-
-    if(stat != Z_OK)
-    {
-        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)
-        {
-            fprintf(stderr, "TNG library: Data corrupt. ");
-        }
-        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)
-    {
-        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);
-    }
-
-    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)
-    {
-        return(TNG_FAILURE);
-    }
-
-    if(data->strings && data->datatype == TNG_CHAR_DATA)
-    {
-        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);
-    }
-    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)
-    {
-        data->strings = malloc(sizeof(char ***) * frame_alloc);
-        for(i = frame_alloc; 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--;)
-            {
-                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,
-                        __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                for(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_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
-    {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
-    }
-
-    block_index = -1;
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
-    {
-        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;
-            }
-        }
-    }
-    else
-    {
-        for(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(block_index == -1)
-    {
-        return(TNG_FAILURE);
+        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_data_find
-                (tng_trajectory_t tng_data,
-                 const int64_t id,
-                 tng_non_particle_data_t *data)
+static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
+                                               tng_gen_block_t block,
+                                               void *start_pos,
+                                               unsigned long uncompressed_len)
 {
-    int64_t block_index, i;
-    tng_trajectory_frame_set_t frame_set = &tng_data->
-                                           current_trajectory_frame_set;
-    char block_type_flag;
+    Bytef *dest;
+    char *temp;
+    unsigned long stat;
+    int offset;
+    (void)tng_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
+    offset = (char *)start_pos - (char *)block->block_contents;
+
+    dest = malloc(uncompressed_len);
+    if(!dest)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
+               uncompressed_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    block_index = -1;
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
+                      block->block_contents_size - offset);
+
+    if(stat != Z_OK)
     {
-        for(i = frame_set->n_data_blocks; i-- ;)
+        free(dest);
+        if(stat == (unsigned long)Z_MEM_ERROR)
         {
-            *data = &frame_set->tr_data[i];
-            if((*data)->block_id == id)
-            {
-                block_index = i;
-                break;
-            }
+            fprintf(stderr, "TNG library: Not enough memory. ");
         }
-        if(block_index == -1)
+        else if(stat == (unsigned long)Z_BUF_ERROR)
         {
-            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: Destination buffer too small. ");
         }
-    }
-    else
-    {
-        for(i = tng_data->n_data_blocks; i-- ;)
+        else if(stat == (unsigned long)Z_DATA_ERROR)
         {
-            *data = &tng_data->non_tr_data[i];
-            if((*data)->block_id == id)
-            {
-                block_index = i;
-                break;
-            }
+            fprintf(stderr, "TNG library: Data corrupt. ");
         }
+        fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
+               __LINE__);
+        return(TNG_FAILURE);
     }
-    if(block_index == -1)
+
+
+    block->block_contents_size = uncompressed_len + offset;
+
+    temp = realloc(block->block_contents, uncompressed_len + offset);
+    if(!temp)
     {
-        return(TNG_FAILURE);
+        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);
     }
+
+    memcpy(temp + offset, dest, uncompressed_len);
+
+    block->block_contents = temp;
+
+    free(dest);
     return(TNG_SUCCESS);
 }
+#endif
 
-/** Read the values of a particle data block
+/** 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 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 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_particle_data_read
+static tng_function_status tng_allocate_particle_data_mem
                 (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,
+                 tng_particle_data_t data,
                  int64_t n_frames,
-                 const int64_t n_values,
-                 const int64_t codec_id,
-                 const double multiplier)
+                 int64_t stride_length,
+                 const int64_t n_particles,
+                 const int64_t n_values_per_frame)
 {
-    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.");
+    void ***values;
+    int64_t i, j, k, size, frame_alloc;
+    (void)tng_data;
 
-    switch(datatype)
+    if(n_particles == 0 || n_values_per_frame == 0)
     {
-    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);
+        return(TNG_FAILURE);
     }
 
-    /* If the block does not exist, create it */
-    if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    if(data->strings && data->datatype == TNG_CHAR_DATA)
     {
-        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)
-        {
-            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_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)
+        for(i = 0; i < data->n_frames; i++)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block->name)+1, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            for(j = 0; j < n_particles; j++)
+            {
+                for(k = 0; 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]);
         }
-        strcpy(data->block_name, block->name);
-
-        data->datatype = datatype;
-
-        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;
-    }
-
-    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;
+        free(data->strings);
     }
+    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;
 
-    n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
-
-    if(codec_id != TNG_UNCOMPRESSED)
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
-        switch(codec_id)
+        data->strings = malloc(sizeof(char ***) * frame_alloc);
+        for(i = 0; i < frame_alloc; i++)
         {
-        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)
+            data->strings[i] = malloc(sizeof(char **) *
+                                    n_particles);
+            if(!data->strings[i])
             {
-                fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
-                       __FILE__, __LINE__);
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                    sizeof(union data_values *) * n_particles,
+                    __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:
-/*            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)
+            for(j = 0; j < n_particles; j++)
             {
-                fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
-                    __LINE__);
-                return(TNG_CRITICAL);
+                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,
+                        __FILE__, __LINE__);
+                    return(TNG_CRITICAL);
+                }
+                for(k = 0; k < n_values_per_frame; k++)
+                {
+                    data->strings[i][j][k] = 0;
+                }
             }
-/*            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(tng_allocate_particle_data_mem(tng_data, data, n_frames,
-                                          stride_length,
-                                          tot_n_particles, n_values) !=
-           TNG_SUCCESS)
+        switch(data->datatype)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
+        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;
     }
+    return(TNG_SUCCESS);
+}
 
-    data->first_frame_with_data = first_frame_with_data;
+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(datatype == TNG_CHAR_DATA)
+    if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
+       tng_data->current_trajectory_frame_set_output_file_pos > 0)
     {
-        for(i = 0; i < n_frames_div; i++)
+        block_type_flag = TNG_TRAJECTORY_BLOCK;
+    }
+    else
+    {
+        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+    }
+
+    block_index = -1;
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
-            first_dim_values = data->strings[i];
-            for(j = num_first_particle; j < num_first_particle + n_particles;
-                j++)
+            *data = &frame_set->tr_particle_data[i];
+            if((*data)->block_id == id)
             {
-                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;
-                }
+                block_index = i;
+                break;
             }
         }
     }
     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)
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
         {
-        case TNG_FLOAT_DATA:
-            if(tng_data->input_endianness_swap_func_32)
-            {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
-                {
-                    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__);
-                    }
-                }
-            }
-            break;
-        case TNG_INT_DATA:
-        case TNG_DOUBLE_DATA:
-            if(tng_data->input_endianness_swap_func_64)
+            *data = &tng_data->non_tr_particle_data[i];
+            if((*data)->block_id == id)
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
-                {
-                    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__);
-                    }
-                }
+                block_index = i;
+                break;
             }
-            break;
-        case TNG_CHAR_DATA:
-            break;
         }
     }
+    if(block_index == -1)
+    {
+        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
+static tng_function_status tng_data_find
                 (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)
+                 const int64_t id,
+                 tng_non_particle_data_t *data)
 {
-    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;
+    int64_t block_index, i;
+    tng_trajectory_frame_set_t frame_set = &tng_data->
+                                           current_trajectory_frame_set;
     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)
+    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;
     }
@@ -4906,28 +5444,71 @@ static tng_function_status tng_particle_data_block_write
         block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
     }
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    block_index = -1;
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        return(TNG_CRITICAL);
+        for(i = 0; i < frame_set->n_data_blocks; i++)
+        {
+            *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;
+                }
+            }
+        }
     }
-
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    else
     {
-        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. */
-        if(data->first_frame_with_data < frame_set->first_frame)
+        for(i = 0; i < tng_data->n_data_blocks; i++)
         {
-            return(TNG_SUCCESS);
+            *data = &tng_data->non_tr_data[i];
+            if((*data)->block_id == id)
+            {
+                block_index = i;
+                break;
+            }
         }
-
-        stride_length = tng_max_i64(1, data->stride_length);
     }
-    else
+    if(block_index == -1)
     {
-        data = &tng_data->non_tr_particle_data[block_index];
-        stride_length = 1;
+        return(TNG_FAILURE);
+    }
+    return(TNG_SUCCESS);
+}
+
+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)
@@ -4946,841 +5527,720 @@ static tng_function_status tng_particle_data_block_write
         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)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
-            return(TNG_CRITICAL);
-        }
-        block->name = temp_name;
-    }
-    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 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);
-    }
-
-    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(mapping && mapping->n_particles != 0)
-    {
-        n_particles = mapping->n_particles;
-        num_first_particle = mapping->num_first_particle;
-    }
-    else
+    *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
+           sizeof(data->codec_id);
+    if(is_particle_data)
     {
-        num_first_particle = 0;
-        if(tng_data->var_num_atoms_flag)
-        {
-            n_particles = frame_set->n_particles;
-        }
-        else
-        {
-            n_particles = tng_data->n_particles;
-        }
+        *len += sizeof(num_first_particle) + sizeof(n_particles);
     }
 
-    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)
     {
-        block->block_contents_size += sizeof(data->first_frame_with_data) +
-                                      sizeof(data->stride_length);
+        *len += sizeof(data->first_frame_with_data) +
+                sizeof(data->stride_length);
     }
 
     if(data->codec_id != TNG_UNCOMPRESSED)
     {
-        block->block_contents_size += sizeof(data->compression_multiplier);
+        *len += sizeof(data->compression_multiplier);
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
-    {
-        dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
-    }
-    else
-    {
-        dependency = TNG_PARTICLE_DEPENDENT;
-    }
     if(dependency & TNG_FRAME_DEPENDENT)
     {
-        block->block_contents_size += sizeof(char);
+        *len += sizeof(char);
     }
 
-    data_start_pos = block->block_contents_size;
+    *data_start_pos = *len;
 
     if(data->datatype == TNG_CHAR_DATA)
     {
-        for(i = n_frames; i--;)
+        if(is_particle_data)
         {
-            first_dim_values = data->strings[i];
-            for(j = num_first_particle; j < num_first_particle + n_particles;
-                j++)
+            for(i = 0; i < n_frames; i++)
             {
-                second_dim_values = first_dim_values[j];
-                for(k = data->n_values_per_frame; k--;)
+                first_dim_values = data->strings[i];
+                for(j = num_first_particle; j < num_first_particle + n_particles;
+                    j++)
                 {
-                    block->block_contents_size +=
-                    strlen(second_dim_values[k]) + 1;
+                    second_dim_values = first_dim_values[j];
+                    for(k = 0; k < data->n_values_per_frame; k++)
+                    {
+                        *len += strlen(second_dim_values[k]) + 1;
+                    }
                 }
             }
         }
-    }
-    else
-    {
-        block->block_contents_size += size * frame_step *
-                                      n_particles * data->n_values_per_frame;
-    }
-
-    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);
-    }
-
-
-    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)
-    {
-        if(stride_length > 1)
-        {
-            temp = 1;
-        }
         else
         {
-            temp = 0;
+            for(i = 0; i < n_frames; i++)
+            {
+                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;
+                }
+            }
         }
-        memcpy(block->block_contents+offset, &temp, sizeof(char));
-        offset += sizeof(char);
     }
-
-    memcpy(block->block_contents+offset, &data->n_values_per_frame,
-           sizeof(data->n_values_per_frame));
-    if(tng_data->output_endianness_swap_func_64)
+    else
     {
-        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 += size * frame_step * n_particles * data->n_values_per_frame;
     }
-    offset += sizeof(data->n_values_per_frame);
 
-    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);
+    return(TNG_SUCCESS);
+}
 
-    if(data->codec_id != TNG_UNCOMPRESSED)
+/** 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).
+ * @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.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+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, 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)
     {
-        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);
+    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(data->n_frames > 0 && stride_length > 1)
+    /* If the block does not exist, create it */
+    if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
     {
-        /* FIXME: first_frame_with_data is not reliably set */
-        if(data->first_frame_with_data == 0)
+        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
         {
-            data->first_frame_with_data = frame_set->first_frame;
+            block_type_flag = TNG_TRAJECTORY_BLOCK;
         }
-        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(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_type_flag = TNG_NON_TRAJECTORY_BLOCK;
         }
-        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)
+        if(tng_particle_data_block_create(tng_data, block_type_flag) !=
+           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 create particle data block. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
-        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)
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            data = &frame_set->tr_particle_data[frame_set->
+                                                n_particle_data_blocks - 1];
         }
-    }
-    offset += sizeof(num_first_particle);
+        else
+        {
+            data = &tng_data->non_tr_particle_data[tng_data->
+                                                   n_particle_data_blocks - 1];
+        }
+        data->block_id = block->id;
 
-    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)
+        data->block_name = malloc(strlen(block->name) + 1);
+        if(!data->block_name)
         {
-            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",
+                   (int)strlen(block->name)+1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
+        strcpy(data->block_name, block->name);
+
+        data->datatype = datatype;
+
+        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;
     }
-    offset += sizeof(n_particles);
 
-    if(data->datatype == TNG_CHAR_DATA)
+    if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
+       tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
+       tng_data->var_num_atoms_flag)
     {
-        if(data->strings)
-        {
-            for(i = 0; i < frame_step; i++)
-            {
-                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 = 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;
-                    }
-                }
-            }
-        }
+        tot_n_particles = frame_set->n_particles;
     }
-    else if(data->values)
+    else
     {
-        memcpy(block->block_contents + offset, data->values,
-               block->block_contents_size - offset);
+        tot_n_particles = tng_data->n_particles;
+    }
 
-        switch(data->datatype)
+    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_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__);
-                        }
-                    }
-                }
-            }
+        case TNG_XTC_COMPRESSION:
+            fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
             break;
-        case TNG_INT_DATA:
-            if(tng_data->input_endianness_swap_func_64)
+        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)
             {
-                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: 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;
-        case TNG_DOUBLE_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
+#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)
             {
-                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: Could not read gzipped block data. %s: %d\n", __FILE__,
+                    __LINE__);
+                return(TNG_CRITICAL);
             }
-            else
+/*            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_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 particle data. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+    }
+
+    data->first_frame_with_data = first_frame_with_data;
+
+    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++)
             {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_64)
+                second_dim_values = first_dim_values[j];
+                for(k = 0; k < n_values; k++)
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
+                    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+                              TNG_MAX_STR_LEN);
+                    if(second_dim_values[k])
                     {
-                        *(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__);
-                        }
+                        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;
                 }
             }
-            break;
-        case TNG_CHAR_DATA:
-            break;
         }
     }
     else
     {
-        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
-    }
-
-    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)
-    {
-        switch(data->codec_id)
+        memcpy((char *)data->values + n_frames_div * size * n_values *
+               num_first_particle,
+               block->block_contents + *offset,
+               block->block_contents_size - *offset);
+        switch(datatype)
         {
-        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)
+        case TNG_FLOAT_DATA:
+            if(tng_data->input_endianness_swap_func_32)
             {
-                fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
-                    __FILE__, __LINE__);
-                if(stat == TNG_CRITICAL)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    return(TNG_CRITICAL);
+                    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__);
+                    }
                 }
-                /* 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)
+        case TNG_INT_DATA:
+        case TNG_DOUBLE_DATA:
+            if(tng_data->input_endianness_swap_func_64)
             {
-                fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
-                    __LINE__);
-                if(stat == TNG_CRITICAL)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    return(TNG_CRITICAL);
+                    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__);
+                    }
                 }
-                /* 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
+        case TNG_CHAR_DATA:
+            break;
         }
     }
-
-    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
+/** Write a 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)
+ * @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_create
+static tng_function_status tng_particle_data_block_write
                 (tng_trajectory_t tng_data,
-                 const char block_type_flag)
+                 tng_gen_block_t block,
+                 const int64_t block_index,
+                 const tng_particle_mapping_t mapping,
+                 const char hash_mode)
 {
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
+    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_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)
+    {
+        block_type_flag = TNG_TRAJECTORY_BLOCK;
+    }
+    else
+    {
+        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+    }
+
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
 
     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)
+        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. */
+        if(data->first_frame_with_data < frame_set->first_frame)
         {
-            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);
+            return(TNG_SUCCESS);
         }
-        frame_set->tr_data = data;
+
+        stride_length = tng_max_i64(1, data->stride_length);
     }
     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)
+        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)
         {
-            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;
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            free(block->name);
+            block->name = 0;
             return(TNG_CRITICAL);
         }
-        tng_data->non_tr_data = data;
+        block->name = temp_name;
     }
+    strncpy(block->name, data->block_name, len);
+    block->id = data->block_id;
 
-    return(TNG_SUCCESS);
-}
+    /* 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);
 
-/* 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(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        /* 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);
+    }
+
+    frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
+                 n_frames / stride_length;
 
-    if(n_values_per_frame == 0)
+    /* 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)
     {
-        return(TNG_FAILURE);
+        data->compression_multiplier = tng_data->compression_precision;
     }
-
-    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    /* 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)
     {
-        for(i = data->n_frames; i--;)
-        {
-            for(j = data->n_values_per_frame; j--;)
-            {
-                if(data->strings[i][j])
-                {
-                    free(data->strings[i][j]);
-                    data->strings[i][j] = 0;
-                }
-            }
-            free(data->strings[i]);
-            data->strings[i] = 0;
-        }
-        free(data->strings);
+        data->compression_multiplier = 1.0;
     }
-    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)
+    if(mapping && mapping->n_particles != 0)
     {
-        data->strings = malloc(sizeof(char **) * frame_alloc);
-        for(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 = n_values_per_frame; j--;)
-            {
-                data->strings[i][j] = 0;
-            }
-        }
+        n_particles = mapping->n_particles;
+        num_first_particle = mapping->num_first_particle;
     }
     else
     {
-        switch(data->datatype)
+        num_first_particle = 0;
+        if(tng_data->var_num_atoms_flag)
         {
-        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);
+            n_particles = frame_set->n_particles;
         }
-
-        values = realloc(data->values,
-                         size * frame_alloc *
-                         n_values_per_frame);
-        if(!values)
+        else
         {
-            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);
+            n_particles = tng_data->n_particles;
         }
-        data->values = values;
     }
 
-    return(TNG_SUCCESS);
-}
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+    {
+        dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
+    }
+    else
+    {
+        dependency = TNG_PARTICLE_DEPENDENT;
+    }
 
-/** 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 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_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)
-{
-    int64_t i, j, n_frames_div;
-    int size, len;
-#ifdef USE_ZLIB
-    unsigned long 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(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)
+    {
+        fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
+                __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+    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);
+    }
 
-/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
 
-    switch(datatype)
+    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)
     {
-    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(stride_length > 1)
+        {
+            temp = 1;
+        }
+        else
+        {
+            temp = 0;
+        }
+        memcpy(block->block_contents+offset, &temp, sizeof(char));
+        offset += sizeof(char);
     }
 
-    /* If the block does not exist, create it */
-    if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    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->current_trajectory_frame_set_input_file_pos > 0)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
-        else
+    }
+    offset += sizeof(data->n_values_per_frame);
+
+    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)
         {
-            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
+    }
+    offset += sizeof(data->codec_id);
 
-        if(tng_data_block_create(tng_data, block_type_flag) !=
-            TNG_SUCCESS)
+    if(data->codec_id != TNG_UNCOMPRESSED)
+    {
+        memcpy(block->block_contents+offset, &data->compression_multiplier,
+               sizeof(data->compression_multiplier));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            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__);
+            }
         }
-        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+        offset += sizeof(data->compression_multiplier);
+    }
+
+    if(data->n_frames > 0 && stride_length > 1)
+    {
+        /* FIXME: first_frame_with_data is not reliably set */
+        if(data->first_frame_with_data == 0)
         {
-            data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+            data->first_frame_with_data = frame_set->first_frame;
         }
-        else
+        memcpy(block->block_contents+offset, &data->first_frame_with_data,
+               sizeof(data->first_frame_with_data));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 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__);
+            }
         }
-        data->block_id = block->id;
+        offset += sizeof(data->first_frame_with_data);
 
-        data->block_name = malloc(strlen(block->name) + 1);
-        if(!data->block_name)
+        memcpy(block->block_contents+offset, &stride_length,
+               sizeof(stride_length));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block->name)+1, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            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__);
+            }
         }
-        strcpy(data->block_name, block->name);
-
-        data->datatype = datatype;
-
-        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;
+        offset += sizeof(stride_length);
     }
 
-    n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
-    if(codec_id != TNG_UNCOMPRESSED)
+    memcpy(block->block_contents+offset, &num_first_particle,
+           sizeof(num_first_particle));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        switch(codec_id)
+        if(tng_data->output_endianness_swap_func_64(tng_data,
+           (int64_t *)block->header_contents+offset)
+            != TNG_SUCCESS)
         {
-#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
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
+    offset += sizeof(num_first_particle);
 
-    /* Allocate memory */
-    if(!data->values || data->n_frames != n_frames ||
-       data->n_values_per_frame != n_values)
+    memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
-                                 n_values) !=
-           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 allocate memory for data. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, __LINE__);
         }
     }
+    offset += sizeof(n_particles);
 
-    data->first_frame_with_data = first_frame_with_data;
-
-    if(datatype == TNG_CHAR_DATA)
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        for(i = 0; i < n_frames_div; i++)
+        if(data->strings)
         {
-            for(j = 0; j < n_values; j++)
+            for(i = 0; i < frame_step; i++)
             {
-                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])
+                first_dim_values = data->strings[i];
+                for(j = num_first_particle; j < num_first_particle + n_particles;
+                    j++)
                 {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                           len, __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
+                    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;
+                    }
                 }
-                strncpy(data->strings[i][j], block->block_contents+*offset,
-                        len);
-                *offset += len;
             }
         }
     }
-    else
+    else if(data->values)
     {
-        memcpy(data->values, block->block_contents + *offset,
-               block->block_contents_size - *offset);
-        switch(datatype)
+        memcpy(block->block_contents + offset, data->values,
+               block->block_contents_size - offset);
+
+        switch(data->datatype)
         {
         case TNG_FLOAT_DATA:
-            if(tng_data->input_endianness_swap_func_32)
+            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+               data->codec_id == TNG_TNG_COMPRESSION)
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+                if(tng_data->input_endianness_swap_func_32)
                 {
-                    if(tng_data->input_endianness_swap_func_32(tng_data,
-                        (int32_t *)((char *)data->values + i))
-                        != TNG_SUCCESS)
+                    for(i = offset; i < block->block_contents_size; 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 *)(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:
-        case TNG_DOUBLE_DATA:
             if(tng_data->input_endianness_swap_func_64)
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+                for(i = offset; i < block->block_contents_size; i+=size)
                 {
                     if(tng_data->input_endianness_swap_func_64(tng_data,
-                        (int64_t *)((char *)data->values + i))
-                        != TNG_SUCCESS)
+                       (int64_t *)(block->block_contents + i))
+                       != TNG_SUCCESS)
                     {
                         fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                                 __FILE__, __LINE__);
@@ -5788,375 +6248,478 @@ static tng_function_status tng_data_read(tng_trajectory_t tng_data,
                 }
             }
             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
+    {
+        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
+    }
+
+    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)
+    {
+        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);*/
+            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);
+                }
+                /* 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);
 }
 
-/** Write a non-particle data block
+/* TEST: */
+/** Create 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.
+ * @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_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_data_block_create
+                (tng_trajectory_t tng_data,
+                 const char block_type_flag)
 {
-    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;
-    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
-    {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
-    }
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        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)
+        frame_set->n_data_blocks++;
+        data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
+                       frame_set->n_data_blocks);
+        if(!data)
         {
-            return(TNG_SUCCESS);
+            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);
         }
-
-        stride_length = tng_max_i64(1, data->stride_length);
+        frame_set->tr_data = data;
     }
     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)
+        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 (%d bytes). %s: %d\n", len+1,
-                   __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
+            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);
         }
-        block->name = temp_name;
-    }
-    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 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);
+        tng_data->non_tr_data = data;
     }
 
-    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;
-    }
+    return(TNG_SUCCESS);
+}
 
-    block->block_contents_size = sizeof(char) * 2 +
-                                 sizeof(data->n_values_per_frame) +
-                                 sizeof(data->codec_id);
+/* 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(stride_length > 1)
+    if(n_values_per_frame == 0)
     {
-        block->block_contents_size += sizeof(data->first_frame_with_data) +
-                                      sizeof(data->stride_length);
+        return(TNG_FAILURE);
     }
 
-    if(data->codec_id != TNG_UNCOMPRESSED)
+    if(data->strings && data->datatype == TNG_CHAR_DATA)
     {
-        block->block_contents_size += sizeof(data->compression_multiplier);
+        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;
+                }
+            }
+            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(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        dependency = TNG_FRAME_DEPENDENT;
+        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;
+            }
+        }
     }
     else
     {
-        dependency = 0;
-    }
-    if(dependency & TNG_FRAME_DEPENDENT)
-    {
-        block->block_contents_size += sizeof(char);
+        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 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 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_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)
+{
+    int64_t i, j, n_frames_div;
+    int size, len;
 #ifdef USE_ZLIB
-    data_start_pos = block->block_contents_size;
+    unsigned long 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(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
-    {
-        block->block_contents_size += size * frame_step *
-        data->n_values_per_frame;
-    }
+    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
+
+    switch(datatype)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+    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);
     }
 
-
-    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)
+    /* If the block does not exist, create it */
+    if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
     {
-        if(stride_length > 1)
+        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
         {
-            temp = 1;
+            block_type_flag = TNG_TRAJECTORY_BLOCK;
         }
         else
         {
-            temp = 0;
+            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
         }
-        memcpy(block->block_contents+offset, &temp, sizeof(char));
-        offset += sizeof(char);
-    }
 
-    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)
+        if(tng_data_block_create(tng_data, block_type_flag) !=
+            TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
-    }
-    offset += sizeof(data->n_values_per_frame);
-
-    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)
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
         }
-    }
-    offset += sizeof(data->codec_id);
-
-    if(data->codec_id != TNG_UNCOMPRESSED)
-    {
-        memcpy(block->block_contents+offset, &data->compression_multiplier,
-               sizeof(data->compression_multiplier));
-        if(tng_data->output_endianness_swap_func_64)
+        else
         {
-            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__);
-            }
+            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
         }
-        offset += sizeof(data->compression_multiplier);
-    }
+        data->block_id = block->id;
 
-    if(data->n_frames > 0 && stride_length > 1)
-    {
-        /* 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)
+        data->block_name = malloc(strlen(block->name) + 1);
+        if(!data->block_name)
         {
-            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 (%d bytes). %s: %d\n",
+                   (int)strlen(block->name)+1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(data->first_frame_with_data);
+        strcpy(data->block_name, block->name);
 
-        memcpy(block->block_contents+offset, &stride_length,
-               sizeof(data->stride_length));
-        if(tng_data->output_endianness_swap_func_64)
+        data->datatype = datatype;
+
+        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;
+    }
+
+    n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+
+    if(codec_id != TNG_UNCOMPRESSED)
+    {
+        switch(codec_id)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
+#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: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                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(data->stride_length);
     }
 
-    if(data->datatype == TNG_CHAR_DATA)
+    /* Allocate memory */
+    if(!data->values || data->n_frames != n_frames ||
+       data->n_values_per_frame != n_values)
     {
-        if(data->strings)
+        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
+                                 n_values) !=
+           TNG_SUCCESS)
         {
-            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;
-                }
-            }
+            fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    else if(data->values)
+
+    data->first_frame_with_data = first_frame_with_data;
+
+    if(datatype == TNG_CHAR_DATA)
     {
-        memcpy(block->block_contents + offset, data->values,
-               block->block_contents_size - offset);
-        switch(data->datatype)
+        for(i = 0; i < n_frames_div; i++)
         {
-        case TNG_FLOAT_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
+            for(j = 0; j < n_values; j++)
             {
-                if(tng_data->input_endianness_swap_func_32)
+                len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+                              TNG_MAX_STR_LEN);
+                if(data->strings[i][j])
                 {
-                    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__);
-                        }
-                    }
+                    free(data->strings[i][j]);
                 }
-            }
-            else
-            {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_32)
+                data->strings[i][j] = malloc(len);
+                if(!data->strings[i][j])
                 {
-                    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__);
-                        }
-                    }
+                    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;
             }
-            break;
-        case TNG_INT_DATA:
-            if(tng_data->input_endianness_swap_func_64)
+        }
+    }
+    else
+    {
+        memcpy(data->values, block->block_contents + *offset,
+               block->block_contents_size - *offset);
+        switch(datatype)
+        {
+        case TNG_FLOAT_DATA:
+            if(tng_data->input_endianness_swap_func_32)
             {
-                for(i = offset; i < block->block_contents_size; i+=size)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                       (int64_t *)(block->block_contents + i))
-                       != TNG_SUCCESS)
+                    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__);
@@ -6164,41 +6727,18 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
                 }
             }
             break;
+        case TNG_INT_DATA:
         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
+            if(tng_data->input_endianness_swap_func_64)
             {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_64)
+                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
                 {
-                    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))
+                    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__);
-                        }
+                    {
+                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                __FILE__, __LINE__);
                     }
                 }
             }
@@ -6207,687 +6747,742 @@ static tng_function_status tng_data_block_write(tng_trajectory_t tng_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
     {
-        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(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
-        switch(data->codec_id)
+        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)
         {
-#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
+            return(TNG_SUCCESS);
         }
+
+        stride_length = tng_max_i64(1, data->stride_length);
+    }
+    else
+    {
+        data = &tng_data->non_tr_data[block_index];
+        stride_length = 1;
     }
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    switch(data->datatype)
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+    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(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
+    len = (unsigned int)strlen(data->block_name) + 1;
+
+    if(!block->name || strlen(block->name) < len)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        temp_name = realloc(block->name, len);
+        if(!temp_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
+                   __FILE__, __LINE__);
+            free(block->name);
+            block->name = 0;
+            return(TNG_CRITICAL);
+        }
+        block->name = temp_name;
     }
+    strncpy(block->name, data->block_name, len);
+    block->id = data->block_id;
 
-    return(TNG_SUCCESS);
-}
+    /* 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);
 
-/** Read the meta information 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).
- * @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)
-{
-    int meta_size;
-    char *contents;
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        /* 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);
 
-    if(block->block_contents)
+        n_frames -= (data->first_frame_with_data - frame_set->first_frame);
+    }
+
+    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)
     {
-        contents = block->block_contents;
+        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
     {
-        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__);
-        }
+        dependency = 0;
+    }
+
+    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);
+    }
 
-        if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
-        {
-            fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
-            free(contents);
-            return(TNG_CRITICAL);
-        }
+    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);
     }
 
-    memcpy(datatype, contents+*offset,
-           sizeof(*datatype));
-    *offset += sizeof(*datatype);
 
-    memcpy(dependency, contents+*offset,
-           sizeof(*dependency));
-    *offset += sizeof(*dependency);
+    memcpy(block->block_contents, &data->datatype, sizeof(char));
+    offset += sizeof(char);
 
-    if(*dependency & TNG_FRAME_DEPENDENT)
+    memcpy(block->block_contents+offset, &dependency, sizeof(char));
+    offset += sizeof(char);
+
+    if(dependency & TNG_FRAME_DEPENDENT)
     {
-        memcpy(sparse_data, contents+*offset,
-               sizeof(*sparse_data));
-        *offset += sizeof(*sparse_data);
+        if(stride_length > 1)
+        {
+            temp = 1;
+        }
+        else
+        {
+            temp = 0;
+        }
+        memcpy(block->block_contents+offset, &temp, sizeof(char));
+        offset += sizeof(char);
     }
 
-    memcpy(n_values, contents+*offset,
-        sizeof(*n_values));
-    if(tng_data->input_endianness_swap_func_64)
+    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->input_endianness_swap_func_64(tng_data,
-                                                   n_values)
+        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_values);
+    offset += sizeof(data->n_values_per_frame);
 
-    memcpy(codec_id, contents+*offset,
-        sizeof(*codec_id));
-    if(tng_data->input_endianness_swap_func_64)
+    memcpy(block->block_contents+offset, &data->codec_id,
+           sizeof(data->codec_id));
+    if(tng_data->output_endianness_swap_func_64)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   codec_id)
+        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(*codec_id);
+    offset += sizeof(data->codec_id);
 
-    if(*codec_id != TNG_UNCOMPRESSED)
+    if(data->codec_id != TNG_UNCOMPRESSED)
     {
-        memcpy(multiplier, contents+*offset,
-            sizeof(*multiplier));
-        if(tng_data->input_endianness_swap_func_64)
+        memcpy(block->block_contents+offset, &data->compression_multiplier,
+               sizeof(data->compression_multiplier));
+        if(tng_data->output_endianness_swap_func_64)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       (int64_t *) multiplier)
+            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(*multiplier);
-    }
-    else
-    {
-        *multiplier = 1;
+        offset += sizeof(data->compression_multiplier);
     }
 
-    if(*dependency & TNG_FRAME_DEPENDENT)
+    if(data->n_frames > 0 && stride_length > 1)
     {
-        if(*sparse_data)
+        /* FIXME: first_frame_with_data is not reliably set */
+        if(data->first_frame_with_data == 0)
         {
-            memcpy(first_frame_with_data, contents+*offset,
-                sizeof(*first_frame_with_data));
-            if(tng_data->input_endianness_swap_func_64)
+            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)
             {
-                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__);
-                }
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
-            *offset += sizeof(*first_frame_with_data);
+        }
+        offset += sizeof(data->first_frame_with_data);
 
-            memcpy(stride_length, contents+*offset,
-                sizeof(*stride_length));
-            if(tng_data->input_endianness_swap_func_64)
+        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)
             {
-                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__);
-                }
+                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;
         }
-    }
-    else
-    {
-        *first_frame_with_data = 0;
-        *stride_length = 1;
-        *n_frames = 1;
+        offset += sizeof(data->stride_length);
     }
 
-    if (*dependency & TNG_PARTICLE_DEPENDENT)
+    if(data->datatype == TNG_CHAR_DATA)
     {
-        memcpy(num_first_particle, contents+*offset,
-               sizeof(*num_first_particle));
-        if(tng_data->input_endianness_swap_func_64)
+        if(data->strings)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       num_first_particle)
-                != TNG_SUCCESS)
+            for(i = 0; i < frame_step; i++)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                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;
+                }
             }
         }
-        *offset += sizeof(*num_first_particle);
-
-        memcpy(block_n_particles, contents+*offset,
-            sizeof(*block_n_particles));
-        if(tng_data->input_endianness_swap_func_64)
+    }
+    else if(data->values)
+    {
+        memcpy(block->block_contents + offset, data->values,
+               block->block_contents_size - offset);
+        switch(data->datatype)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       block_n_particles)
-                != TNG_SUCCESS)
+        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
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                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;
         }
-        *offset += sizeof(*block_n_particles);
-    }
-
-    if(!block->block_contents)
-    {
-        free(contents);
-    }
-    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;
-
-    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)
-    {
-        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)
+    else
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        memset(block->block_contents+offset, 0, 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. */
+    frame_set->n_written_frames += frame_set->n_unwritten_frames;
+    frame_set->n_unwritten_frames = 0;
 
-    if(hash_mode == TNG_USE_HASH)
+    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
     {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
+        switch(data->codec_id)
         {
-            fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
-                block->name, __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
+#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
         }
     }
 
-    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));
-    }
-}
-
-/** 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)
-    {
-        free(block->block_contents);
-    }
-
-    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);
-    }
+        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__);
+        }
 
-    contents_start_pos = ftell(tng_data->output_file);
+        if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
+        {
+            fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
+            free(contents);
+            return(TNG_CRITICAL);
+        }
+    }
 
-    fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
-          sizeof(int64_t), SEEK_CUR);
+    memcpy(datatype, contents+*offset,
+           sizeof(*datatype));
+    *offset += sizeof(*datatype);
 
-    tng_data->input_file = temp;
+    memcpy(dependency, contents+*offset,
+           sizeof(*dependency));
+    *offset += sizeof(*dependency);
 
-    pos = tng_data->first_trajectory_frame_set_output_file_pos;
+    if(*dependency & TNG_FRAME_DEPENDENT)
+    {
+        memcpy(sparse_data, contents+*offset,
+               sizeof(*sparse_data));
+        *offset += sizeof(*sparse_data);
+    }
 
+    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);
-    }
-
-    pos = tng_data->last_trajectory_frame_set_output_file_pos;
-
+    memcpy(codec_id, contents+*offset,
+        sizeof(*codec_id));
     if(tng_data->input_endianness_swap_func_64)
     {
         if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                    &pos)
+                                                   codec_id)
             != TNG_SUCCESS)
         {
             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                     __FILE__, __LINE__);
         }
     }
+    *offset += sizeof(*codec_id);
 
-    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)
+    if(*codec_id != TNG_UNCOMPRESSED)
     {
-        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;
-
+        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, header_start_pos,
-                                contents_start_pos);
+            *first_frame_with_data = 0;
+            *stride_length = 1;
+            *n_frames = tng_data->current_trajectory_frame_set.n_frames;
         }
-        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)
+    else
     {
-        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)
-        {
-            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 = 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;
+        *first_frame_with_data = 0;
+        *stride_length = 1;
+        *n_frames = 1;
+    }
 
+    if (*dependency & TNG_PARTICLE_DEPENDENT)
+    {
+        memcpy(num_first_particle, contents+*offset,
+               sizeof(*num_first_particle));
         if(tng_data->input_endianness_swap_func_64)
         {
             if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                        &pos)
+                                                       num_first_particle)
                 != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
                         __FILE__, __LINE__);
             }
         }
+        *offset += sizeof(*num_first_particle);
 
-        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)
+        memcpy(block_n_particles, contents+*offset,
+            sizeof(*block_n_particles));
+        if(tng_data->input_endianness_swap_func_64)
         {
-            tng_md5_hash_update(tng_data, block,
-                                frame_set->medium_stride_prev_frame_set_file_pos,
-                                contents_start_pos);
+            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__);
+            }
         }
+        *offset += sizeof(*block_n_particles);
     }
 
-    /* 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)
+    if(!block->block_contents)
     {
-        fseek(tng_data->output_file,
-              (long)frame_set->long_stride_prev_frame_set_file_pos,
-              SEEK_SET);
+        free(contents);
+    }
+    return(TNG_SUCCESS);
+}
 
-        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);
-        }
+/** 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;
 
-        contents_start_pos = ftell(tng_data->output_file);
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
 
-        fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+    if(block->block_contents)
+    {
+        free(block->block_contents);
+    }
 
-        pos = tng_data->current_trajectory_frame_set_output_file_pos;
+    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);
+    }
 
-        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__);
-            }
-        }
+    /* 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);
+    }
 
-        if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
-        {
-            tng_data->input_file = temp;
-            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. */
 
-        if(hash_mode == TNG_USE_HASH)
+    if(hash_mode == TNG_USE_HASH)
+    {
+        tng_md5_hash_match_verify(block, &same_hash);
+        if(same_hash != TNG_TRUE)
         {
-            tng_md5_hash_update(tng_data, block,
-                                frame_set->long_stride_prev_frame_set_file_pos,
-                                contents_start_pos);
+            fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
+                block->name, __FILE__, __LINE__);
+    /*         return(TNG_FAILURE); */
         }
     }
 
-    fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
-
-    tng_data->input_file = temp;
-
-    tng_block_destroy(&block);
+    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);
+    }
 
-    return(TNG_SUCCESS);
+    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
@@ -7262,29 +7857,19 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_add
                  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 +7882,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.");
@@ -7343,17 +7928,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 +7939,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,
@@ -7506,12 +8070,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 +8096,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 +8144,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)
@@ -7858,7 +8422,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 +8445,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 +8471,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;
 
@@ -7926,16 +8501,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,21 +8515,9 @@ 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));
@@ -8006,7 +8559,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 +8677,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 +8700,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 +8726,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;
@@ -8223,6 +8788,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 +8800,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 +8914,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 +8942,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;
@@ -8410,16 +8979,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++;
 
@@ -8492,7 +9051,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 +9066,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 +9081,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]);
         }
@@ -9095,7 +9654,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)
@@ -9165,7 +9724,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 +9861,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 +9957,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 +9971,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 +10010,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 +10024,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 +10065,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 +10077,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 +10123,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 +10135,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 +10170,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]);
         }
@@ -9692,7 +10255,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 +10458,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);
 }
@@ -10831,7 +11394,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];
     }
@@ -11172,7 +11735,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);
@@ -11912,11 +12475,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 = ftell(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);
+    }
+    fseek(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;
+        fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+    }
+
+    fseek(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.");
@@ -11932,8 +12539,8 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
     {
         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);
     }
+    fseek(tng_data->input_file, 0, SEEK_SET);
 
     tng_block_init(&block);
     /* Non trajectory blocks (they come before the trajectory
@@ -11943,11 +12550,7 @@ 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++;
-        }
+        tng_block_read_next(tng_data, block, hash_mode);
         prev_pos = ftell(tng_data->input_file);
     }
 
@@ -11967,7 +12570,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 +12581,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 +12666,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);
 }
@@ -12077,7 +12745,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
 
     /* 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",
                file_pos, __FILE__, __LINE__);
@@ -12096,7 +12765,8 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
         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);
@@ -12211,7 +12881,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)
         {
@@ -12545,8 +13216,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);
+            fseek(tng_data->output_file, (long)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)
@@ -12601,8 +13272,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);
+                    fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
+                          sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
                     tng_block_destroy(&block);
 
@@ -13396,7 +14067,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)
                 {
@@ -13464,7 +14136,8 @@ 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);
@@ -13824,7 +14497,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)
                 {
@@ -13903,7 +14577,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)
             {
@@ -13964,7 +14639,8 @@ 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);
@@ -14319,7 +14995,7 @@ static tng_function_status tng_data_values_alloc
 
     }
 
-    for(i = n_frames; i--;)
+    for(i = 0; i < n_frames; i++)
     {
         (*values)[i] = malloc(sizeof(union data_values) *
                            n_values_per_frame);
@@ -14355,7 +15031,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)
                         {
@@ -14413,7 +15089,7 @@ static tng_function_status tng_particle_data_values_alloc
 
     }
 
-    for(i = n_frames; i--;)
+    for(i = 0; i < n_frames; i++)
     {
         (*values)[i] = malloc(sizeof(union data_values *) *
                            n_particles);
@@ -14426,7 +15102,7 @@ static tng_function_status tng_particle_data_values_alloc
             *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);
@@ -14468,7 +15144,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)
                             {
@@ -14526,7 +15202,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get
         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,
@@ -14548,7 +15225,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 +15258,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 +15270,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 +15281,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 +15293,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));
@@ -14666,7 +15343,8 @@ tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
         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,
@@ -14688,7 +15366,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)
@@ -14794,7 +15472,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
         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);
@@ -14819,7 +15498,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 +15547,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 +15569,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 +15591,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 +15614,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 *
@@ -15013,7 +15692,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
         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)
             {
@@ -15236,7 +15916,8 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
         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,
@@ -15258,7 +15939,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 +15997,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 +16015,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 +16033,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 +16052,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 *
@@ -15431,7 +16112,8 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
         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,
@@ -15453,7 +16135,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 +16216,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 *
@@ -15601,7 +16283,8 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
         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);
@@ -15686,10 +16369,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 +16396,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 +16425,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 +16455,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 *
@@ -15857,7 +16540,8 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
         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)
             {
@@ -16182,6 +16866,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
     }
     else if(mode == 'a')
     {
+        if((*tng_data_p)->output_file)
+        {
+            fclose((*tng_data_p)->output_file);
+        }
+        (*tng_data_p)->output_file = (*tng_data_p)->input_file;
         fseek((*tng_data_p)->input_file,
                 (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
                 SEEK_SET);
@@ -16192,6 +16881,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 +16889,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);
@@ -18375,19 +19062,18 @@ 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 */
         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);
index baceef75d1cd51fc05539d1dc6e7f1216897eca7..d53d15b07b043b8cfddb753003e22f75a1edaeca 100644 (file)
@@ -1,6 +1,4 @@
 /* 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.
index b57eff41c8ba8bf5e5a818c180849e3cb5816822..fd9f4b0e770a7cb07c7699f8e2d3222f01284b96 100644 (file)
@@ -5,7 +5,7 @@
 # include <time.h>
 # include <math.h>
 # include <omp.h>
-# include "tng_io.h"
+#include "../../include/tng_io.h"
 
 int main ();
 void compute ( int np, int nd, double pos[], double vel[],
index 34b8964144e5a5412a55783a88d80fbc3b1f024a..8c332f32eed114d8be0eb671ff44826090a3536c 100644 (file)
@@ -5,7 +5,7 @@
 # include <time.h>
 # include <math.h>
 # include <omp.h>
-# include "tng_io.h"
+#include "../../include/tng_io.h"
 
 int main ();
 void compute ( int np, int nd, float pos[], float vel[],
index 079cad7e48066b49110db2c7814f54a1f0ee9ed7..2a0bb0974176cfe2333907cf709d6c1fe461c928 100644 (file)
@@ -1,6 +1,4 @@
 /* This code is part of the tng binary trajectory format.
- *
- *                      VERSION 1.0
  *
  * Written by Magnus Lundborg
  * Copyright (c) 2012-2013, The GROMACS development team.
index 64df9df278261e66a484c051dcaf8724a513828b..1667bae2d8e3501bf99d6272ffdf86d7158495d1 100644 (file)
@@ -2,8 +2,6 @@
  *
  *  The high-level API of the TNG API is used where appropriate.
  *
- *                      VERSION 1.0
- *
  * Written by Magnus Lundborg
  * Copyright (c) 2012-2013, The GROMACS development team.
  * Check out http://www.gromacs.org for more information.
index 973ac4fb7b6268c0c5f2e9133f2133382fb9e7db..dd13d925d3dd3bfb39d9276519694bed4932559f 100644 (file)
@@ -1,9 +1,7 @@
 /* This code is part of the tng binary trajectory format.
- *
- *                      VERSION 1.0
  *
  * 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.
  *
  *
@@ -149,6 +147,9 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
     tng_medium_stride_length_set(*traj, 10);
     tng_long_stride_length_set(*traj, 100);
 
+    tng_first_user_name_set(*traj, "User1");
+    tng_first_program_name_set(*traj, "tng_testing");
+
     /* Create molecules */
     if(tng_test_setup_molecules(*traj) == TNG_CRITICAL)
     {
@@ -212,7 +213,7 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
     /* Generate a custom annotation data block */
     strcpy(annotation, "This trajectory was generated from tng_io_testing. "
                        "It is not a real MD trajectory.");
-    if(tng_data_block_add(*traj, 10100, "DETAILS", TNG_CHAR_DATA,
+    if(tng_data_block_add(*traj, TNG_TRAJ_GENERAL_COMMENTS, "COMMENTS", TNG_CHAR_DATA,
                           TNG_NON_TRAJECTORY_BLOCK, 1, 1, 1, TNG_UNCOMPRESSED,
                           annotation) != TNG_SUCCESS)
     {
@@ -569,6 +570,26 @@ tng_function_status tng_test_get_positions_data(tng_trajectory_t traj)
     return(TNG_SUCCESS);
 }
 
+
+tng_function_status tng_test_append(tng_trajectory_t traj)
+{
+    tng_function_status stat;
+
+    stat = tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_test.tng", 'a', &traj);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
+
+    tng_last_user_name_set(traj, "User2");
+    tng_last_program_name_set(traj, "tng_testing");
+    tng_file_headers_write(traj, TNG_USE_HASH);
+
+    stat = tng_util_trajectory_close(&traj);
+
+    return(stat);
+}
+
 int main()
 {
     tng_trajectory_t traj;
@@ -683,6 +704,17 @@ int main()
         printf("Test Utility function close:\t\t\tSucceeded.\n");
     }
 
+    if(tng_test_append(traj) != TNG_SUCCESS)
+    {
+        printf("Test Append:\t\t\t\t\tFailed. %s: %d.\n",
+               __FILE__, __LINE__);
+        exit(1);
+    }
+    else
+    {
+        printf("Test Append:\t\t\t\t\tSucceeded.\n");
+    }
+
     printf("Tests finished\n");
 
     exit(0);
index 95d1c9a3fcb23e1056779d9548ae9d897dafc4f4..e2e23c6b4f709bd2b0c461386c758f3c3de38cb7 100644 (file)
@@ -1,8 +1,6 @@
 #ifdef TNG_BUILD_OPENMP_EXAMPLES
 
 /* This code is part of the tng binary trajectory format.
- *
- *                      VERSION 1.0
  *
  * Written by Magnus Lundborg
  * Copyright (c) 2012-2013, The GROMACS development team.