TNG version 1.7.3
authorMagnus Lundborg <lundborg.magnus@gmail.com>
Tue, 9 Dec 2014 12:43:16 +0000 (13:43 +0100)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Tue, 21 Apr 2015 06:49:13 +0000 (08:49 +0200)
Corresponds to commit e862ebe8 in the TNG repository.

Large parts of the TNG code have been rewritten to avoid code duplication. Some functions have been combined.

Summary of additional changes (see git log for full details):
  Bug fixes:
    Fixed bug reading last frame and time of last frame.
    Fix MingW build
    Fixed bug reading non-particle data.
    Check that ZLib is available before using it.
    Fixed bug when appending to trajectory.

  New functions:
    tng_util_num_frames_with_data_of_block_id_get()

  Fixed compiler warnings
  Improved testing suite

Change-Id: I97334b1d93f21646fe1625e65e5fcdf38a0450d9

44 files changed:
docs/install-guide/index.rst
src/external/tng_io/BuildTNG.cmake
src/external/tng_io/Doxyfile.in
src/external/tng_io/include/compression/bwlzh.h
src/external/tng_io/include/compression/bwt.h
src/external/tng_io/include/compression/coder.h
src/external/tng_io/include/compression/dict.h
src/external/tng_io/include/compression/fixpoint.h
src/external/tng_io/include/compression/huffman.h
src/external/tng_io/include/compression/lz77.h
src/external/tng_io/include/compression/merge_sort.h
src/external/tng_io/include/compression/mtf.h
src/external/tng_io/include/compression/rle.h
src/external/tng_io/include/compression/tng_compress.h
src/external/tng_io/include/compression/vals16.h
src/external/tng_io/include/compression/warnmalloc.h
src/external/tng_io/include/compression/widemuldiv.h
src/external/tng_io/include/tng/tng_io.h
src/external/tng_io/include/tng/tng_io_fwd.h
src/external/tng_io/src/compression/bwlzh.c
src/external/tng_io/src/compression/bwt.c
src/external/tng_io/src/compression/coder.c
src/external/tng_io/src/compression/dict.c
src/external/tng_io/src/compression/fixpoint.c
src/external/tng_io/src/compression/huffman.c
src/external/tng_io/src/compression/huffmem.c
src/external/tng_io/src/compression/lz77.c
src/external/tng_io/src/compression/merge_sort.c
src/external/tng_io/src/compression/mtf.c
src/external/tng_io/src/compression/rle.c
src/external/tng_io/src/compression/tng_compress.c
src/external/tng_io/src/compression/vals16.c
src/external/tng_io/src/compression/warnmalloc.c
src/external/tng_io/src/compression/widemuldiv.c
src/external/tng_io/src/compression/xtc2.c
src/external/tng_io/src/compression/xtc3.c
src/external/tng_io/src/lib/md5.c
src/external/tng_io/src/lib/tng_io.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 8c245f4245da181896fcad7a458b1544770ccf76..86462019e3dea19521467cc15dfd2629ef5d311a 100644 (file)
@@ -289,7 +289,7 @@ Optional build components
   Motif/Lesstif libraries and header files. You may prefer to use
   third-party software for visualization, such as VMD_ or PyMol_.
 * An external TNG library for trajectory-file handling can be used,
-  but TNG 1.6 is bundled in the |Gromacs| source already
+  but TNG 1.7.3 is bundled in the |Gromacs| source already
 * zlib is used by TNG for compressing some kinds of trajectory data
 * Running the |Gromacs| test suite requires libxml2
 * Building the |Gromacs| documentation requires ImageMagick, pdflatex,
index ea77430cf92c228b80425a7db2d486884fb8e21e..a00d5b5e4ed2ddb5550eb9366123fd40fefafede 100644 (file)
@@ -4,10 +4,10 @@ set(TNG_ROOT_BINARY_DIR ${CMAKE_BINARY_DIR}/${TNG_ROOT_BINARY_DIR})
 
 function (TNG_GENERATE_VERSION_H)
     set(TNG_MAJOR_VERSION "1")
-    set(TNG_MINOR_VERSION "6")
-    set(TNG_VERSION_PATCH_LEVEL "1")
+    set(TNG_MINOR_VERSION "7")
+    set(TNG_VERSION_PATCH_LEVEL "3")
     set(TNG_IO_VERSION "${TNG_MAJOR_VERSION}.${TNG_MINOR_VERSION}.${TNG_VERSION_PATCH_LEVEL}")
-    set(TNG_API_VERSION "6")
+    set(TNG_API_VERSION "7")
     configure_file(${TNG_ROOT_SOURCE_DIR}/include/tng/version.h.in
                    ${TNG_ROOT_BINARY_DIR}/include/tng/version.h)
 
index 03ba55355acc4f4809bc44dbc0363a29f978557c..27ca707b15822852083e95789d44ec85e64cca0b 100644 (file)
@@ -32,7 +32,7 @@ PROJECT_NAME           = "TNG API"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = "1.4"
+PROJECT_NUMBER         = "@TNG_IO_VERSION@"
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer
@@ -626,7 +626,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = @PROJECT_SOURCE_DIR@/src/lib @PROJECT_SOURCE_DIR@/include
+INPUT                  = @PROJECT_SOURCE_DIR@/src/lib @PROJECT_SOURCE_DIR@/include/tng/
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -658,7 +658,7 @@ RECURSIVE              = NO
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = @PROJECT_SOURCE_DIR@/src/lib/md5.c @PROJECT_SOURCE_DIR@/include/tng/md5.h @PROJECT_SOURCE_DIR@/include/tng/tng_io.hpp @PROJECT_SOURCE_DIR@/src/lib/tng_io.c
+EXCLUDE                = @PROJECT_SOURCE_DIR@/src/lib/md5.c @PROJECT_SOURCE_DIR@/include/tng/md5.h @PROJECT_SOURCE_DIR@/include/tng/tng_io.hpp @PROJECT_SOURCE_DIR@/src/lib/tng_io.c @PROJECT_SOURCE_DIR@/src/lib/tng_io_fortran.c
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
index 70d586a2d9c321f0362ed359156218a04b557f82..ce08f69cb836738647594043c3922e90e5fc27c2 100644 (file)
    allocated to be able to hold worst case. You can obtain this length
    conveniently by calling comp_get_buflen()
 */
-void DECLSPECDLLEXPORT bwlzh_compress(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress(unsigned int *vals, const int nvals,
                  unsigned char *output, int *output_len);
 
-void DECLSPECDLLEXPORT bwlzh_compress_no_lz77(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_no_lz77(unsigned int *vals, const int nvals,
                  unsigned char *output, int *output_len);
 
-int DECLSPECDLLEXPORT bwlzh_get_buflen(int nvals);
+int DECLSPECDLLEXPORT bwlzh_get_buflen(const int nvals);
 
-void DECLSPECDLLEXPORT bwlzh_decompress(unsigned char *input, int nvals,
+void DECLSPECDLLEXPORT bwlzh_decompress(unsigned char *input, const int nvals,
                    unsigned int *vals);
 
 
 /* The routines below are mostly useful for testing, and for internal
    use by the library. */
 
-void DECLSPECDLLEXPORT bwlzh_compress_verbose(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_verbose(unsigned int *vals, const int nvals,
                          unsigned char *output, int *output_len);
 
-void DECLSPECDLLEXPORT bwlzh_compress_no_lz77_verbose(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_no_lz77_verbose(unsigned int *vals, const int nvals,
                  unsigned char *output, int *output_len);
 
-void DECLSPECDLLEXPORT bwlzh_decompress_verbose(unsigned char *input, int nvals,
+void DECLSPECDLLEXPORT bwlzh_decompress_verbose(unsigned char *input, const int nvals,
                            unsigned int *vals);
 
 /* Compress the integers (positive, small integers are preferable)
@@ -47,12 +47,12 @@ void DECLSPECDLLEXPORT bwlzh_decompress_verbose(unsigned char *input, int nvals,
    to be able to hold worst case. You can obtain this length
    conveniently by calling comp_huff_buflen()
 */
-void Ptngc_comp_huff_compress(unsigned int *vals, int nvals,
+void Ptngc_comp_huff_compress(unsigned int *vals, const int nvals,
                        unsigned char *huffman, int *huffman_len);
 
-int Ptngc_comp_huff_buflen(int nvals);
+int Ptngc_comp_huff_buflen(const int nvals);
 
-void Ptngc_comp_huff_decompress(unsigned char *huffman, int huffman_len,
+void Ptngc_comp_huff_decompress(unsigned char *huffman, const int huffman_len,
                          unsigned int *vals);
 
 
@@ -62,11 +62,11 @@ void Ptngc_comp_huff_compress_verbose(unsigned int *vals, int nvals,
                                unsigned char *huffman, int *huffman_len,
                                int *huffdatalen,
                                int *huffman_lengths,int *chosen_algo,
-                               int isvals16);
+                               const int isvals16);
 
 #define N_HUFFMAN_ALGO 3
-char *Ptngc_comp_get_huff_algo_name(int algo);
-char *Ptngc_comp_get_algo_name(int algo);
+char *Ptngc_comp_get_huff_algo_name(const int algo);
+char *Ptngc_comp_get_algo_name(const int algo);
 
 
 #endif
index 9f927f8226f97d2dd028929e7657a84432cec503..fedfc3d0adc245a235780b46b3c5e9dab61e8c84 100644 (file)
 #ifndef BWT_H
 #define BWT_H
 
-void Ptngc_comp_to_bwt(unsigned int *vals, int nvals,
+void Ptngc_comp_to_bwt(unsigned int *vals, const int nvals,
                 unsigned int *output, int *index);
 
-void Ptngc_comp_from_bwt(unsigned int *input, int nvals, int index,
+void Ptngc_comp_from_bwt(unsigned int *input, const int nvals, int index,
                   unsigned int *vals);
 
-void Ptngc_bwt_merge_sort_inner(int *indices, int nvals,unsigned int *vals,
-                         int start, int end,
-                         unsigned int *nrepeat,
-                         int *workarray);
+void Ptngc_bwt_merge_sort_inner(int *indices, const int nvals, unsigned int *vals,
+                                const int start, const int end,
+                                unsigned int *nrepeat,
+                                int *workarray);
 
 #endif
index 34b56c1fe0d11506140bb905b679119454b6948d..d714c82f6f06dd293dbf70c09b34c528c0500f89 100644 (file)
@@ -29,10 +29,10 @@ struct coder
 
 struct coder DECLSPECDLLEXPORT *Ptngc_coder_init(void);
 void DECLSPECDLLEXPORT Ptngc_coder_deinit(struct coder *coder);
-unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder,int *input, int *length, int coding, int coding_parameter, int natoms, int speed);
-int DECLSPECDLLEXPORT Ptngc_unpack_array(struct coder *coder,unsigned char *packed,int *output, int length, int coding, int coding_parameter, int natoms);
+unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder,int *input, int *length, const int coding, const int coding_parameter, const int natoms, const int speed);
+int DECLSPECDLLEXPORT Ptngc_unpack_array(struct coder *coder,unsigned char *packed,int *output, const int length, const int coding, const int coding_parameter, const int natoms);
 unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array_xtc2(struct coder *coder,int *input, int *length);
-int DECLSPECDLLEXPORT Ptngc_unpack_array_xtc2(struct coder *coder,unsigned char *packed,int *output, int length);
+int DECLSPECDLLEXPORT Ptngc_unpack_array_xtc2(struct coder *coder, unsigned char *packed, int *output, const int length);
 unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array_xtc3(int *input, int *length, int natoms, int speed);
 int DECLSPECDLLEXPORT Ptngc_unpack_array_xtc3(unsigned char *packed,int *output, int length, int natoms);
 
@@ -40,7 +40,7 @@ void DECLSPECDLLEXPORT Ptngc_out8bits(struct coder *coder, unsigned char **outpu
 void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder,unsigned char **output);
 void DECLSPECDLLEXPORT Ptngc_write_pattern(struct coder *coder,unsigned int pattern, int nbits, unsigned char **output);
 
-void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder,unsigned int value,int nbits, unsigned char **output_ptr);
+void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder, unsigned int value, const int nbits, unsigned char **output_ptr);
 void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder,unsigned int value,int nbits, unsigned char **output_ptr);
 void DECLSPECDLLEXPORT Ptngc_writemanybits(struct coder *coder,unsigned char *value,int nbits, unsigned char **output_ptr);
 
index d66dd23ac1c5b1e499f9c44378e0aac6c4bbb758..26eed2736eb84d26cfc06336d9c7c83b2f1ffeae 100644 (file)
@@ -14,7 +14,7 @@
 
 void Ptngc_comp_canonical_dict(unsigned int *dict, int *ndict);
 
-void Ptngc_comp_make_dict_hist(unsigned int *vals, int nvals,
+void Ptngc_comp_make_dict_hist(unsigned int *vals, const int nvals,
                         unsigned int *dict, int *ndict,
                         unsigned int *hist);
 
index 6be748295b70df60331ad568fbe28666e67025f5..7b6a66725ef8dd73365dfea1f2d74faa7f1802fb 100644 (file)
 typedef unsigned long fix_t;
 
 /* Positive double to 32 bit fixed point value */
-fix_t Ptngc_ud_to_fix_t(double d,double max);
+fix_t Ptngc_ud_to_fix_t(double d, const double max);
 
 /* double to signed 32 bit fixed point value */
-fix_t Ptngc_d_to_fix_t(double d,double max);
+fix_t Ptngc_d_to_fix_t(double d, const double max);
 
 /* 32 bit fixed point value to positive double */
-double Ptngc_fix_t_to_ud(fix_t f, double max);
+double Ptngc_fix_t_to_ud(fix_t f, const double max);
 
 /* signed 32 bit fixed point value to double */
-double Ptngc_fix_t_to_d(fix_t f, double max);
+double Ptngc_fix_t_to_d(fix_t f, const double max);
 
 /* Convert a floating point variable to two 32 bit integers with range
    -2.1e9 to 2.1e9 and precision to somewhere around 1e-9. */
index 49347de2baccfa91f1bc81a6ce071d48aac42b89..f2ce1875b6af33dec84de286ba226684a94c1793 100644 (file)
@@ -12,8 +12,8 @@
 #ifndef HUFFMAN_H
 #define HUFFMAN_H
 
-void Ptngc_comp_conv_to_huffman(unsigned int *vals, int nvals,
-                         unsigned int *dict, int ndict,
+void Ptngc_comp_conv_to_huffman(unsigned int *vals, const int nvals,
+                         unsigned int *dict, const int ndict,
                          unsigned int *prob,
                          unsigned char *huffman,
                          int *huffman_len,
@@ -23,11 +23,11 @@ void Ptngc_comp_conv_to_huffman(unsigned int *vals, int nvals,
                          int *huffman_dict_unpackedlen);
 
 void Ptngc_comp_conv_from_huffman(unsigned char *huffman,
-                           unsigned int *vals, int nvals,
-                           int ndict,
+                           unsigned int *vals, const int nvals,
+                           const int ndict,
                            unsigned char *huffman_dict,
-                           int huffman_dictlen,
+                           const int huffman_dictlen,
                            unsigned int *huffman_dict_unpacked,
-                           int huffman_dict_unpackedlen);
+                           const int huffman_dict_unpackedlen);
 
 #endif
index ad37e5b30cf69dc6f636e9cf5ee826875243581e..d4a4beb856fc86313e04a7fa2e34909304a69a14 100644 (file)
 #ifndef LZ77_H
 #define LZ77_H
 
-void Ptngc_comp_to_lz77(unsigned int *vals, int nvals,
+void Ptngc_comp_to_lz77(unsigned int *vals, const int nvals,
                  unsigned int *data, int *ndata,
                  unsigned int *len, int *nlens,
                  unsigned int *offsets, int *noffsets);
 
-void Ptngc_comp_from_lz77(unsigned int *data, int ndata,
-                   unsigned int *len, int nlens,
-                   unsigned int *offsets, int noffsets,
-                   unsigned int *vals, int nvals);
+void Ptngc_comp_from_lz77(unsigned int *data, const int ndata,
+                   unsigned int *len, const int nlens,
+                   unsigned int *offsets, const int noffsets,
+                   unsigned int *vals, const int nvals);
 
 #endif
index 48ab41038ac546fffdcb37c5f28af2a4f00078a5..f8aaeb79bacc65305f0d9a617e39f65113290328 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef MERGE_SORT_H
 #define MERGE_SORT_H
 
-void Ptngc_merge_sort(void *base, size_t nmemb, size_t size,
+void Ptngc_merge_sort(void *base, const size_t nmemb, const size_t size,
                int (*compar)(const void *v1,const void *v2,const void *private),
                void *private);
 
index bc4b2c81f537daf1de4e22ad9916ac6c1e039383..3dc9ace1ea50b25ca5336809cf1772f780a96029 100644 (file)
 #ifndef MTF_H
 #define MTF_H
 
-void Ptngc_comp_conv_to_mtf(unsigned int *vals, int nvals,
-                     unsigned int *dict, int ndict,
+void Ptngc_comp_conv_to_mtf(unsigned int *vals, const int nvals,
+                     unsigned int *dict, const int ndict,
                      unsigned int *valsmtf);
 
-void Ptngc_comp_conv_from_mtf(unsigned int *valsmtf, int nvals,
-                       unsigned int *dict, int ndict,
+void Ptngc_comp_conv_from_mtf(unsigned int *valsmtf, const int nvals,
+                       unsigned int *dict, const int ndict,
                        unsigned int *vals);
 
-void Ptngc_comp_conv_to_mtf_partial(unsigned int *vals, int nvals,
+void Ptngc_comp_conv_to_mtf_partial(unsigned int *vals, const int nvals,
                              unsigned int *valsmtf);
 
-void Ptngc_comp_conv_from_mtf_partial(unsigned int *valsmtf, int nvals,
+void Ptngc_comp_conv_from_mtf_partial(unsigned int *valsmtf, const int nvals,
                                unsigned int *vals);
 
-void Ptngc_comp_conv_to_mtf_partial3(unsigned int *vals, int nvals,
+void Ptngc_comp_conv_to_mtf_partial3(unsigned int *vals, const int nvals,
                               unsigned char *valsmtf);
 
-void Ptngc_comp_conv_from_mtf_partial3(unsigned char *valsmtf, int nvals,
+void Ptngc_comp_conv_from_mtf_partial3(unsigned char *valsmtf, const int nvals,
                                 unsigned int *vals);
 
 #endif
index c6d47069b505129d1ed7e112246aaed6988d5b75..3665dd07177935ae0d3bca7265424dc4cab8ed46 100644 (file)
 #ifndef RLE_H
 #define RLE_H
 
-void Ptngc_comp_conv_to_rle(unsigned int *vals, int nvals,
-                     unsigned int *rle, int *nrle,
-                     int min_rle);
+void Ptngc_comp_conv_to_rle(unsigned int *vals, const int nvals,
+                                   unsigned int *rle, int *nrle,
+                                   const int min_rle);
 
 void Ptngc_comp_conv_from_rle(unsigned int *rle,
-                       unsigned int *vals, int nvals);
+                                         unsigned int *vals, const int nvals);
 
 #endif
index c8b8db1eadffd223314d1246ec863379e4c285d8..0082ba35d6282af38b9eb5d2847688718e6d19f0 100644 (file)
    If too large values are input (compared to the precision), NULL is returned.
 */
 
-char DECLSPECDLLEXPORT *tng_compress_pos(double *pos, int natoms, int nframes,
-                                        double desired_precision,
-                                        int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos(double *pos, const int natoms, const int nframes,
+                                        const double desired_precision,
+                                        const int speed, int *algo,
                                         int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_pos_float(float *pos, int natoms, int nframes,
-                                              float desired_precision,
-                                              int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos_float(float *pos, const int natoms, const int nframes,
+                                              const float desired_precision,
+                                              const int speed, int *algo,
                                               int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, int natoms, int nframes,
-                                            unsigned long prec_hi, unsigned long prec_lo,
+char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, const int natoms, const int nframes,
+                                            const unsigned long prec_hi, const unsigned long prec_lo,
                                             int speed,int *algo,
                                             int *nitems);
 
@@ -90,21 +90,21 @@ char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, int natoms, int nframes,
    by calling tng_compress_nalgo
 */
 
-char DECLSPECDLLEXPORT *tng_compress_pos_find_algo(double *pos, int natoms, int nframes,
-                                                  double desired_precision,
-                                                  int speed,
+char DECLSPECDLLEXPORT *tng_compress_pos_find_algo(double *pos, const int natoms, const int nframes,
+                                                  const double desired_precision,
+                                                  const int speed,
                                                   int *algo,
                                                   int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_pos_float_find_algo(float *pos, int natoms, int nframes,
-                                                        float desired_precision,
-                                                        int speed,
+char DECLSPECDLLEXPORT *tng_compress_pos_float_find_algo(float *pos, const int natoms, const int nframes,
+                                                        const float desired_precision,
+                                                        const int speed,
                                                         int *algo,
                                                         int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_pos_int_find_algo(int *pos, int natoms, int nframes,
-                                                      unsigned long prec_hi, unsigned long prec_lo,
-                                                      int speed,int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos_int_find_algo(int *pos, const int natoms, const int nframes,
+                                                      const unsigned long prec_hi, const unsigned long prec_lo,
+                                                      const int speed, int *algo,
                                                       int *nitems);
 
 /* This returns the number of integers required for the storage of the algorithm
@@ -116,36 +116,36 @@ int DECLSPECDLLEXPORT tng_compress_nalgo(void);
    selection for velocities is different, so the position and
    velocities routines should not be mixed. */
 
-char DECLSPECDLLEXPORT *tng_compress_vel(double *vel, int natoms, int nframes,
-                                        double desired_precision,
-                                        int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_vel(double *vel, const int natoms, const int nframes,
+                                        const double desired_precision,
+                                        const int speed, int *algo,
                                         int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_vel_float(float *vel, int natoms, int nframes,
-                                              float desired_precision,
-                                              int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_vel_float(float *vel, const int natoms, const int nframes,
+                                              const float desired_precision,
+                                              const int speed, int *algo,
                                               int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_vel_int(int *vel, int natoms, int nframes,
-                                            unsigned long prec_hi, unsigned long prec_lo,
+char DECLSPECDLLEXPORT *tng_compress_vel_int(int *vel, const int natoms, const int nframes,
+                                            const unsigned long prec_hi, const unsigned long prec_lo,
                                             int speed, int *algo,
                                             int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_vel_find_algo(double *vel, int natoms, int nframes,
-                                                  double desired_precision,
-                                                  int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_find_algo(double *vel, const int natoms, const int nframes,
+                                                  const double desired_precision,
+                                                  const int speed,
                                                   int *algo,
                                                   int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_vel_float_find_algo(float *vel, int natoms, int nframes,
-                                                        float desired_precision,
-                                                        int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_float_find_algo(float *vel, const int natoms, const int nframes,
+                                                        const float desired_precision,
+                                                        const int speed,
                                                         int *algo,
                                                         int *nitems);
 
-char DECLSPECDLLEXPORT *tng_compress_vel_int_find_algo(int *vel, int natoms, int nframes,
-                                                      unsigned long prec_hi, unsigned long prec_lo,
-                                                      int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_int_find_algo(int *vel, const int natoms, const int nframes,
+                                                      const unsigned long prec_hi, const unsigned long prec_lo,
+                                                      const int speed,
                                                       int *algo,
                                                       int *nitems);
 
@@ -170,12 +170,12 @@ int DECLSPECDLLEXPORT tng_compress_uncompress_int(char *data,int *posvel, unsign
 
 /* This converts a block of integers, as obtained from tng_compress_uncompress_int, to floating point values
    either double precision or single precision. */
-void DECLSPECDLLEXPORT tng_compress_int_to_double(int *posvel_int,unsigned long prec_hi, unsigned long prec_lo,
-                                                 int natoms,int nframes,
+void DECLSPECDLLEXPORT tng_compress_int_to_double(int *posvel_int, const unsigned long prec_hi, const unsigned long prec_lo,
+                                                 const int natoms, const int nframes,
                                                  double *posvel_double);
 
-void DECLSPECDLLEXPORT tng_compress_int_to_float(int *posvel_int,unsigned long prec_hi, unsigned long prec_lo,
-                                                int natoms,int nframes,
+void DECLSPECDLLEXPORT tng_compress_int_to_float(int *posvel_int, const unsigned long prec_hi, const unsigned long prec_lo,
+                                                const int natoms, const int nframes,
                                                 float *posvel_float);
 
 
index 4585755640d6b33b9a187d347445c14d8cf40fd2..ba1b8fb2e3912817708ef3795adc24a66e9592aa 100644 (file)
 #ifndef VALS16_H
 #define VALS16_H
 
-void Ptngc_comp_conv_to_vals16(unsigned int *vals,int nvals,
-                        unsigned int *vals16, int *nvals16);
+void Ptngc_comp_conv_to_vals16(unsigned int *vals, const int nvals,
+                               unsigned int *vals16, int *nvals16);
 
-void Ptngc_comp_conv_from_vals16(unsigned int *vals16,int nvals16,
-                          unsigned int *vals, int *nvals);
+void Ptngc_comp_conv_from_vals16(unsigned int *vals16, const int nvals16,
+                                 unsigned int *vals, int *nvals);
 
 #endif
index 44442714c7947d06ab094d158544bf61f3808fbe..aa631117ed0bc8e6b62c602059aeab66113a5e8e 100644 (file)
 
 #include "../compression/tng_compress.h"
 
-void DECLSPECDLLEXPORT *Ptngc_warnmalloc_x(size_t size, char *file, int line);
+void DECLSPECDLLEXPORT *Ptngc_warnmalloc_x(const size_t size, char *file, const int line);
 
 #define warnmalloc(size) Ptngc_warnmalloc_x(size,__FILE__,__LINE__)
 
-void DECLSPECDLLEXPORT *Ptngc_warnrealloc_x(void *old, size_t size, char *file, int line);
+void DECLSPECDLLEXPORT *Ptngc_warnrealloc_x(void *old, const size_t size, char *file, const int line);
 
 #define warnrealloc(old,size) Ptngc_warnrealloc_x(old,size,__FILE__,__LINE__)
 
index 8ca24eee6b801ebd8f5a1df63d9cc7af7a1ea6a7..dfa905be4ec763dc51a7a493ef3c3c08cda64dd0 100644 (file)
 #ifndef WIDEMULDIV_H
 #define WIDEMULDIV_H
 
-/* Multiply two 32 bit unsigned integers returning a 64 bit unsigned value (in two integers) */
-void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned int *olo);
-
-/* Divide a 64 bit unsigned value in hi:lo with the 32 bit value i and
-   return the result in result and the remainder in remainder */
-void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned int *result, unsigned int *remainder);
-
 /* Add a unsigned int to a largeint. */
-void Ptngc_largeint_add(unsigned int v1, unsigned int *largeint, int n);
+void Ptngc_largeint_add(const unsigned int v1, unsigned int *largeint, const int n);
 
 /* Multiply v1 with largeint_in and return result in largeint_out */
-void Ptngc_largeint_mul(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n);
+void Ptngc_largeint_mul(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n);
 
 /* Return the remainder from dividing largeint_in with v1. Result of the division is returned in largeint_out */
-unsigned int Ptngc_largeint_div(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n);
+unsigned int Ptngc_largeint_div(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n);
 
 #endif
index c607aad2c5d9849e4c66217a988903b664ed5ecb..668acbea7b214c9968d4c0f6a9866f2075d1e1fb 100644 (file)
  *
  * Revisions
  *
+ * v. 1.7 - Fifth stable release of the API
+ *
+ *        - Added function tng_util_num_frames_with_data_of_block_id_get().
+ *        - Merged some functions and data structures
+ *          to make less difference between data blocks.
+ *        - Bugs fixed
+ *
  * v. 1.6 - Fourth stable release of the API.
  *
  *        - Removed OpenMP option when building.
@@ -331,6 +338,7 @@ typedef unsigned __int64 uint64_t;
 #ifndef PRId64
 # define PRId64         __PRI64_PREFIX "d"
 #endif
+
 #ifndef PRIu64
 # define PRIu64         __PRI64_PREFIX "u"
 #endif
@@ -345,12 +353,6 @@ typedef unsigned __int64 uint64_t;
 #endif /* win32... */
 #endif /* not defined USE_WINDOWS */
 
-#ifdef USE_WINDOWS
-#define TNG_PRIsize "Iu"
-#else
-#define TNG_PRIsize "zu"
-#endif
-
 #ifndef DECLSPECDLLEXPORT
 #ifdef USE_WINDOWS
 #define DECLSPECDLLEXPORT __declspec(dllexport)
@@ -638,7 +640,7 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
-                (tng_trajectory_t src, tng_trajectory_t *dest_p);
+                (const tng_trajectory_t src, tng_trajectory_t *dest_p);
 
 /**
  * @brief Get the name of the input file.
@@ -670,7 +672,7 @@ tng_function_status DECLSPECDLLEXPORT tng_input_file_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *file_name);
 
 /**
@@ -703,7 +705,7 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *file_name);
 
 /**
@@ -719,7 +721,7 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_set
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *file_name);
 
 /**
@@ -750,7 +752,7 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
  * could not be set.
  */
 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const tng_file_endianness endianness);
 
 /**
@@ -783,7 +785,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -816,7 +818,7 @@ tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -849,7 +851,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -882,7 +884,7 @@ tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -915,7 +917,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -948,7 +950,7 @@ tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -981,7 +983,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *signature);
 
 /**
@@ -1014,7 +1016,7 @@ tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *signature);
 
 /**
@@ -1047,7 +1049,7 @@ tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *new_name);
 
 /**
@@ -1073,7 +1075,7 @@ tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
  * has occurred.
  */
 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t len);
 
 /**
@@ -1099,7 +1101,7 @@ tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
  * has occurred.
  */
 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t len);
 
 /**
@@ -1126,7 +1128,7 @@ tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
  * has occurred.
  */
 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const double time);
 
 /**
@@ -1185,7 +1187,7 @@ tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const double precision);
 
 /**
@@ -1200,7 +1202,7 @@ tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t n);
 
 /**
@@ -1376,7 +1378,7 @@ tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t nr);
 
 /**
@@ -1392,7 +1394,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame);
 
 /**
@@ -1478,7 +1480,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t t
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_init
                 (const tng_trajectory_t tng_data,
-                 tng_molecule_t molecule);
+                 const tng_molecule_t molecule);
 
 /**
  * @brief Clean up a molecule container.
@@ -1491,7 +1493,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_init
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy
                 (const tng_trajectory_t tng_data,
-                 tng_molecule_t molecule);
+                 const tng_molecule_t molecule);
 
 /**
  * @brief Add a molecule to the trajectory.
@@ -1506,7 +1508,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *name,
                  tng_molecule_t *molecule);
 
@@ -1524,7 +1526,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_add
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *name,
                  const int64_t id,
                  tng_molecule_t *molecule);
@@ -1540,7 +1542,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  tng_molecule_t *molecule);
 
 /**
@@ -1576,8 +1578,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *new_name);
 
 /**
@@ -1608,8 +1610,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const int64_t cnt);
 
 /**
@@ -1630,9 +1632,9 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
  * be found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *name,
-                 int64_t id,
+                 const int64_t id,
                  tng_molecule_t *molecule);
 
 /**
@@ -1647,8 +1649,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_find
  * molecule is not found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
-                (tng_trajectory_t tng_data,
-                 int64_t index,
+                (const tng_trajectory_t tng_data,
+                 const int64_t index,
                  tng_molecule_t *molecule);
 
 /**
@@ -1665,8 +1667,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
  * @return TNG_SUCCESS(0) if the copying is successful, TNG_FAILURE if a minor
  * error has occured or TNG_CRITICAL(2) if a major error has occured.
  */
-tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
-                                                               tng_trajectory_t tng_data_dest);
+tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
+                                                               const tng_trajectory_t tng_data_dest);
 
 /**
  * @brief Get the number of chains in a molecule.
@@ -1695,9 +1697,9 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
  * chain is not found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 int64_t index,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const int64_t index,
                  tng_chain_t *chain);
 
 /**
@@ -1783,10 +1785,10 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
  * be found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
-                 int64_t id,
+                 const int64_t id,
                  tng_chain_t *chain);
 
 /**
@@ -1803,8 +1805,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
                  tng_chain_t *chain);
 
@@ -1823,8 +1825,8 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
                  const int64_t id,
                  tng_chain_t *chain);
@@ -1843,7 +1845,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
                 (const tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                 const tng_molecule_t molecule,
                  const int64_t from_atom_id,
                  const int64_t to_atom_id,
                  tng_bond_t *bond);
@@ -1865,10 +1867,10 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
  * be found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
-                 int64_t id,
+                 const int64_t id,
                  tng_atom_t *atom);
 
 /**
@@ -1902,8 +1904,8 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *new_name);
 
 /**
@@ -1955,10 +1957,10 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
  * be found.
  */
 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *name,
-                 int64_t id,
+                 const int64_t id,
                  tng_residue_t *residue);
 
 /**
@@ -1975,8 +1977,8 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *name,
                  tng_residue_t *residue);
 
@@ -1995,8 +1997,8 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *name,
                  const int64_t id,
                  tng_residue_t *residue);
@@ -2034,8 +2036,8 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set
-                (tng_trajectory_t tng_data,
-                 tng_residue_t residue,
+                (const tng_trajectory_t tng_data,
+                 const tng_residue_t residue,
                  const char *new_name);
 
 /**
@@ -2087,8 +2089,8 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
-                (tng_trajectory_t tng_data,
-                 tng_residue_t residue,
+                (const tng_trajectory_t tng_data,
+                 const tng_residue_t residue,
                  const char *atom_name,
                  const char *atom_type,
                  tng_atom_t *atom);
@@ -2111,8 +2113,8 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
  * not be set properly or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_residue_t residue,
+                (const tng_trajectory_t tng_data,
+                 const tng_residue_t residue,
                  const char *atom_name,
                  const char *atom_type,
                  const int64_t id,
@@ -2163,8 +2165,8 @@ tng_function_status DECLSPECDLLEXPORT tng_atom_name_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_atom_name_set
-                (tng_trajectory_t tng_data,
-                 tng_atom_t atom,
+                (const tng_trajectory_t tng_data,
+                 const tng_atom_t atom,
                  const char *new_name);
 
 /**
@@ -2200,8 +2202,8 @@ tng_function_status DECLSPECDLLEXPORT tng_atom_type_get
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_atom_type_set
-                (tng_trajectory_t tng_data,
-                 tng_atom_t atom,
+                (const tng_trajectory_t tng_data,
+                 const tng_atom_t atom,
                  const char *new_type);
 
 /**
@@ -2222,7 +2224,7 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
                  const int64_t nr,
                  char *name,
-                 int max_len);
+                 const int max_len);
 
 /**
  * @brief Get the molecule id of real particle number (number in mol system).
@@ -2288,7 +2290,7 @@ tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
                  const int64_t nr,
                  char *name,
-                 int max_len);
+                 const int max_len);
 
 /**
  * @brief Get the residue name of real particle number (number in mol system).
@@ -2308,7 +2310,7 @@ tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
                  const int64_t nr,
                  char *name,
-                 int max_len);
+                 const int max_len);
 
 /**
  * @brief Get the residue id (local to molecule) of real particle number
@@ -2362,7 +2364,7 @@ tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
                  const int64_t nr,
                  char *name,
-                 int max_len);
+                 const int max_len);
 
 /**
  * @brief Get the atom type of real particle number (number in mol system).
@@ -2382,7 +2384,7 @@ tng_function_status DECLSPECDLLEXPORT tng_atom_type_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
                  const int64_t nr,
                  char *type,
-                 int max_len);
+                 const int max_len);
 
 /**
  * @brief Add a particle mapping table.
@@ -2406,7 +2408,7 @@ tng_function_status DECLSPECDLLEXPORT tng_atom_type_of_particle_nr_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t num_first_particle,
                  const int64_t n_particles,
                  const int64_t *mapping_table);
@@ -2422,7 +2424,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free
-                (tng_trajectory_t tng_data);
+                (const tng_trajectory_t tng_data);
 
 /**
  * @brief Read the header blocks from the input_file of tng_data.
@@ -2441,7 +2443,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2460,7 +2462,7 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
  * error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2484,8 +2486,8 @@ tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block_data,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block_data,
                  const char hash_mode);
 
 /**
@@ -2501,7 +2503,7 @@ tng_function_status DECLSPECDLLEXPORT tng_block_read_next
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2521,7 +2523,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode,
                  const int64_t block_id);
 
@@ -2541,7 +2543,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2561,7 +2563,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode,
                  const int64_t block_id);
 
@@ -2580,7 +2582,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_blo
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2601,7 +2603,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_write
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode);
 
 /**
@@ -2620,7 +2622,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t n_frames);
 
@@ -2642,7 +2644,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t n_frames,
                  const double first_frame_time);
@@ -2659,7 +2661,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const double first_frame_time);
 
 /**
@@ -2708,7 +2710,7 @@ tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t id,
                  const char *block_name,
                  const char datatype,
@@ -2753,7 +2755,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_block_add
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t id,
                  const char *block_name,
                  const char datatype,
@@ -2781,10 +2783,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
  * TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
-                (tng_trajectory_t tng_data,
-                 int64_t block_id,
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
                  char *name,
-                 int max_len);
+                 const int max_len);
 
 /** @brief Get the dependency of a data block of a specific ID.
  * @param tng_data is the trajectory data container.
@@ -2803,7 +2805,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
                 (const tng_trajectory_t tng_data,
-                 int64_t block_id,
+                 const int64_t block_id,
                  int *block_dependency);
 
 /** @brief Get the number of values per frame of a data block of a specific ID.
@@ -2820,7 +2822,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
                 (const tng_trajectory_t tng_data,
-                 int64_t block_id,
+                 const int64_t block_id,
                  int64_t *n_values_per_frame);
 
 /**
@@ -2844,7 +2846,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const int64_t block_id,
                  const void *values,
@@ -2878,7 +2880,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const int64_t block_id,
                  const int64_t val_first_particle,
@@ -2893,6 +2895,9 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
  * @param n_frames is the number of frames in the data array.
  * @param n_values_per_frame is the number of values per frame in the data array.
  * @param type is the data type of the data in the array (e.g. int/float/char).
+ * @details This function should not be used. The data_values union is obsolete.
+ * This function also causes memory leaks, but its signature cannot be changed
+ * without disturbing the API.
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
@@ -2910,6 +2915,9 @@ tng_function_status DECLSPECDLLEXPORT tng_data_values_free
  * @param n_particles is the number of particles in the data array.
  * @param n_values_per_frame is the number of values per frame in the data array.
  * @param type is the data type of the data in the array (e.g. int/float/char).
+ * @details This function should not be used. The data_values union is obsolete.
+ * This function also causes memory leaks, but its signature cannot be changed
+ * without disturbing the API.
  * @return TNG_SUCCESS (0) if successful.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
@@ -2949,7 +2957,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
-tng_function_status DECLSPECDLLEXPORT tng_data_get(tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_data_get(const tng_trajectory_t tng_data,
                                                    const int64_t block_id,
                                                    union data_values ***values,
                                                    int64_t *n_frames,
@@ -2987,7 +2995,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get(tng_trajectory_t tng_data,
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  int64_t *n_frames,
@@ -3028,7 +3036,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
@@ -3073,7 +3081,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
@@ -3120,7 +3128,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  union data_values ****values,
                  int64_t *n_frames,
@@ -3165,7 +3173,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  int64_t *n_frames,
@@ -3216,7 +3224,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
@@ -3270,7 +3278,7 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
@@ -3366,7 +3374,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
  * minor error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  double *time);
 
@@ -3384,7 +3392,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
  * @return TNG_SUCCESS (0) if successful.
  */
 /*tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *n_mols,
                  int64_t **molecule_cnt_list,
                  tng_molecule_t *mols);
@@ -3402,14 +3410,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
  * has occured or TNG_CRITICAL (2) if a major error has occured.
  */
 /*tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *name,
                  const int64_t cnt,
                  tng_molecule_t *mol);
 */
 /*
 // tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
-//                 (tng_trajectory_t tng_data,
+//                 (const tng_trajectory_t tng_data,
 //                  const tng_molecule_t mol,
 //                  int64_t *n_particles,
 //                  char ***names,
@@ -3420,7 +3428,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
 //                  int64_t **chain_ids);
 //
 // tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
-//                 (tng_trajectory_t tng_data,
+//                 (const tng_trajectory_t tng_data,
 //                  tng_molecule_t mol,
 //                  const int64_t n_particles,
 //                  const char **names,
@@ -3451,7 +3459,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **positions,
                  int64_t *stride_length);
 
@@ -3476,7 +3484,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **velocities,
                  int64_t *stride_length);
 
@@ -3501,7 +3509,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **forces,
                  int64_t *stride_length);
 
@@ -3529,7 +3537,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **box_shape,
                  int64_t *stride_length);
 
@@ -3564,7 +3572,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  char *data_type,
@@ -3600,7 +3608,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  char *data_type,
@@ -3632,7 +3640,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **positions,
@@ -3663,7 +3671,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **velocities,
@@ -3694,7 +3702,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **forces,
@@ -3731,7 +3739,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **box_shape,
@@ -3766,7 +3774,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -3804,7 +3812,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -3841,7 +3849,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -3865,7 +3873,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3884,7 +3892,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3905,7 +3913,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3924,7 +3932,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3943,7 +3951,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3961,7 +3969,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3980,7 +3988,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -3999,7 +4007,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -4017,7 +4025,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -4036,7 +4044,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -4055,7 +4063,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
@@ -4073,13 +4081,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_s
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i);
 
 /**
  * @brief High-level function for writing data of one frame to a data block.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param values is a 1D array of data to add. The array should be of length
  * n_particles * n_values_per_frame if writing particle related data, otherwise
  * it should be n_values_per_frame.
@@ -4098,7 +4107,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
  * Only required if the block did not exist, i.e. a new block is created.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code values != 0 \endcode The pointer to the values array must not
  * be a NULL pointer.
  * @details n_values_per_frame, block_name, particle_dependency and
@@ -4112,7 +4120,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *values,
                  const int64_t n_values_per_frame,
@@ -4125,7 +4133,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
  * @brief High-level function for writing data of one frame to a double precision
  * data block.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param values is a 1D array of data to add. The array should be of length
  * n_particles * n_values_per_frame if writing particle related data, otherwise
  * it should be n_values_per_frame.
@@ -4144,7 +4153,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
  * Only required if the block did not exist, i.e. a new block is created.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code values != 0 \endcode The pointer to the values array must not
  * be a NULL pointer.
  * @details n_values_per_frame, block_name, particle_dependency and
@@ -4158,7 +4166,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *values,
                  const int64_t n_values_per_frame,
@@ -4170,12 +4178,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
 /**
  * @brief High-level function for adding data to positions data blocks.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param positions is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code positions != 0 \endcode The pointer to the positions array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4189,7 +4197,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *positions);
 
@@ -4197,12 +4205,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
  * @brief High-level function for adding data to positions data blocks at double
  * precision.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param positions is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code positions != 0 \endcode The pointer to the positions array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4216,19 +4224,19 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *positions);
 
 /**
  * @brief High-level function for adding data to velocities data blocks.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param velocities is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code velocities != 0 \endcode The pointer to the velocities array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4242,7 +4250,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *velocities);
 
@@ -4250,12 +4258,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
  * @brief High-level function for adding data to velocities data blocks at double
  * precision.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param velocities is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code velocities != 0 \endcode The pointer to the velocities array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4269,19 +4277,19 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *velocities);
 
 /**
  * @brief High-level function for adding data to forces data blocks.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param forces is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code forces != 0 \endcode The pointer to the forces array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4295,7 +4303,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *forces);
 
@@ -4303,12 +4311,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write
  * @brief High-level function for adding data to forces data blocks at double
  * precision.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param forces is a 1D array of data to add. The array should be of length
  * n_particles * 3.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code forces != 0 \endcode The pointer to the forces array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4322,18 +4330,18 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *forces);
 
 /**
  * @brief High-level function for adding data to box shape data blocks.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param box_shape is a 1D array of data to add. The array should be of length 9.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code box_shape != 0 \endcode The pointer to the box_shape array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4347,7 +4355,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *box_shape);
 
@@ -4355,11 +4363,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
  * @brief High-level function for adding data to box shape data blocks at double
  * precision.
  * @param tng_data is the trajectory to use.
- * @param frame_nr is the frame number of the data.
+ * @param frame_nr is the frame number of the data. If frame_nr < 0 the
+ * data is written as non-trajectory data.
  * @param box_shape is a 1D array of data to add. The array should be of length 9.
  * @pre \code tng_data != 0 \endcode The trajectory container (tng_data)
  * must be initialised before using it.
- * @pre \code frame_nr >= 0 \endcode The frame number to write must be >= 0.
  * @pre \code box_shape != 0 \endcode The pointer to the box_shape array must not
  * be a NULL pointer.
  * @details This function uses tng_util_generic_write() and will
@@ -4373,7 +4381,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *box_shape);
 
@@ -4417,7 +4425,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *values,
@@ -4467,7 +4475,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *values,
@@ -4503,7 +4511,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *positions);
@@ -4534,7 +4542,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *positions);
@@ -4565,7 +4573,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *velocities);
@@ -4596,7 +4604,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *velocities);
@@ -4627,7 +4635,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *forces);
@@ -4658,7 +4666,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *forces);
@@ -4688,7 +4696,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *box_shape);
@@ -4718,7 +4726,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *box_shape);
@@ -4745,7 +4753,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  int64_t *codec_id,
                  double  *factor);
@@ -4784,7 +4792,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
  * has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t current_frame,
                  const int64_t n_requested_data_block_ids,
                  const int64_t *requested_data_block_ids,
@@ -4850,7 +4858,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
  */
 /*
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *n_data_blocks,
                  int64_t **data_block_ids,
                  char ***data_block_names,
@@ -4873,9 +4881,22 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
  * if a major error has occured.
  */
 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t prev_frame);
 
+
+/** @brief Get the number of frames containing data of a specific type.
+ * @param tng_data is the trajectory to use.
+ * @param block_id is the id of the block of the data type.
+ * @param n_frames is set to the number of frames containing data of
+ * the requested data type.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 int64_t *n_frames);
 /** @} */ /* end of group2 */
 
 
index 8b63a9a55ee4deb4c9881715955fc40b7dddaf2a..68bcafdea1b7d4cc3336d2bd1c321da4733f9062 100644 (file)
@@ -31,9 +31,7 @@ typedef struct tng_gen_block *tng_gen_block_t;
 typedef struct tng_particle_mapping *tng_particle_mapping_t;
 /** A pointer to a structure containing frame set information. */
 typedef struct tng_trajectory_frame_set *tng_trajectory_frame_set_t;
-/** A pointer to a particle data container. */
-typedef struct tng_particle_data *tng_particle_data_t;
-/** A pointer to a non-particle data container. */
-typedef struct tng_non_particle_data *tng_non_particle_data_t;
+/** A pointer to a data container. */
+typedef struct tng_data *tng_data_t;
 
 #endif
index de009d93f96954f8c51656f22ee78ce3b0fc4f7f..f4c0c28e4845058795402c528bf98e572bb52458 100644 (file)
 #define PARTIAL_MTF
 #endif
 
-int bwlzh_get_buflen(int nvals)
+int bwlzh_get_buflen(const int nvals)
 {
   return 132000+nvals*8+12*((nvals+MAX_VALS_PER_BLOCK)/MAX_VALS_PER_BLOCK);
 }
 
 #ifdef SHOWIT
-static void printvals(char *name, unsigned int *vals, int nvals)
+static void printvals(const char *name, unsigned int *vals, const int nvals)
 {
   int i;
   int nvalsmax=nvals;
@@ -69,10 +69,10 @@ static void printvals(char *name, unsigned int *vals, int nvals)
 #endif
 
 
-static void bwlzh_compress_gen(unsigned int *vals, int nvals,
+static void bwlzh_compress_gen(unsigned int *vals, const int nvals,
                                unsigned char *output, int *output_len,
-                               int enable_lz77,
-                               int verbose)
+                               const int enable_lz77,
+                               const int verbose)
 {
   unsigned int *vals16;
   int nvals16;
@@ -460,35 +460,35 @@ static void bwlzh_compress_gen(unsigned int *vals, int nvals,
 }
 
 
-void DECLSPECDLLEXPORT bwlzh_compress(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress(unsigned int *vals, const int nvals,
                   unsigned char *output, int *output_len)
 {
   bwlzh_compress_gen(vals,nvals,output,output_len,1,0);
 }
 
-void DECLSPECDLLEXPORT bwlzh_compress_verbose(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_verbose(unsigned int *vals, const int nvals,
                           unsigned char *output, int *output_len)
 {
   bwlzh_compress_gen(vals,nvals,output,output_len,1,1);
 }
 
 
-void DECLSPECDLLEXPORT bwlzh_compress_no_lz77(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_no_lz77(unsigned int *vals, const int nvals,
                   unsigned char *output, int *output_len)
 {
   bwlzh_compress_gen(vals,nvals,output,output_len,0,0);
 }
 
-void DECLSPECDLLEXPORT bwlzh_compress_no_lz77_verbose(unsigned int *vals, int nvals,
+void DECLSPECDLLEXPORT bwlzh_compress_no_lz77_verbose(unsigned int *vals, const int nvals,
                           unsigned char *output, int *output_len)
 {
   bwlzh_compress_gen(vals,nvals,output,output_len,0,1);
 }
 
 
-static void bwlzh_decompress_gen(unsigned char *input, int nvals,
+static void bwlzh_decompress_gen(unsigned char *input, const int nvals,
                                unsigned int *vals,
-                               int verbose)
+                               const int verbose)
 {
   unsigned int *vals16;
   int nvals16;
@@ -785,13 +785,13 @@ static void bwlzh_decompress_gen(unsigned char *input, int nvals,
 }
 
 
-void DECLSPECDLLEXPORT bwlzh_decompress(unsigned char *input, int nvals,
+void DECLSPECDLLEXPORT bwlzh_decompress(unsigned char *input, const int nvals,
                     unsigned int *vals)
 {
   bwlzh_decompress_gen(input,nvals,vals,0);
 }
 
-void DECLSPECDLLEXPORT bwlzh_decompress_verbose(unsigned char *input, int nvals,
+void DECLSPECDLLEXPORT bwlzh_decompress_verbose(unsigned char *input, const int nvals,
                             unsigned int *vals)
 {
   bwlzh_decompress_gen(input,nvals,vals,1);
index 66d3ecf1de56b4fc3e18e91c31d47b22181923fe..c5c46dfe38ed5bc6b1c93ed78330b9b134ab225e 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -22,7 +22,7 @@
 #define SHOWIT2
 #endif
 
-static int compare_index(int i1,int i2,int nvals,unsigned int *vals,unsigned int *nrepeat)
+static int compare_index(int i1,int i2, const int nvals, unsigned int *vals, unsigned int *nrepeat)
 {
   int i,j;
   for (i=0; i<nvals; i++)
@@ -75,10 +75,10 @@ static int compare_index(int i1,int i2,int nvals,unsigned int *vals,unsigned int
   return 0;
 }
 
-void Ptngc_bwt_merge_sort_inner(int *indices, int nvals,unsigned int *vals,
-                          int start, int end,
-                          unsigned int *nrepeat,
-                          int *workarray)
+void Ptngc_bwt_merge_sort_inner(int *indices, const int nvals,unsigned int *vals,
+                                const int start, const int end,
+                                unsigned int *nrepeat,
+                                int *workarray)
 {
   int middle;
   if ((end-start)>1)
@@ -140,8 +140,8 @@ void Ptngc_bwt_merge_sort_inner(int *indices, int nvals,unsigned int *vals,
 }
 
 /* Burrows-Wheeler transform. */
-void Ptngc_comp_to_bwt(unsigned int *vals, int nvals,
-                 unsigned int *output, int *index)
+void Ptngc_comp_to_bwt(unsigned int *vals, const int nvals,
+                       unsigned int *output, int *index)
 {
   int i;
   int *indices=warnmalloc(2*nvals*sizeof *indices);
@@ -162,8 +162,9 @@ void Ptngc_comp_to_bwt(unsigned int *vals, int nvals,
     indices[i]=i;
   /* Find the length of the initial repeating pattern for the strings. */
   /* First mark that the index does not have a found repeating string. */
-  for (i=0; i<nvals; i++)
-    nrepeat[i]=0U;
+
+  memset(nrepeat, 0U, sizeof(unsigned int) * nvals);
+
 #ifdef SHOWIT
   printf("nvals is %d\n",nvals);
 #endif
@@ -304,16 +305,17 @@ void Ptngc_comp_to_bwt(unsigned int *vals, int nvals,
 }
 
 /* Burrows-Wheeler inverse transform. */
-void Ptngc_comp_from_bwt(unsigned int *input, int nvals, int index,
-                   unsigned int *vals)
+void Ptngc_comp_from_bwt(unsigned int *input, const int nvals, int index,
+                         unsigned int *vals)
 {
   /* Straightforward from the Burrows-Wheeler paper (page 13). */
   int i;
   unsigned int *c=warnmalloc(0x10000*sizeof *c);
   unsigned int *p=warnmalloc(nvals*sizeof *p);
   unsigned int sum=0;
-  for (i=0; i<0x10000; i++)
-    c[i]=0;
+
+  memset(c, 0, sizeof(unsigned int) * 0x10000);
+
   for (i=0; i<nvals; i++)
     {
       p[i]=c[input[i]];
index cf891400db46385f5366d18a6f408ad5759fe16e..d0a0d99f66da866a0edd600aa8e029ff6f84b277 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -44,19 +44,17 @@ void DECLSPECDLLEXPORT Ptngc_coder_deinit(struct coder *coder_inst)
 
 TNG_INLINE void DECLSPECDLLEXPORT Ptngc_out8bits(struct coder *coder_inst, unsigned char **output)
 {
-  int pack_temporary_bits=coder_inst->pack_temporary_bits;
-  unsigned int pack_temporary=coder_inst->pack_temporary;
-  while (pack_temporary_bits>=8)
+  while (coder_inst->pack_temporary_bits>=8)
     {
-      unsigned int mask=~(0xFFU<<(pack_temporary_bits-8));
-      unsigned char out=(unsigned char)(pack_temporary>>(pack_temporary_bits-8));
+      unsigned int mask;
+      unsigned char out;
+      coder_inst->pack_temporary_bits-=8;
+      mask=~(0xFFU<<(coder_inst->pack_temporary_bits));
+      out=(unsigned char)(coder_inst->pack_temporary>>(coder_inst->pack_temporary_bits));
       **output=out;
       (*output)++;
-      pack_temporary_bits-=8;
-      pack_temporary&=mask;
+      coder_inst->pack_temporary&=mask;
     }
-  coder_inst->pack_temporary_bits=pack_temporary_bits;
-  coder_inst->pack_temporary=pack_temporary;
 }
 
 void DECLSPECDLLEXPORT Ptngc_write_pattern(struct coder *coder_inst, unsigned int pattern,
@@ -80,7 +78,7 @@ void DECLSPECDLLEXPORT Ptngc_write_pattern(struct coder *coder_inst, unsigned in
 
 /* Write up to 24 bits */
 TNG_INLINE void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder_inst,
-                                unsigned int value, int nbits,
+                                unsigned int value, const int nbits,
                                 unsigned char **output_ptr)
 {
   /* Make room for the bits. */
@@ -91,7 +89,7 @@ TNG_INLINE void DECLSPECDLLEXPORT Ptngc_writebits(struct coder *coder_inst,
 }
 
 /* Write up to 32 bits */
-void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder_inst,unsigned int value,
+void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder_inst, unsigned int value,
                        int nbits, unsigned char **output_ptr)
 {
   unsigned int mask;
@@ -102,11 +100,11 @@ void DECLSPECDLLEXPORT Ptngc_write32bits(struct coder *coder_inst,unsigned int v
   while (nbits>8)
     {
       /* Make room for the bits. */
+      nbits-=8;
       coder_inst->pack_temporary<<=8;
       coder_inst->pack_temporary_bits+=8;
-      coder_inst->pack_temporary|=(value&mask)>>(nbits-8);
+      coder_inst->pack_temporary|=(value&mask)>>(nbits);
       Ptngc_out8bits(coder_inst,output_ptr);
-      nbits-=8;
       mask>>=8;
     }
   if (nbits)
@@ -167,8 +165,8 @@ static int write_stop_bit_code(struct coder *coder_inst, unsigned int s,
   return 0;
 }
 
-static int pack_stopbits_item(struct coder *coder_inst,int item,
-                              unsigned char **output, int coding_parameter)
+static int pack_stopbits_item(struct coder *coder_inst, const int item,
+                              unsigned char **output, const int coding_parameter)
 {
     /* Find this symbol in table. */
     int s=0;
@@ -180,8 +178,8 @@ static int pack_stopbits_item(struct coder *coder_inst,int item,
 }
 
 static int pack_triplet(struct coder *coder_inst, unsigned int *s,
-                        unsigned char **output, int coding_parameter,
-                        unsigned int max_base, int maxbits)
+                        unsigned char **output, const int coding_parameter,
+                        const unsigned int max_base, const int maxbits)
 {
   /* Determine base for this triplet. */
   unsigned int min_base=1U<<coding_parameter;
@@ -213,7 +211,7 @@ static int pack_triplet(struct coder *coder_inst, unsigned int *s,
   return 0;
 }
 
-void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder_inst,unsigned char **output)
+void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder_inst, unsigned char **output)
 {
   /* Zero-fill just enough. */
   if (coder_inst->pack_temporary_bits>0)
@@ -221,8 +219,8 @@ void DECLSPECDLLEXPORT Ptngc_pack_flush(struct coder *coder_inst,unsigned char *
 }
 
 unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder_inst,
-                                int *input, int *length, int coding,
-                                int coding_parameter, int natoms, int speed)
+                                int *input, int *length, const int coding,
+                                const int coding_parameter, const int natoms, const int speed)
 {
   if ((coding==TNG_COMPRESS_ALGO_BWLZH1) || (coding==TNG_COMPRESS_ALGO_BWLZH2))
     {
@@ -246,7 +244,6 @@ unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder_inst,
             {
               int item=input[k*3*natoms+i*3+j];
               pval[cnt++]=(unsigned int)(item+most_negative);
-
             }
       if (speed>=5)
         bwlzh_compress(pval,n,output+4,length);
@@ -340,7 +337,7 @@ unsigned char DECLSPECDLLEXPORT *Ptngc_pack_array(struct coder *coder_inst,
 
 static int unpack_array_stop_bits(struct coder *coder_inst,
                                   unsigned char *packed,int *output,
-                                  int length, int coding_parameter)
+                                  const int length, const int coding_parameter)
 {
   int i,j;
   unsigned int extract_mask=0x80;
@@ -395,7 +392,7 @@ static int unpack_array_stop_bits(struct coder *coder_inst,
 
 static int unpack_array_triplet(struct coder *coder_inst,
                                 unsigned char *packed, int *output,
-                                int length, int coding_parameter)
+                                int length, const int coding_parameter)
 {
   int i,j;
   unsigned int extract_mask=0x80;
@@ -469,7 +466,7 @@ static int unpack_array_triplet(struct coder *coder_inst,
 
 static int unpack_array_bwlzh(struct coder *coder_inst,
                               unsigned char *packed, int *output,
-                              int length, int natoms)
+                              const int length, const int natoms)
 {
   int i,j,k,n=length;
   unsigned int *pval=warnmalloc(n*sizeof *pval);
@@ -494,8 +491,8 @@ static int unpack_array_bwlzh(struct coder *coder_inst,
 
 int DECLSPECDLLEXPORT Ptngc_unpack_array(struct coder *coder_inst,
                        unsigned char *packed, int *output,
-                       int length, int coding, int coding_parameter,
-                       int natoms)
+                       const int length, const int coding, const int coding_parameter,
+                       const int natoms)
 {
   if ((coding==TNG_COMPRESS_ALGO_STOPBIT) ||
       (coding==TNG_COMPRESS_ALGO_VEL_STOPBIT_INTER))
index 24e6ae7cac234898a260a3d7859e0e37012dd92e..7c32d7458864be2dd09d183c0dbd012745af0875 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -17,27 +17,29 @@ void Ptngc_comp_canonical_dict(unsigned int *dict, int *ndict)
   int i;
   for (i=0; i<0x20004; i++)
     dict[i]=i;
+
   *ndict=0x20004;
 }
 
-void Ptngc_comp_make_dict_hist(unsigned int *vals, int nvals,
+void Ptngc_comp_make_dict_hist(unsigned int *vals, const int nvals,
                          unsigned int *dict, int *ndict,
                          unsigned int *hist)
 {
   int i;
   int j=0;
-  for (i=0; i<0x20004; i++)
-    hist[i]=0;
-  for (i=0; i<0x20004; i++)
-    dict[i]=i;
+
+  memset(hist, 0, sizeof(unsigned int)*0x20004);
+
   for (i=0; i<nvals; i++)
     hist[vals[i]]++;
   for (i=0; i<0x20004; i++)
     if (hist[i]!=0)
       {
         hist[j]=hist[i];
-        dict[j]=dict[i];
+        dict[j]=i;
         j++;
+        if(j==nvals)
+          break;
       }
   *ndict=j;
 }
index 17fe6e8006c8aaeb00f8817339cbe9bcbf91a0a7..f769a43d378b5ee56a947eef0cd4a40762b5ae84 100644 (file)
@@ -19,7 +19,7 @@
 /* Conversion routines from / to double precision */
 
 /* Positive double to 32 bit fixed point value */
-fix_t Ptngc_ud_to_fix_t(double d,double max)
+fix_t Ptngc_ud_to_fix_t(double d, const double max)
 {
   fix_t val;
   if (d<0.)
@@ -33,7 +33,7 @@ fix_t Ptngc_ud_to_fix_t(double d,double max)
 }
 
 /* double to signed 32 bit fixed point value */
-fix_t Ptngc_d_to_fix_t(double d,double max)
+fix_t Ptngc_d_to_fix_t(double d, const double max)
 {
   fix_t val;
   int sign=0;
@@ -54,13 +54,13 @@ fix_t Ptngc_d_to_fix_t(double d,double max)
 
 
 /* 32 bit fixed point value to positive double */
-double Ptngc_fix_t_to_ud(fix_t f, double max)
+double Ptngc_fix_t_to_ud(fix_t f, const double max)
 {
   return (double)f*(max/MAX32BIT);
 }
 
 /* signed 32 bit fixed point value to double */
-double Ptngc_fix_t_to_d(fix_t f, double max)
+double Ptngc_fix_t_to_d(fix_t f, const double max)
 {
   int sign=0;
   double d;
index 2abcbcf09a7c22d1ce7c28fc8ba213a7f66c8e67..f2a2933856c1bff1f52b9921e11c7ed0f4025f33 100644 (file)
@@ -70,7 +70,7 @@ static void assign_codes(union htree_nodeleaf *htree,
                          struct codelength *codelength,
                          unsigned int code,
                          int length,
-                         int top)
+                         const int top)
 {
 #if 0
   printf("Assign codes called with code %d length %d\n",code,length);
@@ -131,7 +131,7 @@ static void flush_8bits(unsigned int *combine, unsigned char **output, int *bitp
     }
 }
 
-static void writebits(unsigned int value,int length, unsigned char **output, int *bitptr)
+static void writebits(unsigned int value, int length, unsigned char **output, int *bitptr)
 {
   unsigned int mask;
   unsigned int combine=(unsigned int)**output;
@@ -216,8 +216,8 @@ static int comp_codes_value(const void *codeptr1, const void *codeptr2, const vo
 /* The huffman_dict array should be 131077 (0x20005) long. The
 huffman_dict_unpacked array should be 131077 long (note five longer than
 0x20000) */
-void Ptngc_comp_conv_to_huffman(unsigned int *vals, int nvals,
-                          unsigned int *dict, int ndict,
+void Ptngc_comp_conv_to_huffman(unsigned int *vals, const int nvals,
+                          unsigned int *dict, const int ndict,
                           unsigned int *prob,
                           unsigned char *huffman,
                           int *huffman_len,
@@ -463,12 +463,12 @@ void Ptngc_comp_conv_to_huffman(unsigned int *vals, int nvals,
 }
 
 void Ptngc_comp_conv_from_huffman(unsigned char *huffman,
-                            unsigned int *vals, int nvals,
-                            int ndict,
+                            unsigned int *vals, const int nvals,
+                            const int ndict,
                             unsigned char *huffman_dict,
-                            int huffman_dictlen,
+                            const int huffman_dictlen,
                             unsigned int *huffman_dict_unpacked,
-                            int huffman_dict_unpackedlen)
+                            const int huffman_dict_unpackedlen)
 {
   struct codelength *codelength=warnmalloc(ndict*sizeof *codelength);
   int i,j;
index 183eff186ded3bd906058232db2934921feb2fb8..38981157db40b86c56d94cf9ef05d80cab089984 100644 (file)
@@ -19,7 +19,7 @@
 #include "../../include/compression/rle.h"
 #include "../../include/compression/vals16.h"
 
-int Ptngc_comp_huff_buflen(int nvals)
+int Ptngc_comp_huff_buflen(const int nvals)
 {
   return 132000+nvals*8;
 }
@@ -29,7 +29,7 @@ void Ptngc_comp_huff_compress_verbose(unsigned int *vals, int nvals,
                                 unsigned char *huffman, int *huffman_len,
                                 int *huffdatalen,
                                 int *huffman_lengths,int *chosen_algo,
-                                int isvals16)
+                                const int isvals16)
 {
   unsigned int *dict=warnmalloc(0x20005*sizeof *dict);
   unsigned int *hist=warnmalloc(0x20005*sizeof *hist);
@@ -227,7 +227,7 @@ void Ptngc_comp_huff_compress_verbose(unsigned int *vals, int nvals,
   free(dict);
 }
 
-void Ptngc_comp_huff_compress(unsigned int *vals, int nvals,
+void Ptngc_comp_huff_compress(unsigned int *vals, const int nvals,
                         unsigned char *huffman, int *huffman_len)
 {
   int huffman_lengths[N_HUFFMAN_ALGO];
@@ -237,7 +237,7 @@ void Ptngc_comp_huff_compress(unsigned int *vals, int nvals,
                              huffman_lengths,&algo,0);
 }
 
-void Ptngc_comp_huff_decompress(unsigned char *huffman, int huffman_len,
+void Ptngc_comp_huff_decompress(unsigned char *huffman, const int huffman_len,
                           unsigned int *vals)
 {
   int isvals16=(int)huffman[0];
@@ -346,7 +346,7 @@ static char *huff_algo_names[N_HUFFMAN_ALGO]=
     "Huffman (dict=RLE+Huffman)"
   };
 
-char *Ptngc_comp_get_huff_algo_name(int algo)
+char *Ptngc_comp_get_huff_algo_name(const int algo)
 {
   if (algo<0)
     return NULL;
index 17b147c8a098b5ed378ae69efcfdf31ab1652eab..d8bfecbf013a1afc5ac1ee3fb8fb620180a3e34d 100644 (file)
@@ -147,7 +147,7 @@ static void sort_strings(unsigned int *vals, int nvals,
 #define MAX_OFFSET 0xFFFF
 #define MAX_STRING_SEARCH 8
 
-static void add_circular(int *previous,int v, int i)
+static void add_circular(int *previous, const int v, const int i)
 {
   if (previous[(NUM_PREVIOUS+3)*v+2]!=i-1)
     {
@@ -162,7 +162,7 @@ static void add_circular(int *previous,int v, int i)
   previous[(NUM_PREVIOUS+3)*v+2]=i;
 }
 
-void Ptngc_comp_to_lz77(unsigned int *vals, int nvals,
+void Ptngc_comp_to_lz77(unsigned int *vals, const int nvals,
                   unsigned int *data, int *ndata,
                   unsigned int *len, int *nlens,
                   unsigned int *offsets, int *noffsets)
@@ -306,10 +306,10 @@ void Ptngc_comp_to_lz77(unsigned int *vals, int nvals,
   free(previous);
 }
 
-void Ptngc_comp_from_lz77(unsigned int *data, int ndata,
-                    unsigned int *len, int nlens,
-                    unsigned int *offsets, int noffsets,
-                    unsigned int *vals, int nvals)
+void Ptngc_comp_from_lz77(unsigned int *data, const int ndata,
+                    unsigned int *len, const int nlens,
+                    unsigned int *offsets, const int noffsets,
+                    unsigned int *vals, const int nvals)
 {
   int i=0;
   int joff=0;
index 7cb983796edf12528cfddd0101b210dfddd3547b..63622ccac8a7fb8f70dc0dd314eacb9985d99eed 100644 (file)
@@ -15,8 +15,8 @@
 #include "../../include/compression/warnmalloc.h"
 #include "../../include/compression/merge_sort.h"
 
-static void ms_inner(void *base, size_t size,
-             size_t start, size_t end,
+static void ms_inner(void *base, const size_t size,
+             const size_t start, const size_t end,
              int (*compar)(const void *v1,const void *v2,const void *private),
              const void *private,
              char *workarray)
@@ -80,7 +80,7 @@ static void ms_inner(void *base, size_t size,
 }
 
 
-void Ptngc_merge_sort(void *base, size_t nmemb, size_t size,
+void Ptngc_merge_sort(void *base, const size_t nmemb, const size_t size,
         int (*compar)(const void *v1,const void *v2,const void *private),
         void *private)
 {
index d6eaf30c64445bb2c1014980fb038868fd08fb30..52194137103617e06ff8d2f2f28f605063eaf41a 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
 
 
 #include <stdlib.h>
+#include <string.h>
 #include "../../include/compression/warnmalloc.h"
 #include "../../include/compression/mtf.h"
 
 /* "Partial" MTF. Byte based. */
 /* Move to front coding.
    Acceptable inputs are max 8 bits (0-0xFF) */
-static void comp_conv_to_mtf_byte(unsigned char *vals, int nvals,
+static void comp_conv_to_mtf_byte(unsigned char *vals, const int nvals,
                                   unsigned char *valsmtf)
 {
   int i;
@@ -58,13 +59,14 @@ static void comp_conv_to_mtf_byte(unsigned char *vals, int nvals,
     }
 }
 
-void Ptngc_comp_conv_to_mtf_partial(unsigned int *vals, int nvals,
+void Ptngc_comp_conv_to_mtf_partial(unsigned int *vals, const int nvals,
                               unsigned int *valsmtf)
 {
   unsigned char *tmp=warnmalloc(nvals*2);
   int i, j;
-  for (i=0; i<nvals; i++)
-    valsmtf[i]=0U;
+
+  memset(valsmtf, 0U, sizeof(unsigned int) * nvals);
+
   for (j=0; j<3; j++)
     {
       for (i=0; i<nvals; i++)
@@ -76,7 +78,7 @@ void Ptngc_comp_conv_to_mtf_partial(unsigned int *vals, int nvals,
   free(tmp);
 }
 
-void Ptngc_comp_conv_to_mtf_partial3(unsigned int *vals, int nvals,
+void Ptngc_comp_conv_to_mtf_partial3(unsigned int *vals, const int nvals,
                                unsigned char *valsmtf)
 {
   unsigned char *tmp=warnmalloc(nvals);
@@ -91,7 +93,7 @@ void Ptngc_comp_conv_to_mtf_partial3(unsigned int *vals, int nvals,
 }
 
 /* Move to front decoding */
-static void comp_conv_from_mtf_byte(unsigned char *valsmtf, int nvals,
+static void comp_conv_from_mtf_byte(unsigned char *valsmtf, const int nvals,
                              unsigned char *vals)
 {
   int i;
@@ -133,13 +135,14 @@ static void comp_conv_from_mtf_byte(unsigned char *valsmtf, int nvals,
     }
 }
 
-void Ptngc_comp_conv_from_mtf_partial(unsigned int *valsmtf, int nvals,
+void Ptngc_comp_conv_from_mtf_partial(unsigned int *valsmtf, const int nvals,
                                 unsigned int *vals)
 {
   unsigned char *tmp=warnmalloc(nvals*2);
   int i, j;
-  for (i=0; i<nvals; i++)
-    vals[i]=0U;
+
+  memset(vals, 0U, sizeof(unsigned int) * nvals);
+
   for (j=0; j<3; j++)
     {
       for (i=0; i<nvals; i++)
@@ -151,13 +154,14 @@ void Ptngc_comp_conv_from_mtf_partial(unsigned int *valsmtf, int nvals,
   free(tmp);
 }
 
-void Ptngc_comp_conv_from_mtf_partial3(unsigned char *valsmtf, int nvals,
+void Ptngc_comp_conv_from_mtf_partial3(unsigned char *valsmtf, const int nvals,
                                  unsigned int *vals)
 {
   unsigned char *tmp=warnmalloc(nvals);
   int i, j;
-  for (i=0; i<nvals; i++)
-    vals[i]=0U;
+
+  memset(vals, 0U, sizeof(unsigned int) * nvals);
+
   for (j=0; j<3; j++)
     {
       comp_conv_from_mtf_byte(valsmtf+j*nvals,nvals,tmp);
@@ -169,8 +173,8 @@ void Ptngc_comp_conv_from_mtf_partial3(unsigned char *valsmtf, int nvals,
 
 /* Move to front coding.
    Acceptable inputs are max 24 bits (0-0xFFFFFF) */
-void Ptngc_comp_conv_to_mtf(unsigned int *vals, int nvals,
-                      unsigned int *dict, int ndict,
+void Ptngc_comp_conv_to_mtf(unsigned int *vals, const int nvals,
+                      unsigned int *dict, const int ndict,
                       unsigned int *valsmtf)
 {
   int i;
@@ -211,8 +215,8 @@ void Ptngc_comp_conv_to_mtf(unsigned int *vals, int nvals,
 }
 
 /* Move to front decoding */
-void Ptngc_comp_conv_from_mtf(unsigned int *valsmtf, int nvals,
-                        unsigned int *dict, int ndict,
+void Ptngc_comp_conv_from_mtf(unsigned int *valsmtf, const int nvals,
+                        unsigned int *dict, const int ndict,
                         unsigned int *vals)
 {
   int i;
index adaee655d691c6b60e376259810626e395db84e3..1273dd82b087420f789267f9515c8c81b0a5b037 100644 (file)
@@ -12,8 +12,8 @@
 #include "../../include/compression/rle.h"
 
 static void add_rle(unsigned int *rle,
-                    int v,int nsim,
-                    int *j,int min_rle)
+                    const int v, int nsim,
+                    int *j, const int min_rle)
 {
   if (nsim>min_rle)
     {
@@ -36,9 +36,9 @@ static void add_rle(unsigned int *rle,
 /* Run length encoding.
    Acceptable inputs are about 16 bits (0-0xFFFF)
    If input is 0-N output will be be values of 0-(N+2) */
-void Ptngc_comp_conv_to_rle(unsigned int *vals, int nvals,
-                      unsigned int *rle, int *nrle,
-                      int min_rle)
+void Ptngc_comp_conv_to_rle(unsigned int *vals, const int nvals,
+                            unsigned int *rle, int *nrle,
+                            const int min_rle)
 {
   int i;
   int j=0;
@@ -69,7 +69,7 @@ void Ptngc_comp_conv_to_rle(unsigned int *vals, int nvals,
 }
 
 void Ptngc_comp_conv_from_rle(unsigned int *rle,
-                        unsigned int *vals, int nvals)
+                              unsigned int *vals, const int nvals)
 {
   int i=0;
   int j=0;
index b39d7220cb3692a11af098d56734965ae635ae63..d6497d5612165a3642c83e53f3719aee8c3dc9d5 100644 (file)
@@ -28,7 +28,7 @@
 
 #define MAX_FVAL 2147483647.
 
-static int verify_input_data(double *x, int natoms, int nframes, double precision)
+static int verify_input_data(double *x, const int natoms, const int nframes, const double precision)
 {
   int iframe, i, j;
   for (iframe=0; iframe<nframes; iframe++)
@@ -48,7 +48,7 @@ static int verify_input_data(double *x, int natoms, int nframes, double precisio
   return 1;
 }
 
-static int verify_input_data_float(float *x, int natoms, int nframes, float precision)
+static int verify_input_data_float(float *x, const int natoms, const int nframes, const float precision)
 {
   int iframe, i, j;
   for (iframe=0; iframe<nframes; iframe++)
@@ -68,9 +68,9 @@ static int verify_input_data_float(float *x, int natoms, int nframes, float prec
   return 1;
 }
 
-static int quantize(double *x, int natoms, int nframes,
-                     double precision,
-                     int *quant)
+static int quantize(double *x, const int natoms, const int nframes,
+                    const double precision,
+                    int *quant)
 {
   int iframe, i, j;
   for (iframe=0; iframe<nframes; iframe++)
@@ -80,9 +80,9 @@ static int quantize(double *x, int natoms, int nframes,
   return verify_input_data(x,natoms,nframes,precision);
 }
 
-static int quantize_float(float *x, int natoms, int nframes,
-                           float precision,
-                           int *quant)
+static int quantize_float(float *x, int natoms, const int nframes,
+                          const float precision,
+                          int *quant)
 {
   int iframe, i, j;
   for (iframe=0; iframe<nframes; iframe++)
@@ -92,7 +92,7 @@ static int quantize_float(float *x, int natoms, int nframes,
   return verify_input_data_float(x,natoms,nframes,precision);
 }
 
-static void quant_inter_differences(int *quant, int natoms, int nframes,
+static void quant_inter_differences(int *quant, const int natoms, const int nframes,
                                     int *quant_inter)
 {
   int iframe, i, j;
@@ -107,7 +107,7 @@ static void quant_inter_differences(int *quant, int natoms, int nframes,
         quant_inter[iframe*natoms*3+i*3+j]=quant[iframe*natoms*3+i*3+j]-quant[(iframe-1)*natoms*3+i*3+j];
 }
 
-static void quant_intra_differences(int *quant, int natoms, int nframes,
+static void quant_intra_differences(int *quant, const int natoms, const int nframes,
                                     int *quant_intra)
 {
   int iframe, i, j;
@@ -123,8 +123,8 @@ static void quant_intra_differences(int *quant, int natoms, int nframes,
     }
 }
 
-static void unquantize(double *x, int natoms, int nframes,
-                       double precision,
+static void unquantize(double *x, int natoms, const int nframes,
+                       const double precision,
                        int *quant)
 {
   int iframe, i, j;
@@ -134,8 +134,8 @@ static void unquantize(double *x, int natoms, int nframes,
         x[iframe*natoms*3+i*3+j]=(double)quant[iframe*natoms*3+i*3+j]*precision;
 }
 
-static void unquantize_float(float *x, int natoms, int nframes,
-                             float precision,
+static void unquantize_float(float *x, const int natoms, const int nframes,
+                             const float precision,
                              int *quant)
 {
   int iframe, i, j;
@@ -145,8 +145,8 @@ static void unquantize_float(float *x, int natoms, int nframes,
         x[iframe*natoms*3+i*3+j]=(float)quant[iframe*natoms*3+i*3+j]*precision;
 }
 
-static void unquantize_inter_differences(double *x, int natoms, int nframes,
-                                         double precision,
+static void unquantize_inter_differences(double *x, int natoms, const int nframes,
+                                         const double precision,
                                          int *quant)
 {
   int iframe, i, j;
@@ -163,8 +163,8 @@ static void unquantize_inter_differences(double *x, int natoms, int nframes,
       }
 }
 
-static void unquantize_inter_differences_float(float *x, int natoms, int nframes,
-                                               float precision,
+static void unquantize_inter_differences_float(float *x, const int natoms, const int nframes,
+                                               const float precision,
                                                int *quant)
 {
   int iframe, i, j;
@@ -181,7 +181,7 @@ static void unquantize_inter_differences_float(float *x, int natoms, int nframes
       }
 }
 
-static void unquantize_inter_differences_int(int *x, int natoms, int nframes,
+static void unquantize_inter_differences_int(int *x, const int natoms, const int nframes,
                                              int *quant)
 {
   int iframe, i, j;
@@ -200,7 +200,7 @@ static void unquantize_inter_differences_int(int *x, int natoms, int nframes,
 
 /* In frame update required for the initial frame if intra-frame
    compression was used. */
-static void unquant_intra_differences_first_frame(int *quant, int natoms)
+static void unquant_intra_differences_first_frame(int *quant, const int natoms)
 {
   int i,j;
   for (j=0; j<3; j++)
@@ -221,8 +221,8 @@ static void unquant_intra_differences_first_frame(int *quant, int natoms)
 #endif
 }
 
-static void unquantize_intra_differences(double *x, int natoms, int nframes,
-                                         double precision,
+static void unquantize_intra_differences(double *x, const int natoms, const int nframes,
+                                         const double precision,
                                          int *quant)
 {
   int iframe, i, j;
@@ -242,8 +242,8 @@ static void unquantize_intra_differences(double *x, int natoms, int nframes,
       }
 }
 
-static void unquantize_intra_differences_float(float *x, int natoms, int nframes,
-                                               float precision,
+static void unquantize_intra_differences_float(float *x, const int natoms, const int nframes,
+                                               const float precision,
                                                int *quant)
 {
   int iframe, i, j;
@@ -260,7 +260,7 @@ static void unquantize_intra_differences_float(float *x, int natoms, int nframes
       }
 }
 
-static void unquantize_intra_differences_int(int *x, int natoms, int nframes,
+static void unquantize_intra_differences_int(int *x, const int natoms, const int nframes,
                                              int *quant)
 {
   int iframe, i, j;
@@ -308,11 +308,11 @@ static fix_t readbufferfix(unsigned char *buf, int num)
 
 /* Perform position compression from the quantized data. */
 static void compress_quantized_pos(int *quant, int *quant_inter, int *quant_intra,
-                                   int natoms, int nframes,
-                                   int speed,
-                                   int initial_coding, int initial_coding_parameter,
-                                   int coding, int coding_parameter,
-                                   fix_t prec_hi, fix_t prec_lo,
+                                   const int natoms, const int nframes,
+                                   const int speed,
+                                   const int initial_coding, const int initial_coding_parameter,
+                                   const int coding, const int coding_parameter,
+                                   const fix_t prec_hi, const fix_t prec_lo,
                                    int *nitems,
                                    char *data)
 {
@@ -436,11 +436,11 @@ static void compress_quantized_pos(int *quant, int *quant_inter, int *quant_intr
 
 /* Perform velocity compression from vel into the data block */
 static void compress_quantized_vel(int *quant, int *quant_inter,
-                                   int natoms, int nframes,
-                                   int speed,
-                                   int initial_coding, int initial_coding_parameter,
-                                   int coding, int coding_parameter,
-                                   fix_t prec_hi, fix_t prec_lo,
+                                   const int natoms, const int nframes,
+                                   const int speed,
+                                   const int initial_coding, const int initial_coding_parameter,
+                                   const int coding, const int coding_parameter,
+                                   const fix_t prec_hi, const fix_t prec_lo,
                                    int *nitems,
                                    char *data)
 {
@@ -544,7 +544,7 @@ static void compress_quantized_vel(int *quant, int *quant_inter,
 }
 
 static int determine_best_coding_stop_bits(struct coder *coder,int *input, int *length,
-                                           int *coding_parameter, int natoms)
+                                           int *coding_parameter, const int natoms)
 {
   int bits;
   unsigned char *packed;
@@ -575,7 +575,7 @@ static int determine_best_coding_stop_bits(struct coder *coder,int *input, int *
 }
 
 static int determine_best_coding_triple(struct coder *coder,int *input, int *length,
-                                        int *coding_parameter, int natoms)
+                                        int *coding_parameter, const int natoms)
 {
   int bits;
   unsigned char *packed;
@@ -605,8 +605,8 @@ static int determine_best_coding_triple(struct coder *coder,int *input, int *len
   return 0;
 }
 
-static void determine_best_pos_initial_coding(int *quant, int *quant_intra, int natoms, int speed,
-                                              fix_t prec_hi, fix_t prec_lo,
+static void determine_best_pos_initial_coding(int *quant, int *quant_intra, const int natoms, const int speed,
+                                              const fix_t prec_hi, const fix_t prec_lo,
                                               int *initial_coding, int *initial_coding_parameter)
 {
   if (*initial_coding==-1)
@@ -718,8 +718,8 @@ static void determine_best_pos_initial_coding(int *quant, int *quant_intra, int
     }
 }
 
-static void determine_best_pos_coding(int *quant, int *quant_inter, int *quant_intra, int natoms, int nframes, int speed,
-                                      fix_t prec_hi, fix_t prec_lo,
+static void determine_best_pos_coding(int *quant, int *quant_inter, int *quant_intra, const int natoms, const int nframes, const int speed,
+                                      const fix_t prec_hi, const fix_t prec_lo,
                                       int *coding, int *coding_parameter)
 {
   if (*coding==-1)
@@ -896,8 +896,8 @@ static void determine_best_pos_coding(int *quant, int *quant_inter, int *quant_i
     }
 }
 
-static void determine_best_vel_initial_coding(int *quant, int natoms, int speed,
-                                              fix_t prec_hi, fix_t prec_lo,
+static void determine_best_vel_initial_coding(int *quant, const int natoms, const int speed,
+                                              const fix_t prec_hi, const fix_t prec_lo,
                                               int *initial_coding, int *initial_coding_parameter)
 {
   if (*initial_coding==-1)
@@ -979,8 +979,8 @@ static void determine_best_vel_initial_coding(int *quant, int natoms, int speed,
     }
 }
 
-static void determine_best_vel_coding(int *quant, int *quant_inter, int natoms, int nframes, int speed,
-                                      fix_t prec_hi, fix_t prec_lo,
+static void determine_best_vel_coding(int *quant, int *quant_inter, const int natoms, const int nframes, const int speed,
+                                      const fix_t prec_hi, const fix_t prec_lo,
                                       int *coding, int *coding_parameter)
 {
   if (*coding==-1)
@@ -1137,8 +1137,8 @@ static void determine_best_vel_coding(int *quant, int *quant_inter, int natoms,
     }
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, int natoms, int nframes,
-                                             unsigned long prec_hi, unsigned long prec_lo,
+char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, const int natoms, const int nframes,
+                                             const unsigned long prec_hi, const unsigned long prec_lo,
                                              int speed,int *algo,
                                              int *nitems)
 {
@@ -1217,9 +1217,9 @@ char DECLSPECDLLEXPORT *tng_compress_pos_int(int *pos, int natoms, int nframes,
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos(double *pos, int natoms, int nframes,
-                                         double desired_precision,
-                                         int speed,int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos(double *pos, const int natoms, const int nframes,
+                                         const double desired_precision,
+                                         const int speed,int *algo,
                                          int *nitems)
 {
   int *quant=malloc(natoms*nframes*3*sizeof *quant);
@@ -1235,9 +1235,9 @@ char DECLSPECDLLEXPORT *tng_compress_pos(double *pos, int natoms, int nframes,
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos_float(float *pos, int natoms, int nframes,
-                                               float desired_precision,
-                                               int speed,int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos_float(float *pos, const int natoms, const int nframes,
+                                               const float desired_precision,
+                                               const int speed, int *algo,
                                                int *nitems)
 {
   int *quant=malloc(natoms*nframes*3*sizeof *quant);
@@ -1253,9 +1253,9 @@ char DECLSPECDLLEXPORT *tng_compress_pos_float(float *pos, int natoms, int nfram
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos_find_algo(double *pos, int natoms, int nframes,
-                                                   double desired_precision,
-                                                   int speed,
+char DECLSPECDLLEXPORT *tng_compress_pos_find_algo(double *pos, const int natoms, const int nframes,
+                                                   const double desired_precision,
+                                                   const int speed,
                                                    int *algo,
                                                    int *nitems)
 {
@@ -1266,9 +1266,9 @@ char DECLSPECDLLEXPORT *tng_compress_pos_find_algo(double *pos, int natoms, int
   return tng_compress_pos(pos,natoms,nframes,desired_precision,speed,algo,nitems);
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos_float_find_algo(float *pos, int natoms, int nframes,
-                                                         float desired_precision,
-                                                         int speed,
+char DECLSPECDLLEXPORT *tng_compress_pos_float_find_algo(float *pos, const int natoms, const int nframes,
+                                                         const float desired_precision,
+                                                         const int speed,
                                                          int *algo,
                                                          int *nitems)
 {
@@ -1279,9 +1279,9 @@ char DECLSPECDLLEXPORT *tng_compress_pos_float_find_algo(float *pos, int natoms,
   return tng_compress_pos_float(pos,natoms,nframes,desired_precision,speed,algo,nitems);
 }
 
-char DECLSPECDLLEXPORT *tng_compress_pos_int_find_algo(int *pos, int natoms, int nframes,
-                                                       unsigned long prec_hi, unsigned long prec_lo,
-                                                       int speed,int *algo,
+char DECLSPECDLLEXPORT *tng_compress_pos_int_find_algo(int *pos, const int natoms, const int nframes,
+                                                       const unsigned long prec_hi, const unsigned long prec_lo,
+                                                       const int speed, int *algo,
                                                        int *nitems)
 {
   algo[0]=-1;
@@ -1303,8 +1303,8 @@ int DECLSPECDLLEXPORT tng_compress_nalgo(void)
  4) One parameter to the algorithm for the remaining frames (the coding parameter). */
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel_int(int *vel, int natoms, int nframes,
-                                             unsigned long prec_hi, unsigned long prec_lo,
+char DECLSPECDLLEXPORT *tng_compress_vel_int(int *vel, const int natoms, const int nframes,
+                                             const unsigned long prec_hi, const unsigned long prec_lo,
                                              int speed, int *algo,
                                              int *nitems)
 {
@@ -1380,9 +1380,9 @@ char DECLSPECDLLEXPORT *tng_compress_vel_int(int *vel, int natoms, int nframes,
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel(double *vel, int natoms, int nframes,
-                                         double desired_precision,
-                                         int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_vel(double *vel, const int natoms, const int nframes,
+                                         const double desired_precision,
+                                         const int speed, int *algo,
                                          int *nitems)
 {
   int *quant=malloc(natoms*nframes*3*sizeof *quant);
@@ -1397,9 +1397,9 @@ char DECLSPECDLLEXPORT *tng_compress_vel(double *vel, int natoms, int nframes,
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel_float(float *vel, int natoms, int nframes,
-                                               float desired_precision,
-                                               int speed, int *algo,
+char DECLSPECDLLEXPORT *tng_compress_vel_float(float *vel, const int natoms, const int nframes,
+                                               const float desired_precision,
+                                               const int speed, int *algo,
                                                int *nitems)
 {
   int *quant=malloc(natoms*nframes*3*sizeof *quant);
@@ -1414,9 +1414,9 @@ char DECLSPECDLLEXPORT *tng_compress_vel_float(float *vel, int natoms, int nfram
   return data;
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel_find_algo(double *vel, int natoms, int nframes,
-                                                   double desired_precision,
-                                                   int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_find_algo(double *vel, const int natoms, const int nframes,
+                                                   const double desired_precision,
+                                                   const int speed,
                                                    int *algo,
                                                    int *nitems)
 {
@@ -1427,9 +1427,9 @@ char DECLSPECDLLEXPORT *tng_compress_vel_find_algo(double *vel, int natoms, int
   return tng_compress_vel(vel,natoms,nframes,desired_precision,speed,algo,nitems);
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel_float_find_algo(float *vel, int natoms, int nframes,
-                                                         float desired_precision,
-                                                         int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_float_find_algo(float *vel, const int natoms, const int nframes,
+                                                         const float desired_precision,
+                                                         const int speed,
                                                          int *algo,
                                                          int *nitems)
 {
@@ -1440,9 +1440,9 @@ char DECLSPECDLLEXPORT *tng_compress_vel_float_find_algo(float *vel, int natoms,
   return tng_compress_vel_float(vel,natoms,nframes,desired_precision,speed,algo,nitems);
 }
 
-char DECLSPECDLLEXPORT *tng_compress_vel_int_find_algo(int *vel, int natoms, int nframes,
-                                                       unsigned long prec_hi, unsigned long prec_lo,
-                                                       int speed,
+char DECLSPECDLLEXPORT *tng_compress_vel_int_find_algo(int *vel, const int natoms, const int nframes,
+                                                       const unsigned long prec_hi, const unsigned long prec_lo,
+                                                       const int speed,
                                                        int *algo,
                                                        int *nitems)
 {
@@ -1811,15 +1811,15 @@ int DECLSPECDLLEXPORT tng_compress_uncompress_int(char *data,int *posvel, unsign
     return 1;
 }
 
-void DECLSPECDLLEXPORT tng_compress_int_to_double(int *posvel_int,unsigned long prec_hi, unsigned long prec_lo,
-                                                  int natoms,int nframes,
+void DECLSPECDLLEXPORT tng_compress_int_to_double(int *posvel_int, const unsigned long prec_hi, const unsigned long prec_lo,
+                                                  const int natoms, const int nframes,
                                                   double *posvel_double)
 {
   unquantize(posvel_double,natoms,nframes,PRECISION(prec_hi,prec_lo),posvel_int);
 }
 
-void DECLSPECDLLEXPORT tng_compress_int_to_float(int *posvel_int,unsigned long prec_hi, unsigned long prec_lo,
-                                                 int natoms,int nframes,
+void DECLSPECDLLEXPORT tng_compress_int_to_float(int *posvel_int, const unsigned long prec_hi, const unsigned long prec_lo,
+                                                 const int natoms, const int nframes,
                                                  float *posvel_float)
 {
   unquantize_float(posvel_float,natoms,nframes,(float)PRECISION(prec_hi,prec_lo),posvel_int);
index c4ed635747c7dc223380511e872f3c08548223c7..48186f675924fd5558146889d2c0907256265538 100644 (file)
@@ -13,8 +13,8 @@
 
 /* Coding 32 bit ints in sequences of 16 bit ints. Worst case
    the output is 3*nvals long. */
-void Ptngc_comp_conv_to_vals16(unsigned int *vals,int nvals,
-                         unsigned int *vals16, int *nvals16)
+void Ptngc_comp_conv_to_vals16(unsigned int *vals, const int nvals,
+                               unsigned int *vals16, int *nvals16)
 {
   int i;
   int j=0;
@@ -45,8 +45,8 @@ void Ptngc_comp_conv_to_vals16(unsigned int *vals,int nvals,
   *nvals16=j;
 }
 
-void Ptngc_comp_conv_from_vals16(unsigned int *vals16,int nvals16,
-                           unsigned int *vals, int *nvals)
+void Ptngc_comp_conv_from_vals16(unsigned int *vals16, const int nvals16,
+                                 unsigned int *vals, int *nvals)
 {
   int i=0;
   int j=0;
index 36f0d9f2f0a7b984a024a188b9954fea07c917c2..55bdaf7ade24bab885814f94c6da793ac2698b5b 100644 (file)
@@ -14,7 +14,7 @@
 #include "../../include/compression/tng_compress.h"
 #include "../../include/compression/warnmalloc.h"
 
-void DECLSPECDLLEXPORT *Ptngc_warnmalloc_x(size_t size, char *file, int line)
+void DECLSPECDLLEXPORT *Ptngc_warnmalloc_x(const size_t size, char *file, const int line)
 {
   void *mem=malloc(size);
   if (!mem)
@@ -25,7 +25,7 @@ void DECLSPECDLLEXPORT *Ptngc_warnmalloc_x(size_t size, char *file, int line)
   return mem;
 }
 
-void DECLSPECDLLEXPORT *Ptngc_warnrealloc_x(void *old, size_t size, char *file, int line)
+void DECLSPECDLLEXPORT *Ptngc_warnrealloc_x(void *old, const size_t size, char *file, const int line)
 {
   void *mem=realloc(old,size);
   if (!mem)
index 7d03c57b63edd14cb8857b00c7fab11e645f0739..c469238209f38f32d57115617a4f789f8bd0def6 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -11,6 +11,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "../../include/compression/tng_compress.h"
 
 #endif /* gcc & x86_64 */
 #endif /* TRAJNG X86 GCC INLINE MULDIV */
 
+#ifdef USE_WINDOWS
+#define TNG_INLINE __inline
+#else
+#define TNG_INLINE inline
+#endif
+
 /* Multiply two 32 bit unsigned integers returning a 64 bit unsigned value (in two integers) */
-void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned int *olo)
+static TNG_INLINE void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned int *olo)
 {
 #if defined(TRAJNG_X86_GCC_INLINE_MULDIV)
   __asm__ __volatile__ ("mull %%edx\n\t"
@@ -99,7 +106,7 @@ void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned
 
 /* Divide a 64 bit unsigned value in hi:lo with the 32 bit value i and
    return the result in result and the remainder in remainder */
-void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned int *result, unsigned int *remainder)
+static TNG_INLINE void Ptngc_widediv(unsigned int hi, unsigned int lo, const unsigned int i, unsigned int *result, unsigned int *remainder)
 {
 #if defined(TRAJNG_X86_GCC_INLINE_MULDIV)
   __asm__ __volatile__ ("divl %%ecx\n\t"
@@ -163,7 +170,7 @@ void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned in
 
 /* Add a unsigned int to a largeint. j determines which value in the
    largeint to add v1 to. */
-static void largeint_add_gen(unsigned int v1, unsigned int *largeint, int n, int j)
+static TNG_INLINE void largeint_add_gen(const unsigned int v1, unsigned int *largeint, const int n, int j)
 {
   /* Add with carry. unsigned ints in C wrap modulo 2**bits when "overflowed". */
   unsigned int v2=(v1+largeint[j])&0xFFFFFFFFU; /* Add and cap at 32 bits */
@@ -184,46 +191,50 @@ static void largeint_add_gen(unsigned int v1, unsigned int *largeint, int n, int
 }
 
 /* Add a unsigned int to a largeint. */
-void Ptngc_largeint_add(unsigned int v1, unsigned int *largeint, int n)
+void Ptngc_largeint_add(const unsigned int v1, unsigned int *largeint, const int n)
 {
   largeint_add_gen(v1,largeint,n,0);
 }
 
 /* Multiply v1 with largeint_in and return result in largeint_out */
-void Ptngc_largeint_mul(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n)
+void Ptngc_largeint_mul(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n)
 {
   int i;
-  for (i=0; i<n; i++)
-    largeint_out[i]=0U;
-  for (i=0; i<n; i++)
+  unsigned int lo,hi;
+
+  memset(largeint_out, 0U, sizeof(unsigned int) * n);
+
+  for (i=0; i<n-1; i++)
     {
       if (largeint_in[i]!=0U)
         {
-          unsigned int lo,hi;
           Ptngc_widemul(v1,largeint_in[i],&hi,&lo); /* 32x32->64 mul */
           largeint_add_gen(lo,largeint_out,n,i);
-          if (i+1<n)
-            largeint_add_gen(hi,largeint_out,n,i+1);
+          largeint_add_gen(hi,largeint_out,n,i+1);
         }
     }
+  if (largeint_in[i]!=0U)
+    {
+      Ptngc_widemul(v1,largeint_in[i],&hi,&lo); /* 32x32->64 mul */
+      largeint_add_gen(lo,largeint_out,n,i);
+    }
 }
 
 /* Return the remainder from dividing largeint_in with v1. Result of the division is returned in largeint_out */
-unsigned int Ptngc_largeint_div(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n)
+unsigned int Ptngc_largeint_div(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n)
 {
   unsigned int result,remainder=0;
   int i;
-  unsigned int hi, lo;
+  unsigned int hi;
   /* Boot */
   hi=0U;
   i=n;
   while (i)
     {
-      lo=largeint_in[i-1];
-      Ptngc_widediv(hi,lo,v1,&result,&remainder);
-      largeint_out[i-1]=result;
-      hi=remainder;
       i--;
+      Ptngc_widediv(hi,largeint_in[i],v1,&result,&remainder);
+      largeint_out[i]=result;
+      hi=remainder;
     }
   return remainder;
 }
index bbd45e9dbbc3f507db969613061d05711e8e0ca1..7332f5ffe20eace47bb9834ccfed9ee81e10f525 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
 /* Generated by gen_magic.py */
 #define MAX_MAGIC  92
 
+#ifdef USE_WINDOWS
+#define TNG_INLINE __inline
+#else
+#define TNG_INLINE inline
+#endif
+
 static unsigned int magic[MAX_MAGIC]={
 2U,  3U,  4U,  5U,
 6U,  8U,  10U,  12U,
@@ -159,20 +165,43 @@ static const double iflipgaincheck=0.89089871814033927; /*  1./(2**(1./6)) */
 #define SHOWIT
 #endif
 
-int Ptngc_magic(unsigned int i)
+#ifdef USE_WINDOWS
+#define TNG_INLINE __inline
+#else
+#define TNG_INLINE inline
+#endif
+
+int Ptngc_magic(const unsigned int i)
 {
   return magic[i];
 }
 
-int Ptngc_find_magic_index(unsigned int maxval)
+int Ptngc_find_magic_index(const unsigned int maxval)
 {
-  int i=0;
+  int i;
+
+  if(maxval > magic[MAX_MAGIC/4])
+  {
+      if(maxval > magic[MAX_MAGIC/2])
+      {
+          i = MAX_MAGIC/2 + 1;
+      }
+      else
+      {
+          i = MAX_MAGIC/4 + 1;
+      }
+  }
+  else
+  {
+      i = 0;
+  }
+
   while (magic[i]<=maxval)
     i++;
   return i;
 }
 
-static unsigned int positive_int(int item)
+static TNG_INLINE unsigned int positive_int(const int item)
 {
   int s=0;
   if (item>0)
@@ -182,7 +211,7 @@ static unsigned int positive_int(int item)
   return s;
 }
 
-static int unpositive_int(int val)
+static TNG_INLINE int unpositive_int(const int val)
 {
   int s=(val+1)/2;
   if ((val%2)==0)
@@ -233,7 +262,7 @@ static const int seq_instr[MAXINSTR][2]=
                more efficiently coded with two large instructions. */
  };
 
-static void write_instruction(struct coder *coder,int instr,unsigned char **output_ptr)
+static void write_instruction(struct coder *coder, const int instr, unsigned char **output_ptr)
 {
   Ptngc_writebits(coder,seq_instr[instr][0],seq_instr[instr][1],output_ptr);
 #ifdef SHOWIT
@@ -359,7 +388,7 @@ static void swap_is_better(int *input, int *minint, int *sum_normal, int *sum_sw
   *sum_swapped=swapped_max;
 }
 
-static void swapdecide(struct coder *coder, int *input,int *swapatoms, int *large_index, int *minint, unsigned char **output_ptr)
+static void swapdecide(struct coder *coder, int *input, int *swapatoms, int *large_index, int *minint, unsigned char **output_ptr)
 {
   int didswap=0;
   int normal,swapped;
@@ -438,23 +467,26 @@ static int compute_magic_bits(int *index)
 /* Convert a sequence of (hopefully) small positive integers
    using the base pointed to by index (x base, y base and z base can be different).
    The largest number of integers supported is 18 (29 to handle/detect overflow) */
-static void trajcoder_base_compress(int *input, int n, int *index, unsigned char *result)
+static void trajcoder_base_compress(int *input, const int n, int *index, unsigned char *result)
 {
   unsigned int largeint[19];
   unsigned int largeint_tmp[19];
-  int i,j;
-  for (i=0; i<19; i++)
-    largeint[i]=0U;
+  int i, j;
+
+  memset(largeint, 0U, sizeof(unsigned int) * 19);
 
-  for (i=0; i<n; i++)
+  if(n > 0)
     {
-      if (i!=0)
-        {
-          /* We must do the multiplication of the largeint with the integer base */
-          Ptngc_largeint_mul(magic[index[i%3]],largeint,largeint_tmp,19);
-          for (j=0; j<19; j++)
-            largeint[j]=largeint_tmp[j];
-        }
+      Ptngc_largeint_add(input[0],largeint,19);
+    }
+
+  for (i=1; i<n; i++)
+    {
+      /* We must do the multiplication of the largeint with the integer base */
+      Ptngc_largeint_mul(magic[index[i%3]],largeint,largeint_tmp,19);
+
+      memcpy(largeint,largeint_tmp,19*sizeof *largeint);
+
       Ptngc_largeint_add(input[i],largeint,19);
     }
   if (largeint[18])
@@ -481,7 +513,7 @@ static void trajcoder_base_compress(int *input, int n, int *index, unsigned char
 }
 
 /* The opposite of base_compress. */
-static void trajcoder_base_decompress(unsigned char *input, int n, int *index, int *output)
+static void trajcoder_base_decompress(unsigned char *input, const int n, int *index, int *output)
 {
   unsigned int largeint[19];
   unsigned int largeint_tmp[19];
@@ -524,7 +556,7 @@ static void trajcoder_base_decompress(unsigned char *input, int n, int *index, i
 /* It is "large" if we have to increase the small index quite a
    bit. Not so much to be rejected by the not very large check
    later. */
-static int is_quite_large(int *input, int small_index, int max_large_index)
+static int is_quite_large(int *input, const int small_index, const int max_large_index)
 {
   int is=0;
   int i;
@@ -547,7 +579,7 @@ int nbits_sum;
 int nvalues_sum;
 #endif
 
-static void write_three_large(struct coder *coder, int *encode_ints, int *large_index, int nbits, unsigned char *compress_buffer, unsigned char **output_ptr)
+static void write_three_large(struct coder *coder, int *encode_ints, int *large_index, const int nbits, unsigned char *compress_buffer, unsigned char **output_ptr)
 {
   trajcoder_base_compress(encode_ints,3,large_index,compress_buffer);
   Ptngc_writemanybits(coder,compress_buffer,nbits,output_ptr);
@@ -559,7 +591,7 @@ static void write_three_large(struct coder *coder, int *encode_ints, int *large_
 #endif
 }
 
-static void insert_batch(int *input_ptr, int ntriplets_left, int *prevcoord,int *minint, int *encode_ints, int startenc, int *nenc)
+static void insert_batch(int *input_ptr, int ntriplets_left, const int *prevcoord,int *minint, int *encode_ints, const int startenc, int *nenc)
 {
   int nencode=startenc*3;
   int tmp_prevcoord[3];
@@ -617,8 +649,8 @@ static void insert_batch(int *input_ptr, int ntriplets_left, int *prevcoord,int
   *nenc=nencode;
 }
 
-static void flush_large(struct coder *coder, int *has_large, int *has_large_ints, int n,
-                        int *large_index, int large_nbits, unsigned char *compress_buffer,
+static void flush_large(struct coder *coder, int *has_large, int *has_large_ints, const int n,
+                        int *large_index, const int large_nbits, unsigned char *compress_buffer,
                         unsigned char **output_ptr)
 {
   int i;
@@ -651,7 +683,7 @@ static void flush_large(struct coder *coder, int *has_large, int *has_large_ints
 }
 
 static void buffer_large(struct coder *coder, int *has_large, int *has_large_ints, int *new_large_ints,
-                        int *large_index, int large_nbits, unsigned char *compress_buffer,
+                        int *large_index, const int large_nbits, unsigned char *compress_buffer,
                         unsigned char **output_ptr)
 {
   /* If it is full we must write them all. */
@@ -709,13 +741,15 @@ unsigned char *Ptngc_pack_array_xtc2(struct coder *coder,int *input, int *length
   maxint[2]=minint[2]=input[2];
 
   for (i=1; i<ntriplets; i++)
-    for (j=0; j<3; j++)
-      {
-        if (input[i*3+j]>maxint[j])
-          maxint[j]=input[i*3+j];
-        if (input[i*3+j]<minint[j])
-          minint[j]=input[i*3+j];
-      }
+    {
+      for (j=0; j<3; j++)
+        {
+          if (input[i*3+j]>maxint[j])
+            maxint[j]=input[i*3+j];
+          if (input[i*3+j]<minint[j])
+            minint[j]=input[i*3+j];
+        }
+    }
 
   large_index[0]=Ptngc_find_magic_index(maxint[0]-minint[0]+1);
   large_index[1]=Ptngc_find_magic_index(maxint[1]-minint[1]+1);
@@ -794,9 +828,7 @@ unsigned char *Ptngc_pack_array_xtc2(struct coder *coder,int *input, int *length
 #endif
 
   /* Initial prevcoord is the minimum integers. */
-  prevcoord[0]=minint[0];
-  prevcoord[1]=minint[1];
-  prevcoord[2]=minint[2];
+  memcpy(prevcoord, minint, 3*sizeof *prevcoord);
 
   while (ntriplets_left)
     {
@@ -1267,7 +1299,7 @@ unsigned char *Ptngc_pack_array_xtc2(struct coder *coder,int *input, int *length
 }
 
 
-int Ptngc_unpack_array_xtc2(struct coder *coder,unsigned char *packed,int *output, int length)
+int Ptngc_unpack_array_xtc2(struct coder *coder, unsigned char *packed, int *output, const int length)
 {
   unsigned char *ptr=packed;
   int bitptr=0;
@@ -1304,9 +1336,7 @@ int Ptngc_unpack_array_xtc2(struct coder *coder,unsigned char *packed,int *outpu
 #endif
 
   /* Initial prevcoord is the minimum integers. */
-  prevcoord[0]=minint[0];
-  prevcoord[1]=minint[1];
-  prevcoord[2]=minint[2];
+  memcpy(prevcoord, minint, 3*sizeof *prevcoord);
 
   while (ntriplets_left)
     {
@@ -1329,9 +1359,7 @@ int Ptngc_unpack_array_xtc2(struct coder *coder,unsigned char *packed,int *outpu
               /* Get the large value. */
               readmanybits(&ptr,&bitptr,large_nbits,compress_buffer);
               trajcoder_base_decompress(compress_buffer,3,large_index,encode_ints);
-              large_ints[0]=encode_ints[0];
-              large_ints[1]=encode_ints[1];
-              large_ints[2]=encode_ints[2];
+              memcpy(large_ints, encode_ints, 3*sizeof *large_ints);
 #ifdef SHOWIT
               fprintf(stderr,"large ints: %d %d %d\n",large_ints[0],large_ints[1],large_ints[2]);
 #endif
@@ -1444,16 +1472,12 @@ int Ptngc_unpack_array_xtc2(struct coder *coder,unsigned char *packed,int *outpu
               /* Get the large value. */
               readmanybits(&ptr,&bitptr,large_nbits,compress_buffer);
               trajcoder_base_decompress(compress_buffer,3,large_index,encode_ints);
-              large_ints[0]=encode_ints[0];
-              large_ints[1]=encode_ints[1];
-              large_ints[2]=encode_ints[2];
+              memcpy(large_ints, encode_ints, 3*sizeof *large_ints);
               /* Output large value */
               *output++=large_ints[0]+minint[0];
               *output++=large_ints[1]+minint[1];
               *output++=large_ints[2]+minint[2];
-              prevcoord[0]=large_ints[0];
-              prevcoord[1]=large_ints[1];
-              prevcoord[2]=large_ints[2];
+              memcpy(prevcoord, large_ints, 3*sizeof *prevcoord);
             }
           ntriplets_left-=n;
         }
index 95483b32794f7ead6ff91c7a9aabb88f65719e96..5cdebdf4b671077c447d3bd589c18e0d804e5c9f 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng compression routines.
  *
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -60,11 +60,17 @@ static const double iflipgaincheck=0.89089871814033927; /*  1./(2**(1./6)) */
 #define SHOWIT_LIGHT
 #endif
 
+#ifdef USE_WINDOWS
+#define TNG_INLINE __inline
+#else
+#define TNG_INLINE inline
+#endif
+
 /* These routines are in xtc2.c */
 int Ptngc_magic(unsigned int i);
-int Ptngc_find_magic_index(unsigned int maxval);
+int Ptngc_find_magic_index(const unsigned int maxval);
 
-static unsigned int positive_int(int item)
+static TNG_INLINE unsigned int positive_int(const int item)
 {
   int s=0;
   if (item>0)
@@ -74,7 +80,7 @@ static unsigned int positive_int(int item)
   return s;
 }
 
-static int unpositive_int(int val)
+static TNG_INLINE int unpositive_int(const int val)
 {
   int s=(val+1)/2;
   if ((val%2)==0)
@@ -153,14 +159,14 @@ static void free_xtc3_context(struct xtc3_context *xtc3_context)
 }
 
 /* Modifies three integer values for better compression of water */
-static void swap_ints(int *in, int *out)
+static void swap_ints(const int *in, int *out)
 {
   out[0]=in[0]+in[1];
   out[1]=-in[1];
   out[2]=in[1]+in[2];
 }
 
-static void swap_is_better(int *input, int *minint, int *sum_normal, int *sum_swapped)
+static void swap_is_better(const int *input, const int *minint, int *sum_normal, int *sum_swapped)
 {
   int normal_max=0;
   int swapped_max=0;
@@ -200,7 +206,7 @@ static void allocate_enough_memory(unsigned int **ptr, int *nele, int *nele_allo
 }
 
 static void insert_value_in_array(unsigned int **ptr, int *nele, int *nele_alloc,
-                                  unsigned int value,
+                                  const unsigned int value,
                                   char *arrayname)
 {
 #ifndef SHOWIT
@@ -266,7 +272,7 @@ static void swapdecide(struct xtc3_context *xtc3_context, int *input,int *swapat
 /* It is "large" if we have to increase the small index quite a
    bit. Not so much to be rejected by the not very large check
    later. */
-static int is_quite_large(int *input, int small_index, int max_large_index)
+static int is_quite_large(const int *input, const int small_index, const int max_large_index)
 {
   int is=0;
   int i;
@@ -289,7 +295,7 @@ int nbits_sum;
 int nvalues_sum;
 #endif
 
-static void insert_batch(int *input_ptr, int ntriplets_left, int *prevcoord, int *encode_ints, int startenc, int *nenc)
+static void insert_batch(const int *input_ptr, const int ntriplets_left, const int *prevcoord, int *encode_ints, const int startenc, int *nenc)
 {
   int nencode=startenc*3;
   int tmp_prevcoord[3];
@@ -347,7 +353,7 @@ static void insert_batch(int *input_ptr, int ntriplets_left, int *prevcoord, int
   *nenc=nencode;
 }
 
-static void large_instruction_change(struct xtc3_context *xtc3_context, int i)
+static void large_instruction_change(struct xtc3_context *xtc3_context, const int i)
 {
   /* If the first large is of a different kind than the currently used we must
      emit an "instruction" to change the large type. */
@@ -369,7 +375,7 @@ static void large_instruction_change(struct xtc3_context *xtc3_context, int i)
 }
 
 static void write_three_large(struct xtc3_context *xtc3_context,
-                              int i)
+                              const int i)
 {
   int m;
   if (xtc3_context->current_large_type==0)
@@ -399,7 +405,7 @@ static void write_three_large(struct xtc3_context *xtc3_context,
 }
 
 static void flush_large(struct xtc3_context *xtc3_context,
-                        int n) /* How many to flush. */
+                        const int n) /* How many to flush. */
 {
   int i;
   i=0;
@@ -464,8 +470,8 @@ static double compute_intlen(unsigned int *ints)
   return (double)m;
 }
 
-static void buffer_large(struct xtc3_context *xtc3_context, int *input, int inpdata,
-                         int natoms, int intradelta_ok)
+static void buffer_large(struct xtc3_context *xtc3_context, int *input, const int inpdata,
+                         const int natoms, const int intradelta_ok)
 {
   unsigned int direct[3], intradelta[3]={0,}, interdelta[3]={0,};
   double minlen;
@@ -536,7 +542,7 @@ static void buffer_large(struct xtc3_context *xtc3_context, int *input, int inpd
   xtc3_context->has_large++;
 }
 
-static void output_int(unsigned char *output,int *outdata, unsigned int n)
+static void output_int(unsigned char *output,int *outdata, const unsigned int n)
 {
   output[(*outdata)++]=((unsigned int)n)&0xFFU;
   output[(*outdata)++]=(((unsigned int)n)>>8)&0xFFU;
@@ -568,21 +574,21 @@ static void printarray(unsigned int *a, int n, char *name)
 #define BASEINTERVAL 8
 
 /* How many bytes are needed to store n values in base base */
-static int base_bytes(unsigned int base, int n)
+static int base_bytes(const unsigned int base, const int n)
 {
   int i,j;
   unsigned int largeint[MAXMAXBASEVALS+1];
   unsigned int largeint_tmp[MAXMAXBASEVALS+1];
   int numbytes=0;
-  for (i=0; i<n+1; i++)
-    largeint[i]=0U;
+
+  memset(largeint, 0U, sizeof(unsigned int) * (n+1));
+
   for (i=0; i<n; i++)
     {
       if (i!=0)
         {
           Ptngc_largeint_mul(base,largeint,largeint_tmp,n+1);
-          for (j=0; j<n+1; j++)
-            largeint[j]=largeint_tmp[j];
+          memcpy(largeint, largeint_tmp, (n+1)*sizeof *largeint);
         }
       Ptngc_largeint_add(base-1U,largeint,n+1);
     }
@@ -594,7 +600,7 @@ static int base_bytes(unsigned int base, int n)
   return numbytes;
 }
 
-static void base_compress(unsigned int *data, int len, unsigned char *output, int *outlen)
+static void base_compress(unsigned int *data, const int len, unsigned char *output, int *outlen)
 {
   unsigned int largeint[MAXBASEVALS+1];
   unsigned int largeint_tmp[MAXBASEVALS+1];
@@ -612,8 +618,9 @@ static void base_compress(unsigned int *data, int len, unsigned char *output, in
       unsigned int base=0U;
       int nvals=0;
       int basegiven=0;
-      for (j=0; j<MAXBASEVALS+1; j++)
-        largeint[j]=0U;
+
+      memset(largeint, 0U, sizeof(unsigned int) * (MAXBASEVALS+1));
+
       for (i=ixyz; i<len; i+=3)
         {
          if (nvals==0)
@@ -679,8 +686,8 @@ static void base_compress(unsigned int *data, int len, unsigned char *output, in
               fprintf(stderr,"\n");
 #endif
               nvals=0;
-              for (j=0; j<MAXBASEVALS+1; j++)
-                largeint[j]=0U;
+
+              memset(largeint, 0U, sizeof(unsigned int) * (MAXBASEVALS+1));
             }
         }
       if (nvals)
@@ -700,7 +707,7 @@ static void base_compress(unsigned int *data, int len, unsigned char *output, in
   *outlen=nwrittenout;
 }
 
-static void base_decompress(unsigned char *input, int len, unsigned int *output)
+static void base_decompress(unsigned char *input, const int len, unsigned int *output)
 {
   unsigned int largeint[MAXMAXBASEVALS+1];
   unsigned int largeint_tmp[MAXMAXBASEVALS+1];
@@ -747,8 +754,7 @@ static void base_decompress(unsigned char *input, int len, unsigned int *output)
               fprintf(stderr,"Base for %d is %u. I need %d bytes for %d values.\n",ixyz,base,numbytes,nvals_left);
 #endif
             }
-          for (j=0; j<maxbasevals+1; j++)
-            largeint[j]=0U;
+          memset(largeint, 0U, sizeof(unsigned int) * (maxbasevals+1));
 #ifdef SHOWIT
           fprintf(stderr,"Reading largeint: ");
 #endif
@@ -789,7 +795,7 @@ static void base_decompress(unsigned char *input, int len, unsigned int *output)
 }
 
 /* If a large proportion of the integers are large (More than 10\% are >14 bits) we return 0, otherwise 1 */
-static int heuristic_bwlzh(unsigned int *ints, int nints)
+static int heuristic_bwlzh(unsigned int *ints, const int nints)
 {
   int i,num;
   num=0;
@@ -808,7 +814,7 @@ static int heuristic_bwlzh(unsigned int *ints, int nints)
    Speed 5 enables the LZ77 component of BWLZH.
    Speed 6 always tests if BWLZH is better and if it is uses it. This can be very slow.
  */
-unsigned char *Ptngc_pack_array_xtc3(int *input, int *length, int natoms, int speed)
+unsigned char *Ptngc_pack_array_xtc3(int *input, int *length, const int natoms, int speed)
 {
   unsigned char *output=NULL;
   int i,ienc,j;
@@ -840,9 +846,8 @@ unsigned char *Ptngc_pack_array_xtc3(int *input, int *length, int natoms, int sp
   struct xtc3_context xtc3_context;
   init_xtc3_context(&xtc3_context);
 
-  xtc3_context.maxint[0]=xtc3_context.minint[0]=input[0];
-  xtc3_context.maxint[1]=xtc3_context.minint[1]=input[1];
-  xtc3_context.maxint[2]=xtc3_context.minint[2]=input[2];
+  memcpy(xtc3_context.maxint, input, 3*sizeof *xtc3_context.maxint);
+  memcpy(xtc3_context.minint, input, 3*sizeof *xtc3_context.maxint);
 
   /* Values of speed should be sane. */
   if (speed<1)
@@ -923,6 +928,7 @@ unsigned char *Ptngc_pack_array_xtc3(int *input, int *length, int natoms, int sp
 #endif
 
   /* Initial prevcoord is the minimum integers. */
+  memcpy(prevcoord, xtc3_context.minint, 3*sizeof *prevcoord);
   prevcoord[0]=xtc3_context.minint[0];
   prevcoord[1]=xtc3_context.minint[1];
   prevcoord[2]=xtc3_context.minint[2];
@@ -1663,7 +1669,7 @@ unsigned char *Ptngc_pack_array_xtc3(int *input, int *length, int natoms, int sp
 }
 
 static void decompress_bwlzh_block(unsigned char **ptr,
-                                   int nvals,
+                                   const int nvals,
                                    unsigned int **vals)
 {
   int bwlzh_buf_len=(int)(((unsigned int)(*ptr)[0]) |
@@ -1677,7 +1683,7 @@ static void decompress_bwlzh_block(unsigned char **ptr,
 }
 
 static void decompress_base_block(unsigned char **ptr,
-                                  int nvals,
+                                  const int nvals,
                                   unsigned int **vals)
 {
   int base_buf_len=(int)(((unsigned int)(*ptr)[0]) |
@@ -1694,8 +1700,8 @@ static void unpack_one_large(struct xtc3_context *xtc3_context,
                              int *ilargedir, int *ilargeintra,
                              int *ilargeinter, int *prevcoord,
                              int *minint, int *output,
-                             int outdata, int didswap,
-                             int natoms, int current_large_type)
+                             const int outdata, const int didswap,
+                             const int natoms, const int current_large_type)
 {
   int large_ints[3]={0,0,0};
   if (current_large_type==0 && xtc3_context->large_direct)
@@ -1722,9 +1728,7 @@ static void unpack_one_large(struct xtc3_context *xtc3_context,
         +output[outdata-natoms*3+2+didswap*3];
       (*ilargeinter)+=3;
     }
-  prevcoord[0]=large_ints[0];
-  prevcoord[1]=large_ints[1];
-  prevcoord[2]=large_ints[2];
+  memcpy(prevcoord, large_ints, 3*sizeof *prevcoord);
   output[outdata]=large_ints[0];
   output[outdata+1]=large_ints[1];
   output[outdata+2]=large_ints[2];
@@ -1734,7 +1738,7 @@ static void unpack_one_large(struct xtc3_context *xtc3_context,
 }
 
 
-int Ptngc_unpack_array_xtc3(unsigned char *packed,int *output, int length, int natoms)
+int Ptngc_unpack_array_xtc3(unsigned char *packed,int *output, const int length, const int natoms)
 {
   int i;
   int minint[3];
@@ -1833,9 +1837,7 @@ int Ptngc_unpack_array_xtc3(unsigned char *packed,int *output, int length, int n
     }
 
   /* Initial prevcoord is the minimum integers. */
-  prevcoord[0]=minint[0];
-  prevcoord[1]=minint[1];
-  prevcoord[2]=minint[2];
+  memcpy(prevcoord, minint, 3*sizeof *prevcoord);
 
   while (ntriplets_left>0 && iinstr<xtc3_context.ninstr)
     {
index 774c0f6841218451a4765d82afa1cb86fd9a9e6e..f6a2391635587c1178dd676ebf6103f2af8df416 100644 (file)
@@ -165,6 +165,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
 #else
     /* Define storage for little-endian or both types of CPUs. */
     md5_word_t xbuf[16];
+    /* cppcheck-suppress unassignedVariable */
     const md5_word_t *X;
 #endif
 
index 7702d23846c5d12cd5aa2351c0a7a4fe2a4f193e..94e74309241feb005515094e6d84a7ef54d8d017 100644 (file)
@@ -1,7 +1,7 @@
 /* This code is part of the tng binary trajectory format.
  *
  * Written by Magnus Lundborg
- * Copyright (c) 2012-2014, The GROMACS development team.
+ * Copyright (c) 2012-2015, The GROMACS development team.
  * Check out http://www.gromacs.org for more information.
  *
  *
@@ -9,6 +9,8 @@
  * modify it under the terms of the Revised BSD License.
  */
 
+/* These three definitions are required to enforce 64 bit file sizes. */
+/* Force 64 bit variants of file access calls. */
 #define _FILE_OFFSET_BITS 64
 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
 #define _LARGEFILE_SOURCE
@@ -200,16 +202,15 @@ struct tng_trajectory_frame_set {
     /** The number of trajectory data blocks of particle dependent data */
     int n_particle_data_blocks;
     /** A list of data blocks containing particle dependent data */
-    struct tng_particle_data *tr_particle_data;
+    struct tng_data *tr_particle_data;
     /** The number of trajectory data blocks independent of particles */
     int n_data_blocks;
     /** A list of data blocks containing particle indepdendent data */
-    struct tng_non_particle_data *tr_data;
+    struct tng_data *tr_data;
 };
 
 /* 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 {
+struct tng_data {
     /** The block ID of the data block containing this particle data.
      *  This is used to determine the kind of data that is stored */
     int64_t block_id;
@@ -218,6 +219,9 @@ struct tng_particle_data {
     char *block_name;
     /** The type of data stored. */
     char datatype;
+    /** A flag to indicate if this data block contains frame and/or particle dependent
+     * data */
+    char dependency;
     /** The frame number of the first data value */
     int64_t first_frame_with_data;
     /** The number of frames in this frame set */
@@ -240,38 +244,6 @@ struct tng_particle_data {
     char ****strings;
 };
 
-struct tng_non_particle_data {
-    /** The ID of the data block */
-    int64_t block_id;
-    /** The name of the data block. This is used to determine the kind of
-     *  data that is stored */
-    char *block_name;
-    /** The type of data stored. */
-    char datatype;
-    /** The first frame number of the first data value */
-    int64_t first_frame_with_data;
-    /** The number of frames in this data block */
-    int64_t n_frames;
-    /** The number of values stored per frame */
-    int64_t n_values_per_frame;
-    /** The number of frames between each data value, e.g. if storing data
-     *  that is not saved every frame. */
-    int64_t stride_length;
-    /** ID of the CODEC used for compression. 0 == no compression. */
-    int64_t codec_id;
-    /** If reading one frame at a time this is the last read frame */
-    int64_t last_retrieved_frame;
-    /** Compressed data is stored as integers. This compression multiplier is
-     *  the multiplication factor to convert from integer to float/double */
-    double compression_multiplier;
-    /** 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 2-dimensional array */
-    char ***strings;
-};
-
-
 
 struct tng_trajectory {
     /** The path of the input trajectory file */
@@ -375,12 +347,12 @@ struct tng_trajectory {
     /** The number of non-frame dependent particle dependent data blocks */
     int n_particle_data_blocks;
     /** A list of data blocks containing particle dependent data */
-    struct tng_particle_data *non_tr_particle_data;
+    struct tng_data *non_tr_particle_data;
 
     /** The number of frame and particle independent data blocks */
     int n_data_blocks;
     /** A list of frame and particle indepdendent data blocks */
-    struct tng_non_particle_data *non_tr_data;
+    struct tng_data *non_tr_data;
 
     /** TNG compression algorithm for compressing positions */
     int *compress_algo_pos;
@@ -404,55 +376,28 @@ struct tng_trajectory {
 #define TNG_SNPRINTF snprintf
 #endif
 
-static TNG_INLINE int tng_min_i(int a, int b)
-{
-    return (a < b ? a : b);
-}
-
-/*
-static TNG_INLINE int tng_max_i(int a, int b)
-{
-    return (a > b ? a : b);
-}
-*/
-static TNG_INLINE int64_t tng_min_i64(int64_t a, int64_t b)
-{
-    return (a < b ? a : b);
-}
-
-static TNG_INLINE int64_t tng_max_i64(int64_t a, int64_t b)
-{
-    return (a > b ? a : b);
-}
-
-/*
-static TNG_INLINE float tng_min_f(float a, float b)
+static TNG_INLINE size_t tng_min_size(const size_t a, const size_t b)
 {
     return (a < b ? a : b);
 }
 
-static TNG_INLINE float tng_max_f(float a, float b)
-{
-    return (a > b ? a : b);
-}
-
-static TNG_INLINE double tng_min_d(double a, double b)
+static TNG_INLINE int64_t tng_min_i64(const int64_t a, const int64_t b)
 {
     return (a < b ? a : b);
 }
 
-static TNG_INLINE double tng_max_d(double a, double b)
+static TNG_INLINE int64_t tng_max_i64(const int64_t a, const int64_t b)
 {
     return (a > b ? a : b);
 }
-*/
 
-/** This function swaps the byte order of a 32 bit numerical variable
+/**
+ * @brief This function swaps the byte order of a 32 bit numerical variable
  * to big endian.
- * It does not only work with integer, but e.g. floats need casting.
- * If the byte order is already big endian no change is needed.
  * @param tng_data is a trajectory data container.
  * @param v is a pointer to a 32 bit numerical value (float or integer).
+ * @details The function does not only work with integer, but e.g. floats need casting.
+ * If the byte order is already big endian no change is needed.
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
  * byte order is not recognised.
  */
@@ -483,14 +428,15 @@ static tng_function_status tng_swap_byte_order_big_endian_32
     }
 }
 
-/** This function swaps the byte order of a 64 bit numerical variable
+/**
+ * @brief This function swaps the byte order of a 64 bit numerical variable
  * to big endian.
- * It does not only work with integer, but e.g. floats need casting.
+ * @param tng_data is a trajectory data container.
+ * @param v is a pointer to a 64 bit numerical value (double or integer).
+ * @details The function does not only work with integer, but e.g. floats need casting.
  * The byte order swapping routine can convert four different byte
  * orders to big endian.
  * If the byte order is already big endian no change is needed.
- * @param tng_data is a trajectory data container.
- * @param v is a pointer to a 64 bit numerical value (double or integer).
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
  * byte order is not recognised.
  */
@@ -537,12 +483,13 @@ static tng_function_status tng_swap_byte_order_big_endian_64
     }
 }
 
-/** This function swaps the byte order of a 32 bit numerical variable
+/**
+ * @brief This function swaps the byte order of a 32 bit numerical variable
  * to little endian.
- * It does not only work with integer, but e.g. floats need casting.
- * If the byte order is already little endian no change is needed.
  * @param tng_data is a trajectory data container.
  * @param v is a pointer to a 32 bit numerical value (float or integer).
+ * @details The function does not only work with integer, but e.g. floats need casting.
+ * If the byte order is already little endian no change is needed.
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
  * byte order is not recognised.
  */
@@ -573,14 +520,15 @@ static tng_function_status tng_swap_byte_order_little_endian_32
     }
 }
 
-/** This function swaps the byte order of a 64 bit numerical variable
+/**
+ * @brief This function swaps the byte order of a 64 bit numerical variable
  * to little endian.
- * It does not only work with integer, but e.g. floats need casting.
+ * @param tng_data is a trajectory data container.
+ * @param v is a pointer to a 64 bit numerical value (double or integer).
+ * @details The function does not only work with integer, but e.g. floats need casting.
  * The byte order swapping routine can convert four different byte
  * orders to little endian.
  * If the byte order is already little endian no change is needed.
- * @param tng_data is a trajectory data container.
- * @param v is a pointer to a 64 bit numerical value (double or integer).
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
  * byte order is not recognised.
  */
@@ -632,12 +580,240 @@ static tng_function_status tng_swap_byte_order_little_endian_64
         return(TNG_FAILURE);
     }
 }
-/** Generate the md5 hash of a block.
+
+/**
+ * @brief Read a NULL terminated string from a file.
+ * @param tng_data is a trajectory data container
+ * @param str is a pointer to the character string that will
+ * contain the read string. *str is reallocated in the function
+ * and must be NULL or pointing at already allocated memory.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * @param md5_state is a pointer to the current md5 storage, which will be
+ * appended with str if hash_mode == TNG_USE_HASH.
+ * @param line_nr is the line number where this function was called, to be
+ * able to give more useful error messages.
+ */
+static tng_function_status tng_freadstr(const tng_trajectory_t tng_data,
+                                        char **str,
+                                        const char hash_mode,
+                                        md5_state_t *md5_state,
+                                        const int line_nr)
+{
+    char temp[TNG_MAX_STR_LEN], *temp_alloc;
+    int c, count = 0;
+
+    do
+    {
+        c = fgetc(tng_data->input_file);
+
+        if (c == EOF)
+        {
+            /* Clear file error flag and return -1 if EOF is read.*/
+            clearerr(tng_data->input_file);
+            return TNG_FAILURE;
+        }
+        else
+        {
+            /* Cast c to char */
+            temp[count++] = (char) c;
+        }
+    } while ((temp[count-1] != '\0') && (count < TNG_MAX_STR_LEN));
+
+    temp_alloc = realloc(*str, count);
+    if(!temp_alloc)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", count,
+               __FILE__, line_nr);
+        free(*str);
+        *str = 0;
+        return TNG_FAILURE;
+    }
+    *str = temp_alloc;
+
+    strncpy(*str, temp, count);
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_append(md5_state, (md5_byte_t *)*str, count);
+    }
+
+    return TNG_SUCCESS;
+}
+
+/**
+ * @brief Write a NULL terminated string to a file.
+ * @param tng_data is a trajectory data container
+ * @param str is a pointer to the character string should be written.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * @param md5_state is a pointer to the current md5 storage, which will be
+ * appended with str if hash_mode == TNG_USE_HASH.
+ * @param line_nr is the line number where this function was called, to be
+ * able to give more useful error messages.
+ */
+static TNG_INLINE tng_function_status tng_fwritestr(tng_trajectory_t tng_data,
+                                                const char *str,
+                                                const char hash_mode,
+                                                md5_state_t *md5_state,
+                                                const int line_nr)
+{
+    size_t len;
+
+    len = tng_min_size(strlen(str) + 1, TNG_MAX_STR_LEN);
+
+    if(fwrite(str, len, 1, tng_data->output_file) != 1)
+    {
+        fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, line_nr);
+        return(TNG_CRITICAL);
+    }
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_append(md5_state, (md5_byte_t *)str, len);
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/**
+ * @brief Read a numerical value from file.
+ * The byte order will be swapped if need be.
+ * @param tng_data is a trajectory data container
+ * @param dest is a pointer to where to store the read data.
+ * @param len is the length (in bytes) of the numerical data type. Should
+ * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * @param md5_state is a pointer to the current md5 storage, which will be
+ * appended with str if hash_mode == TNG_USE_HASH.
+ * @param line_nr is the line number where this function was called, to be
+ * able to give more useful error messages.
+ */
+static TNG_INLINE tng_function_status tng_file_input_numerical
+                (const tng_trajectory_t tng_data,
+                 void *dest,
+                 const size_t len,
+                 const char hash_mode,
+                 md5_state_t *md5_state,
+                 const int line_nr)
+{
+    if(fread(dest, len, 1, tng_data->input_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, line_nr);
+        return(TNG_CRITICAL);
+    }
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_append(md5_state, (md5_byte_t *)dest, len);
+    }
+    switch(len)
+    {
+    case 8:
+        if(tng_data->input_endianness_swap_func_64 &&
+           tng_data->input_endianness_swap_func_64(tng_data, dest) != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, line_nr);
+        }
+        break;
+    case 4:
+        if(tng_data->input_endianness_swap_func_32 &&
+           tng_data->input_endianness_swap_func_32(tng_data, dest) != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                    __FILE__, line_nr);
+        }
+        break;
+    default:
+        break;
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/**
+ * @brief Write a numerical value to file.
+ * The byte order will be swapped if need be.
+ * @param tng_data is a trajectory data container
+ * @param src is a pointer to the data to write.
+ * @param len is the length (in bytes) of the numerical data type. Should
+ * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * @param md5_state is a pointer to the current md5 storage, which will be
+ * appended with str if hash_mode == TNG_USE_HASH.
+ * @param line_nr is the line number where this function was called, to be
+ * able to give more useful error messages.
+ */
+static TNG_INLINE tng_function_status tng_file_output_numerical
+                (const tng_trajectory_t tng_data,
+                 const void *src,
+                 const size_t len,
+                 const char hash_mode,
+                 md5_state_t *md5_state,
+                 const int line_nr)
+{
+    int32_t temp_i32;
+    int64_t temp_i64;
+
+    switch(len)
+    {
+        case 8:
+            temp_i64 = *((int64_t *)src);
+            if(tng_data->output_endianness_swap_func_64 &&
+            tng_data->output_endianness_swap_func_64(tng_data, &temp_i64) != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, line_nr);
+            }
+            if(fwrite(&temp_i64, len, 1, tng_data->output_file) != 1)
+            {
+                fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
+                return(TNG_CRITICAL);
+            }
+            if(hash_mode == TNG_USE_HASH)
+            {
+                md5_append(md5_state, (md5_byte_t *)&temp_i64, len);
+            }
+            break;
+        case 4:
+            temp_i32 = *((int32_t *)src);
+            if(tng_data->output_endianness_swap_func_32 &&
+            tng_data->output_endianness_swap_func_32(tng_data, &temp_i32) != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, line_nr);
+            }
+            if(fwrite(&temp_i32, len, 1, tng_data->output_file) != 1)
+            {
+                fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
+                return(TNG_CRITICAL);
+            }
+            if(hash_mode == TNG_USE_HASH)
+            {
+                md5_append(md5_state, (md5_byte_t *)&temp_i32, len);
+            }
+            break;
+        default:
+            if(fwrite(src, len, 1, tng_data->output_file) != 1)
+            {
+                fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
+                return(TNG_CRITICAL);
+            }
+            if(hash_mode == TNG_USE_HASH)
+            {
+                md5_append(md5_state, (md5_byte_t *)src, len);
+            }
+            break;
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/**
+ * @brief Generate the md5 hash of a block.
  * The hash is created based on the actual block contents.
  * @param block is a general block container.
  * @return TNG_SUCCESS (0) if successful.
  */
-static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
+static tng_function_status tng_block_md5_hash_generate(const tng_gen_block_t block)
 {
     md5_state_t md5_state;
 
@@ -649,48 +825,59 @@ static tng_function_status tng_block_md5_hash_generate(tng_gen_block_t block)
     return(TNG_SUCCESS);
 }
 
-/** Compare the current block md5 hash (e.g. read from file) with the md5 hash
- * calculated from the current contents.
- * If the current md5 hash is not set skip the comparison.
- * @param block is a general block container.
- * @param results If the hashes match results is set to TNG_TRUE, otherwise it is
- * set to TNG_FALSE. If the hash was not set results is set to TNG_TRUE.
- * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the hash was not
- * set.
+/**
+ * @brief If there is data left in the block read that to append that to the MD5 hash.
+ * @param tng_data is a trajectory data container.
+ * @param block is the data block that is being read.
+ * @param start_pos is the file position where the block started.
+ * @param md5_state is the md5 to which the md5 of the remaining block
+ * will be appended.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
  */
-static tng_function_status tng_md5_hash_match_verify(tng_gen_block_t block,
-                                                     tng_bool *results)
+static tng_function_status tng_md5_remaining_append(const tng_trajectory_t tng_data,
+                                                    const tng_gen_block_t block,
+                                                    const int64_t start_pos,
+                                                    md5_state_t *md5_state)
 {
-    md5_state_t md5_state;
-    char hash[TNG_MD5_HASH_LEN];
-
-    TNG_ASSERT(block->block_contents_size > 0, "The block contents size must be > 0");
+    int64_t curr_file_pos;
+    char *temp_data;
 
-    *results = TNG_TRUE;
-    if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0)
+    curr_file_pos = ftello(tng_data->input_file);
+    if(curr_file_pos < start_pos + block->block_contents_size)
     {
-        return(TNG_FAILURE);
-    }
-    md5_init(&md5_state);
-    md5_append(&md5_state, (md5_byte_t *)block->block_contents,
-               (int)block->block_contents_size);
-    md5_finish(&md5_state, (md5_byte_t *)hash);
-
-    if(strncmp(block->md5_hash, hash, 16) != 0)
-    {
-        *results = TNG_FALSE;
+        temp_data = malloc(start_pos + block->block_contents_size - curr_file_pos);
+        if(!temp_data)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                    start_pos + block->block_contents_size - curr_file_pos, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        if(fread(temp_data, start_pos + block->block_contents_size - curr_file_pos,
+                    1, tng_data->input_file) == 0)
+        {
+            fprintf(stderr, "TNG library: Cannot read remaining part of block to generate MD5 sum. %s: %d\n", __FILE__, __LINE__);
+            free(temp_data);
+            return(TNG_CRITICAL);
+        }
+        md5_append(md5_state, (md5_byte_t *)temp_data,
+                   start_pos + block->block_contents_size - curr_file_pos);
+        free(temp_data);
     }
 
     return(TNG_SUCCESS);
 }
 
-/** Open the input file if it is not already opened.
+/**
+ * @brief Open the input file if it is not already opened.
  * @param tng_data is a trajectory data container.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
+static tng_function_status tng_input_file_init(const tng_trajectory_t tng_data)
 {
+    int64_t file_pos;
+
     if(!tng_data->input_file)
     {
         if(!tng_data->input_file_path)
@@ -707,15 +894,25 @@ static tng_function_status tng_input_file_init(tng_trajectory_t tng_data)
             return(TNG_CRITICAL);
         }
     }
+
+    if(!tng_data->input_file_len)
+    {
+        file_pos = ftello(tng_data->input_file);
+        fseeko(tng_data->input_file, 0, SEEK_END);
+        tng_data->input_file_len = ftello(tng_data->input_file);
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
+    }
+
     return(TNG_SUCCESS);
 }
 
-/** Open the output file if it is not already opened
+/**
+ * @brief Open the output file if it is not already opened
  * @param tng_data is a trajectory data container.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
+static tng_function_status tng_output_file_init(const tng_trajectory_t tng_data)
 {
     if(!tng_data->output_file)
     {
@@ -738,7 +935,8 @@ static tng_function_status tng_output_file_init(tng_trajectory_t tng_data)
     return(TNG_SUCCESS);
 }
 
-/** Setup a file block container.
+/**
+ * @brief Setup a file block container.
  * @param block_p a pointer to memory to initialise as a file block container.
  * @details Memory is allocated during initialisation.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
@@ -751,7 +949,7 @@ static tng_function_status tng_block_init(struct tng_gen_block **block_p)
     *block_p = malloc(sizeof(struct tng_gen_block));
     if(!*block_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
                sizeof(struct tng_gen_block), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
@@ -760,7 +958,7 @@ static tng_function_status tng_block_init(struct tng_gen_block **block_p)
 
     block->id = -1;
     /* 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);
+    memset(block->md5_hash, '\0', TNG_MD5_HASH_LEN);
     block->name = 0;
     block->block_version = TNG_API_VERSION;
     block->header_contents = 0;
@@ -810,7 +1008,8 @@ static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
     return(TNG_SUCCESS);
 }
 
-/** Read the header of a data block, regardless of its type
+/**
+ * @brief 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, TNG_FAILURE(1) if a minor
@@ -818,10 +1017,9 @@ static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
  * 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)
+                (const tng_trajectory_t tng_data, const tng_gen_block_t block)
 {
-    int len;
-    int64_t offset = 0;
+    int64_t start_pos;
 
     TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
 
@@ -830,6 +1028,8 @@ static tng_function_status tng_block_header_read
         return(TNG_CRITICAL);
     }
 
+    start_pos = ftello(tng_data->input_file);
+
     /* First read the header size to be able to read the whole header. */
     if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
         1, tng_data->input_file) == 0)
@@ -901,119 +1101,49 @@ static tng_function_status tng_block_header_read
         }
     }
 
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &block->header_contents_size)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-
-    /* Move the reading position to the beginning of the header. */
-    fseeko(tng_data->input_file, -(int64_t)sizeof(block->header_contents_size),
-           SEEK_CUR);
-
-    /* If there is already memory allocated for the contents free it (we do not
-     * know if the size is correct). */
-    if(block->header_contents)
+    if(tng_data->input_endianness_swap_func_64 &&
+       tng_data->input_endianness_swap_func_64(tng_data, &block->header_contents_size) != TNG_SUCCESS)
     {
-        free(block->header_contents);
+        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                __FILE__, __LINE__);
     }
 
-    block->header_contents = malloc(block->header_contents_size);
-    if(!block->header_contents)
+    if(tng_file_input_numerical(tng_data, &block->block_contents_size,
+                                sizeof(block->block_contents_size),
+                                TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->header_contents_size, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    /* Read the whole header into header_contents. This way it can be saved
-     * even if it cannot be interpreted
-     * for one reason or another. */
-    if(fread(block->header_contents, block->header_contents_size, 1,
-        tng_data->input_file) == 0)
+    if(tng_file_input_numerical(tng_data, &block->id,
+                                sizeof(block->id),
+                                TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot read header. %s: %d\n", __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    /* The header contents size has already been read. Skip ahead. */
-    offset = sizeof(block->header_contents_size);
-
-
-    /* Copy the respective parameters from the header contents block */
-    memcpy(&block->block_contents_size, block->header_contents+offset,
-           sizeof(block->block_contents_size));
-    if(tng_data->input_endianness_swap_func_64)
+    if(fread(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->input_file) == 0)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &block->block_contents_size)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    offset += sizeof(block->block_contents_size);
+    tng_freadstr(tng_data, &block->name, TNG_SKIP_HASH, 0, __LINE__);
 
-    memcpy(&block->id, block->header_contents+offset, sizeof(block->id));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &block->block_version,
+                                sizeof(block->block_version),
+                                TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &block->id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
 
-    offset += sizeof(block->id);
-
-    memcpy(block->md5_hash, block->header_contents+offset, TNG_MD5_HASH_LEN);
-    offset += TNG_MD5_HASH_LEN;
+    fseeko(tng_data->input_file, start_pos + block->header_contents_size, SEEK_SET);
 
-    if(block->name && strcmp(block->name, block->header_contents+offset) != 0)
-    {
-        free(block->name);
-        block->name = 0;
-    }
-    len = tng_min_i((int)strlen(block->header_contents+offset) + 1, TNG_MAX_STR_LEN);
-    if(!block->name)
-    {
-        block->name = malloc(len);
-        if(!block->name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-                    __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-        strncpy(block->name, block->header_contents+offset, len);
-    }
-    offset += len;
+    return(TNG_SUCCESS);
+}
 
-    memcpy(&block->block_version, block->header_contents+offset,
-           sizeof(block->block_version));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &block->block_version)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-
-    return(TNG_SUCCESS);
-}
-
-/** Write a whole block, both header and contents, regardless of it type
+/**
+ * @brief Write a whole block, both header and contents, regardless of it type
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
@@ -1054,7 +1184,8 @@ static tng_function_status tng_block_header_read
 // }
 */
 
-/** Update the md5 hash of a block already written to the file
+/**
+ * @brief 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.
@@ -1063,8 +1194,8 @@ static tng_function_status tng_block_header_read
  * @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,
+static tng_function_status tng_md5_hash_update(const tng_trajectory_t tng_data,
+                                               const tng_gen_block_t block,
                                                const int64_t header_start_pos,
                                                const int64_t contents_start_pos)
 {
@@ -1098,7 +1229,8 @@ static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
     return(TNG_SUCCESS);
 }
 
-/** Update the frame set pointers in the file header (general info block),
+/**
+ * @brief 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 hash_mode specifies whether to update the block md5 hash when
@@ -1107,7 +1239,7 @@ static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
  * error has occured.
  */
 static tng_function_status tng_header_pointers_update
-                (tng_trajectory_t tng_data, const char hash_mode)
+                (const tng_trajectory_t tng_data, const char hash_mode)
 {
     tng_gen_block_t block;
     FILE *temp = tng_data->input_file;
@@ -1139,7 +1271,7 @@ static tng_function_status tng_header_pointers_update
     contents_start_pos = ftello(tng_data->output_file);
 
     fseeko(tng_data->output_file, block->block_contents_size - 5 *
-          sizeof(int64_t), SEEK_CUR);
+           sizeof(int64_t), SEEK_CUR);
 
     tng_data->input_file = temp;
 
@@ -1194,7 +1326,8 @@ static tng_function_status tng_header_pointers_update
     return(TNG_SUCCESS);
 }
 
-/** Update the frame set pointers in the current frame set block, already
+/**
+ * @brief 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.
@@ -1204,7 +1337,7 @@ static tng_function_status tng_header_pointers_update
  * error has occured.
  */
 static tng_function_status tng_frame_set_pointers_update
-                (tng_trajectory_t tng_data, const char hash_mode)
+                (const tng_trajectory_t tng_data, const char hash_mode)
 {
     tng_gen_block_t block;
     tng_trajectory_frame_set_t frame_set;
@@ -1230,8 +1363,7 @@ static tng_function_status tng_frame_set_pointers_update
     /* Update next frame set */
     if(frame_set->next_frame_set_file_pos > 0)
     {
-        fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos,
-              SEEK_SET);
+        fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos, SEEK_SET);
 
         if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
@@ -1245,7 +1377,7 @@ static tng_function_status tng_frame_set_pointers_update
         contents_start_pos = ftello(tng_data->output_file);
 
         fseeko(tng_data->output_file, block->block_contents_size - (5 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
         if(tng_data->input_endianness_swap_func_64)
         {
@@ -1270,7 +1402,6 @@ static tng_function_status tng_frame_set_pointers_update
             tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
                                 contents_start_pos);
         }
-        fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
     }
     /* Update previous frame set */
     if(frame_set->prev_frame_set_file_pos > 0)
@@ -1290,7 +1421,7 @@ static tng_function_status tng_frame_set_pointers_update
         contents_start_pos = ftello(tng_data->output_file);
 
         fseeko(tng_data->output_file, block->block_contents_size - (6 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
         if(tng_data->input_endianness_swap_func_64)
         {
@@ -1315,15 +1446,14 @@ static tng_function_status tng_frame_set_pointers_update
             tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
                                 contents_start_pos);
         }
-        fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
     }
 
     /* Update the frame set one medium stride step after */
     if(frame_set->medium_stride_next_frame_set_file_pos > 0)
     {
         fseeko(tng_data->output_file,
-               frame_set->medium_stride_next_frame_set_file_pos,
-               SEEK_SET);
+              frame_set->medium_stride_next_frame_set_file_pos,
+              SEEK_SET);
 
         if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
         {
@@ -1337,7 +1467,7 @@ static tng_function_status tng_frame_set_pointers_update
         contents_start_pos = ftello(tng_data->output_file);
 
         fseeko(tng_data->output_file, block->block_contents_size - (3 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
         if(tng_data->input_endianness_swap_func_64)
         {
@@ -1383,7 +1513,7 @@ static tng_function_status tng_frame_set_pointers_update
         contents_start_pos = ftello(tng_data->output_file);
 
         fseeko(tng_data->output_file, block->block_contents_size - (4 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
         if(tng_data->input_endianness_swap_func_64)
         {
@@ -1476,7 +1606,7 @@ static tng_function_status tng_frame_set_pointers_update
         contents_start_pos = ftello(tng_data->output_file);
 
         fseeko(tng_data->output_file, block->block_contents_size - (2 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+               sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
 
         if(tng_data->input_endianness_swap_func_64)
         {
@@ -1514,7 +1644,7 @@ static tng_function_status tng_frame_set_pointers_update
 }
 
 static tng_function_status tng_reread_frame_set_at_file_pos
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t pos)
 {
     tng_gen_block_t block;
@@ -1548,7 +1678,7 @@ static tng_function_status tng_reread_frame_set_at_file_pos
 }
 
 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *pos)
 {
     int64_t orig_pos, curr_frame_set_pos;
@@ -1628,13 +1758,21 @@ static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
     return(TNG_SUCCESS);
 }
 
+/**
+ * @brief Migrate a whole frame set from one position in the file to another.
+ * @param tng_data is a trajectory data container.
+ * @param block_start_pos is the starting position in the file of the frame set.
+ * @param block_len is the length of the whole frame set (including all data blocks etc).
+ * @param new_pos is the new position in the file of the frame set.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ */
 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)
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_start_pos,
+                 const int64_t block_len,
+                 const int64_t new_pos,
+                 const char hash_mode)
 {
-    int64_t i;
     tng_bool updated = TNG_FALSE;
 
     char *contents;
@@ -1673,7 +1811,7 @@ static tng_function_status tng_frame_set_complete_migrate
 
     tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
 
-    tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
+    tng_frame_set_pointers_update(tng_data, hash_mode);
 
     /* Update the general info block if needed */
     if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
@@ -1688,14 +1826,11 @@ static tng_function_status tng_frame_set_complete_migrate
     }
     if(updated)
     {
-        tng_header_pointers_update(tng_data, TNG_USE_HASH);
+        tng_header_pointers_update(tng_data, hash_mode);
     }
 
     /* Fill the block with NULL to avoid confusion. */
-    for(i = 0; i < block_len; i++)
-    {
-        contents[i] = '\0';
-    }
+    memset(contents, '\0', block_len);
     fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
 
     /* FIXME: casting block_len to size_t is dangerous */
@@ -1707,7 +1842,7 @@ static tng_function_status tng_frame_set_complete_migrate
 }
 
 static tng_function_status tng_length_of_current_frame_set_contents_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *len)
 {
     int64_t orig_pos, pos, curr_frame_set_pos;
@@ -1759,38 +1894,37 @@ static tng_function_status tng_length_of_current_frame_set_contents_get
     return(TNG_SUCCESS);
 }
 
-/** Migrate blocks in the file to make room for new data in a block. This
+/**
+ * @brief 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.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
  * @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)
+                (const tng_trajectory_t tng_data,
+                 const int64_t start_pos,
+                 const int64_t offset,
+                 const char hash_mode)
 {
     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);
     }
 
@@ -1815,27 +1949,24 @@ static tng_function_status tng_migrate_data_in_file
             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);
+                                              frame_set_length, tng_data->input_file_len,
+                                              hash_mode);
         if(stat != TNG_SUCCESS)
         {
-            tng_data->input_file = temp;
             tng_block_destroy(&block);
             return(stat);
         }
@@ -1850,7 +1981,7 @@ static tng_function_status tng_migrate_data_in_file
 
 static tng_function_status tng_block_header_len_calculate
                 (const tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
+                 const tng_gen_block_t block,
                  int64_t *len)
 {
     int name_len;
@@ -1870,7 +2001,7 @@ static tng_function_status tng_block_header_len_calculate
         block->name[0] = 0;
     }
 
-    name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+    name_len = tng_min_size(strlen(block->name) + 1, TNG_MAX_STR_LEN);
 
     /* Calculate the size of the header to write */
     *len = sizeof(block->header_contents_size) +
@@ -1883,7 +2014,8 @@ static tng_function_status tng_block_header_len_calculate
     return (TNG_SUCCESS);
 }
 
-/** Write the header of a data block, regardless of its type
+/**
+ * @brief 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.
@@ -1892,12 +2024,9 @@ static tng_function_status tng_block_header_len_calculate
  * 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)
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block)
 {
-    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)
@@ -1915,106 +2044,57 @@ static tng_function_status tng_block_header_write
         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)
+    if(tng_file_output_numerical(tng_data, &block->header_contents_size,
+                                 sizeof(block->header_contents_size),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        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_file_output_numerical(tng_data, &block->block_contents_size,
+                                 sizeof(block->block_contents_size),
+                                 TNG_SKIP_HASH, 0, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    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_file_output_numerical(tng_data, &block->id,
+                                 sizeof(block->id),
+                                 TNG_SKIP_HASH, 0, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    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(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fprintf(stderr, "TNG library: Could not write header data. %s: %d\n", __FILE__, __LINE__);
+        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;
 
-    memcpy(block->header_contents+offset, &block->block_version,
-           sizeof(block->block_version));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_fwritestr(tng_data, block->name, TNG_SKIP_HASH, 0, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
 
-    if(fwrite(block->header_contents, block->header_contents_size,
-       1, tng_data->output_file) != 1)
+    if(tng_file_output_numerical(tng_data, &block->block_version,
+                                 sizeof(block->block_version),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        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,
+                (const 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;
+    size_t first_program_name_len, first_user_name_len;
+    size_t first_computer_name_len, first_pgp_signature_len;
+    size_t last_program_name_len, last_user_name_len;
+    size_t last_computer_name_len, last_pgp_signature_len;
+    size_t forcefield_name_len;
 
     /* If the strings are unallocated allocate memory for just string
      * termination */
@@ -2118,23 +2198,23 @@ static tng_function_status tng_general_info_block_len_calculate
         tng_data->forcefield_name[0] = 0;
     }
 
-    first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
+    first_program_name_len = tng_min_size(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,
+    last_program_name_len = tng_min_size(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,
+    first_user_name_len = tng_min_size(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,
+    last_user_name_len = tng_min_size(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,
+    first_computer_name_len = tng_min_size(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,
+    last_computer_name_len = tng_min_size(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,
+    first_pgp_signature_len = tng_min_size(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,
+    last_pgp_signature_len = tng_min_size(strlen(tng_data->last_pgp_signature) + 1,
                             TNG_MAX_STR_LEN);
-    forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
+    forcefield_name_len = tng_min_size(strlen(tng_data->forcefield_name) + 1,
                               TNG_MAX_STR_LEN);
 
     *len = sizeof(tng_data->time) +
@@ -2158,8 +2238,9 @@ static tng_function_status tng_general_info_block_len_calculate
     return(TNG_SUCCESS);
 }
 
-/** Read a general info block. This is the first block of a TNG file.
- *  Populate the fields in tng_data.
+/**
+ * @brief 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.
@@ -2169,13 +2250,13 @@ static tng_function_status tng_general_info_block_len_calculate
  * error has occured.
  */
 static tng_function_status tng_general_info_block_read
-                (tng_trajectory_t tng_data, tng_gen_block_t block,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
                  const char hash_mode)
 {
-    int len, offset = 0;
-    tng_bool same_hash;
-
-    void *temp;
+    int64_t start_pos;
+    char hash[TNG_MD5_HASH_LEN];
+    md5_state_t md5_state;
 
     TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
 
@@ -2184,315 +2265,156 @@ static tng_function_status tng_general_info_block_read
         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;
+    start_pos = ftello(tng_data->input_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)
+    if(hash_mode == TNG_USE_HASH)
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        md5_init(&md5_state);
     }
 
-    /* FIXME: Does not check if the size of the contents matches the expected
-     * size or if the contents can be read. */
+    tng_freadstr(tng_data, &tng_data->first_program_name, hash_mode, &md5_state, __LINE__);
 
-    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); */
-        }
-    }
+    tng_freadstr(tng_data, &tng_data->last_program_name, hash_mode, &md5_state, __LINE__);
 
-    len = tng_min_i((int)strlen(block->block_contents) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_program_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_program_name);
-        tng_data->first_program_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->first_program_name = temp;
-    strncpy(tng_data->first_program_name, block->block_contents, len);
-    offset += len;
+    tng_freadstr(tng_data, &tng_data->first_user_name, hash_mode, &md5_state, __LINE__);
 
-    len = tng_min_i((int)strlen(block->block_contents + offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_program_name, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_program_name);
-        tng_data->last_program_name = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->last_program_name = temp;
-    strncpy(tng_data->last_program_name, block->block_contents + offset, len);
-    offset += len;
+    tng_freadstr(tng_data, &tng_data->last_user_name, hash_mode, &md5_state, __LINE__);
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_user_name, len);
-    if(!temp)
+    tng_freadstr(tng_data, &tng_data->first_computer_name, hash_mode, &md5_state, __LINE__);
+
+    tng_freadstr(tng_data, &tng_data->last_computer_name, hash_mode, &md5_state, __LINE__);
+
+    tng_freadstr(tng_data, &tng_data->first_pgp_signature, hash_mode, &md5_state, __LINE__);
+
+    tng_freadstr(tng_data, &tng_data->last_pgp_signature, hash_mode, &md5_state, __LINE__);
+
+    tng_freadstr(tng_data, &tng_data->forcefield_name, hash_mode, &md5_state, __LINE__);
+
+    if(tng_file_input_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_user_name);
-        tng_data->first_user_name = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->first_user_name = temp;
-    strncpy(tng_data->first_user_name, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_user_name, len);
-    if(!temp)
+
+    if(tng_file_input_numerical(tng_data, &tng_data->var_num_atoms_flag,
+                                sizeof(tng_data->var_num_atoms_flag),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_user_name);
-        tng_data->last_user_name = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->last_user_name = temp;
-    strncpy(tng_data->last_user_name, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_computer_name, len);
-    if(!temp)
+    if(tng_file_input_numerical(tng_data, &tng_data->frame_set_n_frames,
+                                sizeof(tng_data->frame_set_n_frames),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_computer_name);
-        tng_data->first_computer_name = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->first_computer_name = temp;
-    strncpy(tng_data->first_computer_name, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_computer_name, len);
-    if(!temp)
+    if(tng_file_input_numerical(tng_data,
+                                &tng_data->first_trajectory_frame_set_input_file_pos,
+                                sizeof(tng_data->first_trajectory_frame_set_input_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_computer_name);
-        tng_data->last_computer_name = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->last_computer_name = temp;
-    strncpy(tng_data->last_computer_name, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->first_pgp_signature, len);
-    if(!temp)
+    tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
+    tng_data->first_trajectory_frame_set_input_file_pos;
+
+    if(tng_file_input_numerical(tng_data,
+                                &tng_data->last_trajectory_frame_set_input_file_pos,
+                                sizeof(tng_data->last_trajectory_frame_set_input_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->first_pgp_signature);
-        tng_data->first_pgp_signature = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->first_pgp_signature = temp;
-    strncpy(tng_data->first_pgp_signature, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->last_pgp_signature, len);
-    if(!temp)
+    if(tng_file_input_numerical(tng_data,
+                                &tng_data->medium_stride_length,
+                                sizeof(tng_data->medium_stride_length),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->last_pgp_signature);
-        tng_data->last_pgp_signature = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->last_pgp_signature = temp;
-    strncpy(tng_data->last_pgp_signature, block->block_contents+offset, len);
-    offset += len;
 
-    len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->forcefield_name, len);
-    if(!temp)
+    if(tng_file_input_numerical(tng_data,
+                                &tng_data->long_stride_length,
+                                sizeof(tng_data->long_stride_length),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->forcefield_name);
-        tng_data->forcefield_name = 0;
         return(TNG_CRITICAL);
     }
-    tng_data->forcefield_name = temp;
-    strncpy(tng_data->forcefield_name, block->block_contents+offset, len);
-    offset += len;
 
-    memcpy(&tng_data->time, block->block_contents+offset,
-           sizeof(tng_data->time));
-    if(tng_data->input_endianness_swap_func_64)
+    if(block->block_version >= 3)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &tng_data->time)
-            != TNG_SUCCESS)
+        if(tng_file_input_numerical(tng_data,
+                                    &tng_data->distance_unit_exponential,
+                                    sizeof(tng_data->distance_unit_exponential),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    offset += sizeof(tng_data->time);
-
-    memcpy(&tng_data->var_num_atoms_flag, block->block_contents+offset,
-           sizeof(tng_data->var_num_atoms_flag));
-    offset += sizeof(tng_data->var_num_atoms_flag);
 
-    memcpy(&tng_data->frame_set_n_frames, block->block_contents+offset,
-           sizeof(tng_data->frame_set_n_frames));
-    if(tng_data->input_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                 &tng_data->frame_set_n_frames)
-            != TNG_SUCCESS)
+        /* If there is data left in the block that the current version of the library
+         * cannot interpret still read that to generate the MD5 hash. */
+        tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
+
+        md5_finish(&md5_state, (md5_byte_t *)hash);
+        if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
+            {
+                fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
+                        "%s: %d\n", __FILE__, __LINE__);
+            }
         }
     }
-    offset += sizeof(tng_data->frame_set_n_frames);
-
-    memcpy(&tng_data->first_trajectory_frame_set_input_file_pos,
-           block->block_contents+offset,
-           sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    else
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                          &tng_data->first_trajectory_frame_set_input_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        /* Seek to the end of the block */
+        fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
     }
-    offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
 
-    tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
-    tng_data->first_trajectory_frame_set_input_file_pos;
+    return(TNG_SUCCESS);
+}
 
+/**
+ * @brief 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
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode)
+{
+    int64_t header_file_pos, curr_file_pos;
+    size_t name_len;
+    tng_gen_block_t block;
+    md5_state_t md5_state;
 
-    memcpy(&tng_data->last_trajectory_frame_set_input_file_pos,
-           block->block_contents+offset,
-           sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                          &tng_data->last_trajectory_frame_set_input_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
 
-    memcpy(&tng_data->medium_stride_length, block->block_contents+offset,
-           sizeof(tng_data->medium_stride_length));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                               &tng_data->medium_stride_length)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(tng_data->medium_stride_length);
-
-    memcpy(&tng_data->long_stride_length, block->block_contents+offset,
-           sizeof(tng_data->long_stride_length));
-    if(tng_data->input_endianness_swap_func_64)
-    {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &tng_data->long_stride_length)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    offset += sizeof(tng_data->long_stride_length);
-
-    if(block->block_version >= 3)
-    {
-        memcpy(&tng_data->distance_unit_exponential, block->block_contents+offset,
-            sizeof(tng_data->distance_unit_exponential));
-        if(tng_data->input_endianness_swap_func_64)
-        {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                          &tng_data->distance_unit_exponential)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-    }
-
-    return(TNG_SUCCESS);
-}
-
-/** Write a general info block. This is the first block of a TNG file.
- * @param tng_data is a trajectory data container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_general_info_block_write
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int first_program_name_len, first_user_name_len;
-    int first_computer_name_len, first_pgp_signature_len;
-    int last_program_name_len, last_user_name_len;
-    int last_computer_name_len, last_pgp_signature_len;
-    int forcefield_name_len, name_len;
-    int offset = 0;
-    tng_gen_block_t block;
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    fseeko(tng_data->output_file, 0, SEEK_SET);
+    fseeko(tng_data->output_file, 0, SEEK_SET);
 
     tng_block_init(&block);
 
-    name_len = (int)strlen("GENERAL INFO");
+    name_len = strlen("GENERAL INFO");
 
     block->name = malloc(name_len + 1);
     if(!block->name)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                name_len+1, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
+                (unsigned int)(name_len+1), __FILE__, __LINE__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
@@ -2509,486 +2431,350 @@ static tng_function_status tng_general_info_block_write
         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,
-                           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);
+    header_file_pos = 0;
 
-    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) != 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__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    strncpy(block->block_contents, tng_data->first_program_name, first_program_name_len);
-    offset += first_program_name_len;
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_init(&md5_state);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->last_program_name, last_program_name_len);
-    offset += last_program_name_len;
+    if(tng_fwritestr(tng_data, tng_data->first_program_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->first_user_name, first_user_name_len);
-    offset += first_user_name_len;
+    if(tng_fwritestr(tng_data, tng_data->last_program_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->last_user_name, last_user_name_len);
-    offset += last_user_name_len;
+    if(tng_fwritestr(tng_data, tng_data->first_user_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->first_computer_name,
-            first_computer_name_len);
-    offset += first_computer_name_len;
+    if(tng_fwritestr(tng_data, tng_data->last_user_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->last_computer_name,
-            last_computer_name_len);
-    offset += last_computer_name_len;
+    if(tng_fwritestr(tng_data, tng_data->first_computer_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->first_pgp_signature,
-            first_pgp_signature_len);
-    offset += first_pgp_signature_len;
+    if(tng_fwritestr(tng_data, tng_data->last_computer_name,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->last_pgp_signature,
-            last_pgp_signature_len);
-    offset += last_pgp_signature_len;
+    if(tng_fwritestr(tng_data, tng_data->first_pgp_signature,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    strncpy(block->block_contents+offset, tng_data->forcefield_name,
-            forcefield_name_len);
-    offset += forcefield_name_len;
+    if(tng_fwritestr(tng_data, tng_data->last_pgp_signature,
+                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    memcpy(block->block_contents+offset, &tng_data->time,
-           sizeof(tng_data->time));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_fwritestr(tng_data, tng_data->forcefield_name,
+                     hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->time);
 
-    memcpy(block->block_contents+offset, &tng_data->var_num_atoms_flag,
-           sizeof(tng_data->var_num_atoms_flag));
-    offset += sizeof(tng_data->var_num_atoms_flag);
 
-    memcpy(block->block_contents+offset, &tng_data->frame_set_n_frames,
-           sizeof(tng_data->frame_set_n_frames));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->frame_set_n_frames);
 
-    memcpy(block->block_contents+offset,
-           &tng_data->first_trajectory_frame_set_output_file_pos,
-           sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->var_num_atoms_flag,
+                                 sizeof(tng_data->var_num_atoms_flag),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &tng_data->last_trajectory_frame_set_output_file_pos,
-           sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->frame_set_n_frames,
+                                 sizeof(tng_data->frame_set_n_frames),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    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));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->first_trajectory_frame_set_output_file_pos,
+                                 sizeof(tng_data->first_trajectory_frame_set_output_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->medium_stride_length);
 
-    memcpy(block->block_contents+offset, &tng_data->long_stride_length,
-           sizeof(tng_data->long_stride_length));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->last_trajectory_frame_set_output_file_pos,
+                                 sizeof(tng_data->last_trajectory_frame_set_output_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->long_stride_length);
 
-    memcpy(block->block_contents+offset, &tng_data->distance_unit_exponential,
-           sizeof(tng_data->distance_unit_exponential));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &tng_data->medium_stride_length,
+                                 sizeof(tng_data->medium_stride_length),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    if(tng_file_output_numerical(tng_data, &tng_data->long_stride_length,
+                                 sizeof(tng_data->long_stride_length),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-        tng_data->output_file) != 1)
+    if(tng_file_output_numerical(tng_data, &tng_data->distance_unit_exponential,
+                                 sizeof(tng_data->distance_unit_exponential),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
+        curr_file_pos = ftello(tng_data->output_file);
+        fseeko(tng_data->output_file, header_file_pos +
+               3 * sizeof(int64_t), SEEK_SET);
+        if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
+    }
 
     tng_block_destroy(&block);
 
     return(TNG_SUCCESS);
 }
 
-/** Read the chain data of a molecules block.
+/**
+ * @brief Read the chain data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param chain is the chain data container.
- * @param offset is the offset of the block input and is updated when reading.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_chain_data_read(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               tng_chain_t chain,
-                                               int *offset)
+static tng_function_status tng_chain_data_read(const tng_trajectory_t tng_data,
+                                               const tng_chain_t chain,
+                                               const char hash_mode,
+                                               md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(&chain->id, block->block_contents+*offset,
-            sizeof(chain->id));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &chain->id,
+                                sizeof(chain->id),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &chain->id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(chain->id);
 
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    chain->name = malloc(len);
-    strncpy(chain->name,
-            block->block_contents+*offset, len);
-    *offset += len;
+    tng_freadstr(tng_data, &chain->name, hash_mode, md5_state, __LINE__);
 
-    memcpy(&chain->n_residues, block->block_contents+*offset,
-        sizeof(chain->n_residues));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &chain->n_residues,
+                                sizeof(chain->n_residues),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &chain->n_residues)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(chain->n_residues);
 
     return(TNG_SUCCESS);
 }
 
-/** Write the chain data of a molecules block.
+/**
+ * @brief Write the chain data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param chain is the chain data container.
- * @param offset is the offset of the block output and is updated when writing.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_chain_data_write(tng_trajectory_t tng_data,
-                                                tng_gen_block_t block,
-                                                tng_chain_t chain,
-                                                int *offset)
+static tng_function_status tng_chain_data_write(const tng_trajectory_t tng_data,
+                                                const tng_chain_t chain,
+                                                const char hash_mode,
+                                                md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(block->block_contents+*offset, &chain->id, sizeof(chain->id));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &chain->id,
+                                 sizeof(chain->id),
+                                 hash_mode, md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(chain->id);
 
-    len = tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, chain->name, len);
-    *offset += len;
+    if(tng_fwritestr(tng_data, chain->name, hash_mode,
+                     md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    memcpy(block->block_contents+*offset, &chain->n_residues,
-        sizeof(chain->n_residues));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &chain->n_residues,
+                                 sizeof(chain->n_residues),
+                                 hash_mode, md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(chain->n_residues);
 
     return(TNG_SUCCESS);
 }
 
-/** Read the residue data of a molecules block.
+/**
+ * @brief Read the residue data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param residue is the residue data container.
- * @param offset is the offset of the block input and is updated when reading.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_residue_data_read(tng_trajectory_t tng_data,
-                                                 tng_gen_block_t block,
-                                                 tng_residue_t residue,
-                                                 int *offset)
+static tng_function_status tng_residue_data_read(const tng_trajectory_t tng_data,
+                                                 const tng_residue_t residue,
+                                                 const char hash_mode,
+                                                 md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(&residue->id, block->block_contents+*offset,
-        sizeof(residue->id));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &residue->id,
+                                sizeof(residue->id),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &residue->id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(residue->id);
 
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    residue->name = malloc(len);
-    strncpy(residue->name,
-            block->block_contents+*offset, len);
-    *offset += len;
+    tng_freadstr(tng_data, &residue->name, hash_mode, md5_state, __LINE__);
 
-    memcpy(&residue->n_atoms, block->block_contents+*offset,
-            sizeof(residue->n_atoms));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &residue->n_atoms,
+                                sizeof(residue->n_atoms),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &residue->n_atoms)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(residue->n_atoms);
 
     return(TNG_SUCCESS);
 }
 
-/** Write the residue data of a molecules block.
+/**
+ * @brief Write the residue data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param residue is the residue data container.
- * @param offset is the offset of the block output and is updated when writing.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_residue_data_write(tng_trajectory_t tng_data,
-                                                  tng_gen_block_t block,
-                                                  tng_residue_t residue,
-                                                  int *offset)
+static tng_function_status tng_residue_data_write(const tng_trajectory_t tng_data,
+                                                  const tng_residue_t residue,
+                                                  const char hash_mode,
+                                                  md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(block->block_contents+*offset, &residue->id, sizeof(residue->id));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &residue->id,
+                                 sizeof(residue->id),
+                                 hash_mode, md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(residue->id);
 
-    len = tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, residue->name, len);
-    *offset += len;
+    if(tng_fwritestr(tng_data, residue->name, hash_mode,
+                     md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    memcpy(block->block_contents+*offset, &residue->n_atoms,
-        sizeof(residue->n_atoms));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &residue->n_atoms,
+                                 sizeof(residue->n_atoms),
+                                 hash_mode, md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(residue->n_atoms);
 
     return(TNG_SUCCESS);
 }
 
-/** Read the atom data of a molecules block.
+/**
+ * @brief Read the atom data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param atom is the atom data container.
- * @param offset is the offset of the block input and is updated when reading.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_atom_data_read(tng_trajectory_t tng_data,
-                                              tng_gen_block_t block,
-                                              tng_atom_t atom,
-                                              int *offset)
+static tng_function_status tng_atom_data_read(const tng_trajectory_t tng_data,
+                                              const tng_atom_t atom,
+                                              const char hash_mode,
+                                              md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(&atom->id, block->block_contents+*offset,
-        sizeof(atom->id));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &atom->id,
+                                sizeof(atom->id),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                    &atom->id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(atom->id);
 
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    atom->name = malloc(len);
-    strncpy(atom->name,
-            block->block_contents+*offset, len);
-    *offset += len;
+    tng_freadstr(tng_data, &atom->name, hash_mode, md5_state, __LINE__);
 
-    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-            TNG_MAX_STR_LEN);
-    atom->atom_type = malloc(len);
-    strncpy(atom->atom_type,
-            block->block_contents+*offset, len);
-    *offset += len;
+    tng_freadstr(tng_data, &atom->atom_type, hash_mode, md5_state, __LINE__);
 
     return(TNG_SUCCESS);
 }
 
-/** Write the atom data of a molecules block.
+/**
+ * @brief Write the atom data of a molecules block.
  * @param tng_data is a trajectory data container.
- * @param block is a general block container.
  * @param atom is the atom data container.
- * @param offset is the offset of the block output and is updated when writing.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @return TNG_SUCCESS(0) is successful.
  */
-static tng_function_status tng_atom_data_write(tng_trajectory_t tng_data,
-                                               tng_gen_block_t block,
-                                               tng_atom_t atom,
-                                               int *offset)
+static tng_function_status tng_atom_data_write(const tng_trajectory_t tng_data,
+                                               const tng_atom_t atom,
+                                               const char hash_mode,
+                                               md5_state_t *md5_state)
 {
-    int len;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-    memcpy(block->block_contents+*offset, &atom->id,
-            sizeof(atom->id));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &atom->id,
+                                 sizeof(atom->id),
+                                 hash_mode, md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    *offset += sizeof(atom->id);
 
-    len = tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, atom->name, len);
-    *offset += len;
+    if(tng_fwritestr(tng_data, atom->name, hash_mode,
+                     md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    len = tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
-    strncpy(block->block_contents + *offset, atom->atom_type, len);
-    *offset += len;
+    if(tng_fwritestr(tng_data, atom->atom_type, hash_mode,
+                     md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
     return(TNG_SUCCESS);
 }
@@ -3020,7 +2806,7 @@ static tng_function_status tng_molecules_block_len_calculate
             }
             molecule->name[0] = 0;
         }
-        *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
+        *len += tng_min_size(strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
 
         chain = molecule->chains;
         for(j = 0; j < molecule->n_chains; j++)
@@ -3038,7 +2824,7 @@ static tng_function_status tng_molecules_block_len_calculate
                 }
                 chain->name[0] = 0;
             }
-            *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
+            *len += tng_min_size(strlen(chain->name) + 1, TNG_MAX_STR_LEN);
 
             *len += sizeof(chain->n_residues);
 
@@ -3061,7 +2847,7 @@ static tng_function_status tng_molecules_block_len_calculate
                 }
                 residue->name[0] = 0;
             }
-            *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
+            *len += tng_min_size(strlen(residue->name) + 1, TNG_MAX_STR_LEN);
 
             *len += sizeof(residue->n_atoms);
 
@@ -3083,7 +2869,7 @@ static tng_function_status tng_molecules_block_len_calculate
                 }
                 atom->name[0] = 0;
             }
-            *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
+            *len += tng_min_size(strlen(atom->name) + 1, TNG_MAX_STR_LEN);
 
             if(!atom->atom_type)
             {
@@ -3096,7 +2882,7 @@ static tng_function_status tng_molecules_block_len_calculate
                 }
                 atom->atom_type[0] = 0;
             }
-            *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
+            *len += tng_min_size(strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
 
             atom++;
         }
@@ -3123,7 +2909,8 @@ static tng_function_status tng_molecules_block_len_calculate
     return(TNG_SUCCESS);
 }
 
-/** Read a molecules block. Contains chain, residue and atom data
+/**
+ * @brief Read a molecules block. Contains chain, residue and atom data
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
@@ -3133,59 +2920,29 @@ static tng_function_status tng_molecules_block_len_calculate
  * error has occured.
  */
 static tng_function_status tng_molecules_block_read
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
                  const char hash_mode)
 {
-    int64_t i, j, k, l;
-    int len, offset = 0;
+    int64_t start_pos, i, j, k, l;
     tng_molecule_t molecule;
     tng_chain_t chain;
     tng_residue_t residue;
     tng_atom_t atom;
     tng_bond_t bond;
-    tng_bool same_hash;
+    char hash[TNG_MD5_HASH_LEN];
+    md5_state_t md5_state;
 
     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)
-    {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-    }
+    start_pos = ftello(tng_data->input_file);
 
     /* 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: Molecules block contents corrupt. Hashes do not match. "
-                "%s: %d\n",
-                __FILE__, __LINE__);
-        }
-    }
-
     if(tng_data->molecules)
     {
         for(i=0; i<tng_data->n_molecules; i++)
@@ -3197,19 +2954,17 @@ static tng_function_status tng_molecules_block_read
         tng_data->n_molecules = 0;
     }
 
-    memcpy(&tng_data->n_molecules, block->block_contents,
-           sizeof(tng_data->n_molecules));
-    if(tng_data->input_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &tng_data->n_molecules)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        md5_init(&md5_state);
+    }
+
+    if(tng_file_input_numerical(tng_data, &tng_data->n_molecules,
+                                sizeof(tng_data->n_molecules),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->n_molecules);
 
     if(tng_data->molecules)
     {
@@ -3250,100 +3005,55 @@ static tng_function_status tng_molecules_block_read
     {
         molecule = &tng_data->molecules[i];
 
-        memcpy(&molecule->id, block->block_contents+offset,
-               sizeof(molecule->id));
-        if(tng_data->input_endianness_swap_func_64)
+        molecule->name = 0;
+
+        if(tng_file_input_numerical(tng_data, &molecule->id,
+                                    sizeof(molecule->id),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->id)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->id);
 
 /*         fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
-        len = tng_min_i((int)strlen(block->block_contents+offset) + 1, TNG_MAX_STR_LEN);
-        molecule->name = malloc(len);
-        strncpy(molecule->name, block->block_contents+offset, len);
-        offset += len;
+        tng_freadstr(tng_data, &molecule->name, hash_mode, &md5_state, __LINE__);
 
-        memcpy(&molecule->quaternary_str, block->block_contents+offset,
-               sizeof(molecule->quaternary_str));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &molecule->quaternary_str,
+                                    sizeof(molecule->quaternary_str),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                     &molecule->quaternary_str)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->quaternary_str);
 
         if(!tng_data->var_num_atoms_flag)
         {
-            memcpy(&tng_data->molecule_cnt_list[i],
-                   block->block_contents+offset,
-                   sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64)
+            if(tng_file_input_numerical(tng_data, &tng_data->molecule_cnt_list[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
             {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                               &tng_data->molecule_cnt_list[i])
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
         }
 
-
-        memcpy(&molecule->n_chains, block->block_contents+offset,
-               sizeof(molecule->n_chains));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &molecule->n_chains,
+                                    sizeof(molecule->n_chains),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_chains)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_chains);
 
-        memcpy(&molecule->n_residues, block->block_contents+offset,
-               sizeof(molecule->n_residues));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &molecule->n_residues,
+                                    sizeof(molecule->n_residues),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_residues)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_residues);
 
-        memcpy(&molecule->n_atoms, block->block_contents+offset,
-               sizeof(molecule->n_atoms));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &molecule->n_atoms,
+                                    sizeof(molecule->n_atoms),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_atoms)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_atoms);
 
         tng_data->n_particles += molecule->n_atoms *
                                  tng_data->molecule_cnt_list[i];
@@ -3420,17 +3130,28 @@ static tng_function_status tng_molecules_block_read
             {
                 chain->molecule = molecule;
 
-                tng_chain_data_read(tng_data, block, chain, &offset);
+                chain->name = 0;
 
-                chain->residues = molecule->residues;
-                residue = chain->residues;
+                tng_chain_data_read(tng_data, chain, hash_mode, &md5_state);
+
+                if(j==0)
+                {
+                    chain->residues = molecule->residues;
+                    residue = chain->residues;
+                }
+                else
+                {
+                    chain->residues = residue;
+                }
 
                 /* Read the residues of the chain */
                 for(k=0; k<chain->n_residues; k++)
                 {
                     residue->chain = chain;
 
-                    tng_residue_data_read(tng_data, block, residue, &offset);
+                    residue->name = 0;
+
+                    tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
 
                     residue->atoms_offset = atom - molecule->atoms;
                     /* Read the atoms of the residue */
@@ -3438,7 +3159,10 @@ static tng_function_status tng_molecules_block_read
                     {
                         atom->residue = residue;
 
-                        tng_atom_data_read(tng_data, block, atom, &offset);
+                        atom->name = 0;
+                        atom->atom_type = 0;
+
+                        tng_atom_data_read(tng_data,atom, hash_mode, &md5_state);
 
                         atom++;
                     }
@@ -3455,7 +3179,9 @@ static tng_function_status tng_molecules_block_read
                 {
                     residue->chain = 0;
 
-                    tng_residue_data_read(tng_data, block, residue, &offset);
+                    residue->name = 0;
+
+                    tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
 
                     residue->atoms_offset = atom - molecule->atoms;
                     /* Read the atoms of the residue */
@@ -3463,7 +3189,7 @@ static tng_function_status tng_molecules_block_read
                     {
                         atom->residue = residue;
 
-                        tng_atom_data_read(tng_data, block, atom, &offset);
+                        tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
 
                         atom++;
                     }
@@ -3476,26 +3202,22 @@ static tng_function_status tng_molecules_block_read
                 {
                     atom->residue = 0;
 
-                    tng_atom_data_read(tng_data, block, atom, &offset);
+                    atom->name = 0;
+                    atom->atom_type = 0;
+
+                    tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
 
                     atom++;
                 }
             }
         }
 
-        memcpy(&molecule->n_bonds, block->block_contents+offset,
-               sizeof(molecule->n_bonds));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &molecule->n_bonds,
+                                    sizeof(molecule->n_bonds),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       &molecule->n_bonds)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_bonds);
 
         if(molecule->n_bonds > 0)
         {
@@ -3528,33 +3250,19 @@ static tng_function_status tng_molecules_block_read
 
             for(j=0; j<molecule->n_bonds; j++)
             {
-                memcpy(&bond->from_atom_id, block->block_contents+offset,
-                    sizeof(bond->from_atom_id));
-                if(tng_data->input_endianness_swap_func_64)
+                if(tng_file_input_numerical(tng_data, &bond->from_atom_id,
+                                            sizeof(bond->from_atom_id),
+                                            hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
                 {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                               &bond->from_atom_id)
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
+                    return(TNG_CRITICAL);
                 }
-                offset += sizeof(bond->from_atom_id);
 
-                memcpy(&bond->to_atom_id, block->block_contents+offset,
-                    sizeof(bond->to_atom_id));
-                if(tng_data->input_endianness_swap_func_64)
+                if(tng_file_input_numerical(tng_data, &bond->to_atom_id,
+                                            sizeof(bond->to_atom_id),
+                                            hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
                 {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                               &bond->to_atom_id)
-                        != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
+                    return(TNG_CRITICAL);
                 }
-                offset += sizeof(bond->to_atom_id);
 
                 bond++;
             }
@@ -3565,10 +3273,34 @@ static tng_function_status tng_molecules_block_read
         }
     }
 
+    if(hash_mode == TNG_USE_HASH)
+    {
+        /* If there is data left in the block that the current version of the library
+         * cannot interpret still read that to generate the MD5 hash. */
+        tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
+
+        md5_finish(&md5_state, (md5_byte_t *)hash);
+        if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
+        {
+            if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
+            {
+                fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
+                        "%s: %d\n", __FILE__, __LINE__);
+            }
+        }
+    }
+
+    else
+    {
+        /* Seek to the end of the block */
+        fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
+    }
+
     return(TNG_SUCCESS);
 }
 
-/** Write a molecules block.
+/**
+ * @brief Write a molecules block.
  * @param tng_data is a trajectory data container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
  * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
@@ -3576,17 +3308,18 @@ static tng_function_status tng_molecules_block_read
  * error has occured.
  */
 static tng_function_status tng_molecules_block_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    int len = 0, name_len, offset = 0;
-    int64_t i, j, k, l;
+    int name_len;
+    int64_t i, j, k, l, header_file_pos, curr_file_pos;
     tng_molecule_t molecule;
     tng_chain_t chain;
     tng_residue_t residue;
     tng_atom_t atom;
     tng_bond_t bond;
     tng_gen_block_t block;
+    md5_state_t md5_state;
 
     if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
@@ -3595,7 +3328,7 @@ static tng_function_status tng_molecules_block_write
 
     tng_block_init(&block);
 
-    name_len = (int)strlen("MOLECULES");
+    name_len = (unsigned int)strlen("MOLECULES");
 
     block->name = malloc(name_len + 1);
     if(!block->name)
@@ -3618,140 +3351,98 @@ static tng_function_status tng_molecules_block_write
         return(TNG_CRITICAL);
     }
 
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    header_file_pos = ftello(tng_data->output_file);
+
+    if(tng_block_header_write(tng_data, block) != 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__);
         tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    memcpy(block->block_contents+offset, &tng_data->n_molecules,
-           sizeof(tng_data->n_molecules));
-    if(tng_data->output_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        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__);
-        }
+        md5_init(&md5_state);
+    }
+
+    if(tng_file_output_numerical(tng_data, &tng_data->n_molecules,
+                                 sizeof(tng_data->n_molecules),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(tng_data->n_molecules);
 
     for(i = 0; i < tng_data->n_molecules; i++)
     {
         molecule = &tng_data->molecules[i];
-        memcpy(block->block_contents+offset, &molecule->id,
-               sizeof(molecule->id));
-        if(tng_data->output_endianness_swap_func_64)
+
+        if(tng_file_output_numerical(tng_data, &molecule->id,
+                                    sizeof(molecule->id),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->id);
 
-/*         fprintf(stderr, "TNG library: Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); */
-        len = tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
-        strncpy(block->block_contents + offset, molecule->name, len);
-        offset += len;
+        if(tng_fwritestr(tng_data, molecule->name, hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+        {
+            return(TNG_CRITICAL);
+        }
 
-        memcpy(block->block_contents+offset, &molecule->quaternary_str,
-               sizeof(molecule->quaternary_str));
-        if(tng_data->output_endianness_swap_func_64)
+        if(tng_file_output_numerical(tng_data, &molecule->quaternary_str,
+                                    sizeof(molecule->quaternary_str),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->quaternary_str);
 
         if(!tng_data->var_num_atoms_flag)
         {
-            memcpy(block->block_contents+offset,
-                   &tng_data->molecule_cnt_list[i], sizeof(int64_t));
-            if(tng_data->output_endianness_swap_func_64)
+            if(tng_file_output_numerical(tng_data, &tng_data->molecule_cnt_list[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == 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__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
         }
 
-        memcpy(block->block_contents+offset, &molecule->n_chains,
-               sizeof(molecule->n_chains));
-        if(tng_data->output_endianness_swap_func_64)
+        if(tng_file_output_numerical(tng_data, &molecule->n_chains,
+                                    sizeof(molecule->n_chains),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_chains);
 
-        memcpy(block->block_contents+offset, &molecule->n_residues,
-               sizeof(molecule->n_residues));
-        if(tng_data->output_endianness_swap_func_64)
+        if(tng_file_output_numerical(tng_data, &molecule->n_residues,
+                                    sizeof(molecule->n_residues),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_residues);
 
-        memcpy(block->block_contents+offset, &molecule->n_atoms,
-               sizeof(molecule->n_atoms));
-        if(tng_data->output_endianness_swap_func_64)
+        if(tng_file_output_numerical(tng_data, &molecule->n_atoms,
+                                    sizeof(molecule->n_atoms),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_atoms);
 
         if(molecule->n_chains > 0)
         {
             chain = molecule->chains;
             for(j = 0; j < molecule->n_chains; j++)
             {
-                tng_chain_data_write(tng_data, block, chain, &offset);
+                tng_chain_data_write(tng_data, chain, hash_mode, &md5_state);
 
                 residue = chain->residues;
                 for(k = 0; k < chain->n_residues; k++)
                 {
-                    tng_residue_data_write(tng_data, block, residue, &offset);
+                    tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
 
                     atom = molecule->atoms + residue->atoms_offset;
                     for(l = 0; l < residue->n_atoms; l++)
                     {
-                        tng_atom_data_write(tng_data, block, atom, &offset);
+                        tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
 
                         atom++;
                     }
@@ -3767,12 +3458,12 @@ static tng_function_status tng_molecules_block_write
                 residue = molecule->residues;
                 for(k = 0; k < molecule->n_residues; k++)
                 {
-                    tng_residue_data_write(tng_data, block, residue, &offset);
+                    tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
 
                     atom = molecule->atoms + residue->atoms_offset;
                     for(l = 0; l < residue->n_atoms; l++)
                     {
-                        tng_atom_data_write(tng_data, block, atom, &offset);
+                        tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
 
                         atom++;
                     }
@@ -3784,77 +3475,53 @@ static tng_function_status tng_molecules_block_write
                 atom = molecule->atoms;
                 for(l = 0; l < molecule->n_atoms; l++)
                 {
-                    tng_atom_data_write(tng_data, block, atom, &offset);
+                    tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
 
                     atom++;
                 }
             }
         }
 
-        memcpy(block->block_contents+offset, &molecule->n_bonds,
-               sizeof(molecule->n_bonds));
-        if(tng_data->output_endianness_swap_func_64)
+        if(tng_file_output_numerical(tng_data, &molecule->n_bonds,
+                                    sizeof(molecule->n_bonds),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(molecule->n_bonds);
 
         bond = molecule->bonds;
         for(j = 0; j < molecule->n_bonds; j++)
         {
-            memcpy(block->block_contents+offset, &bond->from_atom_id,
-                   sizeof(bond->from_atom_id));
-            if(tng_data->output_endianness_swap_func_64)
+            if(tng_file_output_numerical(tng_data, &bond->from_atom_id,
+                                        sizeof(bond->from_atom_id),
+                                        hash_mode, &md5_state, __LINE__) == 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__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(bond->from_atom_id);
 
-            memcpy(block->block_contents+offset, &bond->to_atom_id,
-                   sizeof(bond->to_atom_id));
-            if(tng_data->output_endianness_swap_func_64)
+            if(tng_file_output_numerical(tng_data, &bond->to_atom_id,
+                                        sizeof(bond->to_atom_id),
+                                        hash_mode, &md5_state, __LINE__) == 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__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(bond->to_atom_id);
 
             bond++;
         }
     }
-
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    if(hash_mode == TNG_USE_HASH)
     {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
-    {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
-               __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
+        curr_file_pos = ftello(tng_data->output_file);
+        fseeko(tng_data->output_file, header_file_pos +
+               3 * sizeof(int64_t), SEEK_SET);
+        if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
     }
 
     tng_block_destroy(&block);
@@ -3876,7 +3543,8 @@ static tng_function_status tng_frame_set_block_len_calculate
     return(TNG_SUCCESS);
 }
 
-/** Read a frame set block. Update tng_data->current_trajectory_frame_set
+/**
+ * @brief 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.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
@@ -3890,99 +3558,45 @@ static tng_function_status tng_frame_set_block_read
                  tng_gen_block_t block,
                  const char hash_mode)
 {
-    int offset = 0;
-    int64_t file_pos, i, prev_n_particles;
-    tng_bool same_hash;
+    int64_t file_pos, start_pos, i, prev_n_particles;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
+    char hash[TNG_MD5_HASH_LEN];
+    md5_state_t md5_state;
 
     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)
-    {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    start_pos = ftello(tng_data->input_file);
 
     /* FIXME: Does not check if the size of the contents matches the expected
      * size or if the contents can be read. */
 
-    file_pos = (int64_t)ftello(tng_data->input_file) -
-               (block->block_contents_size + block->header_contents_size);
-
-    if(hash_mode == TNG_USE_HASH)
-    {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
-        {
-            fprintf(stderr, "TNG library: Frame set block contents corrupt. File pos %"PRId64" Hashes do not match. "
-                "%s: %d\n",
-                file_pos, __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
-        }
-    }
+    file_pos = start_pos - block->header_contents_size;
 
     tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
 
     tng_frame_set_particle_mapping_free(tng_data);
 
-    if(tng_data->first_trajectory_frame_set_input_file_pos <= 0)
-    {
-        tng_data->first_trajectory_frame_set_input_file_pos = file_pos;
-    }
-    /* FIXME: Should check the frame number instead of the file_pos, in case
-     * frame sets are not in order */
-    if(tng_data->last_trajectory_frame_set_input_file_pos < file_pos)
+    if(hash_mode == TNG_USE_HASH)
     {
-        tng_data->last_trajectory_frame_set_input_file_pos = file_pos;
+        md5_init(&md5_state);
     }
-
-    memcpy(&frame_set->first_frame, block->block_contents,
-           sizeof(frame_set->first_frame));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->first_frame,
+                                sizeof(frame_set->first_frame),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &frame_set->first_frame)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->first_frame);
 
-    memcpy(&frame_set->n_frames, block->block_contents + offset,
-           sizeof(frame_set->n_frames));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->n_frames,
+                                sizeof(frame_set->n_frames),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &frame_set->n_frames)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->n_frames);
 
     if(tng_data->var_num_atoms_flag)
     {
@@ -4005,20 +3619,13 @@ static tng_function_status tng_frame_set_block_read
         }
         for(i = 0; i < tng_data->n_molecules; i++)
         {
-            memcpy(&frame_set->molecule_cnt_list[i],
-                   block->block_contents + offset,
-                   sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64)
+            if(tng_file_input_numerical(tng_data, &frame_set->molecule_cnt_list[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
             {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                                              &frame_set->molecule_cnt_list[i])
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
+
             frame_set->n_particles += tng_data->molecules[i].n_atoms *
                                       frame_set->molecule_cnt_list[i];
         }
@@ -4028,125 +3635,62 @@ static tng_function_status tng_frame_set_block_read
         }
     }
 
-    memcpy(&frame_set->next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->next_frame_set_file_pos,
+                                sizeof(frame_set->next_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                           &frame_set->next_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-    memcpy(&frame_set->prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
+                                sizeof(frame_set->prev_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                           &frame_set->prev_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->prev_frame_set_file_pos);
 
-    memcpy(&frame_set->medium_stride_next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
+                                sizeof(frame_set->medium_stride_next_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                             &frame_set->medium_stride_next_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
 
-    memcpy(&frame_set->medium_stride_prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
+                                sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                             &frame_set->medium_stride_prev_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
 
-    memcpy(&frame_set->long_stride_next_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->long_stride_next_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
+                                sizeof(frame_set->long_stride_next_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                               &frame_set->long_stride_next_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
 
-    memcpy(&frame_set->long_stride_prev_frame_set_file_pos,
-           block->block_contents + offset,
-           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
+                                sizeof(frame_set->long_stride_prev_frame_set_file_pos),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                               &frame_set->long_stride_prev_frame_set_file_pos)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
 
     if(block->block_version >= 3)
     {
-        memcpy(&frame_set->first_frame_time,
-            block->block_contents + offset,
-            sizeof(frame_set->first_frame_time));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &frame_set->first_frame_time,
+                                    sizeof(frame_set->first_frame_time),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                (int64_t *)&frame_set->first_frame_time)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(frame_set->first_frame_time);
 
-        memcpy(&tng_data->time_per_frame,
-            block->block_contents + offset,
-            sizeof(tng_data->time_per_frame));
-        if(tng_data->input_endianness_swap_func_64)
+        if(tng_file_input_numerical(tng_data, &tng_data->time_per_frame,
+                                    sizeof(tng_data->time_per_frame),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                (int64_t *)&tng_data->time_per_frame)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            return(TNG_CRITICAL);
         }
     }
     else
@@ -4155,6 +3699,28 @@ static tng_function_status tng_frame_set_block_read
         tng_data->time_per_frame = -1;
     }
 
+    if(hash_mode == TNG_USE_HASH)
+    {
+        /* If there is data left in the block that the current version of the library
+         * cannot interpret still read that to generate the MD5 hash. */
+        tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
+
+        md5_finish(&md5_state, (md5_byte_t *)hash);
+        if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
+        {
+            if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
+            {
+                fprintf(stderr, "TNG library: Frame set block contents corrupt (first frame %"PRId64"). Hashes do not match. "
+                        "%s: %d\n", frame_set->first_frame, __FILE__, __LINE__);
+            }
+        }
+    }
+    else
+    {
+        /* Seek to the end of the block */
+        fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
+    }
+
     /* 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
@@ -4167,7 +3733,8 @@ static tng_function_status tng_frame_set_block_read
     return(TNG_SUCCESS);
 }
 
-/** Write tng_data->current_trajectory_frame_set to file
+/**
+ * @brief Write tng_data->current_trajectory_frame_set to file
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
@@ -4176,23 +3743,23 @@ static tng_function_status tng_frame_set_block_read
  * error has occured.
  */
 static tng_function_status tng_frame_set_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
                  const char hash_mode)
 {
     char *temp_name;
-    int64_t i;
-    int offset = 0;
+    int64_t i, header_file_pos, curr_file_pos;
     unsigned int name_len;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
+    md5_state_t md5_state;
 
     if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
         return(TNG_CRITICAL);
     }
 
-    name_len = (int)strlen("TRAJECTORY FRAME SET");
+    name_len = (unsigned int)strlen("TRAJECTORY FRAME SET");
 
     if(!block->name || strlen(block->name) < name_len)
     {
@@ -4218,197 +3785,114 @@ static tng_function_status tng_frame_set_block_write
         return(TNG_CRITICAL);
     }
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    header_file_pos = ftello(tng_data->output_file);
+
+    if(tng_block_header_write(tng_data, block) != 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);
     }
 
-    memcpy(block->block_contents, &frame_set->first_frame,
-           sizeof(frame_set->first_frame));
-    if(tng_data->output_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        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__);
-        }
+        md5_init(&md5_state);
+    }
+    if(tng_file_output_numerical(tng_data, &frame_set->first_frame,
+                                 sizeof(frame_set->first_frame),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->first_frame);
 
-    memcpy(block->block_contents+offset, &frame_set->n_frames,
-           sizeof(frame_set->n_frames));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->n_frames,
+                                 sizeof(frame_set->n_frames),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->n_frames);
 
     if(tng_data->var_num_atoms_flag)
     {
         for(i = 0; i < tng_data->n_molecules; i++)
         {
-            memcpy(block->block_contents+offset,
-                   &frame_set->molecule_cnt_list[i],
-                   sizeof(int64_t));
-            if(tng_data->output_endianness_swap_func_64)
+            if(tng_file_output_numerical(tng_data, &frame_set->molecule_cnt_list[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == 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__);
-                }
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
-        }
-    }
-
-
-    memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos,
-           sizeof(frame_set->next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-                                      (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
         }
     }
-    offset += sizeof(frame_set->next_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos,
-           sizeof(frame_set->prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->next_frame_set_file_pos,
+                                 sizeof(frame_set->next_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->prev_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->medium_stride_next_frame_set_file_pos,
-           sizeof(frame_set->medium_stride_next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
+                                 sizeof(frame_set->prev_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->medium_stride_next_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->medium_stride_prev_frame_set_file_pos,
-           sizeof(frame_set->medium_stride_prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
+                                 sizeof(frame_set->medium_stride_next_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->medium_stride_prev_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->long_stride_next_frame_set_file_pos,
-           sizeof(frame_set->long_stride_next_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
+                                 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->long_stride_next_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->long_stride_prev_frame_set_file_pos,
-           sizeof(frame_set->long_stride_prev_frame_set_file_pos));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
+                                 sizeof(frame_set->long_stride_next_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos);
 
-    memcpy(block->block_contents+offset,
-           &frame_set->first_frame_time,
-           sizeof(frame_set->first_frame_time));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
+                                 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(frame_set->first_frame_time);
 
-    memcpy(block->block_contents+offset,
-           &tng_data->time_per_frame,
-           sizeof(tng_data->time_per_frame));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &frame_set->first_frame_time,
+                                 sizeof(frame_set->first_frame_time),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
 
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+    if(tng_file_output_numerical(tng_data, &tng_data->time_per_frame,
+                                 sizeof(tng_data->time_per_frame),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        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)
+    if(hash_mode == TNG_USE_HASH)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
+        curr_file_pos = ftello(tng_data->output_file);
+        fseeko(tng_data->output_file, header_file_pos +
+               3 * sizeof(int64_t), SEEK_SET);
+        if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
     }
 
     return(TNG_SUCCESS);
@@ -4425,7 +3909,8 @@ static tng_function_status tng_trajectory_mapping_block_len_calculate
     return(TNG_SUCCESS);
 }
 
-/** Read an atom mappings block (translating between real atom indexes and how
+/**
+ * @brief Read an atom mappings block (translating between real atom indexes and how
  *  the atom info is written in this frame set).
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
@@ -4436,60 +3921,27 @@ static tng_function_status tng_trajectory_mapping_block_len_calculate
  * error has occured.
  */
 static tng_function_status tng_trajectory_mapping_block_read
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
                  const char hash_mode)
 {
-    int64_t i;
-    int offset = 0;
-    tng_bool same_hash;
+    int64_t start_pos, i;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
-
     tng_particle_mapping_t mapping, mappings;
+    char hash[TNG_MD5_HASH_LEN];
+    md5_state_t md5_state;
 
     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)
-    {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    start_pos = ftello(tng_data->input_file);
 
     /* 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: Particle mapping block contents corrupt. Hashes do not match. "
-                "%s: %d\n",
-                __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
-        }
-    }
-
     frame_set->n_mapping_blocks++;
     mappings = realloc(frame_set->mappings,
                        sizeof(struct tng_particle_mapping) *
@@ -4506,33 +3958,24 @@ static tng_function_status tng_trajectory_mapping_block_read
     mapping = &mappings[frame_set->n_mapping_blocks - 1];
 
 
-    memcpy(&mapping->num_first_particle, block->block_contents+offset,
-           sizeof(mapping->num_first_particle));
-    if(tng_data->input_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &mapping->num_first_particle)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        md5_init(&md5_state);
     }
-    offset += sizeof(mapping->num_first_particle);
 
-    memcpy(&mapping->n_particles, block->block_contents+offset,
-           sizeof(mapping->n_particles));
-    if(tng_data->input_endianness_swap_func_64)
+    if(tng_file_input_numerical(tng_data, &mapping->num_first_particle,
+                                sizeof(mapping->num_first_particle),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   &mapping->n_particles)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        return(TNG_CRITICAL);
+    }
+
+    if(tng_file_input_numerical(tng_data, &mapping->n_particles,
+                                sizeof(mapping->n_particles),
+                                hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(mapping->n_particles);
 
     mapping->real_particle_numbers = malloc(mapping->n_particles *
                                             sizeof(int64_t));
@@ -4549,31 +3992,56 @@ static tng_function_status tng_trajectory_mapping_block_read
     {
         for(i = 0; i < mapping->n_particles; i++)
         {
-            memcpy(&mapping->real_particle_numbers[i],
-                    block->block_contents + offset,
-                    sizeof(int64_t));
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                            &mapping->real_particle_numbers[i])
-                != TNG_SUCCESS)
+            if(tng_file_input_numerical(tng_data, &mapping->real_particle_numbers[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
         }
     }
     /* Otherwise the data can be read all at once */
     else
     {
-        memcpy(mapping->real_particle_numbers, block->block_contents + offset,
-               mapping->n_particles * sizeof(int64_t));
+        if(fread(mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t),
+                1, tng_data->input_file) == 0)
+        {
+            fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        if(hash_mode == TNG_USE_HASH)
+        {
+            md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t));
+        }
     }
 
+    if(hash_mode == TNG_USE_HASH)
+    {
+        /* If there is data left in the block that the current version of the library
+         * cannot interpret still read that to generate the MD5 hash. */
+        tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
+
+        md5_finish(&md5_state, (md5_byte_t *)hash);
+        if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
+        {
+            if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
+            {
+                fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
+                        "%s: %d\n", __FILE__, __LINE__);
+            }
+        }
+    }
+    else
+    {
+        /* Seek to the end of the block */
+        fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
+    }
 
     return(TNG_SUCCESS);
 }
 
-/** Write the atom mappings of the current trajectory frame set
+/**
+ * @brief Write the atom mappings of the current trajectory frame set
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
  * @param mapping_block_nr is the index of the mapping block to write.
@@ -4583,14 +4051,16 @@ static tng_function_status tng_trajectory_mapping_block_read
  * has occurred or TNG_CRITICAL (2) if a major error has occured.
  */
 static tng_function_status tng_trajectory_mapping_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 int mapping_block_nr,
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
+                 const int mapping_block_nr,
                  const char hash_mode)
 {
+    int64_t header_file_pos, curr_file_pos;
     char *temp_name;
-    int i, offset = 0;
+    int i;
     unsigned int name_len;
+    md5_state_t md5_state;
     tng_particle_mapping_t mapping =
     &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
 
@@ -4607,7 +4077,7 @@ static tng_function_status tng_trajectory_mapping_block_write
         return(TNG_CRITICAL);
     }
 
-    name_len = (int)strlen("PARTICLE MAPPING");
+    name_len = (unsigned int)strlen("PARTICLE MAPPING");
 
     if(!block->name || strlen(block->name) < name_len)
     {
@@ -4635,87 +4105,81 @@ static tng_function_status tng_trajectory_mapping_block_write
         return(TNG_CRITICAL);
     }
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    header_file_pos = ftello(tng_data->output_file);
+
+    if(tng_block_header_write(tng_data, block) != 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);
     }
 
-    memcpy(block->block_contents, &mapping->num_first_particle,
-           sizeof(mapping->num_first_particle));
-    if(tng_data->output_endianness_swap_func_64)
+    if(hash_mode == TNG_USE_HASH)
     {
-        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__);
-        }
+        md5_init(&md5_state);
+    }
+    if(tng_file_output_numerical(tng_data, &mapping->num_first_particle,
+                                 sizeof(mapping->num_first_particle),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(mapping->num_first_particle);
 
-    memcpy(block->block_contents+offset, &mapping->n_particles,
-           sizeof(mapping->n_particles));
-    if(tng_data->output_endianness_swap_func_64)
+    if(tng_file_output_numerical(tng_data, &mapping->n_particles,
+                                 sizeof(mapping->n_particles),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    offset += sizeof(mapping->n_particles);
 
     if(tng_data->output_endianness_swap_func_64)
     {
         for(i = 0; i < mapping->n_particles; i++)
         {
-            memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i],
-                sizeof(int64_t));
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                                        (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
+            if(tng_file_output_numerical(tng_data, &mapping->real_particle_numbers[i],
+                                        sizeof(int64_t),
+                                        hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                return(TNG_CRITICAL);
             }
-            offset += sizeof(int64_t);
         }
     }
     else
     {
-        memcpy(block->block_contents+offset, mapping->real_particle_numbers,
-               mapping->n_particles * sizeof(int64_t));
-    }
-
-
-    if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
-               tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        if(fwrite(mapping->real_particle_numbers,
+                  mapping->n_particles * sizeof(int64_t),
+                  1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        if(hash_mode == TNG_USE_HASH)
+        {
+            md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers,
+                       mapping->n_particles * sizeof(int64_t));
+        }
     }
 
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-              tng_data->output_file) != 1)
+    if(hash_mode == TNG_USE_HASH)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
+        curr_file_pos = ftello(tng_data->output_file);
+        fseeko(tng_data->output_file, header_file_pos +
+               3 * sizeof(int64_t), SEEK_SET);
+        if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
     }
 
     return(TNG_SUCCESS);
 }
 
-/** Prepare a block for storing particle data
+/**
+ * @brief Prepare a block for storing particle data
  * @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)
@@ -4723,24 +4187,24 @@ static tng_function_status tng_trajectory_mapping_block_write
  * error has occured.
  */
 static tng_function_status tng_particle_data_block_create
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char block_type_flag)
 {
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
 
-    tng_particle_data_t data;
+    tng_data_t data;
 
     if(block_type_flag == TNG_TRAJECTORY_BLOCK)
     {
         frame_set->n_particle_data_blocks++;
         data = realloc(frame_set->tr_particle_data,
-                    sizeof(struct tng_particle_data) *
+                    sizeof(struct tng_data) *
                     frame_set->n_particle_data_blocks);
         if(!data)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-                sizeof(struct tng_particle_data) *
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+                sizeof(struct tng_data) *
                 frame_set->n_particle_data_blocks,
                 __FILE__, __LINE__);
             free(frame_set->tr_particle_data);
@@ -4753,12 +4217,12 @@ static tng_function_status tng_particle_data_block_create
     {
         tng_data->n_particle_data_blocks++;
         data = realloc(tng_data->non_tr_particle_data,
-                        sizeof(struct tng_particle_data) *
+                        sizeof(struct tng_data) *
                         tng_data->n_particle_data_blocks);
         if(!data)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-                    sizeof(struct tng_particle_data) *
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+                    sizeof(struct tng_data) *
                     tng_data->n_particle_data_blocks,
                     __FILE__, __LINE__);
             free(tng_data->non_tr_particle_data);
@@ -4771,18 +4235,19 @@ static tng_function_status tng_particle_data_block_create
     return(TNG_SUCCESS);
 }
 
-static tng_function_status tng_compress(tng_trajectory_t tng_data,
-                                        tng_gen_block_t block,
+static tng_function_status tng_compress(const tng_trajectory_t tng_data,
+                                        const tng_gen_block_t block,
                                         const int64_t n_frames,
                                         const int64_t n_particles,
                                         const char type,
-                                        void *start_pos)
+                                        char **data,
+                                        int64_t *new_len)
 {
     int nalgo;
-    int new_len;
+    int compressed_len;
     int *alt_algo = 0;
-    char *dest, *temp, *temp_data_contents;
-    int64_t algo_find_n_frames, compressed_len, offset;
+    char *dest;
+    int64_t algo_find_n_frames = -1;
     float f_precision;
     double d_precision;
 
@@ -4809,17 +4274,6 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
     f_precision = 1/(float)tng_data->compression_precision;
     d_precision = 1/tng_data->compression_precision;
 
-    compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
-    temp_data_contents = malloc(compressed_len);
-    if(!temp_data_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                compressed_len, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    memcpy(temp_data_contents, (char *)start_pos, compressed_len);
-
     if(block->id == TNG_TRAJ_POSITIONS)
     {
         /* If there is only one frame in this frame set and there might be more
@@ -4828,28 +4282,61 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
         if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
         {
             nalgo = tng_compress_nalgo();
-            alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_pos);
+            alt_algo = malloc(nalgo * sizeof *tng_data->compress_algo_pos);
+
+            /* If we have already determined the initial coding and
+             * initial coding parameter do not determine them again. */
+            if(tng_data->compress_algo_pos)
+            {
+                alt_algo[0] = tng_data->compress_algo_pos[0];
+                alt_algo[1] = tng_data->compress_algo_pos[1];
+                alt_algo[2] = tng_data->compress_algo_pos[2];
+                alt_algo[3] = tng_data->compress_algo_pos[3];
+            }
+            else
+            {
+                alt_algo[0] = -1;
+                alt_algo[1] = -1;
+                alt_algo[2] = -1;
+                alt_algo[3] = -1;
+            }
+
+            /* If the initial coding and initial coding parameter are -1
+             * they will be determined in tng_compress_pos/_float/. */
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
-                                                        (int)n_frames,
-                                                        f_precision,
-                                                        0, alt_algo,
-                                                        &new_len);
+                dest = tng_compress_pos_float((float *)*data, (int)n_particles,
+                                              (int)n_frames,
+                                              f_precision,
+                                              0, alt_algo,
+                                              &compressed_len);
 
             }
             else
             {
-                dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
-                                           (int)n_frames,
-                                           d_precision,
-                                           0, alt_algo,
-                                           &new_len);
+                dest = tng_compress_pos((double *)*data, (int)n_particles,
+                                        (int)n_frames,
+                                        d_precision,
+                                        0, alt_algo,
+                                        &compressed_len);
+            }
+            /* If there had been no algorithm determined before keep the initial coding
+             * and initial coding parameter so that they won't have to be determined again. */
+            if(!tng_data->compress_algo_pos)
+            {
+                nalgo = tng_compress_nalgo();
+                tng_data->compress_algo_pos=malloc(nalgo *
+                                                   sizeof *tng_data->compress_algo_pos);
+                tng_data->compress_algo_pos[0] = alt_algo[0];
+                tng_data->compress_algo_pos[1] = alt_algo[1];
+                tng_data->compress_algo_pos[2] = -1;
+                tng_data->compress_algo_pos[3] = -1;
             }
         }
-        else if(!tng_data->compress_algo_pos)
+        else if(!tng_data->compress_algo_pos || tng_data->compress_algo_pos[2] == -1 ||
+                tng_data->compress_algo_pos[2] == -1)
         {
-            if(n_frames > 10)
+            if(n_frames > 6)
             {
                 algo_find_n_frames = 5;
             }
@@ -4858,43 +4345,54 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
                 algo_find_n_frames = n_frames;
             }
 
-            nalgo = tng_compress_nalgo();
-            tng_data->compress_algo_pos=malloc(nalgo *
-                                           sizeof *tng_data->compress_algo_pos);
+            /* If the algorithm parameters are -1 they will be determined during the
+             * compression. */
+            if(!tng_data->compress_algo_pos)
+            {
+                nalgo = tng_compress_nalgo();
+                tng_data->compress_algo_pos=malloc(nalgo *
+                                                   sizeof *tng_data->compress_algo_pos);
+                tng_data->compress_algo_pos[0] = -1;
+                tng_data->compress_algo_pos[1] = -1;
+                tng_data->compress_algo_pos[2] = -1;
+                tng_data->compress_algo_pos[3] = -1;
+            }
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_pos_float_find_algo((float *)temp_data_contents, (int)n_particles,
-                                                        (int)algo_find_n_frames,
-                                                        f_precision,
-                                                        0, tng_data->
-                                                        compress_algo_pos,
-                                                        &new_len);
+                dest = tng_compress_pos_float((float *)*data, (int)n_particles,
+                                              (int)algo_find_n_frames,
+                                              f_precision,
+                                              0, tng_data->
+                                              compress_algo_pos,
+                                              &compressed_len);
 
                 if(algo_find_n_frames < n_frames)
                 {
-                    dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
+                    free(dest);
+                    dest = tng_compress_pos_float((float *)*data, (int)n_particles,
                                                   (int)n_frames,
                                                   f_precision,
                                                   0, tng_data->compress_algo_pos,
-                                                  &new_len);
+                                                  &compressed_len);
                 }
             }
             else
             {
-                dest = tng_compress_pos_find_algo((double *)temp_data_contents, (int)n_particles,
-                                           (int)algo_find_n_frames,
-                                           d_precision,
-                                           0, tng_data->
-                                           compress_algo_pos,
-                                           &new_len);
+                dest = tng_compress_pos((double *)*data, (int)n_particles,
+                                        (int)algo_find_n_frames,
+                                        d_precision,
+                                        0, tng_data->
+                                        compress_algo_pos,
+                                        &compressed_len);
 
                 if(algo_find_n_frames < n_frames)
                 {
-                    dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
+                    free(dest);
+                    dest = tng_compress_pos((double *)*data, (int)n_particles,
                                             (int)n_frames,
                                             d_precision, 0,
                                             tng_data->compress_algo_pos,
-                                            &new_len);
+                                            &compressed_len);
                 }
             }
         }
@@ -4902,18 +4400,18 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
         {
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_pos_float((float *)temp_data_contents, (int)n_particles,
+                dest = tng_compress_pos_float((float *)*data, (int)n_particles,
                                               (int)n_frames,
                                               f_precision, 0,
-                                              tng_data->compress_algo_pos, &new_len);
+                                              tng_data->compress_algo_pos, &compressed_len);
             }
             else
             {
-                dest = tng_compress_pos((double *)temp_data_contents, (int)n_particles,
+                dest = tng_compress_pos((double *)*data, (int)n_particles,
                                         (int)n_frames,
                                         d_precision, 0,
                                         tng_data->compress_algo_pos,
-                                        &new_len);
+                                        &compressed_len);
             }
         }
     }
@@ -4926,27 +4424,60 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
         {
             nalgo = tng_compress_nalgo();
             alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_vel);
+
+            /* If we have already determined the initial coding and
+             * initial coding parameter do not determine them again. */
+            if(tng_data->compress_algo_vel)
+            {
+                alt_algo[0] = tng_data->compress_algo_vel[0];
+                alt_algo[1] = tng_data->compress_algo_vel[1];
+                alt_algo[2] = tng_data->compress_algo_vel[2];
+                alt_algo[3] = tng_data->compress_algo_vel[3];
+            }
+            else
+            {
+                alt_algo[0] = -1;
+                alt_algo[1] = -1;
+                alt_algo[2] = -1;
+                alt_algo[3] = -1;
+            }
+
+            /* If the initial coding and initial coding parameter are -1
+             * they will be determined in tng_compress_pos/_float/. */
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
-                                                        (int)n_frames,
-                                                        f_precision,
-                                                        0, alt_algo,
-                                                        &new_len);
+                dest = tng_compress_vel_float((float *)*data, (int)n_particles,
+                                              (int)n_frames,
+                                              f_precision,
+                                              0, alt_algo,
+                                              &compressed_len);
 
             }
             else
             {
-                dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
-                                                  (int)n_frames,
-                                                  d_precision,
-                                                  0, alt_algo,
-                                                  &new_len);
+                dest = tng_compress_vel((double *)*data, (int)n_particles,
+                                        (int)n_frames,
+                                        d_precision,
+                                        0, alt_algo,
+                                        &compressed_len);
+            }
+            /* If there had been no algorithm determined before keep the initial coding
+             * and initial coding parameter so that they won't have to be determined again. */
+            if(!tng_data->compress_algo_vel)
+            {
+                nalgo = tng_compress_nalgo();
+                tng_data->compress_algo_vel=malloc(nalgo *
+                                                   sizeof *tng_data->compress_algo_vel);
+                tng_data->compress_algo_vel[0] = alt_algo[0];
+                tng_data->compress_algo_vel[1] = alt_algo[1];
+                tng_data->compress_algo_vel[2] = -1;
+                tng_data->compress_algo_vel[3] = -1;
             }
         }
-        else if(!tng_data->compress_algo_vel)
+        else if(!tng_data->compress_algo_vel || tng_data->compress_algo_vel[2] == -1 ||
+                tng_data->compress_algo_vel[2] == -1)
         {
-            if(n_frames > 10)
+            if(n_frames > 6)
             {
                 algo_find_n_frames = 5;
             }
@@ -4955,42 +4486,52 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
                 algo_find_n_frames = n_frames;
             }
 
-            nalgo = tng_compress_nalgo();
-            tng_data->compress_algo_vel=malloc(nalgo *
-                                           sizeof *tng_data->compress_algo_vel);
-
+            /* If the algorithm parameters are -1 they will be determined during the
+             * compression. */
+            if(!tng_data->compress_algo_vel)
+            {
+                nalgo = tng_compress_nalgo();
+                tng_data->compress_algo_vel=malloc(nalgo *
+                                                   sizeof *tng_data->compress_algo_vel);
+                tng_data->compress_algo_vel[0] = -1;
+                tng_data->compress_algo_vel[1] = -1;
+                tng_data->compress_algo_vel[2] = -1;
+                tng_data->compress_algo_vel[3] = -1;
+            }
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_vel_float_find_algo((float *)temp_data_contents, (int)n_particles,
-                                                        (int)algo_find_n_frames,
-                                                        f_precision,
-                                                        0, tng_data->
-                                                        compress_algo_vel,
-                                                        &new_len);
+                dest = tng_compress_vel_float((float *)*data, (int)n_particles,
+                                              (int)algo_find_n_frames,
+                                              f_precision,
+                                              0, tng_data->
+                                              compress_algo_vel,
+                                              &compressed_len);
                 if(algo_find_n_frames < n_frames)
                 {
-                    dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
+                    free(dest);
+                    dest = tng_compress_vel_float((float *)*data, (int)n_particles,
                                                   (int)n_frames,
                                                   f_precision,
                                                   0, tng_data->compress_algo_vel,
-                                                  &new_len);
+                                                  &compressed_len);
                 }
             }
             else
             {
-                dest = tng_compress_vel_find_algo((double *)temp_data_contents, (int)n_particles,
-                                                  (int)algo_find_n_frames,
-                                                  d_precision,
-                                                  0, tng_data->
-                                                  compress_algo_vel,
-                                                  &new_len);
+                dest = tng_compress_vel((double *)*data, (int)n_particles,
+                                        (int)algo_find_n_frames,
+                                        d_precision,
+                                        0, tng_data->
+                                        compress_algo_vel,
+                                        &compressed_len);
                 if(algo_find_n_frames < n_frames)
                 {
-                    dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
+                    free(dest);
+                    dest = tng_compress_vel((double *)*data, (int)n_particles,
                                             (int)n_frames,
                                             d_precision,
                                             0, tng_data->compress_algo_vel,
-                                            &new_len);
+                                            &compressed_len);
                 }
             }
         }
@@ -4998,77 +4539,52 @@ static tng_function_status tng_compress(tng_trajectory_t tng_data,
         {
             if(type == TNG_FLOAT_DATA)
             {
-                dest = tng_compress_vel_float((float *)temp_data_contents, (int)n_particles,
+                dest = tng_compress_vel_float((float *)*data, (int)n_particles,
                                               (int)n_frames,
                                               f_precision,
                                               0, tng_data->
                                               compress_algo_vel,
-                                              &new_len);
+                                              &compressed_len);
             }
             else
             {
-                dest = tng_compress_vel((double *)temp_data_contents, (int)n_particles,
+                dest = tng_compress_vel((double *)*data, (int)n_particles,
                                         (int)n_frames,
                                         d_precision,
                                         0, tng_data->
                                         compress_algo_vel,
-                                        &new_len);
+                                        &compressed_len);
             }
         }
     }
     else
     {
         fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
-        free(temp_data_contents);
         return(TNG_FAILURE);
     }
 
-    offset = (unsigned long)((char *)start_pos - block->block_contents);
-
     if(alt_algo)
     {
         free(alt_algo);
     }
 
-    block->block_contents_size = new_len + offset;
+    free(*data);
 
-    free(temp_data_contents);
+    *data = (char *)dest;
 
-    temp = realloc(block->block_contents, block->block_contents_size);
-    if(!temp)
-    {
-        free(block->block_contents);
-        block->block_contents = 0;
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-    block->block_contents = temp;
-    if(dest)
-    {
-        memcpy(temp + offset, dest, new_len);
-        free(dest);
-    }
-    else
-    {
-        fprintf(stderr, "TNG library: Error during TNG compression. %s: %d\n", __FILE__, __LINE__);
-        return(TNG_FAILURE);
-    }
+    *new_len = compressed_len;
 
     return(TNG_SUCCESS);
 }
 
-static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
-                                          tng_gen_block_t block,
+static tng_function_status tng_uncompress(const tng_trajectory_t tng_data,
+                                          const tng_gen_block_t block,
                                           const char type,
-                                          void *start_pos,
+                                          char **data,
                                           const int64_t uncompressed_len)
 {
-    char *temp, *temp_data_contents;
-    int64_t compressed_len;
     double *d_dest = 0;
     float *f_dest = 0;
-    int64_t offset;
     int result;
     (void)tng_data;
 
@@ -5087,17 +4603,6 @@ static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
         return(TNG_FAILURE);
     }
 
-    compressed_len = block->block_contents_size - (int64_t)((char *)start_pos - (char *)block->block_contents);
-    temp_data_contents = malloc(compressed_len);
-    if(!temp_data_contents)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-                uncompressed_len, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    memcpy(temp_data_contents, (char *)start_pos, compressed_len);
-
     if(type == TNG_FLOAT_DATA)
     {
         f_dest = malloc(uncompressed_len);
@@ -5105,10 +4610,13 @@ static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                 uncompressed_len, __FILE__, __LINE__);
-            free(temp_data_contents);
             return(TNG_CRITICAL);
         }
-        result = tng_compress_uncompress_float(temp_data_contents, f_dest);
+        result = tng_compress_uncompress_float(*data, f_dest);
+
+        free(*data);
+
+        *data = (char *)f_dest;
     }
     else
     {
@@ -5117,73 +4625,31 @@ static tng_function_status tng_uncompress(tng_trajectory_t tng_data,
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                 uncompressed_len, __FILE__, __LINE__);
-            free(temp_data_contents);
             return(TNG_CRITICAL);
         }
-        result = tng_compress_uncompress(temp_data_contents, d_dest);
+        result = tng_compress_uncompress(*data, d_dest);
+
+        free(*data);
+
+        *data = (char *)d_dest;
     }
 
     if(result == 1)
     {
         fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
-        free(temp_data_contents);
         return(TNG_FAILURE);
     }
 
-    offset = (unsigned long)((char *)start_pos - (char *)block->block_contents);
-
-    block->block_contents_size = (int64_t)(uncompressed_len + offset);
-
-    temp = realloc(block->block_contents, uncompressed_len + offset);
-    if(!temp)
-    {
-        free(block->block_contents);
-        block->block_contents = 0;
-        if(d_dest)
-        {
-            free(d_dest);
-        }
-        if(f_dest)
-        {
-            free(f_dest);
-        }
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        free(temp_data_contents);
-        return(TNG_CRITICAL);
-    }
-
-    if(type == TNG_FLOAT_DATA)
-    {
-        memcpy(temp + offset, f_dest, uncompressed_len);
-    }
-    else
-    {
-        memcpy(temp + offset, d_dest, uncompressed_len);
-    }
-
-    block->block_contents = temp;
-
-    free(temp_data_contents);
-    if(d_dest)
-    {
-        free(d_dest);
-    }
-    if(f_dest)
-    {
-        free(f_dest);
-    }
     return(TNG_SUCCESS);
 }
 
 #ifdef USE_ZLIB
-static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
-                                             tng_gen_block_t block,
-                                             void *start_pos, const int len)
+static tng_function_status tng_gzip_compress(const tng_trajectory_t tng_data,
+                                             char **data, const int64_t len,
+                                             int64_t *new_len)
 {
     Bytef *dest;
-    char *temp;
-    unsigned long max_len, stat, offset;
+    uLongf stat, max_len;
     (void)tng_data;
 
     max_len = compressBound(len);
@@ -5195,7 +4661,7 @@ static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
         return(TNG_CRITICAL);
     }
 
-    stat = compress(dest, &max_len, start_pos, len);
+    stat = compress(dest, &max_len, (Bytef *)*data, len);
     if(stat != (unsigned long)Z_OK)
     {
         free(dest);
@@ -5211,53 +4677,35 @@ static tng_function_status tng_gzip_compress(tng_trajectory_t tng_data,
         return(TNG_FAILURE);
     }
 
-    offset = (char *)start_pos - block->block_contents;
-
-    block->block_contents_size = max_len + offset;
-
-    temp = realloc(block->block_contents, block->block_contents_size);
-    if(!temp)
-    {
-        free(block->block_contents);
-        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;
+    *new_len = max_len;
 
-    memcpy(temp + offset, dest, max_len);
+    free(*data);
 
-    free(dest);
+    *data = (char *)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)
+static tng_function_status tng_gzip_uncompress(const tng_trajectory_t tng_data,
+                                               char **data,
+                                               const int64_t compressed_len,
+                                               const int64_t uncompressed_len)
 {
     Bytef *dest;
-    char *temp;
     unsigned long stat;
-    int offset;
     (void)tng_data;
-
-    offset = (char *)start_pos - (char *)block->block_contents;
+    uLongf new_len = uncompressed_len;
 
     dest = malloc(uncompressed_len);
     if(!dest)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
                uncompressed_len, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
-                      block->block_contents_size - offset);
+    stat = uncompress(dest, &new_len, (Bytef *) *data,
+                      compressed_len);
 
     if(stat != Z_OK)
     {
@@ -5279,30 +4727,16 @@ static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
         return(TNG_FAILURE);
     }
 
+    free(*data);
 
-    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;
+    *data = (char *)dest;
 
-    free(dest);
     return(TNG_SUCCESS);
 }
 #endif
 
-/** Allocate memory for storing particle data.
+/**
+ * @brief 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
@@ -5315,10 +4749,10 @@ static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
  * error has occured.
  */
 static tng_function_status tng_allocate_particle_data_mem
-                (tng_trajectory_t tng_data,
-                 tng_particle_data_t data,
+                (const tng_trajectory_t tng_data,
+                 const tng_data_t data,
                  int64_t n_frames,
-                 int64_t stride_length,
+                 const int64_t stride_length,
                  const int64_t n_particles,
                  const int64_t n_values_per_frame)
 {
@@ -5422,9 +4856,9 @@ static tng_function_status tng_allocate_particle_data_mem
 }
 
 static tng_function_status tng_particle_data_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t id,
-                 tng_particle_data_t *data)
+                 tng_data_t *data)
 {
     int64_t block_index, i;
     tng_trajectory_frame_set_t frame_set = &tng_data->
@@ -5474,9 +4908,9 @@ static tng_function_status tng_particle_data_find
 }
 
 static tng_function_status tng_data_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t id,
-                 tng_non_particle_data_t *data)
+                 tng_data_t *data)
 {
     int64_t block_index, i;
     tng_trajectory_frame_set_t frame_set = &tng_data->
@@ -5539,14 +4973,13 @@ static tng_function_status tng_data_find
 
 static tng_function_status tng_data_block_len_calculate
                 (const tng_trajectory_t tng_data,
-                 const tng_particle_data_t data,
+                 const tng_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)
 {
@@ -5594,7 +5027,7 @@ static tng_function_status tng_data_block_len_calculate
         *len += sizeof(data->compression_multiplier);
     }
 
-    if(dependency & TNG_FRAME_DEPENDENT)
+    if(data->dependency & TNG_FRAME_DEPENDENT)
     {
         *len += sizeof(char);
     }
@@ -5623,7 +5056,7 @@ static tng_function_status tng_data_block_len_calculate
         {
             for(i = 0; i < n_frames; i++)
             {
-                second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
+                second_dim_values = data->strings[0][i];
                 for(j = 0; j < data->n_values_per_frame; j++)
                 {
                     *len += strlen(second_dim_values[j]) + 1;
@@ -5639,57 +5072,223 @@ static tng_function_status tng_data_block_len_calculate
     return(TNG_SUCCESS);
 }
 
-/** Read the values of a particle data block
+/* TEST: */
+/**
+ * @brief Create a non-particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block_type_flag specifies if this is a trajectory block or a
+ * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_create
+                (const tng_trajectory_t tng_data,
+                 const char block_type_flag)
+{
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+
+    tng_data_t data;
+
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    {
+        frame_set->n_data_blocks++;
+        data = realloc(frame_set->tr_data, sizeof(struct tng_data) *
+                       frame_set->n_data_blocks);
+        if(!data)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+                sizeof(struct tng_data) * frame_set->n_data_blocks,
+                __FILE__, __LINE__);
+            free(frame_set->tr_data);
+            frame_set->tr_data = 0;
+            return(TNG_CRITICAL);
+        }
+        frame_set->tr_data = data;
+    }
+    else
+    {
+        tng_data->n_data_blocks++;
+        data = realloc(tng_data->non_tr_data, sizeof(struct tng_data) *
+                        tng_data->n_data_blocks);
+        if(!data)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+                sizeof(struct tng_data) * tng_data->n_data_blocks,
+                __FILE__, __LINE__);
+            free(tng_data->non_tr_data);
+            tng_data->non_tr_data = 0;
+            return(TNG_CRITICAL);
+        }
+        tng_data->non_tr_data = data;
+    }
+
+    return(TNG_SUCCESS);
+}
+
+/* TEST: */
+/**
+ * @brief 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
+                (const tng_trajectory_t tng_data,
+                 const tng_data_t data,
+                 int64_t n_frames,
+                 const int64_t stride_length,
+                 const int64_t n_values_per_frame)
+{
+    void **values;
+    int64_t i, j, size, frame_alloc;
+    (void)tng_data;
+
+    if(n_values_per_frame == 0)
+    {
+        return(TNG_FAILURE);
+    }
+
+    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    {
+        for(i = 0; i < data->n_frames; i++)
+        {
+            for(j = 0; j < data->n_values_per_frame; j++)
+            {
+                if(data->strings[0][i][j])
+                {
+                    free(data->strings[0][i][j]);
+                    data->strings[0][i][j] = 0;
+                }
+            }
+            free(data->strings[0][i]);
+            data->strings[0][i] = 0;
+        }
+        free(data->strings[0]);
+        data->strings[0] = 0;
+        free(data->strings);
+    }
+    data->n_frames = n_frames;
+    data->stride_length = tng_max_i64(1, stride_length);
+    n_frames = tng_max_i64(1, n_frames);
+    data->n_values_per_frame = n_values_per_frame;
+    frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+
+    if(data->datatype == TNG_CHAR_DATA)
+    {
+        data->strings = malloc(sizeof(char ***));
+        data->strings[0] = malloc(sizeof(char **) * frame_alloc);
+        for(i = 0; i < frame_alloc; i++)
+        {
+            data->strings[0][i] = malloc(sizeof(char *) * n_values_per_frame);
+            if(!data->strings[0][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[0][i][j] = 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_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);
+}
+
+/**
+ * @brief Read the values of a 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 block_data_len is the length of the data contents of the block.
  * @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.
+ * block. Only used if reading particle dependent data.
  * @param n_particles is the number of particles in the data block. This should
- * be the same as in the corresponding particle mapping block.
+ * be the same as in the corresponding particle mapping block. Only used if
+ * reading particle dependent data.
  * @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 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.
+ * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
+ * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
+ * if hash_mode == TNG_USE_HASH.
  * @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)
+static tng_function_status tng_data_read(const tng_trajectory_t tng_data,
+                                         const tng_gen_block_t block,
+                                         const int64_t block_data_len,
+                                         const char datatype,
+                                         const int64_t num_first_particle,
+                                         const int64_t n_particles,
+                                         const int64_t first_frame_with_data,
+                                         const int64_t stride_length,
+                                         int64_t n_frames,
+                                         const int64_t n_values,
+                                         const int64_t codec_id,
+                                         const double multiplier,
+                                         const char hash_mode,
+                                         md5_state_t *md5_state)
 {
-    int64_t i, j, k, tot_n_particles, n_frames_div;
+    int64_t i, j, k, tot_n_particles, n_frames_div, offset;
+    int64_t full_data_len;
     int size, len;
-    int64_t data_size;
     char ***first_dim_values, **second_dim_values;
-    tng_particle_data_t data;
+    tng_data_t data;
     tng_trajectory_frame_set_t frame_set =
     &tng_data->current_trajectory_frame_set;
-    char block_type_flag;
+    char block_type_flag, *contents;
+    tng_bool is_particle_data;
+    tng_function_status stat;
 
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
 
     /* This must be caught early to avoid creating a data block if not necessary. */
 #ifndef USE_ZLIB
@@ -5717,42 +5316,90 @@ static tng_function_status tng_particle_data_read
         size = sizeof(double);
     }
 
+    if(n_particles > 0)
+    {
+        is_particle_data = TNG_TRUE;
+    }
+    else
+    {
+        if(codec_id == TNG_XTC_COMPRESSION || codec_id == TNG_TNG_COMPRESSION)
+        {
+            fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_FAILURE);
+        }
+        is_particle_data = TNG_FALSE;
+    }
+
+    if(is_particle_data == TNG_TRUE)
+    {
+        stat = tng_particle_data_find(tng_data, block->id, &data);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block->id, &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 the block does not exist, create it */
-    if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+    if(stat != TNG_SUCCESS)
     {
-        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
+        if(is_particle_data == TNG_TRUE)
         {
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
+            stat = tng_particle_data_block_create(tng_data, block_type_flag);
         }
         else
         {
-            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+            stat = tng_data_block_create(tng_data, block_type_flag);
         }
 
-        if(tng_particle_data_block_create(tng_data, block_type_flag) !=
-           TNG_SUCCESS)
+        if(stat != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+            fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
                    __FILE__, __LINE__);
             return(TNG_CRITICAL);
         }
-        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+
+        if(is_particle_data == TNG_TRUE)
         {
-            data = &frame_set->tr_particle_data[frame_set->
-                                                n_particle_data_blocks - 1];
+            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];
+            }
         }
         else
         {
-            data = &tng_data->non_tr_particle_data[tng_data->
-                                                   n_particle_data_blocks - 1];
+            if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+            {
+                data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+            }
+            else
+            {
+                data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
+            }
         }
+
         data->block_id = block->id;
 
         data->block_name = malloc(strlen(block->name) + 1);
         if(!data->block_name)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block->name)+1, __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
+                   (unsigned int)strlen(block->name)+1, __FILE__, __LINE__);
             return(TNG_CRITICAL);
         }
         strcpy(data->block_name, block->name);
@@ -5763,27 +5410,70 @@ static tng_function_status tng_particle_data_read
         /* FIXME: Memory leak from strings. */
         data->strings = 0;
         data->n_frames = 0;
+        data->dependency = 0;
+        if(is_particle_data == TNG_TRUE)
+        {
+            data->dependency += TNG_PARTICLE_DEPENDENT;
+        }
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+                              (n_frames > 1 ||
+                               frame_set->n_frames == n_frames ||
+                               stride_length > 1))
+        {
+            data->dependency += TNG_FRAME_DEPENDENT;
+        }
         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)
+    if(is_particle_data == TNG_TRUE)
     {
-        tot_n_particles = frame_set->n_particles;
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+           tng_data->var_num_atoms_flag)
+        {
+            tot_n_particles = frame_set->n_particles;
+        }
+        else
+        {
+            tot_n_particles = tng_data->n_particles;
+        }
     }
+    /* If there are no particles in this data block, still set tot_n_particles = 1
+     * to calculate block lengths etc properly. */
     else
     {
-        tot_n_particles = tng_data->n_particles;
+        tot_n_particles = 1;
     }
 
     n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
 
+    contents = malloc(block_data_len);
+    if(!contents)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                block_data_len, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(fread(contents, block_data_len, 1, tng_data->input_file) == 0)
+    {
+        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(hash_mode == TNG_USE_HASH)
+    {
+        md5_append(md5_state, (md5_byte_t *)contents, block_data_len);
+    }
+
     if(codec_id != TNG_UNCOMPRESSED)
     {
-        data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
+        full_data_len = n_frames_div * size * n_values;
+        if(is_particle_data == TNG_TRUE)
+        {
+            full_data_len *= n_particles;
+        }
         switch(codec_id)
         {
         case TNG_XTC_COMPRESSION:
@@ -5792,42 +5482,56 @@ static tng_function_status tng_particle_data_read
         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)
+                              &contents, full_data_len) != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
                        __FILE__, __LINE__);
+                free(contents);
                 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)
+    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+            if(tng_gzip_uncompress(tng_data, &contents,
+                                   block_data_len, full_data_len) != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
                     __LINE__);
+                free(contents);
                 return(TNG_CRITICAL);
             }
-/*            fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
+    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
             break;
 #endif
         }
     }
+    else
+    {
+        full_data_len = block_data_len;
+    }
+
     /* 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)
+        if(is_particle_data == TNG_TRUE)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
+                                                  stride_length,
+                                                  tot_n_particles, n_values);
+        }
+        else
+        {
+            stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
+                                         n_values);
+        }
+        if(stat != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
                    __FILE__, __LINE__);
+            free(contents);
             return(TNG_CRITICAL);
         }
     }
@@ -5836,47 +5540,83 @@ static tng_function_status tng_particle_data_read
 
     if(datatype == TNG_CHAR_DATA)
     {
-        for(i = 0; i < n_frames_div; i++)
+        offset = 0;
+        /* Strings are stores slightly differently if the data block contains particle
+         * data (frames * particles * n_values) or not (frames * n_values). */
+        if(is_particle_data == TNG_TRUE)
         {
-            first_dim_values = data->strings[i];
-            for(j = num_first_particle; j < num_first_particle + n_particles;
-                j++)
+            for(i = 0; i < n_frames_div; i++)
             {
-                second_dim_values = first_dim_values[j];
-                for(k = 0; k < n_values; k++)
+                first_dim_values = data->strings[i];
+                for(j = num_first_particle; j < num_first_particle + n_particles;
+                    j++)
                 {
-                    len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-                              TNG_MAX_STR_LEN);
-                    if(second_dim_values[k])
+                    second_dim_values = first_dim_values[j];
+                    for(k = 0; k < n_values; k++)
+                    {
+                        len = tng_min_size(strlen(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__);
+                            free(contents);
+                            return(TNG_CRITICAL);
+                        }
+                        strncpy(second_dim_values[k], contents+offset, len);
+                        offset += len;
+                    }
+                }
+            }
+        }
+        else
+        {
+            for(i = 0; i < n_frames_div; i++)
+            {
+                for(j = 0; j < n_values; j++)
+                {
+                    len = tng_min_size(strlen(contents+offset) + 1,
+                                     TNG_MAX_STR_LEN);
+                    if(data->strings[0][i][j])
                     {
-                        free(second_dim_values[k]);
+                        free(data->strings[0][i][j]);
                     }
-                    second_dim_values[k] = malloc(len);
-                    if(!second_dim_values[k])
+                    data->strings[0][i][j] = malloc(len);
+                    if(!data->strings[0][i][j])
                     {
                         fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                            len, __FILE__, __LINE__);
+                               len, __FILE__, __LINE__);
+                        free(contents);
                         return(TNG_CRITICAL);
                     }
-                    strncpy(second_dim_values[k],
-                            block->block_contents+*offset, len);
-                    *offset += len;
+                    strncpy(data->strings[0][i][j], contents+offset, len);
+                    offset += len;
                 }
             }
         }
     }
     else
     {
-        memcpy((char *)data->values + n_frames_div * size * n_values *
-               num_first_particle,
-               block->block_contents + *offset,
-               block->block_contents_size - *offset);
+        if(is_particle_data)
+        {
+            memcpy((char *)data->values + n_frames_div * size * n_values *
+                   num_first_particle, contents, full_data_len);
+        }
+        else
+        {
+            memcpy(data->values, contents, full_data_len);
+        }
         switch(datatype)
         {
         case TNG_FLOAT_DATA:
             if(tng_data->input_endianness_swap_func_32)
             {
-                for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+                for(i = 0; i < full_data_len; i+=size)
                 {
                     if(tng_data->input_endianness_swap_func_32(tng_data,
                         (int32_t *)((char *)data->values + i))
@@ -5892,7 +5632,7 @@ static tng_function_status tng_particle_data_read
         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 = 0; i < full_data_len; i+=size)
                 {
                     if(tng_data->input_endianness_swap_func_64(tng_data,
                         (int64_t *)((char *)data->values + i))
@@ -5908,42 +5648,47 @@ static tng_function_status tng_particle_data_read
             break;
         }
     }
+
+    free(contents);
+
     return(TNG_SUCCESS);
 }
 
-/** Write a particle data block
+/**
+ * @brief Write 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 and the block contents).
  * @param block_index is the index number of the data block in the frame set.
+ * @param is_particle_data is a flag to specify if the data to write is
+ * particle dependent or not.
  * @param mapping is the particle mapping that is relevant for the data block.
+ * Only relevant if writing particle dependent data.
  * @param hash_mode is an option to decide whether to use the md5 hash or not.
  * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_particle_data_block_write
-                (tng_trajectory_t tng_data,
-                 tng_gen_block_t block,
-                 const int64_t block_index,
-                 const tng_particle_mapping_t mapping,
-                 const char hash_mode)
+static tng_function_status tng_data_block_write(const tng_trajectory_t tng_data,
+                                                const tng_gen_block_t block,
+                                                const int64_t block_index,
+                                                const tng_bool is_particle_data,
+                                                const tng_particle_mapping_t mapping,
+                                                const char hash_mode)
 {
     int64_t n_particles, num_first_particle, n_frames, stride_length;
-    int64_t frame_step, data_start_pos;
-    int64_t i, j, k;
+    int64_t full_data_len, block_data_len, frame_step, data_start_pos;
+    int64_t i, j, k, curr_file_pos, header_file_pos;
     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;
+    size_t len;
     tng_function_status stat;
-
-    tng_particle_data_t data;
+    char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
+    double multiplier;
+    tng_trajectory_frame_set_t frame_set =
+    &tng_data->current_trajectory_frame_set;
+    tng_data_t data;
     char block_type_flag;
-
-    frame_set = &tng_data->current_trajectory_frame_set;
+    md5_state_t md5_state;
 
     /* If we have already started writing frame sets it is too late to write
      * non-trajectory data blocks */
@@ -5961,23 +5706,47 @@ static tng_function_status tng_particle_data_block_write
         return(TNG_CRITICAL);
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    if(is_particle_data == TNG_TRUE)
     {
-        data = &frame_set->tr_particle_data[block_index];
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+        {
+            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)
+            {
+                return(TNG_SUCCESS);
+            }
 
-        /* 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)
+            stride_length = tng_max_i64(1, data->stride_length);
+        }
+        else
         {
-            return(TNG_SUCCESS);
+            data = &tng_data->non_tr_particle_data[block_index];
+            stride_length = 1;
         }
-
-        stride_length = tng_max_i64(1, data->stride_length);
     }
     else
     {
-        data = &tng_data->non_tr_particle_data[block_index];
-        stride_length = 1;
+        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)
+            {
+                return(TNG_SUCCESS);
+            }
+
+            stride_length = tng_max_i64(1, data->stride_length);
+        }
+        else
+        {
+            data = &tng_data->non_tr_data[block_index];
+            stride_length = 1;
+        }
     }
 
     switch(data->datatype)
@@ -6003,7 +5772,7 @@ static tng_function_status tng_particle_data_block_write
         temp_name = realloc(block->name, len);
         if(!temp_name)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n", len,
+            fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n", len+1,
                    __FILE__, __LINE__);
             free(block->name);
             block->name = 0;
@@ -6045,63 +5814,81 @@ static tng_function_status tng_particle_data_block_write
         data->compression_multiplier = 1.0;
     }
 
-    if(mapping && mapping->n_particles != 0)
-    {
-        n_particles = mapping->n_particles;
-        num_first_particle = mapping->num_first_particle;
-    }
-    else
+    if(data->dependency & TNG_PARTICLE_DEPENDENT)
     {
-        num_first_particle = 0;
-        if(tng_data->var_num_atoms_flag)
+        if(mapping && mapping->n_particles != 0)
         {
-            n_particles = frame_set->n_particles;
+            n_particles = mapping->n_particles;
+            num_first_particle = mapping->num_first_particle;
         }
         else
         {
-            n_particles = tng_data->n_particles;
+            num_first_particle = 0;
+            if(tng_data->var_num_atoms_flag)
+            {
+                n_particles = frame_set->n_particles;
+            }
+            else
+            {
+                n_particles = tng_data->n_particles;
+            }
         }
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+    if(data->dependency & TNG_PARTICLE_DEPENDENT)
     {
-        dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
+        if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
+                                        frame_step, stride_length, num_first_particle,
+                                        n_particles, &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);
+        }
     }
     else
     {
-        dependency = TNG_PARTICLE_DEPENDENT;
+        if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
+                                        frame_step, stride_length, 0,
+                                        1, &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(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)
+    header_file_pos = ftello(tng_data->output_file);
+
+    if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
-                __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);
     }
 
-    if(block->block_contents)
+    if(hash_mode == TNG_USE_HASH)
     {
-        free(block->block_contents);
+        md5_init(&md5_state);
     }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+
+    if(tng_file_output_numerical(tng_data, &data->datatype,
+                                 sizeof(data->datatype),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
+    if(tng_file_output_numerical(tng_data, &data->dependency,
+                                 sizeof(data->dependency),
+                                 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        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(data->dependency & TNG_FRAME_DEPENDENT)
     {
         if(stride_length > 1)
         {
@@ -6111,53 +5898,36 @@ static tng_function_status tng_particle_data_block_write
         {
             temp = 0;
         }
-        memcpy(block->block_contents+offset, &temp, sizeof(char));
-        offset += sizeof(char);
+        if(tng_file_output_numerical(tng_data, &temp,
+                                    sizeof(temp),
+                                    hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+        {
+            return(TNG_CRITICAL);
+        }
     }
 
-    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_file_output_numerical(tng_data, &data->n_values_per_frame,
+                                 sizeof(data->n_values_per_frame),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        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_file_output_numerical(tng_data, &data->codec_id,
+                                 sizeof(data->codec_id),
+                                 hash_mode, &md5_state, __LINE__) == 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__);
-        }
+        return(TNG_CRITICAL);
     }
-    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)
+        if(tng_file_output_numerical(tng_data, &data->compression_multiplier,
+                                    sizeof(data->compression_multiplier),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        offset += sizeof(data->compression_multiplier);
     }
 
     if(data->n_frames > 0 && stride_length > 1)
@@ -6167,156 +5937,147 @@ static tng_function_status tng_particle_data_block_write
         {
             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_file_output_numerical(tng_data, &data->first_frame_with_data,
+                                    sizeof(data->first_frame_with_data),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            return(TNG_CRITICAL);
         }
-        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_file_output_numerical(tng_data, &stride_length,
+                                    sizeof(stride_length),
+                                    hash_mode, &md5_state, __LINE__) == 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__);
-            }
+            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(data->dependency & TNG_PARTICLE_DEPENDENT)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        if(tng_file_output_numerical(tng_data, &num_first_particle,
+                                     sizeof(num_first_particle),
+                                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
-    }
-    offset += sizeof(num_first_particle);
 
-    memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        if(tng_file_output_numerical(tng_data, &n_particles,
+                                     sizeof(n_particles),
+                                     hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    offset += sizeof(n_particles);
 
     if(data->datatype == TNG_CHAR_DATA)
     {
         if(data->strings)
         {
-            for(i = 0; i < frame_step; i++)
+            if(data->dependency & TNG_PARTICLE_DEPENDENT)
             {
-                first_dim_values = data->strings[i];
-                for(j = num_first_particle; j < num_first_particle + n_particles;
-                    j++)
+                for(i = 0; i < frame_step; i++)
                 {
-                    second_dim_values = first_dim_values[j];
-                    for(k = 0; 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++)
                     {
-                        len = (unsigned int)strlen(second_dim_values[k]) + 1;
-                        strncpy(block->block_contents+offset,
-                                second_dim_values[k], len);
-                        offset += len;
+                        second_dim_values = first_dim_values[j];
+                        for(k = 0; k < data->n_values_per_frame; k++)
+                        {
+                            if(tng_fwritestr(tng_data, second_dim_values[k],
+                                            hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
+                            {
+                                return(TNG_CRITICAL);
+                            }
+                        }
                     }
                 }
             }
-        }
-    }
-    else if(data->values)
-    {
-        memcpy(block->block_contents + offset, data->values,
-               block->block_contents_size - offset);
-
-        switch(data->datatype)
-        {
-        case TNG_FLOAT_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
+            else
             {
-                if(tng_data->input_endianness_swap_func_32)
+                for(i = 0; i < frame_step; i++)
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
+                    for(j = 0; j < data->n_values_per_frame; j++)
                     {
-                        if(tng_data->input_endianness_swap_func_32(tng_data,
-                           (int32_t *)(block->block_contents + i))
-                           != TNG_SUCCESS)
+                        if(tng_fwritestr(tng_data, data->strings[0][i][j],
+                                         hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
                         {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
+                            return(TNG_CRITICAL);
                         }
                     }
                 }
             }
-            else
+        }
+    }
+    else
+    {
+        if(data->dependency & TNG_PARTICLE_DEPENDENT)
+        {
+            full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
+        }
+        else
+        {
+            full_data_len = size * frame_step * data->n_values_per_frame;
+        }
+        contents = malloc(full_data_len);
+        if(!contents)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+                    full_data_len, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+
+        if(data->values)
+        {
+            memcpy(contents, data->values, full_data_len);
+            switch(data->datatype)
             {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_32)
+            case TNG_FLOAT_DATA:
+                if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+                   data->codec_id == TNG_TNG_COMPRESSION)
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
+                    if(tng_data->output_endianness_swap_func_32)
                     {
-                        *(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)
+                        for(i = 0; i < full_data_len; i+=size)
                         {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
+                            if(tng_data->output_endianness_swap_func_32(tng_data,
+                               (int32_t *)(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)
+                else
                 {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                       (int64_t *)(block->block_contents + i))
-                       != TNG_SUCCESS)
+                    multiplier = data->compression_multiplier;
+                    if(fabs(multiplier - 1.0) > 0.00001 ||
+                       tng_data->output_endianness_swap_func_32)
                     {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
+                        for(i = 0; full_data_len; i+=size)
+                        {
+                            *(float *)(contents + i) *= (float)multiplier;
+                            if(tng_data->output_endianness_swap_func_32 &&
+                            tng_data->output_endianness_swap_func_32(tng_data,
+                            (int32_t *)(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)
+                break;
+            case TNG_INT_DATA:
+                if(tng_data->output_endianness_swap_func_64)
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
+                    for(i = 0; i < full_data_len; i+=size)
                     {
-                        if(tng_data->input_endianness_swap_func_64(tng_data,
-                           (int64_t *)(block->block_contents + i))
+                        if(tng_data->output_endianness_swap_func_64(tng_data,
+                           (int64_t *)(contents + i))
                            != TNG_SUCCESS)
                         {
                             fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
@@ -6324,42 +6085,57 @@ static tng_function_status tng_particle_data_block_write
                         }
                     }
                 }
-            }
-            else
-            {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_64)
+                break;
+            case TNG_DOUBLE_DATA:
+                if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+                   data->codec_id == TNG_TNG_COMPRESSION)
                 {
-                    for(i = offset; i < block->block_contents_size; i+=size)
+                    if(tng_data->output_endianness_swap_func_64)
                     {
-                        *(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)
+                        for(i = 0; i < full_data_len; i+=size)
                         {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
+                            if(tng_data->output_endianness_swap_func_64(tng_data,
+                               (int64_t *)(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->output_endianness_swap_func_64)
+                    {
+                        for(i = 0; i < full_data_len; i+=size)
+                        {
+                            *(double *)(contents + i) *= multiplier;
+                            if(tng_data->output_endianness_swap_func_64 &&
+                            tng_data->output_endianness_swap_func_64(tng_data,
+                            (int64_t *)(contents + i))
+                            != TNG_SUCCESS)
+                            {
+                                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                        __FILE__, __LINE__);
+                            }
+                        }
+                    }
+                }
+                break;
+            case TNG_CHAR_DATA:
+                break;
             }
-            break;
-        case TNG_CHAR_DATA:
-            break;
         }
-    }
-    else
-    {
-        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
-    }
+        else
+        {
+            memset(contents, 0, full_data_len);
+        }
 
-    frame_set->n_written_frames += frame_set->n_unwritten_frames;
-    frame_set->n_unwritten_frames = 0;
+        block_data_len = full_data_len;
 
-    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
-    {
         switch(data->codec_id)
         {
         case TNG_XTC_COMPRESSION:
@@ -6369,7 +6145,7 @@ static tng_function_status tng_particle_data_block_write
         case TNG_TNG_COMPRESSION:
             stat = tng_compress(tng_data, block, frame_step,
                                 n_particles, data->datatype,
-                                block->block_contents + data_start_pos);
+                                &contents, &block_data_len);
             if(stat != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
@@ -6381,18 +6157,20 @@ static tng_function_status tng_particle_data_block_write
                 /* 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);
+                stat = tng_data_block_write(tng_data, block,
+                                            block_index, is_particle_data, mapping,
+                                            hash_mode);
+                free(contents);
                 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);
+    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+            stat = tng_gzip_compress(tng_data,
+                                     &contents,
+                                     full_data_len,
+                                     &block_data_len);
             if(stat != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
@@ -6401,1768 +6179,1475 @@ static tng_function_status tng_particle_data_block_write
                 {
                     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);*/
+    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
             break;
 #endif
         }
-    }
+        if(block_data_len != full_data_len)
+        {
+            block->block_contents_size -= full_data_len - block_data_len;
 
-    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);
+            curr_file_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, header_file_pos + sizeof(block->header_contents_size), SEEK_SET);
+
+            if(tng_file_output_numerical(tng_data, &block->block_contents_size,
+                                         sizeof(block->block_contents_size),
+                                         TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+            {
+                return(TNG_CRITICAL);
+            }
+            fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
+        }
+        if(fwrite(contents, block_data_len, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        if(hash_mode == TNG_USE_HASH)
+        {
+            md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
+        }
+
+        free(contents);
     }
 
-    if(fwrite(block->block_contents, block->block_contents_size, 1,
-        tng_data->output_file) != 1)
+    if(hash_mode == TNG_USE_HASH)
     {
-        fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
-                __LINE__);
-        return(TNG_CRITICAL);
+        md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
+        curr_file_pos = ftello(tng_data->output_file);
+        fseeko(tng_data->output_file, header_file_pos +
+                3 * sizeof(int64_t), SEEK_SET);
+        if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
+        {
+            fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
+                    __LINE__);
+            return(TNG_CRITICAL);
+        }
+        fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
     }
 
+    frame_set->n_written_frames += frame_set->n_unwritten_frames;
+    frame_set->n_unwritten_frames = 0;
+
     return(TNG_SUCCESS);
 }
 
-/* TEST: */
-/** Create a non-particle data block
+/**
+ * @brief Read the meta information of a data block (particle or non-particle data).
  * @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 datatype is set to the datatype of the data block.
+ * @param dependency is set to the dependency (particle and/or frame dependent)
+ * @param sparse_data is set to TRUE if data is not written every frame.
+ * @param n_values is set to the number of values per frame of the data.
+ * @param codec_id is set to the ID of the codec used to compress the data.
+ * @param first_frame_with_data is set to the first frame with data (only relevant if
+ * sparse_data == TRUE).
+ * @param stride_length is set to the writing interval of the data (1 if sparse_data
+ * == FALSE).
+ * @param num_first_particle is set to the number of the first particle with data written
+ * in this block.
+ * @param block_n_particles is set to the number of particles in this data block.
+ * @param multiplier is set to the compression multiplier.
+ * @param hash_mode specifies whether to check if the hash matches the contents or not.
+ * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
  * error has occured.
  */
-static tng_function_status tng_data_block_create
-                (tng_trajectory_t tng_data,
-                 const char block_type_flag)
+static tng_function_status tng_data_block_meta_information_read
+                (const tng_trajectory_t tng_data,
+                 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,
+                 const char hash_mode,
+                 md5_state_t *md5_state)
 {
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
-
-    tng_non_particle_data_t data;
+    if(tng_file_input_numerical(tng_data, datatype,
+                                sizeof(*datatype),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+    if(tng_file_input_numerical(tng_data, dependency,
+                                sizeof(*dependency),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        frame_set->n_data_blocks++;
-        data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
-                       frame_set->n_data_blocks);
-        if(!data)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-                sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
-                __FILE__, __LINE__);
-            free(frame_set->tr_data);
-            frame_set->tr_data = 0;
-            return(TNG_CRITICAL);
-        }
-        frame_set->tr_data = data;
+        return(TNG_CRITICAL);
     }
-    else
+
+    if(*dependency & TNG_FRAME_DEPENDENT)
     {
-        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)
+        if(tng_file_input_numerical(tng_data, sparse_data,
+                                    sizeof(*sparse_data),
+                                    hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-                sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
-                __FILE__, __LINE__);
-            free(tng_data->non_tr_data);
-            tng_data->non_tr_data = 0;
             return(TNG_CRITICAL);
         }
-        tng_data->non_tr_data = data;
     }
 
-    return(TNG_SUCCESS);
-}
-
-/* TEST: */
-/** Allocate memory for storing non-particle data.
- * The allocated block will be refered to by data->values.
- * @param tng_data is a trajectory data container.
- * @param data is the data struct, which will contain the allocated memory in
- * data->values.
- * @param n_frames is the number of frames of data to store.
- * @param n_values_per_frame is the number of data values per frame.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_allocate_data_mem
-                (tng_trajectory_t tng_data,
-                 tng_non_particle_data_t data,
-                 int64_t n_frames,
-                 int64_t stride_length,
-                 const int64_t n_values_per_frame)
-{
-    void **values;
-    int64_t i, j, size, frame_alloc;
-    (void)tng_data;
+    if(tng_file_input_numerical(tng_data, n_values,
+                                sizeof(*n_values),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
 
-    if(n_values_per_frame == 0)
+    if(tng_file_input_numerical(tng_data, codec_id,
+                                sizeof(*codec_id),
+                                hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
     {
-        return(TNG_FAILURE);
+        return(TNG_CRITICAL);
     }
 
-    if(data->strings && data->datatype == TNG_CHAR_DATA)
+    if(*codec_id != TNG_UNCOMPRESSED)
     {
-        for(i = 0; i < data->n_frames; i++)
+        if(tng_file_input_numerical(tng_data, multiplier,
+                                    sizeof(*multiplier),
+                                    hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
         {
-            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;
+            return(TNG_CRITICAL);
         }
-        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;
+    else
+    {
+        *multiplier = 1;
+    }
 
-    if(data->datatype == TNG_CHAR_DATA)
+    if(*dependency & TNG_FRAME_DEPENDENT)
     {
-        data->strings = malloc(sizeof(char **) * frame_alloc);
-        for(i = 0; i < frame_alloc; i++)
+        if(*sparse_data)
         {
-            data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
-            if(!data->strings[i])
+            if(tng_file_input_numerical(tng_data, first_frame_with_data,
+                                        sizeof(*first_frame_with_data),
+                                        hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
             {
-                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++)
+
+            if(tng_file_input_numerical(tng_data, stride_length,
+                                        sizeof(*stride_length),
+                                        hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
             {
-                data->strings[i][j] = 0;
+                return(TNG_CRITICAL);
             }
+
+            *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 = tng_data->current_trajectory_frame_set.first_frame;
+            *stride_length = 1;
+            *n_frames = tng_data->current_trajectory_frame_set.n_frames;
         }
     }
     else
     {
-        switch(data->datatype)
+        *first_frame_with_data = 0;
+        *stride_length = 1;
+        *n_frames = 1;
+    }
+
+    if (*dependency & TNG_PARTICLE_DEPENDENT)
+    {
+        if(tng_file_input_numerical(tng_data, num_first_particle,
+                                    sizeof(*num_first_particle),
+                                    hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
         {
-        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_CRITICAL);
         }
 
-        values = realloc(data->values,
-                         size * frame_alloc *
-                         n_values_per_frame);
-        if(!values)
+        if(tng_file_input_numerical(tng_data, block_n_particles,
+                                    sizeof(*block_n_particles),
+                                    hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
         {
-            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;
+    }
+    else
+    {
+        *num_first_particle = -1;
+        *block_n_particles = 0;
     }
 
     return(TNG_SUCCESS);
 }
 
-/** Read the values of a non-particle data block
+/**
+ * @brief 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 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.
+ * 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_read(tng_trajectory_t tng_data,
-                                         tng_gen_block_t block,
-                                         int *offset,
-                                         const char datatype,
-                                         const int64_t first_frame_with_data,
-                                         const int64_t stride_length,
-                                         int64_t n_frames,
-                                         const int64_t n_values,
-                                         const int64_t codec_id,
-                                         const double multiplier)
+static tng_function_status tng_data_block_contents_read
+                (const tng_trajectory_t tng_data,
+                 const tng_gen_block_t block,
+                 const char hash_mode)
 {
-    int64_t i, j, n_frames_div;
-    int size, len;
-#ifdef USE_ZLIB
-    int64_t data_size;
-#endif
-    tng_non_particle_data_t data;
-    tng_trajectory_frame_set_t frame_set =
-    &tng_data->current_trajectory_frame_set;
-    char block_type_flag;
-
-    TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
-
-/*     fprintf(stderr, "TNG library: %s\n", block->name);*/
+    int64_t start_pos, n_values, codec_id, n_frames, first_frame_with_data;
+    int64_t remaining_len, stride_length, block_n_particles, num_first_particle;
+    double multiplier;
+    char datatype, dependency, sparse_data;
+    tng_function_status stat = TNG_SUCCESS;
+    char hash[TNG_MD5_HASH_LEN];
+    md5_state_t md5_state;
 
-    /* This must be caught early to avoid creating a data block if not necessary. */
-#ifndef USE_ZLIB
-    if(codec_id == TNG_GZIP_COMPRESSION)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
-                __LINE__);
-        return(TNG_FAILURE);
+        return(TNG_CRITICAL);
     }
-#endif
 
-    switch(datatype)
+    start_pos = ftello(tng_data->input_file);
+
+    if(hash_mode == TNG_USE_HASH)
     {
-    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);
+        md5_init(&md5_state);
     }
 
-    /* If the block does not exist, create it */
-    if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
-    {
-        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
-        {
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
-        }
-        else
-        {
-            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
-        }
-
-        if(tng_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_data[frame_set->n_data_blocks - 1];
-        }
-        else
-        {
-            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
-        }
-        data->block_id = block->id;
-
-        data->block_name = malloc(strlen(block->name) + 1);
-        if(!data->block_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block->name)+1, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-        strcpy(data->block_name, block->name);
-
-        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;
+    /* FIXME: Does not check if the size of the contents matches the expected
+     * size or if the contents can be read. */
 
-    if(codec_id != TNG_UNCOMPRESSED)
+    if(tng_data_block_meta_information_read(tng_data,
+                                            &datatype,
+                                            &dependency, &sparse_data,
+                                            &n_values, &codec_id,
+                                            &first_frame_with_data,
+                                            &stride_length, &n_frames,
+                                            &num_first_particle,
+                                            &block_n_particles,
+                                            &multiplier,
+                                            hash_mode,
+                                            &md5_state) == TNG_CRITICAL)
     {
-        switch(codec_id)
-        {
-#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 read data block (%s) meta information. %s: %d\n",
+            block->name, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    /* Allocate memory */
-    if(!data->values || data->n_frames != n_frames ||
-       data->n_values_per_frame != n_values)
-    {
-        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
-                                 n_values) !=
-           TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
+    remaining_len = block->block_contents_size - (ftello(tng_data->input_file) - start_pos);
 
-    data->first_frame_with_data = first_frame_with_data;
+    stat = tng_data_read(tng_data, block,
+                         remaining_len,
+                         datatype,
+                         num_first_particle,
+                         block_n_particles,
+                         first_frame_with_data,
+                         stride_length,
+                         n_frames, n_values,
+                         codec_id, multiplier,
+                         hash_mode,
+                         &md5_state);
 
-    if(datatype == TNG_CHAR_DATA)
+    if(hash_mode == TNG_USE_HASH)
     {
-        for(i = 0; i < n_frames_div; i++)
+        /* If there is data left in the block that the current version of the library
+         * cannot interpret still read that to generate the MD5 hash. */
+        tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
+
+        md5_finish(&md5_state, (md5_byte_t *)hash);
+        if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
         {
-            for(j = 0; j < n_values; j++)
+            if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
             {
-                len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
-                              TNG_MAX_STR_LEN);
-                if(data->strings[i][j])
-                {
-                    free(data->strings[i][j]);
-                }
-                data->strings[i][j] = malloc(len);
-                if(!data->strings[i][j])
-                {
-                    fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                           len, __FILE__, __LINE__);
-                    return(TNG_CRITICAL);
-                }
-                strncpy(data->strings[i][j], block->block_contents+*offset,
-                        len);
-                *offset += len;
+                fprintf(stderr, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
+                        "%s: %d\n", block->name, __FILE__, __LINE__);
             }
         }
     }
     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 = 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)
-            {
-                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__);
-                    }
-                }
-            }
-            break;
-        case TNG_CHAR_DATA:
-            break;
-        }
+        /* Seek to the end of the block */
+        fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
     }
-    return(TNG_SUCCESS);
+
+    return(stat);
 }
 
-/** Write a non-particle data block
+/*
+// ** 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
+//  * be done e.g. if the last frame set in the file has fewer frames than
+//  * default or after compressing data blocks in a frame set.
+//  * @param tng_data is a trajectory data container.
+//  * @details the current_trajectory_frame_set is the one that will be modified.
+//  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
+//  * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
+//  * FIXME: This function is not finished!!!
+//  *
+// static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
+// {
+//     tng_gen_block_t block;
+//     tng_trajectory_frame_set_t frame_set;
+//     FILE *temp = tng_data->input_file;
+//     int64_t pos, contents_start_pos, output_file_len;
+//
+//     frame_set = &tng_data->current_trajectory_frame_set;
+//
+//     if(frame_set->n_written_frames == frame_set->n_frames)
+//     {
+//         return(TNG_SUCCESS);
+//     }
+//
+//     if(tng_data->current_trajectory_frame_set_output_file_pos !=
+//        tng_data->last_trajectory_frame_set_output_file_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 = ftello(tng_data->output_file);
+//
+//     tng_data->input_file = tng_data->output_file;
+//
+//     pos = tng_data->current_trajectory_frame_set_output_file_pos;
+//
+//     fseeko(tng_data->output_file, pos, SEEK_SET);
+//     if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+//     {
+//         fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+//             __FILE__, __LINE__);
+//         tng_data->input_file = temp;
+//         tng_block_destroy(&block);
+//         return(TNG_CRITICAL);
+//     }
+//
+//     contents_start_pos = ftello(tng_data->output_file);
+//
+//     fseeko(tng_data->output_file, 0, SEEK_END);
+//     output_file_len = ftello(tng_data->output_file);
+//     pos = contents_start_pos + block->block_contents_size;
+//     fseeko(tng_data->output_file, pos,
+//           SEEK_SET);
+//
+//     while(pos < output_file_len)
+//     {
+//         if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+//         {
+//             fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
+//                    __FILE__, __LINE__);
+//             tng_data->input_file = temp;
+//             tng_block_destroy(&block);
+//             return(TNG_CRITICAL);
+//         }
+//         pos += block->header_contents_size + block->block_contents_size;
+//         fseeko(tng_data->output_file, pos, SEEK_SET);
+//     }
+//
+//     return(TNG_SUCCESS);
+// }
+*/
+/**
+ * @brief Finish writing the current frame set. Update the number of frames
+ * and the hashes of the frame set and all its data blocks (if hash_mode
+ * == TNG_USE_HASH).
  * @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 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_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_frame_set_finalize
+                (const tng_trajectory_t tng_data,
+                 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_gen_block_t block;
+    tng_trajectory_frame_set_t frame_set;
+    FILE *temp = tng_data->input_file;
+    int64_t pos, curr_file_pos;
 
-    tng_non_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
+    if(frame_set->n_written_frames == frame_set->n_frames)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        return(TNG_SUCCESS);
     }
 
+    frame_set->n_written_frames = frame_set->n_frames;
+
     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(block_type_flag == TNG_TRAJECTORY_BLOCK)
-    {
-        data = &frame_set->tr_data[block_index];
+    tng_block_init(&block);
+/*     output_file_pos = ftello(tng_data->output_file); */
 
-        /* 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)
-        {
-            return(TNG_SUCCESS);
-        }
+    tng_data->input_file = tng_data->output_file;
 
-        stride_length = tng_max_i64(1, data->stride_length);
-    }
-    else
+    curr_file_pos = ftello(tng_data->output_file);
+
+    pos = tng_data->current_trajectory_frame_set_output_file_pos;
+
+    fseeko(tng_data->output_file, pos, SEEK_SET);
+
+    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
     {
-        data = &tng_data->non_tr_data[block_index];
-        stride_length = 1;
+        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);
     }
 
-    switch(data->datatype)
+//     contents_start_pos = ftello(tng_data->output_file);
+
+    fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
+    if(fwrite(&frame_set->n_frames, sizeof(frame_set->n_frames),
+              1, tng_data->output_file) != 1)
     {
-    case TNG_CHAR_DATA:
-        size = 1;
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int64_t);
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
+        tng_data->input_file = temp;
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
 
-    len = (unsigned int)strlen(data->block_name) + 1;
-
-    if(!block->name || strlen(block->name) < len)
+    if(hash_mode == TNG_USE_HASH)
     {
-        temp_name = realloc(block->name, len);
-        if(!temp_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n", len+1,
-                   __FILE__, __LINE__);
-            free(block->name);
-            block->name = 0;
-            return(TNG_CRITICAL);
-        }
-        block->name = temp_name;
+        tng_md5_hash_update(tng_data, block, pos,
+                            pos + block->header_contents_size);
     }
-    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);
+    fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
 
-    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);
+    tng_data->input_file = temp;
+    tng_block_destroy(&block);
+    return(TNG_SUCCESS);
+}
 
-        n_frames -= (data->first_frame_with_data - frame_set->first_frame);
-    }
+/*
+// ** Sets the name of a file contents block
+//  * @param tng_data is a trajectory data container.
+//  * @param block is the block, of which to change names.
+//  * @param new_name is the new name of the block.
+//  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+//  * error has occured.
+//
+// static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
+//                                               tng_gen_block_t block,
+//                                               const char *new_name)
+// {
+//     int len;
+//
+//     len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
+//
+//      * If the currently stored string length is not enough to store the new
+//      * string it is freed and reallocated. *
+//     if(block->name && strlen(block->name) < len)
+//     {
+//         free(block->name);
+//         block->name = 0;
+//     }
+//     if(!block->name)
+//     {
+//         block->name = malloc(len);
+//         if(!block->name)
+//         {
+//             fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+//                    __FILE__, __LINE__);
+//             return(TNG_CRITICAL);
+//         }
+//     }
+//
+//     strncpy(block->name, new_name, len);
+//
+//     return(TNG_SUCCESS);
+// }
+*/
 
-    frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
-                 n_frames / stride_length;
+tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
+                                         const tng_atom_t atom,
+                                         tng_residue_t *residue)
+{
+    (void) tng_data;
 
-    /* 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;
-    }
+    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
-    {
-        dependency = TNG_FRAME_DEPENDENT;
-    }
-    else
-    {
-        dependency = 0;
-    }
+    *residue = atom->residue;
 
-    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);
-    }
+    return(TNG_SUCCESS);
+}
 
-    if(block->block_contents)
-    {
-        free(block->block_contents);
-    }
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
+                                      const tng_atom_t atom,
+                                      char *name,
+                                      const int max_len)
+{
+    (void) tng_data;
+    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+
+    strncpy(name, atom->name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(atom->name) > (unsigned int)max_len - 1)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
+    return(TNG_SUCCESS);
+}
 
+tng_function_status tng_atom_name_set(const tng_trajectory_t tng_data,
+                                      const tng_atom_t atom,
+                                      const char *new_name)
+{
+    unsigned int len;
+    (void)tng_data;
 
-    memcpy(block->block_contents, &data->datatype, sizeof(char));
-    offset += sizeof(char);
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
 
-    memcpy(block->block_contents+offset, &dependency, sizeof(char));
-    offset += sizeof(char);
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    if(dependency & TNG_FRAME_DEPENDENT)
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(atom->name && strlen(atom->name) < len)
     {
-        if(stride_length > 1)
-        {
-            temp = 1;
-        }
-        else
-        {
-            temp = 0;
-        }
-        memcpy(block->block_contents+offset, &temp, sizeof(char));
-        offset += sizeof(char);
+        free(atom->name);
+        atom->name = 0;
     }
-
-    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(!atom->name)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-           (int64_t *)block->header_contents+offset)
-            != TNG_SUCCESS)
+        atom->name = malloc(len);
+        if(!atom->name)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __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)
+    strncpy(atom->name, new_name, len);
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
+                                      const tng_atom_t atom,
+                                      char *type,
+                                      const int max_len)
+{
+    (void) tng_data;
+    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
+
+    strncpy(type, atom->atom_type, max_len - 1);
+    type[max_len - 1] = 0;
+
+    if(strlen(atom->atom_type) > (unsigned int)max_len - 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__);
-        }
+        return(TNG_FAILURE);
     }
-    offset += sizeof(data->codec_id);
+    return(TNG_SUCCESS);
+}
 
-    if(data->codec_id != TNG_UNCOMPRESSED)
+tng_function_status tng_atom_type_set(const tng_trajectory_t tng_data,
+                                      const tng_atom_t atom,
+                                      const char *new_type)
+{
+    unsigned int len;
+    (void)tng_data;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
+
+    len = tng_min_size(strlen(new_type) + 1, TNG_MAX_STR_LEN);
+
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(atom->atom_type && strlen(atom->atom_type) < len)
     {
-        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);
+        free(atom->atom_type);
+        atom->atom_type = 0;
     }
-
-    if(data->n_frames > 0 && stride_length > 1)
+    if(!atom->atom_type)
     {
-        /* FIXME: first_frame_with_data is not reliably set */
-        if(data->first_frame_with_data == 0)
+        atom->atom_type = malloc(len);
+        if(!atom->atom_type)
         {
-            data->first_frame_with_data = frame_set->first_frame;
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
-        memcpy(block->block_contents+offset, &data->first_frame_with_data,
-               sizeof(data->first_frame_with_data));
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        offset += sizeof(data->first_frame_with_data);
-
-        memcpy(block->block_contents+offset, &stride_length,
-               sizeof(data->stride_length));
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-            (int64_t *)block->header_contents+offset)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        offset += sizeof(data->stride_length);
     }
 
-    if(data->datatype == TNG_CHAR_DATA)
-    {
-        if(data->strings)
-        {
-            for(i = 0; i < frame_step; i++)
-            {
-                for(j = 0; j < data->n_values_per_frame; j++)
-                {
-                    len = (unsigned int)strlen(data->strings[i][j]) + 1;
-                    strncpy(block->block_contents+offset, data->strings[i][j],
-                            len);
-                    offset += len;
-                }
-            }
-        }
-    }
-    else if(data->values)
+    strncpy(atom->atom_type, new_type, len);
+
+    return(TNG_SUCCESS);
+}
+
+/**
+ * @brief Initialise an atom struct
+ * @param atom is the atom to initialise.
+ * @return TNG_SUCCESS (0) if successful.
+ */
+static tng_function_status tng_atom_init(const tng_atom_t atom)
+{
+    atom->name = 0;
+    atom->atom_type = 0;
+
+    return(TNG_SUCCESS);
+}
+
+/**
+ * @brief Free the memory in an atom struct
+ * @param atom is the atom to destroy.
+ * @return TNG_SUCCESS (0) if successful.
+ */
+static tng_function_status tng_atom_destroy(const tng_atom_t atom)
+{
+    if(atom->name)
     {
-        memcpy(block->block_contents + offset, data->values,
-               block->block_contents_size - offset);
-        switch(data->datatype)
-        {
-        case TNG_FLOAT_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
-            {
-                if(tng_data->input_endianness_swap_func_32)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        if(tng_data->input_endianness_swap_func_32(tng_data,
-                           (int32_t *)(block->block_contents + i))
-                           != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_32)
-                {
-                    for(i = offset; block->block_contents_size; i+=size)
-                    {
-                        *(float *)(block->block_contents + i) *= (float)multiplier;
-                        if(tng_data->input_endianness_swap_func_32 &&
-                        tng_data->input_endianness_swap_func_32(tng_data,
-                        (int32_t *)(block->block_contents + i))
-                        != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            break;
-        case TNG_INT_DATA:
-            if(tng_data->input_endianness_swap_func_64)
-            {
-                for(i = offset; i < block->block_contents_size; i+=size)
-                {
-                    if(tng_data->input_endianness_swap_func_64(tng_data,
-                       (int64_t *)(block->block_contents + i))
-                       != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                __FILE__, __LINE__);
-                    }
-                }
-            }
-            break;
-        case TNG_DOUBLE_DATA:
-            if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
-               data->codec_id == TNG_TNG_COMPRESSION)
-            {
-                if(tng_data->input_endianness_swap_func_64)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        if(tng_data->input_endianness_swap_func_64(tng_data,
-                           (int64_t *)(block->block_contents + i))
-                           != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                multiplier = data->compression_multiplier;
-                if(fabs(multiplier - 1.0) > 0.00001 ||
-                   tng_data->input_endianness_swap_func_64)
-                {
-                    for(i = offset; i < block->block_contents_size; i+=size)
-                    {
-                        *(double *)(block->block_contents + i) *= multiplier;
-                        if(tng_data->input_endianness_swap_func_64 &&
-                        tng_data->input_endianness_swap_func_64(tng_data,
-                        (int64_t *)(block->block_contents + i))
-                        != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-                }
-            }
-            break;
-        case TNG_CHAR_DATA:
-            break;
-        }
+        free(atom->name);
+        atom->name = 0;
     }
-    else
+    if(atom->atom_type)
     {
-        memset(block->block_contents+offset, 0, block->block_contents_size - offset);
+        free(atom->atom_type);
+        atom->atom_type = 0;
     }
 
-    frame_set->n_written_frames += frame_set->n_unwritten_frames;
-    frame_set->n_unwritten_frames = 0;
+    return(TNG_SUCCESS);
+}
 
-    if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
-    {
-        switch(data->codec_id)
-        {
-#ifdef USE_ZLIB
-        case TNG_GZIP_COMPRESSION:
-    /*         fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
-            stat = tng_gzip_compress(tng_data, block,
-                                     block->block_contents + data_start_pos,
-                                     block->block_contents_size - data_start_pos);
-            if(stat != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
-                    __LINE__);
-                if(stat == TNG_CRITICAL)
-                {
-                    return(TNG_CRITICAL);
-                }
-                data->codec_id = TNG_UNCOMPRESSED;
-            }
-    /*         fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
-            break;
-#endif
-        }
-    }
+tng_function_status DECLSPECDLLEXPORT tng_version_major
+                (const tng_trajectory_t tng_data,
+                 int *version)
+{
+    (void)tng_data;
 
-    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);
-    }
+    *version = TNG_VERSION_MAJOR;
 
-    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);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_version_minor
+                (const tng_trajectory_t tng_data,
+                 int *version)
+{
+    (void)tng_data;
+
+    *version = TNG_VERSION_MINOR;
 
     return(TNG_SUCCESS);
 }
 
-/** 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)
+tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
+                (const tng_trajectory_t tng_data,
+                 int *patch_level)
 {
-    int meta_size;
-    char *contents;
+    (void)tng_data;
 
-    if(block->block_contents)
-    {
-        contents = block->block_contents;
-    }
-    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__);
-        }
+    *patch_level = TNG_VERSION_PATCHLEVEL;
 
-        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);
-        }
-    }
+    return(TNG_SUCCESS);
+}
 
-    memcpy(datatype, contents+*offset,
-           sizeof(*datatype));
-    *offset += sizeof(*datatype);
+tng_function_status DECLSPECDLLEXPORT tng_version
+                (const tng_trajectory_t tng_data,
+                 char *version,
+                 const int max_len)
+{
+    (void)tng_data;
+    TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
 
-    memcpy(dependency, contents+*offset,
-           sizeof(*dependency));
-    *offset += sizeof(*dependency);
+    TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
 
-    if(*dependency & TNG_FRAME_DEPENDENT)
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_molecule_add
+                (const tng_trajectory_t tng_data,
+                 const char *name,
+                 tng_molecule_t *molecule)
+{
+    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 molecule + 1 */
+    if(tng_data->n_molecules)
     {
-        memcpy(sparse_data, contents+*offset,
-               sizeof(*sparse_data));
-        *offset += sizeof(*sparse_data);
+        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
     }
-
-    memcpy(n_values, contents+*offset,
-        sizeof(*n_values));
-    if(tng_data->input_endianness_swap_func_64)
+    else
     {
-        if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                   n_values)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        id = 1;
     }
-    *offset += sizeof(*n_values);
 
-    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,
-                                                   codec_id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
-    }
-    *offset += sizeof(*codec_id);
+    return(tng_molecule_w_id_add(tng_data, name, id, molecule));
+}
 
-    if(*codec_id != TNG_UNCOMPRESSED)
-    {
-        memcpy(multiplier, contents+*offset,
-            sizeof(*multiplier));
-        if(tng_data->input_endianness_swap_func_64)
-        {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       (int64_t *) multiplier)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        *offset += sizeof(*multiplier);
-    }
-    else
+tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
+                (const tng_trajectory_t tng_data,
+                 const char *name,
+                 const int64_t id,
+                 tng_molecule_t *molecule)
+{
+    tng_molecule_t new_molecules;
+    int64_t *new_molecule_cnt_list;
+    tng_function_status stat = TNG_SUCCESS;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+
+    new_molecules = realloc(tng_data->molecules,
+                            sizeof(struct tng_molecule) *
+                            (tng_data->n_molecules + 1));
+
+    if(!new_molecules)
     {
-        *multiplier = 1;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
+               __FILE__, __LINE__);
+        free(tng_data->molecules);
+        tng_data->molecules = 0;
+        return(TNG_CRITICAL);
     }
 
-    if(*dependency & TNG_FRAME_DEPENDENT)
-    {
-        if(*sparse_data)
-        {
-            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);
+    new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
+                                    sizeof(int64_t) *
+                                    (tng_data->n_molecules + 1));
 
-            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
-        {
-            *first_frame_with_data = 0;
-            *stride_length = 1;
-            *n_frames = tng_data->current_trajectory_frame_set.n_frames;
-        }
-    }
-    else
+    if(!new_molecule_cnt_list)
     {
-        *first_frame_with_data = 0;
-        *stride_length = 1;
-        *n_frames = 1;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * (tng_data->n_molecules + 1),
+               __FILE__, __LINE__);
+        free(tng_data->molecule_cnt_list);
+        tng_data->molecule_cnt_list = 0;
+        free(new_molecules);
+        return(TNG_CRITICAL);
     }
 
-    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,
-                                                       num_first_particle)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        *offset += sizeof(*num_first_particle);
+    tng_data->molecules = new_molecules;
+    tng_data->molecule_cnt_list = new_molecule_cnt_list;
 
-        memcpy(block_n_particles, contents+*offset,
-            sizeof(*block_n_particles));
-        if(tng_data->input_endianness_swap_func_64)
-        {
-            if(tng_data->input_endianness_swap_func_64(tng_data,
-                                                       block_n_particles)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        *offset += sizeof(*block_n_particles);
-    }
+    *molecule = &new_molecules[tng_data->n_molecules];
 
-    if(!block->block_contents)
-    {
-        free(contents);
-    }
-    return(TNG_SUCCESS);
+    tng_molecule_init(tng_data, *molecule);
+    tng_molecule_name_set(tng_data, *molecule, name);
+
+    /* FIXME: Should this be a function argument instead? */
+    tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
+
+    (*molecule)->id = id;
+
+    tng_data->n_molecules++;
+
+    return(stat);
 }
 
-/** 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)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
+                (const tng_trajectory_t tng_data,
+                 tng_molecule_t *molecule_p)
 {
-    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;
+    int64_t *new_molecule_cnt_list, id;
+    tng_molecule_t new_molecules, molecule;
 
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    /* Set ID to the ID of the last molecule + 1 */
+    if(tng_data->n_molecules)
     {
-        return(TNG_CRITICAL);
+        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
     }
-
-    if(block->block_contents)
+    else
     {
-        free(block->block_contents);
+        id = 1;
     }
 
-    block->block_contents = malloc(block->block_contents_size);
-    if(!block->block_contents)
+    new_molecules = realloc(tng_data->molecules,
+                            sizeof(struct tng_molecule) *
+                            (tng_data->n_molecules + 1));
+
+    if(!new_molecules)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               block->block_contents_size, __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
+               __FILE__, __LINE__);
+        free(tng_data->molecules);
+        tng_data->molecules = 0;
         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)
+    new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
+                                    sizeof(int64_t) *
+                                    (tng_data->n_molecules + 1));
+
+    if(!new_molecule_cnt_list)
     {
-        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * (tng_data->n_molecules + 1),
+               __FILE__, __LINE__);
+        free(tng_data->molecule_cnt_list);
+        tng_data->molecule_cnt_list = 0;
+        free(new_molecules);
         return(TNG_CRITICAL);
     }
 
-    /* FIXME: Does not check if the size of the contents matches the expected
-     * size or if the contents can be read. */
+    molecule = *molecule_p;
 
-    if(hash_mode == TNG_USE_HASH)
-    {
-        tng_md5_hash_match_verify(block, &same_hash);
-        if(same_hash != TNG_TRUE)
-        {
-            fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
-                block->name, __FILE__, __LINE__);
-    /*         return(TNG_FAILURE); */
-        }
-    }
+    tng_data->molecules = new_molecules;
+    tng_data->molecule_cnt_list = new_molecule_cnt_list;
 
-    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);
-    }
+    new_molecules[tng_data->n_molecules] = *molecule;
 
-    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
+    tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
+
+    free(*molecule_p);
+
+    molecule = &new_molecules[tng_data->n_molecules];
+
+    *molecule_p = molecule;
+
+    molecule->id = id;
+
+    tng_data->n_molecules++;
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
+                                          const tng_molecule_t molecule,
+                                          char *name,
+                                          const int max_len)
+{
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+
+    strncpy(name, molecule->name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(molecule->name) > (unsigned int)max_len - 1)
     {
-        return(tng_data_read(tng_data, block,
-                             &offset, datatype,
-                             first_frame_with_data,
-                             stride_length,
-                             n_frames, n_values,
-                             codec_id, multiplier));
+        return(TNG_FAILURE);
     }
+    return(TNG_SUCCESS);
 }
 
-/*
-// ** 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
-//  * be done e.g. if the last frame set in the file has fewer frames than
-//  * default or after compressing data blocks in a frame set.
-//  * @param tng_data is a trajectory data container.
-//  * @details the current_trajectory_frame_set is the one that will be modified.
-//  * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
-//  * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
-//  * FIXME: This function is not finished!!!
-//  *
-// static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
-// {
-//     tng_gen_block_t block;
-//     tng_trajectory_frame_set_t frame_set;
-//     FILE *temp = tng_data->input_file;
-//     int64_t pos, contents_start_pos, output_file_len;
-//
-//     frame_set = &tng_data->current_trajectory_frame_set;
-//
-//     if(frame_set->n_written_frames == frame_set->n_frames)
-//     {
-//         return(TNG_SUCCESS);
-//     }
-//
-//     if(tng_data->current_trajectory_frame_set_output_file_pos !=
-//        tng_data->last_trajectory_frame_set_output_file_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 = ftello(tng_data->output_file);
-//
-//     tng_data->input_file = tng_data->output_file;
-//
-//     pos = tng_data->current_trajectory_frame_set_output_file_pos;
-//
-//     fseeko(tng_data->output_file, pos, SEEK_SET);
-//     if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
-//     {
-//         fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
-//             __FILE__, __LINE__);
-//         tng_data->input_file = temp;
-//         tng_block_destroy(&block);
-//         return(TNG_CRITICAL);
-//     }
-//
-//     contents_start_pos = ftello(tng_data->output_file);
-//
-//     fseeko(tng_data->output_file, 0, SEEK_END);
-//     output_file_len = ftello(tng_data->output_file);
-//     pos = contents_start_pos + block->block_contents_size;
-//     fseeko(tng_data->output_file, pos,
-//           SEEK_SET);
-//
-//     while(pos < output_file_len)
-//     {
-//         if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
-//         {
-//             fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
-//                    __FILE__, __LINE__);
-//             tng_data->input_file = temp;
-//             tng_block_destroy(&block);
-//             return(TNG_CRITICAL);
-//         }
-//         pos += block->header_contents_size + block->block_contents_size;
-//         fseeko(tng_data->output_file, pos, SEEK_SET);
-//     }
-//
-//     return(TNG_SUCCESS);
-// }
-*/
-/** Finish writing the current frame set. Update the number of frames
- * and the hashes of the frame set and all its data blocks (if hash_mode
- * == TNG_USE_HASH).
- * @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_finalize
-                (tng_trajectory_t tng_data, const char hash_mode)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const char *new_name)
 {
-    tng_gen_block_t block;
-    tng_trajectory_frame_set_t frame_set;
-    FILE *temp = tng_data->input_file;
-    int64_t pos, contents_start_pos, output_file_len;
+    unsigned int len;
+    (void)tng_data;
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
 
-    if(frame_set->n_written_frames == frame_set->n_frames)
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
+
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(molecule->name && strlen(molecule->name) < len)
     {
-        return(TNG_SUCCESS);
+        free(molecule->name);
+        molecule->name = 0;
     }
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    if(!molecule->name)
     {
-        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        molecule->name = malloc(len);
+        if(!molecule->name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
     }
 
-    tng_block_init(&block);
-/*     output_file_pos = ftello(tng_data->output_file); */
+    strncpy(molecule->name, new_name, len);
 
-    tng_data->input_file = tng_data->output_file;
+    return(TNG_SUCCESS);
+}
 
-    pos = tng_data->current_trajectory_frame_set_output_file_pos;
+tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 int64_t *cnt)
+{
+    int64_t i, index = -1;
 
-    fseeko(tng_data->output_file, pos, SEEK_SET);
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
 
-    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
-            __FILE__, __LINE__);
-        tng_data->input_file = temp;
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        if(&tng_data->molecules[i] == molecule)
+        {
+            index = i;
+            break;
+        }
     }
-
-    contents_start_pos = ftello(tng_data->output_file);
-
-    fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
-    if(fwrite(&frame_set->n_written_frames, sizeof(frame_set->n_frames),
-              1, tng_data->output_file) != 1)
+    if(index == -1)
     {
-        tng_data->input_file = temp;
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
+    *cnt = tng_data->molecule_cnt_list[index];
 
+    return(TNG_SUCCESS);
+}
 
-    if(hash_mode == TNG_USE_HASH)
-    {
-        tng_md5_hash_update(tng_data, block, pos,
-                            pos + block->header_contents_size);
-    }
+tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const int64_t cnt)
+{
+    int64_t i, old_cnt, index = -1;
 
-    fseeko(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftello(tng_data->output_file);
-    pos = contents_start_pos + block->block_contents_size;
-    fseeko(tng_data->output_file, pos, SEEK_SET);
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-    while(pos < output_file_len)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+        if(&tng_data->molecules[i] == molecule)
         {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
-                   __FILE__, __LINE__);
-            tng_data->input_file = temp;
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
+            index = i;
+            break;
         }
+    }
+    if(index == -1)
+    {
+        fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
+    {
+        old_cnt = tng_data->molecule_cnt_list[index];
+        tng_data->molecule_cnt_list[index] = cnt;
 
-        if(hash_mode == TNG_USE_HASH)
-        {
-            tng_md5_hash_update(tng_data, block, pos,
-                                pos + block->header_contents_size);
-        }
-        pos += block->header_contents_size + block->block_contents_size;
-        fseeko(tng_data->output_file, pos, SEEK_SET);
+        tng_data->n_particles += (cnt-old_cnt) *
+                                 tng_data->molecules[index].n_atoms;
+    }
+    else
+    {
+        old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
+        tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
+
+        tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
+                tng_data->molecules[index].n_atoms;
     }
 
-    tng_data->input_file = temp;
-    tng_block_destroy(&block);
     return(TNG_SUCCESS);
 }
 
-/*
-// ** Sets the name of a file contents block
-//  * @param tng_data is a trajectory data container.
-//  * @param block is the block, of which to change names.
-//  * @param new_name is the new name of the block.
-//  * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
-//  * error has occured.
-//
-// static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
-//                                               tng_gen_block_t block,
-//                                               const char *new_name)
-// {
-//     int len;
-//
-//     len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
-//
-//      * If the currently stored string length is not enough to store the new
-//      * string it is freed and reallocated. *
-//     if(block->name && strlen(block->name) < len)
-//     {
-//         free(block->name);
-//         block->name = 0;
-//     }
-//     if(!block->name)
-//     {
-//         block->name = malloc(len);
-//         if(!block->name)
-//         {
-//             fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-//                    __FILE__, __LINE__);
-//             return(TNG_CRITICAL);
-//         }
-//     }
-//
-//     strncpy(block->name, new_name, len);
-//
-//     return(TNG_SUCCESS);
-// }
-*/
-
-tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
-                                         const tng_atom_t atom,
-                                         tng_residue_t *residue)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_find
+                (const tng_trajectory_t tng_data,
+                 const char *name,
+                 const int64_t nr,
+                 tng_molecule_t *molecule)
 {
-    (void) tng_data;
+    int64_t i, n_molecules;
 
-    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
 
-    *residue = atom->residue;
+    n_molecules = tng_data->n_molecules;
 
-    return(TNG_SUCCESS);
+    for(i = n_molecules - 1; i >= 0; i--)
+    {
+        *molecule = &tng_data->molecules[i];
+        if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
+        {
+            if(nr == -1 || nr == (*molecule)->id)
+            {
+                return(TNG_SUCCESS);
+            }
+        }
+    }
+
+    *molecule = 0;
+
+    return(TNG_FAILURE);
 }
 
-tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
-                                      const tng_atom_t atom,
-                                      char *name,
-                                      const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t index,
+                 tng_molecule_t *molecule)
 {
-    (void) tng_data;
-    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
-
-    strncpy(name, atom->name, max_len - 1);
-    name[max_len - 1] = 0;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
 
-    if(strlen(atom->name) > (unsigned int)max_len - 1)
+    if(index >= tng_data->n_molecules)
     {
+        *molecule = 0;
         return(TNG_FAILURE);
     }
+    *molecule = &tng_data->molecules[index];
     return(TNG_SUCCESS);
 }
 
-tng_function_status tng_atom_name_set(tng_trajectory_t tng_data,
-                                      tng_atom_t atom,
-                                      const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
+                                                               const tng_trajectory_t tng_data_dest)
 {
-    unsigned int len;
-    (void)tng_data;
+    tng_molecule_t molecule, molecule_temp;
+    tng_chain_t chain, chain_temp;
+    tng_residue_t residue, residue_temp;
+    tng_atom_t atom, atom_temp;
+    tng_bond_t bond_temp;
+    tng_function_status stat;
+    int64_t i, j, k, l, *list_temp;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
+    TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    for(i = 0; i < tng_data_dest->n_molecules; i++)
+    {
+        molecule = &tng_data_dest->molecules[i];
+        tng_molecule_destroy(tng_data_dest, molecule);
+    }
 
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(atom->name && strlen(atom->name) < len)
+    tng_data_dest->n_molecules = 0;
+    tng_data_dest->n_particles = 0;
+
+    molecule_temp = realloc(tng_data_dest->molecules,
+                    sizeof(struct tng_molecule) * tng_data_src->n_molecules);
+    if(!molecule_temp)
     {
-        free(atom->name);
-        atom->name = 0;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(struct tng_molecule) * tng_data_src->n_molecules,
+               __FILE__, __LINE__);
+        free(tng_data_dest->molecules);
+        tng_data_dest->molecules = 0;
+        return(TNG_CRITICAL);
     }
-    if(!atom->name)
+    list_temp = realloc(tng_data_dest->molecule_cnt_list,
+                                     sizeof(int64_t) * tng_data_src->n_molecules);
+    if(!list_temp)
     {
-        atom->name = malloc(len);
-        if(!atom->name)
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * tng_data_src->n_molecules,
+               __FILE__, __LINE__);
+        free(tng_data_dest->molecule_cnt_list);
+        tng_data_dest->molecule_cnt_list = 0;
+        free(molecule_temp);
+        return(TNG_CRITICAL);
+    }
+
+    tng_data_dest->molecules = molecule_temp;
+    tng_data_dest->molecule_cnt_list = list_temp;
+
+    for(i = 0; i < tng_data_src->n_molecules; i++)
+    {
+        molecule = &tng_data_src->molecules[i];
+        stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
+                                     &molecule_temp);
+        if(stat != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+            fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
                    __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            return(stat);
+        }
+        molecule_temp->quaternary_str = molecule->quaternary_str;
+        for(j = 0; j < molecule->n_chains; j++)
+        {
+            chain = &molecule->chains[j];
+            stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
+                                               chain->name, chain->id,
+                                               &chain_temp);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(stat);
+            }
+            for(k = 0; k < chain->n_residues; k++)
+            {
+                residue = &chain->residues[k];
+                stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
+                                                  residue->name, residue->id,
+                                                  &residue_temp);
+                if(stat != TNG_SUCCESS)
+                {
+                    fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
+                           __FILE__, __LINE__);
+                    return(stat);
+                }
+                for(l = 0; l < residue->n_atoms; l++)
+                {
+                    atom = &molecule->atoms[residue->atoms_offset + l];
+                    stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
+                                                     atom->name, atom->atom_type,
+                                                     atom->id, &atom_temp);
+                    if(stat != TNG_SUCCESS)
+                    {
+                    fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
+                           __FILE__, __LINE__);
+                        return(stat);
+                    }
+                }
+            }
+        }
+        molecule_temp->n_bonds = molecule->n_bonds;
+        if(molecule->n_bonds > 0)
+        {
+            bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
+                                molecule->n_bonds);
+            if(!bond_temp)
+            {
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                       sizeof(struct tng_bond) * molecule->n_bonds,
+                       __FILE__, __LINE__);
+                free(molecule_temp->bonds);
+                molecule_temp->n_bonds = 0;
+                return(TNG_CRITICAL);
+            }
+            molecule_temp->bonds = bond_temp;
+            for(j = 0; j < molecule->n_bonds; j++)
+            {
+                molecule_temp->bonds[j] = molecule->bonds[j];
+            }
+        }
+        stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
+                                    tng_data_src->molecule_cnt_list[i]);
+        if(stat != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
+                   __FILE__, __LINE__);
+            return(stat);
         }
     }
+    return(TNG_SUCCESS);
+}
 
-    strncpy(atom->name, new_name, len);
+tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 int64_t *n)
+{
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
+
+    *n = molecule->n_chains;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
-                                      const tng_atom_t atom,
-                                      char *type,
-                                      const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const int64_t index,
+                 tng_chain_t *chain)
 {
     (void) tng_data;
-    TNG_ASSERT(atom, "TNG library: atom must not be NULL");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
-
-    strncpy(type, atom->atom_type, max_len - 1);
-    type[max_len - 1] = 0;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
+    TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
 
-    if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
+    if(index >= molecule->n_chains)
     {
+        *chain = 0;
         return(TNG_FAILURE);
     }
+    *chain = &molecule->chains[index];
     return(TNG_SUCCESS);
 }
 
-tng_function_status tng_atom_type_set(tng_trajectory_t tng_data,
-                                      tng_atom_t atom,
-                                      const char *new_type)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 int64_t *n)
 {
-    unsigned int len;
-    (void)tng_data;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
-
-    len = tng_min_i((int)strlen(new_type) + 1, TNG_MAX_STR_LEN);
-
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(atom->atom_type && strlen(atom->atom_type) < len)
-    {
-        free(atom->atom_type);
-        atom->atom_type = 0;
-    }
-    if(!atom->atom_type)
-    {
-        atom->atom_type = malloc(len);
-        if(!atom->atom_type)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
 
-    strncpy(atom->atom_type, new_type, len);
+    *n = molecule->n_residues;
 
     return(TNG_SUCCESS);
 }
 
-/** Initialise an atom struct
- * @param atom is the atom to initialise.
- * @return TNG_SUCCESS (0) if successful.
- */
-static tng_function_status tng_atom_init(tng_atom_t atom)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const int64_t index,
+                 tng_residue_t *residue)
 {
-    atom->name = 0;
-    atom->atom_type = 0;
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
+    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
 
+    if(index >= molecule->n_residues)
+    {
+        *residue = 0;
+        return(TNG_FAILURE);
+    }
+    *residue = &molecule->residues[index];
     return(TNG_SUCCESS);
 }
 
-/** Free the memory in an atom struct
- * @param atom is the atom to destroy.
- * @return TNG_SUCCESS (0) if successful.
- */
-static tng_function_status tng_atom_destroy(tng_atom_t atom)
-{
-    if(atom->name)
-    {
-        free(atom->name);
-        atom->name = 0;
-    }
-    if(atom->atom_type)
-    {
-        free(atom->atom_type);
-        atom->atom_type = 0;
-    }
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_version_major
+tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
                 (const tng_trajectory_t tng_data,
-                 int *version)
+                 const tng_molecule_t molecule,
+                 int64_t *n)
 {
-    (void)tng_data;
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
 
-    *version = TNG_VERSION_MAJOR;
+    *n = molecule->n_atoms;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_version_minor
+tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
                 (const tng_trajectory_t tng_data,
-                 int *version)
+                 const tng_molecule_t molecule,
+                 const int64_t index,
+                 tng_atom_t *atom)
 {
-    (void)tng_data;
-
-    *version = TNG_VERSION_MINOR;
+    (void) tng_data;
+    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
+    TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
 
+    if(index >= molecule->n_atoms)
+    {
+        *atom = 0;
+        return(TNG_FAILURE);
+    }
+    *atom = &molecule->atoms[index];
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
+tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
                 (const tng_trajectory_t tng_data,
-                 int *patch_level)
+                 const tng_molecule_t molecule,
+                 const char *name,
+                 const int64_t nr,
+                 tng_chain_t *chain)
 {
+    int64_t i, n_chains;
     (void)tng_data;
 
-    *patch_level = TNG_VERSION_PATCHLEVEL;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    return(TNG_SUCCESS);
-}
+    n_chains = molecule->n_chains;
 
-tng_function_status DECLSPECDLLEXPORT tng_version
-                (const tng_trajectory_t tng_data,
-                 char *version,
-                 const int max_len)
-{
-    (void)tng_data;
-    TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
+    for(i = n_chains - 1; i >= 0; i--)
+    {
+        *chain = &molecule->chains[i];
+        if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
+        {
+            if(nr == -1 || nr == (*chain)->id)
+            {
+                return(TNG_SUCCESS);
+            }
+        }
+    }
 
-    TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
+    *chain = 0;
 
-    return(TNG_SUCCESS);
+    return(TNG_FAILURE);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_add
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
-                 tng_molecule_t *molecule)
+                 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 molecule + 1 */
-    if(tng_data->n_molecules)
+    /* Set ID to the ID of the last chain + 1 */
+    if(molecule->n_chains)
     {
-        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
+        id = molecule->chains[molecule->n_chains-1].id + 1;
     }
     else
     {
         id = 1;
     }
 
-    return(tng_molecule_w_id_add(tng_data, name, id, molecule));
+    return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
+                                       id, chain));
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
                  const char *name,
                  const int64_t id,
-                 tng_molecule_t *molecule)
+                 tng_chain_t *chain)
 {
-    tng_molecule_t new_molecules;
-    int64_t *new_molecule_cnt_list;
+    tng_chain_t new_chains;
     tng_function_status stat = TNG_SUCCESS;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    new_molecules = realloc(tng_data->molecules,
-                            sizeof(struct tng_molecule) *
-                            (tng_data->n_molecules + 1));
-
-    if(!new_molecules)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
-               __FILE__, __LINE__);
-        free(tng_data->molecules);
-        tng_data->molecules = 0;
-        return(TNG_CRITICAL);
-    }
-
-    new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
-                                    sizeof(int64_t) *
-                                    (tng_data->n_molecules + 1));
+    new_chains = realloc(molecule->chains,
+                         sizeof(struct tng_chain) *
+                         (molecule->n_chains + 1));
 
-    if(!new_molecule_cnt_list)
+    if(!new_chains)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * (tng_data->n_molecules + 1),
+               sizeof(struct tng_chain) * (molecule->n_chains + 1),
                __FILE__, __LINE__);
-        free(tng_data->molecule_cnt_list);
-        tng_data->molecule_cnt_list = 0;
-        free(new_molecules);
+        free(molecule->chains);
+        molecule->chains = 0;
         return(TNG_CRITICAL);
     }
 
-    tng_data->molecules = new_molecules;
-    tng_data->molecule_cnt_list = new_molecule_cnt_list;
+    molecule->chains = new_chains;
 
-    *molecule = &new_molecules[tng_data->n_molecules];
+    *chain = &new_chains[molecule->n_chains];
+    (*chain)->name = 0;
 
-    tng_molecule_init(tng_data, *molecule);
-    tng_molecule_name_set(tng_data, *molecule, name);
+    tng_chain_name_set(tng_data, *chain, name);
 
-    /* FIXME: Should this be a function argument instead? */
-    tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
+    (*chain)->molecule = molecule;
+    (*chain)->n_residues = 0;
 
-    (*molecule)->id = id;
+    molecule->n_chains++;
 
-    tng_data->n_molecules++;
+    (*chain)->id = id;
 
     return(stat);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t *molecule_p)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const int64_t from_atom_id,
+                 const int64_t to_atom_id,
+                 tng_bond_t *bond)
 {
-    int64_t *new_molecule_cnt_list, id;
-    tng_molecule_t new_molecules, molecule;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    /* Set ID to the ID of the last molecule + 1 */
-    if(tng_data->n_molecules)
-    {
-        id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
-    }
-    else
-    {
-        id = 1;
-    }
+    tng_bond_t new_bonds;
+    (void)tng_data;
 
-    new_molecules = realloc(tng_data->molecules,
-                            sizeof(struct tng_molecule) *
-                            (tng_data->n_molecules + 1));
+    new_bonds = realloc(molecule->bonds,
+                        sizeof(struct tng_bond) *
+                        (molecule->n_bonds + 1));
 
-    if(!new_molecules)
+    if(!new_bonds)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
+               sizeof(struct tng_bond) * (molecule->n_bonds + 1),
                __FILE__, __LINE__);
-        free(tng_data->molecules);
-        tng_data->molecules = 0;
+        *bond = 0;
+        free(molecule->bonds);
+        molecule->bonds = 0;
         return(TNG_CRITICAL);
     }
 
-    new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
-                                    sizeof(int64_t) *
-                                    (tng_data->n_molecules + 1));
-
-    if(!new_molecule_cnt_list)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * (tng_data->n_molecules + 1),
-               __FILE__, __LINE__);
-        free(tng_data->molecule_cnt_list);
-        tng_data->molecule_cnt_list = 0;
-        free(new_molecules);
-        return(TNG_CRITICAL);
-    }
+    molecule->bonds = new_bonds;
 
-    molecule = *molecule_p;
+    *bond = &new_bonds[molecule->n_bonds];
 
-    tng_data->molecules = new_molecules;
-    tng_data->molecule_cnt_list = new_molecule_cnt_list;
+    (*bond)->from_atom_id = from_atom_id;
+    (*bond)->to_atom_id = to_atom_id;
 
-    new_molecules[tng_data->n_molecules] = *molecule;
+    molecule->n_bonds++;
 
-    tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
+    return(TNG_SUCCESS);
+}
 
-    free(*molecule_p);
+tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t molecule,
+                 const char *name,
+                 const int64_t id,
+                 tng_atom_t *atom)
+{
+    int64_t i, n_atoms;
+    (void)tng_data;
 
-    molecule = &new_molecules[tng_data->n_molecules];
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    *molecule_p = molecule;
+    n_atoms = molecule->n_atoms;
 
-    molecule->id = id;
+    for(i = n_atoms - 1; i >= 0; i--)
+    {
+        *atom = &molecule->atoms[i];
+        if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
+        {
+            if(id == -1 || id == (*atom)->id)
+            {
+                return(TNG_SUCCESS);
+            }
+        }
+    }
 
-    tng_data->n_molecules++;
+    *atom = 0;
 
-    return(TNG_SUCCESS);
+    return(TNG_FAILURE);
 }
 
-tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
-                                          const tng_molecule_t molecule,
-                                          char *name,
-                                          const int max_len)
-{
-    (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
+                                       const tng_chain_t chain,
+                                       char *name,
+                                       const int max_len)
+{
+    (void) tng_data;
+    TNG_ASSERT(chain, "TNG library: chain must not be NULL");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    strncpy(name, molecule->name, max_len - 1);
+    strncpy(name, chain->name, max_len - 1);
     name[max_len - 1] = 0;
 
-    if(strlen(molecule->name) > (unsigned int)max_len - 1)
+    if(strlen(chain->name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
+tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *new_name)
 {
     unsigned int len;
     (void)tng_data;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
     /* If the currently stored string length is not enough to store the new
      * string it is freed and reallocated. */
-    if(molecule->name && strlen(molecule->name) < len)
+    if(chain->name && strlen(chain->name) < len)
     {
-        free(molecule->name);
-        molecule->name = 0;
+        free(chain->name);
+        chain->name = 0;
     }
-    if(!molecule->name)
+    if(!chain->name)
     {
-        molecule->name = malloc(len);
-        if(!molecule->name)
+        chain->name = malloc(len);
+        if(!chain->name)
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
@@ -8170,1695 +7655,1670 @@ tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
         }
     }
 
-    strncpy(molecule->name, new_name, len);
+    strncpy(chain->name, new_name, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
+tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
                 (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
-                 int64_t *cnt)
+                 const tng_chain_t chain,
+                 int64_t *n)
 {
-    int64_t i, index = -1;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
+    (void) tng_data;
+    TNG_ASSERT(chain, "TNG library: chain must not be NULL");
+    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
 
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        if(&tng_data->molecules[i] == molecule)
-        {
-            index = i;
-            break;
-        }
-    }
-    if(index == -1)
-    {
-        return(TNG_FAILURE);
-    }
-    *cnt = tng_data->molecule_cnt_list[index];
+    *n = chain->n_residues;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const int64_t cnt)
+tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
+                 const int64_t index,
+                 tng_residue_t *residue)
 {
-    int64_t i, old_cnt, index = -1;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    (void) tng_data;
+    TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
+    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
 
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        if(&tng_data->molecules[i] == molecule)
-        {
-            index = i;
-            break;
-        }
-    }
-    if(index == -1)
+    if(index >= chain->n_residues)
     {
-        fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
-               __FILE__, __LINE__);
+        *residue = 0;
         return(TNG_FAILURE);
     }
-    if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
-    {
-        old_cnt = tng_data->molecule_cnt_list[index];
-        tng_data->molecule_cnt_list[index] = cnt;
-
-        tng_data->n_particles += (cnt-old_cnt) *
-                                 tng_data->molecules[index].n_atoms;
-    }
-    else
-    {
-        old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
-        tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
-
-        tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
-                tng_data->molecules[index].n_atoms;
-    }
-
+    *residue = &chain->residues[index];
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_find
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
                  const char *name,
-                 int64_t nr,
-                 tng_molecule_t *molecule)
+                 const int64_t id,
+                 tng_residue_t *residue)
 {
-    int64_t i, n_molecules;
+    int64_t i, n_residues;
+    (void)tng_data;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
-    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
 
-    n_molecules = tng_data->n_molecules;
+    n_residues = chain->n_residues;
 
-    for(i = n_molecules - 1; i >= 0; i--)
+    for(i = n_residues - 1; i >= 0; i--)
     {
-        *molecule = &tng_data->molecules[i];
-        if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
+        *residue = &chain->residues[i];
+        if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
         {
-            if(nr == -1 || nr == (*molecule)->id)
+            if(id == -1 || id == (*residue)->id)
             {
                 return(TNG_SUCCESS);
             }
         }
     }
 
-    *molecule = 0;
+    *residue = 0;
 
     return(TNG_FAILURE);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
-                (tng_trajectory_t tng_data,
-                 int64_t index,
-                 tng_molecule_t *molecule)
+tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
+                 const char *name,
+                 tng_residue_t *residue)
 {
+    int64_t id;
+
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    if(index >= tng_data->n_molecules)
+    /* Set ID to the ID of the last residue + 1 */
+    if(chain->n_residues)
     {
-        *molecule = 0;
-        return(TNG_FAILURE);
+        id = chain->residues[chain->n_residues-1].id + 1;
     }
-    *molecule = &tng_data->molecules[index];
-    return(TNG_SUCCESS);
+    else
+    {
+        id = 0;
+    }
+
+    return(tng_chain_residue_w_id_add(tng_data, chain, name,
+                                      id, residue));
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(tng_trajectory_t tng_data_src,
-                                                               tng_trajectory_t tng_data_dest)
+tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
+                (const tng_trajectory_t tng_data,
+                 const tng_chain_t chain,
+                 const char *name,
+                 const int64_t id,
+                 tng_residue_t *residue)
 {
-    tng_molecule_t molecule, molecule_temp;
-    tng_chain_t chain, chain_temp;
-    tng_residue_t residue, residue_temp;
-    tng_atom_t atom, atom_temp;
-    tng_bond_t bond_temp;
-    tng_function_status stat;
-    int64_t i, j, k, l, *list_temp;
+    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;
 
-    TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    for(i = 0; i < tng_data_dest->n_molecules; i++)
+    if(chain->n_residues)
     {
-        molecule = &tng_data_dest->molecules[i];
-        tng_molecule_destroy(tng_data_dest, molecule);
+        curr_index = chain->residues - molecule->residues;
     }
-
-    tng_data_dest->n_molecules = 0;
-    tng_data_dest->n_particles = 0;
-
-    molecule_temp = realloc(tng_data_dest->molecules,
-                    sizeof(struct tng_molecule) * tng_data_src->n_molecules);
-    if(!molecule_temp)
+    else
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_molecule) * tng_data_src->n_molecules,
-               __FILE__, __LINE__);
-        free(tng_data_dest->molecules);
-        tng_data_dest->molecules = 0;
-        return(TNG_CRITICAL);
+        curr_index = -1;
     }
-    list_temp = realloc(tng_data_dest->molecule_cnt_list,
-                                     sizeof(int64_t) * tng_data_src->n_molecules);
-    if(!list_temp)
+
+    new_residues = realloc(molecule->residues,
+                           sizeof(struct tng_residue) *
+                           (molecule->n_residues + 1));
+
+    if(!new_residues)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * tng_data_src->n_molecules,
+               sizeof(struct tng_residue) * (molecule->n_residues + 1),
                __FILE__, __LINE__);
-        free(tng_data_dest->molecule_cnt_list);
-        tng_data_dest->molecule_cnt_list = 0;
-        free(molecule_temp);
+        free(molecule->residues);
+        molecule->residues = 0;
         return(TNG_CRITICAL);
     }
 
-    tng_data_dest->molecules = molecule_temp;
-    tng_data_dest->molecule_cnt_list = list_temp;
+    molecule->residues = new_residues;
 
-    for(i = 0; i < tng_data_src->n_molecules; i++)
+    if(curr_index != -1)
     {
-        molecule = &tng_data_src->molecules[i];
-        stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
-                                     &molecule_temp);
-        if(stat != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(stat);
-        }
-        molecule_temp->quaternary_str = molecule->quaternary_str;
-        for(j = 0; j < molecule->n_chains; j++)
+        chain->residues = new_residues + curr_index;
+        if(molecule->n_residues)
         {
-            chain = &molecule->chains[j];
-            stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
-                                               chain->name, chain->id,
-                                               &chain_temp);
-            if(stat != TNG_SUCCESS)
+            last_residue = &new_residues[molecule->n_residues - 1];
+
+            temp_residue = chain->residues + (chain->n_residues - 1);
+            /* Make space in list of residues to add the new residues together with the other
+            * residues of this chain */
+            if(temp_residue != last_residue)
             {
-                fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
-                       __FILE__, __LINE__);
-                return(stat);
+                ++temp_residue;
+                memmove(temp_residue + 1, temp_residue,
+                        last_residue - temp_residue);
             }
-            for(k = 0; k < chain->n_residues; k++)
-            {
-                residue = &chain->residues[k];
-                stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
-                                                  residue->name, residue->id,
-                                                  &residue_temp);
-                if(stat != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
-                           __FILE__, __LINE__);
-                    return(stat);
-                }
-                for(l = 0; l < residue->n_atoms; l++)
-                {
-                    atom = &molecule->atoms[residue->atoms_offset + l];
-                    stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
-                                                     atom->name, atom->atom_type,
-                                                     atom->id, &atom_temp);
-                    if(stat != TNG_SUCCESS)
-                    {
-                    fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
-                           __FILE__, __LINE__);
-                        return(stat);
-                    }
-                }
-            }
-        }
-        molecule_temp->n_bonds = molecule->n_bonds;
-        if(molecule->n_bonds > 0)
-        {
-            bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
-                                molecule->n_bonds);
-            if(!bond_temp)
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-                       sizeof(struct tng_bond) * molecule->n_bonds,
-                       __FILE__, __LINE__);
-                free(molecule_temp->bonds);
-                molecule_temp->n_bonds = 0;
-                return(TNG_CRITICAL);
-            }
-            molecule_temp->bonds = bond_temp;
-            for(j = 0; j < molecule->n_bonds; j++)
-            {
-                molecule_temp->bonds[j] = molecule->bonds[j];
-            }
-        }
-        stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
-                                    tng_data_src->molecule_cnt_list[i]);
-        if(stat != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
-                   __FILE__, __LINE__);
-            return(stat);
         }
     }
-    return(TNG_SUCCESS);
-}
+    else
+    {
+        curr_index = molecule->n_residues;
+    }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
-                (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
-                 int64_t *n)
-{
-    (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
-    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
+    *residue = &molecule->residues[curr_index + chain->n_residues];
 
-    *n = molecule->n_chains;
+    if(!chain->n_residues)
+    {
+        chain->residues = *residue;
+    }
+    else
+    {
+        chain->residues = &molecule->residues[curr_index];
+    }
 
-    return(TNG_SUCCESS);
+    (*residue)->name = 0;
+    tng_residue_name_set(tng_data, *residue, name);
+
+    (*residue)->chain = chain;
+    (*residue)->n_atoms = 0;
+    (*residue)->atoms_offset = 0;
+
+    chain->n_residues++;
+    molecule->n_residues++;
+
+    (*residue)->id = id;
+
+    return(stat);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 int64_t index,
-                 tng_chain_t *chain)
+tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
+                                         const tng_residue_t residue,
+                                         char *name,
+                                         const int max_len)
 {
     (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
-    TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
+    TNG_ASSERT(residue, "TNG library: residue must not be NULL");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    if(index >= molecule->n_chains)
+    strncpy(name, residue->name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(residue->name) > (unsigned int)max_len - 1)
     {
-        *chain = 0;
         return(TNG_FAILURE);
     }
-    *chain = &molecule->chains[index];
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
-                (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
-                 int64_t *n)
+tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
+                                                           const tng_residue_t residue,
+                                                           const char *new_name)
 {
-    (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
-    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
-
-    *n = molecule->n_residues;
+    unsigned int len;
+    (void)tng_data;
 
-    return(TNG_SUCCESS);
-}
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
-                (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
-                 const int64_t index,
-                 tng_residue_t *residue)
-{
-    (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
-    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    if(index >= molecule->n_residues)
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(residue->name && strlen(residue->name) < len)
     {
-        *residue = 0;
-        return(TNG_FAILURE);
+        free(residue->name);
+        residue->name = 0;
     }
-    *residue = &molecule->residues[index];
+    if(!residue->name)
+    {
+        residue->name = malloc(len);
+        if(!residue->name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+    }
+
+    strncpy(residue->name, new_name, len);
+
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
+tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
                 (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
+                 const tng_residue_t residue,
                  int64_t *n)
 {
     (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
+    TNG_ASSERT(residue, "TNG library: residue must not be NULL");
     TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
 
-    *n = molecule->n_atoms;
+    *n = residue->n_atoms;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
+tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
                 (const tng_trajectory_t tng_data,
-                 const tng_molecule_t molecule,
+                 const tng_residue_t residue,
                  const int64_t index,
                  tng_atom_t *atom)
 {
+    tng_chain_t chain;
+    tng_molecule_t molecule;
+
     (void) tng_data;
-    TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
+    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
     TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
 
-    if(index >= molecule->n_atoms)
+    if(index >= residue->n_atoms)
     {
         *atom = 0;
         return(TNG_FAILURE);
     }
-    *atom = &molecule->atoms[index];
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const char *name,
-                 int64_t nr,
-                 tng_chain_t *chain)
-{
-    int64_t i, n_chains;
-    (void)tng_data;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
-
-    n_chains = molecule->n_chains;
+    chain = residue->chain;
+    molecule = chain->molecule;
 
-    for(i = n_chains - 1; i >= 0; i--)
+    if(index + residue->atoms_offset >= molecule->n_atoms)
     {
-        *chain = &molecule->chains[i];
-        if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
-        {
-            if(nr == -1 || nr == (*chain)->id)
-            {
-                return(TNG_SUCCESS);
-            }
-        }
+        *atom = 0;
+        return(TNG_FAILURE);
     }
 
-    *chain = 0;
-
-    return(TNG_FAILURE);
+    *atom = &molecule->atoms[residue->atoms_offset + index];
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const char *name,
-                 tng_chain_t *chain)
+tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
+                (const tng_trajectory_t tng_data,
+                 const tng_residue_t residue,
+                 const char *atom_name,
+                 const char *atom_type,
+                 tng_atom_t *atom)
 {
     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.");
+    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 chain + 1 */
-    if(molecule->n_chains)
+    /* Set ID to the ID of the last atom + 1 */
+    if(residue->chain->molecule->n_atoms)
     {
-        id = molecule->chains[molecule->n_chains-1].id + 1;
+        id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
     }
     else
     {
-        id = 1;
+        id = 0;
     }
 
-    return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
-                                       id, chain));
+    return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
+                                     id, atom));
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const char *name,
+tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
+                (const tng_trajectory_t tng_data,
+                 const tng_residue_t residue,
+                 const char *atom_name,
+                 const char *atom_type,
                  const int64_t id,
-                 tng_chain_t *chain)
+                 tng_atom_t *atom)
 {
-    tng_chain_t new_chains;
+    tng_atom_t new_atoms;
+    tng_molecule_t molecule = residue->chain->molecule;
     tng_function_status stat = TNG_SUCCESS;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
-
-    new_chains = realloc(molecule->chains,
-                         sizeof(struct tng_chain) *
-                         (molecule->n_chains + 1));
+    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.");
 
-    if(!new_chains)
+    if(!residue->n_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_chain) * (molecule->n_chains + 1),
-               __FILE__, __LINE__);
-        free(molecule->chains);
-        molecule->chains = 0;
-        return(TNG_CRITICAL);
+        residue->atoms_offset = molecule->n_atoms;
     }
 
-    molecule->chains = new_chains;
+    new_atoms = realloc(molecule->atoms,
+                        sizeof(struct tng_atom) *
+                        (molecule->n_atoms + 1));
 
-    *chain = &new_chains[molecule->n_chains];
-    (*chain)->name = 0;
+    if(!new_atoms)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(struct tng_atom) * (molecule->n_atoms + 1),
+               __FILE__, __LINE__);
+        free(molecule->atoms);
+        molecule->atoms = 0;
+        return(TNG_CRITICAL);
+    }
 
-    tng_chain_name_set(tng_data, *chain, name);
+    molecule->atoms = new_atoms;
 
-    (*chain)->molecule = molecule;
-    (*chain)->n_residues = 0;
+    *atom = &new_atoms[molecule->n_atoms];
 
-    molecule->n_chains++;
+    tng_atom_init(*atom);
+    tng_atom_name_set(tng_data, *atom, atom_name);
+    tng_atom_type_set(tng_data, *atom, atom_type);
 
-    (*chain)->id = id;
+    (*atom)->residue = residue;
+
+    residue->n_atoms++;
+    molecule->n_atoms++;
+
+    (*atom)->id = id;
 
     return(stat);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
-                (const tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const int64_t from_atom_id,
-                 const int64_t to_atom_id,
-                 tng_bond_t *bond)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
+                                                         tng_molecule_t *molecule_p)
 {
-    tng_bond_t new_bonds;
-    (void)tng_data;
+    *molecule_p = malloc(sizeof(struct tng_molecule));
+    if(!*molecule_p)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+               sizeof(struct tng_molecule), __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-    new_bonds = realloc(molecule->bonds,
-                        sizeof(struct tng_bond) *
-                        (molecule->n_bonds + 1));
+    tng_molecule_init(tng_data, *molecule_p);
 
-    if(!new_bonds)
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
+                                                        tng_molecule_t *molecule_p)
+{
+    if(!*molecule_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_bond) * (molecule->n_bonds + 1),
-               __FILE__, __LINE__);
-        *bond = 0;
-        free(molecule->bonds);
-        molecule->bonds = 0;
-        return(TNG_CRITICAL);
+        return(TNG_SUCCESS);
     }
 
-    molecule->bonds = new_bonds;
+    tng_molecule_destroy(tng_data, *molecule_p);
 
-    *bond = &new_bonds[molecule->n_bonds];
+    free(*molecule_p);
+    *molecule_p = 0;
 
-    (*bond)->from_atom_id = from_atom_id;
-    (*bond)->to_atom_id = to_atom_id;
+    return(TNG_SUCCESS);
+}
 
-    molecule->n_bonds++;
+tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
+                                                        const tng_molecule_t molecule)
+{
+    (void)tng_data;
+    molecule->quaternary_str = 1;
+    molecule->name = 0;
+    molecule->n_chains = 0;
+    molecule->chains = 0;
+    molecule->n_residues = 0;
+    molecule->residues = 0;
+    molecule->n_atoms = 0;
+    molecule->atoms = 0;
+    molecule->n_bonds = 0;
+    molecule->bonds = 0;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t molecule,
-                 const char *name,
-                 int64_t id,
-                 tng_atom_t *atom)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
+                                                           const tng_molecule_t molecule)
 {
-    int64_t i, n_atoms;
+    int64_t i;
     (void)tng_data;
 
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+    if(molecule->name)
+    {
+        free(molecule->name);
+        molecule->name = 0;
+    }
 
-    n_atoms = molecule->n_atoms;
+    if(molecule->chains)
+    {
+        for(i = 0; i < molecule->n_chains; i++)
+        {
+            if(molecule->chains[i].name)
+            {
+                free(molecule->chains[i].name);
+                molecule->chains[i].name = 0;
+            }
+        }
+        free(molecule->chains);
+        molecule->chains = 0;
+    }
+    molecule->n_chains = 0;
 
-    for(i = n_atoms - 1; i >= 0; i--)
+    if(molecule->residues)
     {
-        *atom = &molecule->atoms[i];
-        if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
+        for(i = 0; i < molecule->n_residues; i++)
         {
-            if(id == -1 || id == (*atom)->id)
+            if(molecule->residues[i].name)
             {
-                return(TNG_SUCCESS);
+                free(molecule->residues[i].name);
+                molecule->residues[i].name = 0;
             }
         }
+        free(molecule->residues);
+        molecule->residues = 0;
     }
+    molecule->n_residues = 0;
 
-    *atom = 0;
+    if(molecule->atoms)
+    {
+        for(i = 0; i < molecule->n_atoms; i++)
+        {
+            tng_atom_destroy(&molecule->atoms[i]);
+        }
+        free(molecule->atoms);
+        molecule->atoms = 0;
+    }
+    molecule->n_atoms = 0;
 
-    return(TNG_FAILURE);
+    if(molecule->bonds)
+    {
+        free(molecule->bonds);
+        molecule->bonds = 0;
+    }
+    molecule->n_bonds = 0;
+
+    return(TNG_SUCCESS);
 }
 
-tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
-                                       const tng_chain_t chain,
-                                       char *name,
-                                       const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 char *name,
+                 const int max_len)
 {
-    (void) tng_data;
-    TNG_ASSERT(chain, "TNG library: chain must not be NULL");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_bool found = TNG_FALSE;
 
-    strncpy(name, chain->name, max_len - 1);
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+
+    if(!molecule_cnt_list)
+    {
+        return(TNG_FAILURE);
+    }
+
+    for(i = 0; i < tng_data->n_molecules; i++)
+    {
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        {
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
+        }
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
+    }
+
+    strncpy(name, mol->name, max_len - 1);
     name[max_len - 1] = 0;
 
-    if(strlen(chain->name) > (unsigned int)max_len - 1)
+    if(strlen(mol->name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
-                 const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 int64_t *id)
 {
-    unsigned int len;
-    (void)tng_data;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_bool found = TNG_FALSE;
 
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
 
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(chain->name && strlen(chain->name) < len)
+    if(!molecule_cnt_list)
     {
-        free(chain->name);
-        chain->name = 0;
+        return(TNG_FAILURE);
     }
-    if(!chain->name)
+
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        chain->name = malloc(len);
-        if(!chain->name)
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
         }
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
     }
 
-    strncpy(chain->name, new_name, len);
+    *id = mol->id;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
+tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
                 (const tng_trajectory_t tng_data,
-                 const tng_chain_t chain,
-                 int64_t *n)
+                 int64_t *n_bonds,
+                 int64_t **from_atoms,
+                 int64_t **to_atoms)
 {
-    (void) tng_data;
-    TNG_ASSERT(chain, "TNG library: chain must not be NULL");
-    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
-
-    *n = chain->n_residues;
+    int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
+    int64_t from_atom, to_atom, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_bond_t bond;
 
-    return(TNG_SUCCESS);
-}
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
+    TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
+    TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
-                (const tng_trajectory_t tng_data,
-                 const tng_chain_t chain,
-                 const int64_t index,
-                 tng_residue_t *residue)
-{
-    (void) tng_data;
-    TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
-    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
 
-    if(index >= chain->n_residues)
+    if(!molecule_cnt_list)
     {
-        *residue = 0;
         return(TNG_FAILURE);
     }
-    *residue = &chain->residues[index];
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
-                 const char *name,
-                 int64_t id,
-                 tng_residue_t *residue)
-{
-    int64_t i, n_residues;
-    (void)tng_data;
 
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+    *n_bonds = 0;
+    /* First count the total number of bonds to allocate memory */
+    for(i = 0; i < tng_data->n_molecules; i++)
+    {
+        mol = &tng_data->molecules[i];
+        mol_cnt = molecule_cnt_list[i];
+        *n_bonds += mol_cnt * mol->n_bonds;
+    }
+    if(*n_bonds == 0)
+    {
+        return(TNG_SUCCESS);
+    }
 
-    n_residues = chain->n_residues;
+    *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
+    if(!*from_atoms)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+    *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
+    if(!*to_atoms)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
+        free(*from_atoms);
+        *from_atoms = 0;
+        return(TNG_CRITICAL);
+    }
 
-    for(i = n_residues - 1; i >= 0; i--)
+    cnt = 0;
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        *residue = &chain->residues[i];
-        if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
+        mol = &tng_data->molecules[i];
+        mol_cnt = molecule_cnt_list[i];
+        for(j = 0; j < mol_cnt; j++)
         {
-            if(id == -1 || id == (*residue)->id)
+            for(k = 0; k < mol->n_bonds; k++)
             {
-                return(TNG_SUCCESS);
+                bond = &mol->bonds[k];
+                from_atom = atom_cnt + bond->from_atom_id;
+                to_atom = atom_cnt + bond->to_atom_id;
+                (*from_atoms)[cnt] = from_atom;
+                (*to_atoms)[cnt++] = to_atom;
             }
+            atom_cnt += mol->n_atoms;
         }
     }
 
-    *residue = 0;
-
-    return(TNG_FAILURE);
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
-                 const char *name,
-                 tng_residue_t *residue)
+tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 char *name,
+                 const int max_len)
 {
-    int64_t id;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
     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)
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+
+    if(!molecule_cnt_list)
     {
-        id = chain->residues[chain->n_residues-1].id + 1;
+        return(TNG_FAILURE);
     }
-    else
+
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        id = 0;
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        {
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
+        }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
+    }
+    if(!atom->residue || !atom->residue->chain)
+    {
+        return(TNG_FAILURE);
     }
 
-    return(tng_chain_residue_w_id_add(tng_data, chain, name,
-                                      id, residue));
+    strncpy(name, atom->residue->chain->name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
+    {
+        return(TNG_FAILURE);
+    }
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_chain_t chain,
-                 const char *name,
-                 const int64_t id,
-                 tng_residue_t *residue)
+tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 char *name,
+                 const int max_len)
 {
-    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;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    if(chain->n_residues)
-    {
-        curr_index = chain->residues - molecule->residues;
-    }
-    else
-    {
-        curr_index = -1;
-    }
-
-    new_residues = realloc(molecule->residues,
-                           sizeof(struct tng_residue) *
-                           (molecule->n_residues + 1));
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
 
-    if(!new_residues)
+    if(!molecule_cnt_list)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_residue) * (molecule->n_residues + 1),
-               __FILE__, __LINE__);
-        free(molecule->residues);
-        molecule->residues = 0;
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
 
-    molecule->residues = new_residues;
-
-    if(curr_index != -1)
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        chain->residues = new_residues + curr_index;
-        if(molecule->n_residues)
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
         {
-            last_residue = &new_residues[molecule->n_residues - 1];
-
-            temp_residue = chain->residues + (chain->n_residues - 1);
-            /* Make space in list of residues to add the new residues together with the other
-            * residues of this chain */
-            if(temp_residue != last_residue)
-            {
-                ++temp_residue;
-                memmove(temp_residue + 1, temp_residue,
-                        last_residue - temp_residue);
-            }
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
         }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
     }
-    else
-    {
-        curr_index = molecule->n_residues;
-    }
-
-    *residue = &molecule->residues[curr_index + chain->n_residues];
-
-    if(!chain->n_residues)
+    if(!found)
     {
-        chain->residues = *residue;
+        return(TNG_FAILURE);
     }
-    else
+    if(!atom->residue)
     {
-        chain->residues = &molecule->residues[curr_index];
+        return(TNG_FAILURE);
     }
 
-    (*residue)->name = 0;
-    tng_residue_name_set(tng_data, *residue, name);
-
-    (*residue)->chain = chain;
-    (*residue)->n_atoms = 0;
-    (*residue)->atoms_offset = 0;
-
-    chain->n_residues++;
-    molecule->n_residues++;
-
-    (*residue)->id = id;
-
-    return(stat);
-}
-
-tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
-                                         const tng_residue_t residue,
-                                         char *name,
-                                         const int max_len)
-{
-    (void) tng_data;
-    TNG_ASSERT(residue, "TNG library: residue must not be NULL");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
-
-    strncpy(name, residue->name, max_len - 1);
+    strncpy(name, atom->residue->name, max_len - 1);
     name[max_len - 1] = 0;
 
-    if(strlen(residue->name) > (unsigned int)max_len - 1)
+    if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(tng_trajectory_t tng_data,
-                                                           tng_residue_t residue,
-                                                           const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 int64_t *id)
 {
-    unsigned int len;
-    (void)tng_data;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
+    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
 
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(residue->name && strlen(residue->name) < len)
+    if(!molecule_cnt_list)
     {
-        free(residue->name);
-        residue->name = 0;
+        return(TNG_FAILURE);
     }
-    if(!residue->name)
+
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        residue->name = malloc(len);
-        if(!residue->name)
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
         }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
+    }
+    if(!atom->residue)
+    {
+        return(TNG_FAILURE);
     }
 
-    strncpy(residue->name, new_name, len);
+    *id = atom->residue->id;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
+tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
-                 const tng_residue_t residue,
-                 int64_t *n)
+                 const int64_t nr,
+                 int64_t *id)
 {
-    (void) tng_data;
-    TNG_ASSERT(residue, "TNG library: residue must not be NULL");
-    TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
+    int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
-    *n = residue->n_atoms;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
+
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+
+    if(!molecule_cnt_list)
+    {
+        return(TNG_FAILURE);
+    }
+
+    for(i = 0; i < tng_data->n_molecules; i++)
+    {
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        {
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            offset += mol->n_residues * molecule_cnt_list[i];
+            continue;
+        }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
+    }
+    if(!atom->residue)
+    {
+        return(TNG_FAILURE);
+    }
+
+    offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
+
+    *id = atom->residue->id + offset;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
+tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
                 (const tng_trajectory_t tng_data,
-                 const tng_residue_t residue,
-                 const int64_t index,
-                 tng_atom_t *atom)
+                 const int64_t nr,
+                 char *name,
+                 const int max_len)
 {
-    tng_chain_t chain;
-    tng_molecule_t molecule;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
-    (void) tng_data;
-    TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
-    TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    if(index >= residue->n_atoms)
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+
+    if(!molecule_cnt_list)
     {
-        *atom = 0;
         return(TNG_FAILURE);
     }
-    chain = residue->chain;
-    molecule = chain->molecule;
 
-    if(index + residue->atoms_offset >= molecule->n_atoms)
+    for(i = 0; i < tng_data->n_molecules; i++)
+    {
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        {
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
+        }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
     {
-        *atom = 0;
         return(TNG_FAILURE);
     }
 
-    *atom = &molecule->atoms[residue->atoms_offset + index];
+    strncpy(name, atom->name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(atom->name) > (unsigned int)max_len - 1)
+    {
+        return(TNG_FAILURE);
+    }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
-                (tng_trajectory_t tng_data,
-                 tng_residue_t residue,
-                 const char *atom_name,
-                 const char *atom_type,
-                 tng_atom_t *atom)
+tng_function_status tng_atom_type_of_particle_nr_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t nr,
+                 char *type,
+                 const int max_len)
 {
-    int64_t id;
+    int64_t cnt = 0, i, *molecule_cnt_list = 0;
+    tng_molecule_t mol;
+    tng_atom_t atom;
+    tng_bool found = TNG_FALSE;
 
     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.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
 
-    /* Set ID to the ID of the last atom + 1 */
-    if(residue->chain->molecule->n_atoms)
+    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+
+    if(!molecule_cnt_list)
     {
-        id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
+        return(TNG_FAILURE);
     }
-    else
+
+    for(i = 0; i < tng_data->n_molecules; i++)
     {
-        id = 0;
+        mol = &tng_data->molecules[i];
+        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        {
+            cnt += mol->n_atoms * molecule_cnt_list[i];
+            continue;
+        }
+        atom = &mol->atoms[nr % mol->n_atoms];
+        found = TNG_TRUE;
+        break;
+    }
+    if(!found)
+    {
+        return(TNG_FAILURE);
     }
 
-    return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
-                                     id, atom));
+    strncpy(type, atom->atom_type, max_len - 1);
+    type[max_len - 1] = 0;
+
+    if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
+    {
+        return(TNG_FAILURE);
+    }
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
-                (tng_trajectory_t tng_data,
-                 tng_residue_t residue,
-                 const char *atom_name,
-                 const char *atom_type,
-                 const int64_t id,
-                 tng_atom_t *atom)
+tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
+                (const tng_trajectory_t tng_data,
+                 const int64_t num_first_particle,
+                 const int64_t n_particles,
+                 const int64_t *mapping_table)
 {
-    tng_atom_t new_atoms;
-    tng_molecule_t molecule = residue->chain->molecule;
-    tng_function_status stat = TNG_SUCCESS;
+    int64_t i;
+    tng_particle_mapping_t mapping;
+    tng_trajectory_frame_set_t frame_set;
 
     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.");
 
-    if(!residue->n_atoms)
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    /* Sanity check of the particle ranges. Split into multiple if
+     * statements for improved readability */
+    for(i = 0; i < frame_set->n_mapping_blocks; i++)
     {
-        residue->atoms_offset = molecule->n_atoms;
+        mapping = &frame_set->mappings[i];
+        if(num_first_particle >= mapping->num_first_particle &&
+           num_first_particle < mapping->num_first_particle +
+                                   mapping->n_particles)
+        {
+            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
+        if(num_first_particle + n_particles >=
+           mapping->num_first_particle &&
+           num_first_particle + n_particles <
+           mapping->num_first_particle + mapping->n_particles)
+        {
+            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
+        if(mapping->num_first_particle >= num_first_particle &&
+           mapping->num_first_particle < num_first_particle +
+                                            n_particles)
+        {
+            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
+        if(mapping->num_first_particle + mapping->n_particles >
+           num_first_particle &&
+           mapping->num_first_particle + mapping->n_particles <
+           num_first_particle + n_particles)
+        {
+            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
     }
 
-    new_atoms = realloc(molecule->atoms,
-                        sizeof(struct tng_atom) *
-                        (molecule->n_atoms + 1));
+    frame_set->n_mapping_blocks++;
 
-    if(!new_atoms)
+    mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
+                      frame_set->n_mapping_blocks);
+
+    if(!mapping)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_atom) * (molecule->n_atoms + 1),
+               sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
                __FILE__, __LINE__);
-        free(molecule->atoms);
-        molecule->atoms = 0;
+        free(frame_set->mappings);
+        frame_set->mappings = 0;
         return(TNG_CRITICAL);
     }
+    frame_set->mappings = mapping;
 
-    molecule->atoms = new_atoms;
+    frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
+    frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
 
-    *atom = &new_atoms[molecule->n_atoms];
-
-    tng_atom_init(*atom);
-    tng_atom_name_set(tng_data, *atom, atom_name);
-    tng_atom_type_set(tng_data, *atom, atom_type);
-
-    (*atom)->residue = residue;
-
-    residue->n_atoms++;
-    molecule->n_atoms++;
-
-    (*atom)->id = id;
-
-    return(stat);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
-                                                         tng_molecule_t *molecule_p)
-{
-    *molecule_p = malloc(sizeof(struct tng_molecule));
-    if(!*molecule_p)
+    frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
+    if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-               sizeof(struct tng_molecule), __FILE__, __LINE__);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(int64_t) * n_particles, __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    tng_molecule_init(tng_data, *molecule_p);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
-                                                        tng_molecule_t *molecule_p)
-{
-    if(!*molecule_p)
+    for(i=0; i<n_particles; i++)
     {
-        return(TNG_SUCCESS);
+        frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
     }
 
-    tng_molecule_destroy(tng_data, *molecule_p);
-
-    free(*molecule_p);
-    *molecule_p = 0;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
-                                                        tng_molecule_t molecule)
-{
-    (void)tng_data;
-    molecule->quaternary_str = 1;
-    molecule->name = 0;
-    molecule->n_chains = 0;
-    molecule->chains = 0;
-    molecule->n_residues = 0;
-    molecule->residues = 0;
-    molecule->n_atoms = 0;
-    molecule->atoms = 0;
-    molecule->n_bonds = 0;
-    molecule->bonds = 0;
-
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
-                                                           tng_molecule_t molecule)
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
 {
+    tng_trajectory_frame_set_t frame_set;
+    tng_particle_mapping_t mapping;
     int64_t i;
-    (void)tng_data;
 
-    if(molecule->name)
-    {
-        free(molecule->name);
-        molecule->name = 0;
-    }
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-    if(molecule->chains)
-    {
-        for(i = 0; i < molecule->n_chains; i++)
-        {
-            if(molecule->chains[i].name)
-            {
-                free(molecule->chains[i].name);
-                molecule->chains[i].name = 0;
-            }
-        }
-        free(molecule->chains);
-        molecule->chains = 0;
-    }
-    molecule->n_chains = 0;
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-    if(molecule->residues)
+    if(frame_set->n_mapping_blocks && frame_set->mappings)
     {
-        for(i = 0; i < molecule->n_residues; i++)
+        for(i = 0; i < frame_set->n_mapping_blocks; i++)
         {
-            if(molecule->residues[i].name)
+            mapping = &frame_set->mappings[i];
+            if(mapping->real_particle_numbers)
             {
-                free(molecule->residues[i].name);
-                molecule->residues[i].name = 0;
+                free(mapping->real_particle_numbers);
+                mapping->real_particle_numbers = 0;
             }
         }
-        free(molecule->residues);
-        molecule->residues = 0;
-    }
-    molecule->n_residues = 0;
-
-    if(molecule->atoms)
-    {
-        for(i = 0; i < molecule->n_atoms; i++)
-        {
-            tng_atom_destroy(&molecule->atoms[i]);
-        }
-        free(molecule->atoms);
-        molecule->atoms = 0;
-    }
-    molecule->n_atoms = 0;
-
-    if(molecule->bonds)
-    {
-        free(molecule->bonds);
-        molecule->bonds = 0;
+        free(frame_set->mappings);
+        frame_set->mappings = 0;
+        frame_set->n_mapping_blocks = 0;
     }
-    molecule->n_bonds = 0;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 char *name,
-                 int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
 {
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
-
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
-
-    if(!molecule_cnt_list)
-    {
-        return(TNG_FAILURE);
-    }
-
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
-        {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
-        }
-        found = TNG_TRUE;
-        break;
-    }
-    if(!found)
-    {
-        return(TNG_FAILURE);
-    }
-
-    strncpy(name, mol->name, max_len - 1);
-    name[max_len - 1] = 0;
+    time_t seconds;
+    tng_trajectory_frame_set_t frame_set;
+    tng_trajectory_t tng_data;
 
-    if(strlen(mol->name) > (unsigned int)max_len - 1)
+    *tng_data_p = malloc(sizeof(struct tng_trajectory));
+    if(!*tng_data_p)
     {
-        return(TNG_FAILURE);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+               sizeof(struct tng_trajectory), __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
-    return(TNG_SUCCESS);
-}
 
-tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 int64_t *id)
-{
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_bool found = TNG_FALSE;
+    tng_data = *tng_data_p;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+    tng_data->input_file_path = 0;
+    tng_data->input_file = 0;
+    tng_data->input_file_len = 0;
+    tng_data->output_file_path = 0;
+    tng_data->output_file = 0;
 
-    if(!molecule_cnt_list)
-    {
-        return(TNG_FAILURE);
-    }
+    tng_data->first_program_name = 0;
+    tng_data->first_user_name = 0;
+    tng_data->first_computer_name = 0;
+    tng_data->first_pgp_signature = 0;
+    tng_data->last_program_name = 0;
+    tng_data->last_user_name = 0;
+    tng_data->last_computer_name = 0;
+    tng_data->last_pgp_signature = 0;
+    tng_data->forcefield_name = 0;
 
-    for(i = 0; i < tng_data->n_molecules; i++)
+    seconds = time(0);
+    if ( seconds == -1)
     {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
-        {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
-        }
-        found = TNG_TRUE;
-        break;
+        fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
     }
-    if(!found)
+    else
     {
-        return(TNG_FAILURE);
+        tng_data->time = seconds;
     }
 
-    *id = mol->id;
+    tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
+    tng_data->first_trajectory_frame_set_input_file_pos = -1;
+    tng_data->last_trajectory_frame_set_input_file_pos = -1;
+    tng_data->current_trajectory_frame_set_input_file_pos = -1;
+    tng_data->first_trajectory_frame_set_output_file_pos = -1;
+    tng_data->last_trajectory_frame_set_output_file_pos = -1;
+    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->medium_stride_length = 100;
+    tng_data->long_stride_length = 10000;
 
-    return(TNG_SUCCESS);
-}
+    tng_data->time_per_frame = -1;
 
-tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
-                (const tng_trajectory_t tng_data,
-                 int64_t *n_bonds,
-                 int64_t **from_atoms,
-                 int64_t **to_atoms)
-{
-    int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
-    int64_t from_atom, to_atom, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_bond_t bond;
+    tng_data->n_particle_data_blocks = 0;
+    tng_data->n_data_blocks = 0;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
-    TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
-    TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
+    tng_data->non_tr_particle_data = 0;
+    tng_data->non_tr_data = 0;
 
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+    tng_data->compress_algo_pos = 0;
+    tng_data->compress_algo_vel = 0;
+    tng_data->compression_precision = 1000;
+    tng_data->distance_unit_exponential = -9;
 
-    if(!molecule_cnt_list)
-    {
-        return(TNG_FAILURE);
-    }
+    frame_set->first_frame = -1;
+    frame_set->n_mapping_blocks = 0;
+    frame_set->mappings = 0;
+    frame_set->molecule_cnt_list = 0;
 
-    *n_bonds = 0;
-    /* First count the total number of bonds to allocate memory */
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        mol = &tng_data->molecules[i];
-        mol_cnt = molecule_cnt_list[i];
-        *n_bonds += mol_cnt * mol->n_bonds;
-    }
-    if(*n_bonds == 0)
-    {
-        return(TNG_SUCCESS);
-    }
+    frame_set->n_particle_data_blocks = 0;
+    frame_set->n_data_blocks = 0;
+
+    frame_set->tr_particle_data = 0;
+    frame_set->tr_data = 0;
+
+    frame_set->n_written_frames = 0;
+    frame_set->n_unwritten_frames = 0;
+
+    frame_set->next_frame_set_file_pos = -1;
+    frame_set->prev_frame_set_file_pos = -1;
+    frame_set->medium_stride_next_frame_set_file_pos = -1;
+    frame_set->medium_stride_prev_frame_set_file_pos = -1;
+    frame_set->long_stride_next_frame_set_file_pos = -1;
+    frame_set->long_stride_prev_frame_set_file_pos = -1;
+
+    frame_set->first_frame_time = -1;
+
+    tng_data->n_molecules = 0;
+    tng_data->molecules = 0;
+    tng_data->molecule_cnt_list = 0;
+    tng_data->n_particles = 0;
 
-    *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
-    if(!*from_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+      /* Check the endianness of the computer */
+      static int32_t endianness_32 = 0x01234567;
+      /* 0x01234567 */
+      if ( *(const unsigned char*)&endianness_32 == 0x01 )
+        {
+          tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
+        }
+
+      /* 0x67452301 */
+      else if( *(const unsigned char*)&endianness_32 == 0x67 )
+        {
+          tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
+
+        }
+
+      /* 0x45670123 */
+      else if ( *(const unsigned char*)&endianness_32 == 0x45 )
+        {
+          tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
+        }
     }
-    *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
-    if(!*to_atoms)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
-        free(*from_atoms);
-        *from_atoms = 0;
-        return(TNG_CRITICAL);
-    }
+      static int64_t endianness_64 = 0x0123456789ABCDEFLL;
+      /* 0x0123456789ABCDEF */
+      if ( *(const unsigned char*)&endianness_64 == 0x01 )
+        {
+          tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
+        }
 
-    cnt = 0;
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        mol = &tng_data->molecules[i];
-        mol_cnt = molecule_cnt_list[i];
-        for(j = 0; j < mol_cnt; j++)
+      /* 0xEFCDAB8967452301 */
+      else if ( *(const unsigned char*)&endianness_64 == 0xEF )
         {
-            for(k = 0; k < mol->n_bonds; k++)
-            {
-                bond = &mol->bonds[k];
-                from_atom = atom_cnt + bond->from_atom_id;
-                to_atom = atom_cnt + bond->to_atom_id;
-                (*from_atoms)[cnt] = from_atom;
-                (*to_atoms)[cnt++] = to_atom;
-            }
-            atom_cnt += mol->n_atoms;
+          tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
+        }
+
+      /* 0x89ABCDEF01234567 */
+      else if ( *(const unsigned char*)&endianness_64 == 0x89 )
+        {
+          tng_data->endianness_64 = TNG_QUAD_SWAP_64;
+        }
+
+      /* 0x45670123CDEF89AB */
+      else if ( *(const unsigned char*)&endianness_64 == 0x45 )
+        {
+          tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
+        }
+
+      /* 0x23016745AB89EFCD */
+      else if ( *(const unsigned char*)&endianness_64 == 0x23 )
+        {
+          tng_data->endianness_64 = TNG_BYTE_SWAP_64;
         }
     }
 
+    /* By default do not swap the byte order, i.e. keep the byte order of the
+     * architecture. The input file endianness will be set when reading the
+     * header. The output endianness can be changed - before the file is
+     * written. */
+    tng_data->input_endianness_swap_func_32 = 0;
+    tng_data->input_endianness_swap_func_64 = 0;
+    tng_data->output_endianness_swap_func_32 = 0;
+    tng_data->output_endianness_swap_func_64 = 0;
+
+    tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
+    tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
+    tng_data->current_trajectory_frame_set.n_frames = 0;
+
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 char *name,
-                 int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
 {
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
-
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+    int64_t i, j, k, l;
+    int64_t n_particles, n_values_per_frame;
+    tng_trajectory_t tng_data = *tng_data_p;
+    tng_trajectory_frame_set_t frame_set;
 
-    if(!molecule_cnt_list)
+    if(!*tng_data_p)
     {
-        return(TNG_FAILURE);
+        return(TNG_SUCCESS);
     }
 
-    for(i = 0; i < tng_data->n_molecules; i++)
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    if(tng_data->input_file)
     {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        if(tng_data->output_file == tng_data->input_file)
         {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
+            tng_frame_set_finalize(tng_data, TNG_USE_HASH);
+            tng_data->output_file = 0;
         }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
+        fclose(tng_data->input_file);
+        tng_data->input_file = 0;
     }
-    if(!found)
+
+    if(tng_data->input_file_path)
     {
-        return(TNG_FAILURE);
+        free(tng_data->input_file_path);
+        tng_data->input_file_path = 0;
     }
-    if(!atom->residue || !atom->residue->chain)
+
+    if(tng_data->output_file)
     {
-        return(TNG_FAILURE);
+        /* FIXME: Do not always write the hash */
+        tng_frame_set_finalize(tng_data, TNG_USE_HASH);
+        fclose(tng_data->output_file);
+        tng_data->output_file = 0;
     }
 
-    strncpy(name, atom->residue->chain->name, max_len - 1);
-    name[max_len - 1] = 0;
-
-    if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
+    if(tng_data->output_file_path)
     {
-        return(TNG_FAILURE);
+        free(tng_data->output_file_path);
+        tng_data->output_file_path = 0;
     }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 char *name,
-                 int max_len)
-{
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+    if(tng_data->first_program_name)
+    {
+        free(tng_data->first_program_name);
+        tng_data->first_program_name = 0;
+    }
 
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+    if(tng_data->last_program_name)
+    {
+        free(tng_data->last_program_name);
+        tng_data->last_program_name = 0;
+    }
 
-    if(!molecule_cnt_list)
+    if(tng_data->first_user_name)
     {
-        return(TNG_FAILURE);
+        free(tng_data->first_user_name);
+        tng_data->first_user_name = 0;
     }
 
-    for(i = 0; i < tng_data->n_molecules; i++)
+    if(tng_data->last_user_name)
     {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
-        {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
-        }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
+        free(tng_data->last_user_name);
+        tng_data->last_user_name = 0;
     }
-    if(!found)
+
+    if(tng_data->first_computer_name)
     {
-        return(TNG_FAILURE);
+        free(tng_data->first_computer_name);
+        tng_data->first_computer_name = 0;
     }
-    if(!atom->residue)
+
+    if(tng_data->last_computer_name)
     {
-        return(TNG_FAILURE);
+        free(tng_data->last_computer_name);
+        tng_data->last_computer_name = 0;
     }
 
-    strncpy(name, atom->residue->name, max_len - 1);
-    name[max_len - 1] = 0;
+    if(tng_data->first_pgp_signature)
+    {
+        free(tng_data->first_pgp_signature);
+        tng_data->first_pgp_signature = 0;
+    }
 
-    if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
+    if(tng_data->last_pgp_signature)
     {
-        return(TNG_FAILURE);
+        free(tng_data->last_pgp_signature);
+        tng_data->last_pgp_signature = 0;
     }
-    return(TNG_SUCCESS);
-}
 
-tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 int64_t *id)
-{
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
-
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
-
-    if(!molecule_cnt_list)
-    {
-        return(TNG_FAILURE);
-    }
-
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
-        {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
-        }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
-    }
-    if(!found)
-    {
-        return(TNG_FAILURE);
-    }
-    if(!atom->residue)
+    if(tng_data->forcefield_name)
     {
-        return(TNG_FAILURE);
+        free(tng_data->forcefield_name);
+        tng_data->forcefield_name = 0;
     }
 
-    *id = atom->residue->id;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 int64_t *id)
-{
-    int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
-
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+    tng_frame_set_particle_mapping_free(tng_data);
 
-    if(!molecule_cnt_list)
+    if(frame_set->molecule_cnt_list)
     {
-        return(TNG_FAILURE);
+        free(frame_set->molecule_cnt_list);
+        frame_set->molecule_cnt_list = 0;
     }
 
-    for(i = 0; i < tng_data->n_molecules; i++)
-    {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
-        {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            offset += mol->n_residues * molecule_cnt_list[i];
-            continue;
-        }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
-    }
-    if(!found)
+    if(tng_data->var_num_atoms_flag)
     {
-        return(TNG_FAILURE);
+        n_particles = frame_set->n_particles;
     }
-    if(!atom->residue)
+    else
     {
-        return(TNG_FAILURE);
+        n_particles = tng_data->n_particles;
     }
 
-    offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
-
-    *id = atom->residue->id + offset;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 char *name,
-                 int max_len)
-{
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+    if(tng_data->non_tr_particle_data)
+    {
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
+        {
+            if(tng_data->non_tr_particle_data[i].values)
+            {
+                free(tng_data->non_tr_particle_data[i].values);
+                tng_data->non_tr_particle_data[i].values = 0;
+            }
 
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
+            if(tng_data->non_tr_particle_data[i].strings)
+            {
+                n_values_per_frame = tng_data->non_tr_particle_data[i].
+                                     n_values_per_frame;
+                if(tng_data->non_tr_particle_data[i].strings[0])
+                {
+                    for(j = 0; j < n_particles; j++)
+                    {
+                        if(tng_data->non_tr_particle_data[i].strings[0][j])
+                        {
+                            for(k = 0; k < n_values_per_frame; k++)
+                            {
+                                if(tng_data->non_tr_particle_data[i].
+                                   strings[0][j][k])
+                                {
+                                    free(tng_data->non_tr_particle_data[i].
+                                         strings[0][j][k]);
+                                    tng_data->non_tr_particle_data[i].
+                                    strings[0][j][k] = 0;
+                                }
+                            }
+                            free(tng_data->non_tr_particle_data[i].
+                                 strings[0][j]);
+                            tng_data->non_tr_particle_data[i].strings[0][j] = 0;
+                        }
+                    }
+                    free(tng_data->non_tr_particle_data[i].strings[0]);
+                    tng_data->non_tr_particle_data[i].strings[0] = 0;
+                }
+                free(tng_data->non_tr_particle_data[i].strings);
+                tng_data->non_tr_particle_data[i].strings = 0;
+            }
 
-    if(!molecule_cnt_list)
-    {
-        return(TNG_FAILURE);
+            if(tng_data->non_tr_particle_data[i].block_name)
+            {
+                free(tng_data->non_tr_particle_data[i].block_name);
+                tng_data->non_tr_particle_data[i].block_name = 0;
+            }
+        }
+        free(tng_data->non_tr_particle_data);
+        tng_data->non_tr_particle_data = 0;
     }
 
-    for(i = 0; i < tng_data->n_molecules; i++)
+    if(tng_data->non_tr_data)
     {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        for(i = 0; i < tng_data->n_data_blocks; i++)
         {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
+            if(tng_data->non_tr_data[i].values)
+            {
+                free(tng_data->non_tr_data[i].values);
+                tng_data->non_tr_data[i].values = 0;
+            }
+
+            if(tng_data->non_tr_data[i].strings)
+            {
+                n_values_per_frame = tng_data->non_tr_data[i].
+                                     n_values_per_frame;
+                if(tng_data->non_tr_data[i].strings[0][0])
+                {
+                    for(j = 0; j < n_values_per_frame; j++)
+                    {
+                        if(tng_data->non_tr_data[i].strings[0][0][j])
+                        {
+                            free(tng_data->non_tr_data[i].strings[0][0][j]);
+                            tng_data->non_tr_data[i].strings[0][0][j] = 0;
+                        }
+                    }
+                    free(tng_data->non_tr_data[i].strings[0][0]);
+                    tng_data->non_tr_data[i].strings[0][0] = 0;
+                }
+                free(tng_data->non_tr_data[i].strings[0]);
+                tng_data->non_tr_data[i].strings[0] = 0;
+                free(tng_data->non_tr_data[i].strings);
+                tng_data->non_tr_data[i].strings = 0;
+            }
+
+            if(tng_data->non_tr_data[i].block_name)
+            {
+                free(tng_data->non_tr_data[i].block_name);
+                tng_data->non_tr_data[i].block_name = 0;
+            }
         }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
-    }
-    if(!found)
-    {
-        return(TNG_FAILURE);
+        free(tng_data->non_tr_data);
+        tng_data->non_tr_data = 0;
     }
 
-    strncpy(name, atom->name, max_len - 1);
-    name[max_len - 1] = 0;
+    tng_data->n_particle_data_blocks = 0;
+    tng_data->n_data_blocks = 0;
 
-    if(strlen(atom->name) > (unsigned int)max_len - 1)
+    if(tng_data->compress_algo_pos)
     {
-        return(TNG_FAILURE);
+        free(tng_data->compress_algo_pos);
+        tng_data->compress_algo_pos = 0;
     }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status tng_atom_type_of_particle_nr_get
-                (const tng_trajectory_t tng_data,
-                 const int64_t nr,
-                 char *type,
-                 int max_len)
-{
-    int64_t cnt = 0, i, *molecule_cnt_list = 0;
-    tng_molecule_t mol;
-    tng_atom_t atom;
-    tng_bool found = TNG_FALSE;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
-    tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
-
-    if(!molecule_cnt_list)
+    if(tng_data->compress_algo_vel)
     {
-        return(TNG_FAILURE);
+        free(tng_data->compress_algo_vel);
+        tng_data->compress_algo_vel = 0;
     }
 
-    for(i = 0; i < tng_data->n_molecules; i++)
+    if(frame_set->tr_particle_data)
     {
-        mol = &tng_data->molecules[i];
-        if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
-            cnt += mol->n_atoms * molecule_cnt_list[i];
-            continue;
-        }
-        atom = &mol->atoms[nr % mol->n_atoms];
-        found = TNG_TRUE;
-        break;
-    }
-    if(!found)
-    {
-        return(TNG_FAILURE);
-    }
+            if(frame_set->tr_particle_data[i].values)
+            {
+                free(frame_set->tr_particle_data[i].values);
+                frame_set->tr_particle_data[i].values = 0;
+            }
 
-    strncpy(type, atom->atom_type, max_len - 1);
-    type[max_len - 1] = 0;
+            if(frame_set->tr_particle_data[i].strings)
+            {
+                n_values_per_frame = frame_set->tr_particle_data[i].
+                                     n_values_per_frame;
+                for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
+                {
+                    if(frame_set->tr_particle_data[i].strings[j])
+                    {
+                        for(k = 0; k < n_particles; k++)
+                        {
+                            if(frame_set->tr_particle_data[i].
+                                strings[j][k])
+                            {
+                                for(l = 0; l < n_values_per_frame; l++)
+                                {
+                                    if(frame_set->tr_particle_data[i].
+                                        strings[j][k][l])
+                                    {
+                                        free(frame_set->tr_particle_data[i].
+                                                strings[j][k][l]);
+                                        frame_set->tr_particle_data[i].
+                                        strings[j][k][l] = 0;
+                                    }
+                                }
+                                free(frame_set->tr_particle_data[i].
+                                        strings[j][k]);
+                                frame_set->tr_particle_data[i].
+                                strings[j][k] = 0;
+                            }
+                        }
+                        free(frame_set->tr_particle_data[i].strings[j]);
+                        frame_set->tr_particle_data[i].strings[j] = 0;
+                    }
+                }
+                free(frame_set->tr_particle_data[i].strings);
+                frame_set->tr_particle_data[i].strings = 0;
+            }
 
-    if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
+            if(frame_set->tr_particle_data[i].block_name)
+            {
+                free(frame_set->tr_particle_data[i].block_name);
+                frame_set->tr_particle_data[i].block_name = 0;
+            }
+        }
+        free(frame_set->tr_particle_data);
+        frame_set->tr_particle_data = 0;
     }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
-                (tng_trajectory_t tng_data,
-                 const int64_t num_first_particle,
-                 const int64_t n_particles,
-                 const int64_t *mapping_table)
-{
-    int64_t i;
-    tng_particle_mapping_t mapping;
-    tng_trajectory_frame_set_t frame_set;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
 
-    /* Sanity check of the particle ranges. Split into multiple if
-     * statements for improved readability */
-    for(i = 0; i < frame_set->n_mapping_blocks; i++)
+    if(frame_set->tr_data)
     {
-        mapping = &frame_set->mappings[i];
-        if(num_first_particle >= mapping->num_first_particle &&
-           num_first_particle < mapping->num_first_particle +
-                                   mapping->n_particles)
-        {
-            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
-            return(TNG_FAILURE);
-        }
-        if(num_first_particle + n_particles >=
-           mapping->num_first_particle &&
-           num_first_particle + n_particles <
-           mapping->num_first_particle + mapping->n_particles)
-        {
-            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
-            return(TNG_FAILURE);
-        }
-        if(mapping->num_first_particle >= num_first_particle &&
-           mapping->num_first_particle < num_first_particle +
-                                            n_particles)
-        {
-            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
-            return(TNG_FAILURE);
-        }
-        if(mapping->num_first_particle + mapping->n_particles >
-           num_first_particle &&
-           mapping->num_first_particle + mapping->n_particles <
-           num_first_particle + n_particles)
+        for(i = 0; i < frame_set->n_data_blocks; i++)
         {
-            fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
-            return(TNG_FAILURE);
-        }
-    }
-
-    frame_set->n_mapping_blocks++;
+            if(frame_set->tr_data[i].values)
+            {
+                free(frame_set->tr_data[i].values);
+                frame_set->tr_data[i].values = 0;
+            }
 
-    mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
-                      frame_set->n_mapping_blocks);
+            if(frame_set->tr_data[i].strings)
+            {
+                n_values_per_frame = frame_set->tr_data[i].
+                                     n_values_per_frame;
+                for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
+                {
+                    if(frame_set->tr_data[i].strings[j])
+                    {
+                        for(k = 0; k < n_values_per_frame; k++)
+                        {
+                            if(frame_set->tr_data[i].strings[j][k])
+                            {
+                                free(frame_set->tr_data[i].strings[j][k]);
+                                frame_set->tr_data[i].strings[j][k] = 0;
+                            }
+                        }
+                        free(frame_set->tr_data[i].strings[j]);
+                        frame_set->tr_data[i].strings[j] = 0;
+                    }
+                }
+                free(frame_set->tr_data[i].strings);
+                frame_set->tr_data[i].strings = 0;
+            }
 
-    if(!mapping)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
-               __FILE__, __LINE__);
-        free(frame_set->mappings);
-        frame_set->mappings = 0;
-        return(TNG_CRITICAL);
+            if(frame_set->tr_data[i].block_name)
+            {
+                free(frame_set->tr_data[i].block_name);
+                frame_set->tr_data[i].block_name = 0;
+            }
+        }
+        free(frame_set->tr_data);
+        frame_set->tr_data = 0;
     }
-    frame_set->mappings = mapping;
 
-    frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
-    frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
+    frame_set->n_particle_data_blocks = 0;
+    frame_set->n_data_blocks = 0;
 
-    frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
-    if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
+    if(tng_data->molecules)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(int64_t) * n_particles, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        for(i = 0; i < tng_data->n_molecules; i++)
+        {
+            tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
+        }
+        free(tng_data->molecules);
+        tng_data->molecules = 0;
+        tng_data->n_molecules = 0;
     }
-
-    for(i=0; i<n_particles; i++)
+    if(tng_data->molecule_cnt_list)
     {
-        frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
+        free(tng_data->molecule_cnt_list);
+        tng_data->molecule_cnt_list = 0;
     }
 
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(tng_trajectory_t tng_data)
-{
-    tng_trajectory_frame_set_t frame_set;
-    tng_particle_mapping_t mapping;
-    int64_t i;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    if(frame_set->n_mapping_blocks && frame_set->mappings)
-    {
-        for(i = 0; i < frame_set->n_mapping_blocks; i++)
-        {
-            mapping = &frame_set->mappings[i];
-            if(mapping->real_particle_numbers)
-            {
-                free(mapping->real_particle_numbers);
-                mapping->real_particle_numbers = 0;
-            }
-        }
-        free(frame_set->mappings);
-        frame_set->mappings = 0;
-        frame_set->n_mapping_blocks = 0;
-    }
+    free(*tng_data_p);
+    *tng_data_p = 0;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
+tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
+                (const tng_trajectory_t src,
+                 tng_trajectory_t *dest_p)
 {
-    time_t seconds;
     tng_trajectory_frame_set_t frame_set;
-    tng_trajectory_t tng_data;
+    tng_trajectory_t dest;
 
-    *tng_data_p = malloc(sizeof(struct tng_trajectory));
-    if(!*tng_data_p)
+    TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
+
+    *dest_p = malloc(sizeof(struct tng_trajectory));
+    if(!*dest_p)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
+        fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
                sizeof(struct tng_trajectory), __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    tng_data = *tng_data_p;
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    tng_data->input_file_path = 0;
-    tng_data->input_file = 0;
-    tng_data->input_file_len = 0;
-    tng_data->output_file_path = 0;
-    tng_data->output_file = 0;
+    dest = *dest_p;
 
-    tng_data->first_program_name = 0;
-    tng_data->first_user_name = 0;
-    tng_data->first_computer_name = 0;
-    tng_data->first_pgp_signature = 0;
-    tng_data->last_program_name = 0;
-    tng_data->last_user_name = 0;
-    tng_data->last_computer_name = 0;
-    tng_data->last_pgp_signature = 0;
-    tng_data->forcefield_name = 0;
+    frame_set = &dest->current_trajectory_frame_set;
 
-    seconds = time(0);
-    if ( seconds == -1)
+    if(src->input_file_path)
     {
-        fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
+        dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
+        if(!dest->input_file_path)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
+                   (unsigned int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        strcpy(dest->input_file_path, src->input_file_path);
+        dest->input_file_len = src->input_file_len;
     }
     else
     {
-        tng_data->time = seconds;
+        dest->input_file_path = 0;
+    }
+    dest->input_file = 0;
+    if(src->output_file_path)
+    {
+        dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
+        if(!dest->output_file_path)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
+                   (unsigned int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        strcpy(dest->output_file_path, src->output_file_path);
+    }
+    else
+    {
+        dest->output_file_path = 0;
     }
+    dest->output_file = 0;
 
-    tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
-    tng_data->first_trajectory_frame_set_input_file_pos = -1;
-    tng_data->last_trajectory_frame_set_input_file_pos = -1;
-    tng_data->current_trajectory_frame_set_input_file_pos = -1;
-    tng_data->first_trajectory_frame_set_output_file_pos = -1;
-    tng_data->last_trajectory_frame_set_output_file_pos = -1;
-    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->medium_stride_length = 100;
-    tng_data->long_stride_length = 10000;
+    dest->first_program_name = 0;
+    dest->first_user_name = 0;
+    dest->first_computer_name = 0;
+    dest->first_pgp_signature = 0;
+    dest->last_program_name = 0;
+    dest->last_user_name = 0;
+    dest->last_computer_name = 0;
+    dest->last_pgp_signature = 0;
+    dest->forcefield_name = 0;
 
-    tng_data->time_per_frame = -1;
+    dest->var_num_atoms_flag = src->var_num_atoms_flag;
+    dest->first_trajectory_frame_set_input_file_pos =
+    src->first_trajectory_frame_set_input_file_pos;
+    dest->last_trajectory_frame_set_input_file_pos =
+    src->last_trajectory_frame_set_input_file_pos;
+    dest->current_trajectory_frame_set_input_file_pos =
+    src->current_trajectory_frame_set_input_file_pos;
+    dest->first_trajectory_frame_set_output_file_pos =
+    src->first_trajectory_frame_set_output_file_pos;
+    dest->last_trajectory_frame_set_output_file_pos =
+    src->last_trajectory_frame_set_output_file_pos;
+    dest->current_trajectory_frame_set_output_file_pos =
+    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->medium_stride_length = src->medium_stride_length;
+    dest->long_stride_length = src->long_stride_length;
 
-    tng_data->n_particle_data_blocks = 0;
-    tng_data->n_data_blocks = 0;
+    dest->time_per_frame = src->time_per_frame;
 
-    tng_data->non_tr_particle_data = 0;
-    tng_data->non_tr_data = 0;
+    /* Currently the non trajectory data blocks are not copied since it
+     * can lead to problems when freeing memory in a parallel block. */
+    dest->n_particle_data_blocks = 0;
+    dest->n_data_blocks = 0;
+    dest->non_tr_particle_data = 0;
+    dest->non_tr_data = 0;
 
-    tng_data->compress_algo_pos = 0;
-    tng_data->compress_algo_vel = 0;
-    tng_data->compression_precision = 1000;
-    tng_data->distance_unit_exponential = -9;
+    dest->compress_algo_pos = 0;
+    dest->compress_algo_vel = 0;
+    dest->distance_unit_exponential = -9;
+    dest->compression_precision = 1000;
 
-    frame_set->first_frame = -1;
     frame_set->n_mapping_blocks = 0;
     frame_set->mappings = 0;
     frame_set->molecule_cnt_list = 0;
@@ -9878,885 +9338,619 @@ tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_
     frame_set->medium_stride_prev_frame_set_file_pos = -1;
     frame_set->long_stride_next_frame_set_file_pos = -1;
     frame_set->long_stride_prev_frame_set_file_pos = -1;
+    frame_set->first_frame = -1;
 
-    frame_set->first_frame_time = -1;
-
-    tng_data->n_molecules = 0;
-    tng_data->molecules = 0;
-    tng_data->molecule_cnt_list = 0;
-    tng_data->n_particles = 0;
-
-    {
-      /* Check the endianness of the computer */
-      static int32_t endianness_32 = 0x01234567;
-      /* 0x01234567 */
-      if ( *(const unsigned char*)&endianness_32 == 0x01 )
-        {
-          tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
-        }
-
-      /* 0x67452301 */
-      else if( *(const unsigned char*)&endianness_32 == 0x67 )
-        {
-          tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
+    dest->n_molecules = 0;
+    dest->molecules = 0;
+    dest->molecule_cnt_list = 0;
+    dest->n_particles = src->n_particles;
 
-        }
+    dest->endianness_32 = src->endianness_32;
+    dest->endianness_64 = src->endianness_64;
+    dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
+    dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
+    dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
+    dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
 
-      /* 0x45670123 */
-      else if ( *(const unsigned char*)&endianness_32 == 0x45 )
-        {
-          tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
-        }
-    }
-    {
-      static int64_t endianness_64 = 0x0123456789ABCDEFLL;
-      /* 0x0123456789ABCDEF */
-      if ( *(const unsigned char*)&endianness_64 == 0x01 )
-        {
-          tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
-        }
+    dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
+    dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
+    dest->current_trajectory_frame_set.n_frames = 0;
 
-      /* 0xEFCDAB8967452301 */
-      else if ( *(const unsigned char*)&endianness_64 == 0xEF )
-        {
-          tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
-        }
+    return(TNG_SUCCESS);
+}
 
-      /* 0x89ABCDEF01234567 */
-      else if ( *(const unsigned char*)&endianness_64 == 0x89 )
-        {
-          tng_data->endianness_64 = TNG_QUAD_SWAP_64;
-        }
+tng_function_status DECLSPECDLLEXPORT tng_input_file_get
+                (const tng_trajectory_t tng_data,
+                 char *file_name,
+                 const int max_len)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
 
-      /* 0x45670123CDEF89AB */
-      else if ( *(const unsigned char*)&endianness_64 == 0x45 )
-        {
-          tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
-        }
+    strncpy(file_name, tng_data->input_file_path, max_len - 1);
+    file_name[max_len - 1] = 0;
 
-      /* 0x23016745AB89EFCD */
-      else if ( *(const unsigned char*)&endianness_64 == 0x23 )
-        {
-          tng_data->endianness_64 = TNG_BYTE_SWAP_64;
-        }
+    if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
+    {
+        return(TNG_FAILURE);
     }
-
-    /* By default do not swap the byte order, i.e. keep the byte order of the
-     * architecture. The input file endianness will be set when reading the
-     * header. The output endianness can be changed - before the file is
-     * written. */
-    tng_data->input_endianness_swap_func_32 = 0;
-    tng_data->input_endianness_swap_func_64 = 0;
-    tng_data->output_endianness_swap_func_32 = 0;
-    tng_data->output_endianness_swap_func_64 = 0;
-
-    tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
-    tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
-    tng_data->current_trajectory_frame_set.n_frames = 0;
-
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
+tng_function_status DECLSPECDLLEXPORT tng_input_file_set
+                (const tng_trajectory_t tng_data,
+                 const char *file_name)
 {
-    int64_t i, j, k, l;
-    int64_t n_particles, n_values_per_frame;
-    tng_trajectory_t tng_data = *tng_data_p;
-    tng_trajectory_frame_set_t frame_set;
+    unsigned int len;
+    char *temp;
 
-    if(!*tng_data_p)
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+
+
+    if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
+                                           file_name) == 0)
     {
         return(TNG_SUCCESS);
     }
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    if(tng_data->input_file)
+    {
+        fclose(tng_data->input_file);
+    }
 
-    if(tng_data->input_file_path)
+    len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->input_file_path, len);
+    if(!temp)
     {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
         free(tng_data->input_file_path);
         tng_data->input_file_path = 0;
+        return(TNG_CRITICAL);
     }
+    tng_data->input_file_path = temp;
 
-    if(tng_data->input_file)
+    strncpy(tng_data->input_file_path, file_name, len);
+
+    return(tng_input_file_init(tng_data));
+}
+
+tng_function_status tng_output_file_get
+                (const tng_trajectory_t tng_data,
+                 char *file_name,
+                 const int max_len)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+
+    strncpy(file_name, tng_data->output_file_path, max_len - 1);
+    file_name[max_len - 1] = 0;
+
+    if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
     {
-        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;
+        return(TNG_FAILURE);
     }
+    return(TNG_SUCCESS);
+}
 
-    if(tng_data->output_file_path)
+tng_function_status DECLSPECDLLEXPORT tng_output_file_set
+                (const tng_trajectory_t tng_data,
+                 const char *file_name)
+{
+    int len;
+    char *temp;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+
+    if(tng_data->output_file_path &&
+       strcmp(tng_data->output_file_path, file_name) == 0)
     {
-        free(tng_data->output_file_path);
-        tng_data->output_file_path = 0;
+        return(TNG_SUCCESS);
     }
 
     if(tng_data->output_file)
     {
-        /* FIXME: Do not always write the hash */
-        tng_frame_set_finalize(tng_data, TNG_USE_HASH);
         fclose(tng_data->output_file);
-        tng_data->output_file = 0;
     }
 
-    if(tng_data->first_program_name)
+    len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->output_file_path, len);
+    if(!temp)
     {
-        free(tng_data->first_program_name);
-        tng_data->first_program_name = 0;
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->output_file_path);
+        tng_data->output_file_path = 0;
+        return(TNG_CRITICAL);
     }
+    tng_data->output_file_path = temp;
 
-    if(tng_data->last_program_name)
+    strncpy(tng_data->output_file_path, file_name, len);
+
+    return(tng_output_file_init(tng_data));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
+                (const tng_trajectory_t tng_data,
+                 const char *file_name)
+{
+    int len;
+    char *temp;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+
+    if(tng_data->output_file_path &&
+       strcmp(tng_data->output_file_path, file_name) == 0)
     {
-        free(tng_data->last_program_name);
-        tng_data->last_program_name = 0;
+        return(TNG_SUCCESS);
     }
 
-    if(tng_data->first_user_name)
+    if(tng_data->output_file)
     {
-        free(tng_data->first_user_name);
-        tng_data->first_user_name = 0;
+        fclose(tng_data->output_file);
     }
 
-    if(tng_data->last_user_name)
-    {
-        free(tng_data->last_user_name);
-        tng_data->last_user_name = 0;
+    len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
+    temp = realloc(tng_data->output_file_path, len);
+    if(!temp)
+    {
+        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
+               __FILE__, __LINE__);
+        free(tng_data->output_file_path);
+        tng_data->output_file_path = 0;
+        return(TNG_CRITICAL);
     }
+    tng_data->output_file_path = temp;
 
-    if(tng_data->first_computer_name)
+    strncpy(tng_data->output_file_path, file_name, len);
+
+    tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
+    if(!tng_data->output_file)
     {
-        free(tng_data->first_computer_name);
-        tng_data->first_computer_name = 0;
+        fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
+                tng_data->output_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
+    tng_data->input_file = tng_data->output_file;
 
-    if(tng_data->last_computer_name)
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
+                (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
+{
+    tng_endianness_32 end_32;
+    tng_endianness_64 end_64;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
+
+    if(tng_data->output_endianness_swap_func_32)
     {
-        free(tng_data->last_computer_name);
-        tng_data->last_computer_name = 0;
+        /* If other endianness variants are added they must be added here as well */
+        if(tng_data->output_endianness_swap_func_32 ==
+           &tng_swap_byte_order_big_endian_32)
+        {
+            end_32 = TNG_BIG_ENDIAN_32;
+        }
+        else if(tng_data->output_endianness_swap_func_32 ==
+                &tng_swap_byte_order_little_endian_32)
+        {
+            end_32 = TNG_LITTLE_ENDIAN_32;
+        }
+        else
+        {
+            return(TNG_FAILURE);
+        }
     }
-
-    if(tng_data->first_pgp_signature)
+    else
     {
-        free(tng_data->first_pgp_signature);
-        tng_data->first_pgp_signature = 0;
+        end_32 = (tng_endianness_32)tng_data->endianness_32;
     }
 
-    if(tng_data->last_pgp_signature)
+    if(tng_data->output_endianness_swap_func_64)
     {
-        free(tng_data->last_pgp_signature);
-        tng_data->last_pgp_signature = 0;
+        /* If other endianness variants are added they must be added here as well */
+        if(tng_data->output_endianness_swap_func_64 ==
+           &tng_swap_byte_order_big_endian_64)
+        {
+            end_64 = TNG_BIG_ENDIAN_64;
+        }
+        else if(tng_data->output_endianness_swap_func_64 ==
+                &tng_swap_byte_order_little_endian_64)
+        {
+            end_64 = TNG_LITTLE_ENDIAN_64;
+        }
+        else
+        {
+            return(TNG_FAILURE);
+        }
     }
-
-    if(tng_data->forcefield_name)
+    else
     {
-        free(tng_data->forcefield_name);
-        tng_data->forcefield_name = 0;
+        end_64 = (tng_endianness_64)tng_data->endianness_64;
     }
 
-    tng_frame_set_particle_mapping_free(tng_data);
+    if((int)end_32 != (int)end_64)
+    {
+        return(TNG_FAILURE);
+    }
 
-    if(frame_set->molecule_cnt_list)
+    if(end_32 == TNG_LITTLE_ENDIAN_32)
     {
-        free(frame_set->molecule_cnt_list);
-        frame_set->molecule_cnt_list = 0;
+        *endianness = TNG_LITTLE_ENDIAN;
     }
 
-    if(tng_data->var_num_atoms_flag)
+    else if(end_32 == TNG_BIG_ENDIAN_32)
     {
-        n_particles = frame_set->n_particles;
+        *endianness = TNG_BIG_ENDIAN;
     }
     else
     {
-        n_particles = tng_data->n_particles;
+        return(TNG_FAILURE);
     }
 
-    if(tng_data->non_tr_particle_data)
-    {
-        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
-        {
-            if(tng_data->non_tr_particle_data[i].values)
-            {
-                free(tng_data->non_tr_particle_data[i].values);
-                tng_data->non_tr_particle_data[i].values = 0;
-            }
+    return(TNG_SUCCESS);
+}
 
-            if(tng_data->non_tr_particle_data[i].strings)
-            {
-                n_values_per_frame = tng_data->non_tr_particle_data[i].
-                                     n_values_per_frame;
-                if(tng_data->non_tr_particle_data[i].strings[0])
-                {
-                    for(j = 0; j < n_particles; j++)
-                    {
-                        if(tng_data->non_tr_particle_data[i].strings[0][j])
-                        {
-                            for(k = 0; k < n_values_per_frame; k++)
-                            {
-                                if(tng_data->non_tr_particle_data[i].
-                                   strings[0][j][k])
-                                {
-                                    free(tng_data->non_tr_particle_data[i].
-                                         strings[0][j][k]);
-                                    tng_data->non_tr_particle_data[i].
-                                    strings[0][j][k] = 0;
-                                }
-                            }
-                            free(tng_data->non_tr_particle_data[i].
-                                 strings[0][j]);
-                            tng_data->non_tr_particle_data[i].strings[0][j] = 0;
-                        }
-                    }
-                    free(tng_data->non_tr_particle_data[i].strings[0]);
-                    tng_data->non_tr_particle_data[i].strings[0] = 0;
-                }
-                free(tng_data->non_tr_particle_data[i].strings);
-                tng_data->non_tr_particle_data[i].strings = 0;
-            }
+tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
+                (const tng_trajectory_t tng_data,
+                 const tng_file_endianness endianness)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-            if(tng_data->non_tr_particle_data[i].block_name)
-            {
-                free(tng_data->non_tr_particle_data[i].block_name);
-                tng_data->non_tr_particle_data[i].block_name = 0;
-            }
-        }
-        free(tng_data->non_tr_particle_data);
-        tng_data->non_tr_particle_data = 0;
+    /* Tne endianness cannot be changed if the data has already been written
+     * to the output file. */
+    if(ftello(tng_data->output_file) > 0)
+    {
+        return(TNG_FAILURE);
     }
 
-    if(tng_data->non_tr_data)
+    if(endianness == TNG_BIG_ENDIAN)
     {
-        for(i = 0; i < tng_data->n_data_blocks; i++)
+        if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
         {
-            if(tng_data->non_tr_data[i].values)
-            {
-                free(tng_data->non_tr_data[i].values);
-                tng_data->non_tr_data[i].values = 0;
-            }
-
-            if(tng_data->non_tr_data[i].strings)
-            {
-                n_values_per_frame = tng_data->non_tr_data[i].
-                                     n_values_per_frame;
-                if(tng_data->non_tr_data[i].strings[0])
-                {
-                    for(j = 0; j < n_values_per_frame; j++)
-                    {
-                        if(tng_data->non_tr_data[i].strings[0][j])
-                        {
-                            free(tng_data->non_tr_data[i].strings[0][j]);
-                            tng_data->non_tr_data[i].strings[0][j] = 0;
-                        }
-                    }
-                    free(tng_data->non_tr_data[i].strings[0]);
-                    tng_data->non_tr_data[i].strings[0] = 0;
-                }
-                free(tng_data->non_tr_data[i].strings);
-                tng_data->non_tr_data[i].strings = 0;
-            }
-
-            if(tng_data->non_tr_data[i].block_name)
-            {
-                free(tng_data->non_tr_data[i].block_name);
-                tng_data->non_tr_data[i].block_name = 0;
-            }
+            tng_data->output_endianness_swap_func_32 = 0;
         }
-        free(tng_data->non_tr_data);
-        tng_data->non_tr_data = 0;
-    }
-
-    tng_data->n_particle_data_blocks = 0;
-    tng_data->n_data_blocks = 0;
-
-    if(tng_data->compress_algo_pos)
-    {
-        free(tng_data->compress_algo_pos);
-        tng_data->compress_algo_pos = 0;
+        else
+        {
+            tng_data->output_endianness_swap_func_32 =
+            &tng_swap_byte_order_big_endian_32;
+        }
+        if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
+        {
+            tng_data->output_endianness_swap_func_64 = 0;
+        }
+        else
+        {
+            tng_data->output_endianness_swap_func_64 =
+            &tng_swap_byte_order_big_endian_64;
+        }
+        return(TNG_SUCCESS);
     }
-    if(tng_data->compress_algo_vel)
+    else if(endianness == TNG_LITTLE_ENDIAN)
     {
-        free(tng_data->compress_algo_vel);
-        tng_data->compress_algo_vel = 0;
+        if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
+        {
+            tng_data->output_endianness_swap_func_32 = 0;
+        }
+        else
+        {
+            tng_data->output_endianness_swap_func_32 =
+            &tng_swap_byte_order_little_endian_32;
+        }
+        if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
+        {
+            tng_data->output_endianness_swap_func_64 = 0;
+        }
+        else
+        {
+            tng_data->output_endianness_swap_func_64 =
+            &tng_swap_byte_order_little_endian_64;
+        }
+        return(TNG_SUCCESS);
     }
 
-    if(frame_set->tr_particle_data)
-    {
-        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
-        {
-            if(frame_set->tr_particle_data[i].values)
-            {
-                free(frame_set->tr_particle_data[i].values);
-                frame_set->tr_particle_data[i].values = 0;
-            }
+    /* If the specified endianness is neither big nor little endian return a
+     * failure. */
+    return(TNG_FAILURE);
+}
 
-            if(frame_set->tr_particle_data[i].strings)
-            {
-                n_values_per_frame = frame_set->tr_particle_data[i].
-                                     n_values_per_frame;
-                for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
-                {
-                    if(frame_set->tr_particle_data[i].strings[j])
-                    {
-                        for(k = 0; k < n_particles; k++)
-                        {
-                            if(frame_set->tr_particle_data[i].
-                                strings[j][k])
-                            {
-                                for(l = 0; l < n_values_per_frame; l++)
-                                {
-                                    if(frame_set->tr_particle_data[i].
-                                        strings[j][k][l])
-                                    {
-                                        free(frame_set->tr_particle_data[i].
-                                                strings[j][k][l]);
-                                        frame_set->tr_particle_data[i].
-                                        strings[j][k][l] = 0;
-                                    }
-                                }
-                                free(frame_set->tr_particle_data[i].
-                                        strings[j][k]);
-                                frame_set->tr_particle_data[i].
-                                strings[j][k] = 0;
-                            }
-                        }
-                        free(frame_set->tr_particle_data[i].strings[j]);
-                        frame_set->tr_particle_data[i].strings[j] = 0;
-                    }
-                }
-                free(frame_set->tr_particle_data[i].strings);
-                frame_set->tr_particle_data[i].strings = 0;
-            }
-
-            if(frame_set->tr_particle_data[i].block_name)
-            {
-                free(frame_set->tr_particle_data[i].block_name);
-                frame_set->tr_particle_data[i].block_name = 0;
-            }
-        }
-        free(frame_set->tr_particle_data);
-        frame_set->tr_particle_data = 0;
-    }
-
-    if(frame_set->tr_data)
-    {
-        for(i = 0; i < frame_set->n_data_blocks; i++)
-        {
-            if(frame_set->tr_data[i].values)
-            {
-                free(frame_set->tr_data[i].values);
-                frame_set->tr_data[i].values = 0;
-            }
-
-            if(frame_set->tr_data[i].strings)
-            {
-                n_values_per_frame = frame_set->tr_data[i].
-                                     n_values_per_frame;
-                for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
-                {
-                    if(frame_set->tr_data[i].strings[j])
-                    {
-                        for(k = 0; k < n_values_per_frame; k++)
-                        {
-                            if(frame_set->tr_data[i].strings[j][k])
-                            {
-                                free(frame_set->tr_data[i].strings[j][k]);
-                                frame_set->tr_data[i].strings[j][k] = 0;
-                            }
-                        }
-                        free(frame_set->tr_data[i].strings[j]);
-                        frame_set->tr_data[i].strings[j] = 0;
-                    }
-                }
-                free(frame_set->tr_data[i].strings);
-                frame_set->tr_data[i].strings = 0;
-            }
-
-            if(frame_set->tr_data[i].block_name)
-            {
-                free(frame_set->tr_data[i].block_name);
-                frame_set->tr_data[i].block_name = 0;
-            }
-        }
-        free(frame_set->tr_data);
-        frame_set->tr_data = 0;
-    }
+tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name,
+                     const int max_len)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    frame_set->n_particle_data_blocks = 0;
-    frame_set->n_data_blocks = 0;
+    strncpy(name, tng_data->first_program_name, max_len - 1);
+    name[max_len - 1] = 0;
 
-    if(tng_data->molecules)
-    {
-        for(i = 0; i < tng_data->n_molecules; i++)
-        {
-            tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
-        }
-        free(tng_data->molecules);
-        tng_data->molecules = 0;
-        tng_data->n_molecules = 0;
-    }
-    if(tng_data->molecule_cnt_list)
+    if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
     {
-        free(tng_data->molecule_cnt_list);
-        tng_data->molecule_cnt_list = 0;
+        return(TNG_FAILURE);
     }
-
-    free(*tng_data_p);
-    *tng_data_p = 0;
-
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src(tng_trajectory_t src,
-                                                 tng_trajectory_t *dest_p)
+tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
+                (const tng_trajectory_t tng_data,
+                 const char *new_name)
 {
-    tng_trajectory_frame_set_t frame_set;
-    tng_trajectory_t dest;
-
-    TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
-
-    *dest_p = malloc(sizeof(struct tng_trajectory));
-    if(!*dest_p)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"TNG_PRIsize" bytes). %s: %d\n",
-               sizeof(struct tng_trajectory), __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
+    unsigned int len;
 
-    dest = *dest_p;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-    frame_set = &dest->current_trajectory_frame_set;
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
-    if(!dest->input_file_path)
+    if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-               (int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        free(tng_data->first_program_name);
+        tng_data->first_program_name = 0;
     }
-    strcpy(dest->input_file_path, src->input_file_path);
-    dest->input_file = 0;
-    dest->input_file_len = src->input_file_len;
-    dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
-    if(!dest->output_file_path)
+    if(!tng_data->first_program_name)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-               (int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        tng_data->first_program_name = malloc(len);
+        if(!tng_data->first_program_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
     }
-    strcpy(dest->output_file_path, src->output_file_path);
-    dest->output_file = 0;
-
-    dest->first_program_name = 0;
-    dest->first_user_name = 0;
-    dest->first_computer_name = 0;
-    dest->first_pgp_signature = 0;
-    dest->last_program_name = 0;
-    dest->last_user_name = 0;
-    dest->last_computer_name = 0;
-    dest->last_pgp_signature = 0;
-    dest->forcefield_name = 0;
-
-    dest->var_num_atoms_flag = src->var_num_atoms_flag;
-    dest->first_trajectory_frame_set_input_file_pos =
-    src->first_trajectory_frame_set_input_file_pos;
-    dest->last_trajectory_frame_set_input_file_pos =
-    src->last_trajectory_frame_set_input_file_pos;
-    dest->current_trajectory_frame_set_input_file_pos =
-    src->current_trajectory_frame_set_input_file_pos;
-    dest->first_trajectory_frame_set_output_file_pos =
-    src->first_trajectory_frame_set_output_file_pos;
-    dest->last_trajectory_frame_set_output_file_pos =
-    src->last_trajectory_frame_set_output_file_pos;
-    dest->current_trajectory_frame_set_output_file_pos =
-    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->medium_stride_length = src->medium_stride_length;
-    dest->long_stride_length = src->long_stride_length;
-
-    dest->time_per_frame = src->time_per_frame;
-
-    /* Currently the non trajectory data blocks are not copied since it
-     * can lead to problems when freeing memory in a parallel block. */
-    dest->n_particle_data_blocks = 0;
-    dest->n_data_blocks = 0;
-    dest->non_tr_particle_data = 0;
-    dest->non_tr_data = 0;
-
-    dest->compress_algo_pos = 0;
-    dest->compress_algo_vel = 0;
-    dest->distance_unit_exponential = -9;
-    dest->compression_precision = 1000;
-
-    frame_set->n_mapping_blocks = 0;
-    frame_set->mappings = 0;
-    frame_set->molecule_cnt_list = 0;
-
-    frame_set->n_particle_data_blocks = 0;
-    frame_set->n_data_blocks = 0;
-
-    frame_set->tr_particle_data = 0;
-    frame_set->tr_data = 0;
-
-    frame_set->next_frame_set_file_pos = -1;
-    frame_set->prev_frame_set_file_pos = -1;
-    frame_set->medium_stride_next_frame_set_file_pos = -1;
-    frame_set->medium_stride_prev_frame_set_file_pos = -1;
-    frame_set->long_stride_next_frame_set_file_pos = -1;
-    frame_set->long_stride_prev_frame_set_file_pos = -1;
-    frame_set->first_frame = -1;
-
-    dest->n_molecules = 0;
-    dest->molecules = 0;
-    dest->molecule_cnt_list = 0;
-    dest->n_particles = src->n_particles;
-
-    dest->endianness_32 = src->endianness_32;
-    dest->endianness_64 = src->endianness_64;
-    dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
-    dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
-    dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
-    dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
 
-    dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
-    dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
-    dest->current_trajectory_frame_set.n_frames = 0;
+    strncpy(tng_data->first_program_name, new_name, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_input_file_get(const tng_trajectory_t tng_data,
-                                       char *file_name, const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    strncpy(file_name, tng_data->input_file_path, max_len - 1);
-    file_name[max_len - 1] = 0;
+    strncpy(name, tng_data->last_program_name, max_len - 1);
+    name[max_len - 1] = 0;
 
-    if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
+    if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_input_file_set(tng_trajectory_t tng_data,
-                                                         const char *file_name)
+tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
+                    (const tng_trajectory_t tng_data,
+                     const char *new_name)
 {
     unsigned int len;
-    char *temp;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
-                                           file_name) == 0)
+    if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
     {
-        return(TNG_SUCCESS);
+        free(tng_data->last_program_name);
+        tng_data->last_program_name = 0;
     }
-
-    if(tng_data->input_file)
+    if(!tng_data->last_program_name)
     {
-        fclose(tng_data->input_file);
-    }
-
-    len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->input_file_path, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->input_file_path);
-        tng_data->input_file_path = 0;
-        return(TNG_CRITICAL);
+        tng_data->last_program_name = malloc(len);
+        if(!tng_data->last_program_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
     }
-    tng_data->input_file_path = temp;
 
-    strncpy(tng_data->input_file_path, file_name, len);
+    strncpy(tng_data->last_program_name, new_name, len);
 
-    return(tng_input_file_init(tng_data));
+    return(TNG_SUCCESS);
 }
 
-tng_function_status tng_output_file_get(const tng_trajectory_t tng_data,
-                                       char *file_name, const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    strncpy(file_name, tng_data->output_file_path, max_len - 1);
-    file_name[max_len - 1] = 0;
+    strncpy(name, tng_data->first_user_name, max_len - 1);
+    name[max_len - 1] = 0;
 
-    if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
+    if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_data,
-                                                          const char *file_name)
+tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
+                    (const tng_trajectory_t tng_data,
+                     const char *new_name)
 {
-    int len;
-    char *temp;
+    unsigned int len;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-    if(tng_data->output_file_path &&
-       strcmp(tng_data->output_file_path, file_name) == 0)
-    {
-        return(TNG_SUCCESS);
-    }
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    if(tng_data->output_file)
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
     {
-        fclose(tng_data->output_file);
+        free(tng_data->first_user_name);
+        tng_data->first_user_name = 0;
     }
-
-    len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->output_file_path, len);
-    if(!temp)
+    if(!tng_data->first_user_name)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->output_file_path);
-        tng_data->output_file_path = 0;
-        return(TNG_CRITICAL);
+        tng_data->first_user_name = malloc(len);
+        if(!tng_data->first_user_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
     }
-    tng_data->output_file_path = temp;
 
-    strncpy(tng_data->output_file_path, file_name, len);
+    strncpy(tng_data->first_user_name, new_name, len);
 
-    return(tng_output_file_init(tng_data));
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
-                (tng_trajectory_t tng_data,
-                 const char *file_name)
+tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name, const int max_len)
 {
-    int len;
-    char *temp;
-
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
-
-    if(tng_data->output_file_path &&
-       strcmp(tng_data->output_file_path, file_name) == 0)
-    {
-        return(TNG_SUCCESS);
-    }
-
-    if(tng_data->output_file)
-    {
-        fclose(tng_data->output_file);
-    }
-
-    len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN);
-    temp = realloc(tng_data->output_file_path, len);
-    if(!temp)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
-               __FILE__, __LINE__);
-        free(tng_data->output_file_path);
-        tng_data->output_file_path = 0;
-        return(TNG_CRITICAL);
-    }
-    tng_data->output_file_path = temp;
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    strncpy(tng_data->output_file_path, file_name, len);
+    strncpy(name, tng_data->last_user_name, max_len - 1);
+    name[max_len - 1] = 0;
 
-    tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
-    if(!tng_data->output_file)
+    if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
     {
-        fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
-                tng_data->output_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
-    tng_data->input_file = tng_data->output_file;
-
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
-                (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
+tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
+                    (const tng_trajectory_t tng_data,
+                     const char *new_name)
 {
-    tng_endianness_32 end_32;
-    tng_endianness_64 end_64;
+    unsigned int len;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-    if(tng_data->output_endianness_swap_func_32)
-    {
-        /* If other endianness variants are added they must be added here as well */
-        if(tng_data->output_endianness_swap_func_32 ==
-           &tng_swap_byte_order_big_endian_32)
-        {
-            end_32 = TNG_BIG_ENDIAN_32;
-        }
-        else if(tng_data->output_endianness_swap_func_32 ==
-                &tng_swap_byte_order_little_endian_32)
-        {
-            end_32 = TNG_LITTLE_ENDIAN_32;
-        }
-        else
-        {
-            return(TNG_FAILURE);
-        }
-    }
-    else
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
+
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
     {
-        end_32 = (tng_endianness_32)tng_data->endianness_32;
+        free(tng_data->last_user_name);
+        tng_data->last_user_name = 0;
     }
-
-    if(tng_data->output_endianness_swap_func_64)
+    if(!tng_data->last_user_name)
     {
-        /* If other endianness variants are added they must be added here as well */
-        if(tng_data->output_endianness_swap_func_64 ==
-           &tng_swap_byte_order_big_endian_64)
-        {
-            end_64 = TNG_BIG_ENDIAN_64;
-        }
-        else if(tng_data->output_endianness_swap_func_64 ==
-                &tng_swap_byte_order_little_endian_64)
-        {
-            end_64 = TNG_LITTLE_ENDIAN_64;
-        }
-        else
+        tng_data->last_user_name = malloc(len);
+        if(!tng_data->last_user_name)
         {
-            return(TNG_FAILURE);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
     }
-    else
-    {
-        end_64 = (tng_endianness_64)tng_data->endianness_64;
-    }
 
-    if((int)end_32 != (int)end_64)
+    strncpy(tng_data->last_user_name, new_name, len);
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name, const int max_len)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+
+    strncpy(name, tng_data->first_computer_name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
+    return(TNG_SUCCESS);
+}
 
-    if(end_32 == TNG_LITTLE_ENDIAN_32)
-    {
-        *endianness = TNG_LITTLE_ENDIAN;
-    }
+tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
+                    (const tng_trajectory_t tng_data,
+                     const char *new_name)
+{
+    unsigned int len;
 
-    else if(end_32 == TNG_BIG_ENDIAN_32)
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
+
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
+
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
     {
-        *endianness = TNG_BIG_ENDIAN;
+        free(tng_data->first_computer_name);
+        tng_data->first_computer_name = 0;
     }
-    else
+    if(!tng_data->first_computer_name)
     {
-        return(TNG_FAILURE);
+        tng_data->first_computer_name = malloc(len);
+        if(!tng_data->first_computer_name)
+        {
+            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
     }
 
+    strncpy(tng_data->first_computer_name, new_name, len);
+
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
-                (tng_trajectory_t tng_data,
-                 const tng_file_endianness endianness)
+tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
+                    (const tng_trajectory_t tng_data,
+                     char *name, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    /* Tne endianness cannot be changed if the data has already been written
-     * to the output file. */
-    if(ftello(tng_data->output_file) > 0)
+    strncpy(name, tng_data->last_computer_name, max_len - 1);
+    name[max_len - 1] = 0;
+
+    if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
+    return(TNG_SUCCESS);
+}
 
-    if(endianness == TNG_BIG_ENDIAN)
-    {
-        if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
-        {
-            tng_data->output_endianness_swap_func_32 = 0;
-        }
-        else
-        {
-            tng_data->output_endianness_swap_func_32 =
-            &tng_swap_byte_order_big_endian_32;
-        }
-        if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
-        {
-            tng_data->output_endianness_swap_func_64 = 0;
-        }
-        else
-        {
-            tng_data->output_endianness_swap_func_64 =
-            &tng_swap_byte_order_big_endian_64;
-        }
-        return(TNG_SUCCESS);
-    }
-    else if(endianness == TNG_LITTLE_ENDIAN)
-    {
-        if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
-        {
-            tng_data->output_endianness_swap_func_32 = 0;
-        }
-        else
-        {
-            tng_data->output_endianness_swap_func_32 =
-            &tng_swap_byte_order_little_endian_32;
-        }
-        if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
-        {
-            tng_data->output_endianness_swap_func_64 = 0;
-        }
-        else
-        {
-            tng_data->output_endianness_swap_func_64 =
-            &tng_swap_byte_order_little_endian_64;
-        }
-        return(TNG_SUCCESS);
-    }
-
-    /* If the specified endianness is neither big nor little endian return a
-     * failure. */
-    return(TNG_FAILURE);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
+tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
                     (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
-
-    strncpy(name, tng_data->first_program_name, max_len - 1);
-    name[max_len - 1] = 0;
-
-    if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_t tng_data,
-                                                                 const char *new_name)
+                     const char *new_name)
 {
     unsigned int len;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
+        len)
     {
-        free(tng_data->first_program_name);
-        tng_data->first_program_name = 0;
+        free(tng_data->last_computer_name);
+        tng_data->last_computer_name = 0;
     }
-    if(!tng_data->first_program_name)
+    if(!tng_data->last_computer_name)
     {
-        tng_data->first_program_name = malloc(len);
-        if(!tng_data->first_program_name)
+        tng_data->last_computer_name = malloc(len);
+        if(!tng_data->last_computer_name)
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
@@ -10764,48 +9958,51 @@ tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set(tng_trajectory_
         }
     }
 
-    strncpy(tng_data->first_program_name, new_name, len);
+    strncpy(tng_data->last_computer_name, new_name, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
+tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
                     (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
+                     char *signature, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
 
-    strncpy(name, tng_data->last_program_name, max_len - 1);
-    name[max_len - 1] = 0;
+    strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
+    signature[max_len - 1] = 0;
 
-    if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
+    if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
-                    (tng_trajectory_t tng_data,
-                     const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
+                    (const tng_trajectory_t tng_data,
+                     const char *signature)
 {
     unsigned int len;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
+    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
 
-    if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
+    /* If the currently stored string length is not enough to store the new
+     * string it is freed and reallocated. */
+    if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
+        len)
     {
-        free(tng_data->last_program_name);
-        tng_data->last_program_name = 0;
+        free(tng_data->first_pgp_signature);
+        tng_data->first_pgp_signature = 0;
     }
-    if(!tng_data->last_program_name)
+    if(!tng_data->first_pgp_signature)
     {
-        tng_data->last_program_name = malloc(len);
-        if(!tng_data->last_program_name)
+        tng_data->first_pgp_signature = malloc(len);
+        if(!tng_data->first_pgp_signature)
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
@@ -10813,50 +10010,51 @@ tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
         }
     }
 
-    strncpy(tng_data->last_program_name, new_name, len);
+    strncpy(tng_data->first_pgp_signature, signature, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
+tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
                     (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
+                     char *signature, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
 
-    strncpy(name, tng_data->first_user_name, max_len - 1);
-    name[max_len - 1] = 0;
+    strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
+    signature[max_len - 1] = 0;
 
-    if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
+    if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
-                    (tng_trajectory_t tng_data,
-                     const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
+                    (const tng_trajectory_t tng_data,
+                     const char *signature)
 {
     unsigned int len;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
+    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
 
     /* If the currently stored string length is not enough to store the new
      * string it is freed and reallocated. */
-    if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
+    if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
+        len)
     {
-        free(tng_data->first_user_name);
-        tng_data->first_user_name = 0;
+        free(tng_data->last_pgp_signature);
+        tng_data->last_pgp_signature = 0;
     }
-    if(!tng_data->first_user_name)
+    if(!tng_data->last_pgp_signature)
     {
-        tng_data->first_user_name = malloc(len);
-        if(!tng_data->first_user_name)
+        tng_data->last_pgp_signature = malloc(len);
+        if(!tng_data->last_pgp_signature)
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
@@ -10864,30 +10062,30 @@ tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
         }
     }
 
-    strncpy(tng_data->first_user_name, new_name, len);
+    strncpy(tng_data->last_pgp_signature, signature, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
+tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
                     (const tng_trajectory_t tng_data,
                      char *name, const int max_len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
 
-    strncpy(name, tng_data->last_user_name, max_len - 1);
+    strncpy(name, tng_data->forcefield_name, max_len - 1);
     name[max_len - 1] = 0;
 
-    if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
+    if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
     {
         return(TNG_FAILURE);
     }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
-                    (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
+                    (const tng_trajectory_t tng_data,
                      const char *new_name)
 {
     unsigned int len;
@@ -10895,19 +10093,19 @@ tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
 
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
+    len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
     /* If the currently stored string length is not enough to store the new
      * string it is freed and reallocated. */
-    if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
+    if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
     {
-        free(tng_data->last_user_name);
-        tng_data->last_user_name = 0;
+        free(tng_data->forcefield_name);
+        tng_data->forcefield_name = 0;
     }
-    if(!tng_data->last_user_name)
+    if(!tng_data->forcefield_name)
     {
-        tng_data->last_user_name = malloc(len);
-        if(!tng_data->last_user_name)
+        tng_data->forcefield_name = malloc(len);
+        if(!tng_data->forcefield_name)
         {
             fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
                    __FILE__, __LINE__);
@@ -10915,319 +10113,61 @@ tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
         }
     }
 
-    strncpy(tng_data->last_user_name, new_name, len);
+    strncpy(tng_data->forcefield_name, new_name, len);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
+tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
                     (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
+                     int64_t *len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+    TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
 
-    strncpy(name, tng_data->first_computer_name, max_len - 1);
-    name[max_len - 1] = 0;
+    *len = tng_data->medium_stride_length;
 
-    if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
-                    (tng_trajectory_t tng_data,
-                     const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
+                    (const tng_trajectory_t tng_data,
+                     const int64_t len)
 {
-    unsigned int len;
-
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
-
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
-    {
-        free(tng_data->first_computer_name);
-        tng_data->first_computer_name = 0;
-    }
-    if(!tng_data->first_computer_name)
+    if(len >= tng_data->long_stride_length)
     {
-        tng_data->first_computer_name = malloc(len);
-        if(!tng_data->first_computer_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
+        return(TNG_FAILURE);
     }
-
-    strncpy(tng_data->first_computer_name, new_name, len);
+    tng_data->medium_stride_length = len;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
-                    (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
+                (const tng_trajectory_t tng_data,
+                 int64_t *len)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
+    TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
 
-    strncpy(name, tng_data->last_computer_name, max_len - 1);
-    name[max_len - 1] = 0;
+    *len = tng_data->long_stride_length;
 
-    if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
-                    (tng_trajectory_t tng_data,
-                     const char *new_name)
+tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
+                (const tng_trajectory_t tng_data,
+                 const int64_t len)
 {
-    unsigned int len;
-
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
-
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
 
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
-        len)
-    {
-        free(tng_data->last_computer_name);
-        tng_data->last_computer_name = 0;
-    }
-    if(!tng_data->last_computer_name)
+    if(len <= tng_data->medium_stride_length)
     {
-        tng_data->last_computer_name = malloc(len);
-        if(!tng_data->last_computer_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
+        return(TNG_FAILURE);
     }
-
-    strncpy(tng_data->last_computer_name, new_name, len);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
-                    (const tng_trajectory_t tng_data,
-                     char *signature, const int max_len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
-
-    strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
-    signature[max_len - 1] = 0;
-
-    if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
-                    (tng_trajectory_t tng_data,
-                     const char *signature)
-{
-    unsigned int len;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
-
-    len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
-
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
-        len)
-    {
-        free(tng_data->first_pgp_signature);
-        tng_data->first_pgp_signature = 0;
-    }
-    if(!tng_data->first_pgp_signature)
-    {
-        tng_data->first_pgp_signature = malloc(len);
-        if(!tng_data->first_pgp_signature)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
-
-    strncpy(tng_data->first_pgp_signature, signature, len);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
-                    (const tng_trajectory_t tng_data,
-                     char *signature, const int max_len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
-
-    strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
-    signature[max_len - 1] = 0;
-
-    if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
-                    (tng_trajectory_t tng_data,
-                     const char *signature)
-{
-    unsigned int len;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
-
-    len = tng_min_i((int)strlen(signature) + 1, TNG_MAX_STR_LEN);
-
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
-        len)
-    {
-        free(tng_data->last_pgp_signature);
-        tng_data->last_pgp_signature = 0;
-    }
-    if(!tng_data->last_pgp_signature)
-    {
-        tng_data->last_pgp_signature = malloc(len);
-        if(!tng_data->last_pgp_signature)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
-
-    strncpy(tng_data->last_pgp_signature, signature, len);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
-                    (const tng_trajectory_t tng_data,
-                     char *name, const int max_len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
-
-    strncpy(name, tng_data->forcefield_name, max_len - 1);
-    name[max_len - 1] = 0;
-
-    if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
-    {
-        return(TNG_FAILURE);
-    }
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
-                    (tng_trajectory_t tng_data,
-                     const char *new_name)
-{
-    unsigned int len;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
-
-    len = tng_min_i((int)strlen(new_name) + 1, TNG_MAX_STR_LEN);
-
-    /* If the currently stored string length is not enough to store the new
-     * string it is freed and reallocated. */
-    if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
-    {
-        free(tng_data->forcefield_name);
-        tng_data->forcefield_name = 0;
-    }
-    if(!tng_data->forcefield_name)
-    {
-        tng_data->forcefield_name = malloc(len);
-        if(!tng_data->forcefield_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-    }
-
-    strncpy(tng_data->forcefield_name, new_name, len);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
-                    (const tng_trajectory_t tng_data,
-                     int64_t *len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
-
-    *len = tng_data->medium_stride_length;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
-                    (tng_trajectory_t tng_data,
-                     const int64_t len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(len >= tng_data->long_stride_length)
-    {
-        return(TNG_FAILURE);
-    }
-    tng_data->medium_stride_length = len;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
-                (const tng_trajectory_t tng_data,
-                 int64_t *len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
-
-    *len = tng_data->long_stride_length;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
-                (tng_trajectory_t tng_data,
-                 const int64_t len)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(len <= tng_data->medium_stride_length)
-    {
-        return(TNG_FAILURE);
-    }
-    tng_data->long_stride_length = len;
+    tng_data->long_stride_length = len;
 
     return(TNG_SUCCESS);
 }
@@ -11245,7 +10185,7 @@ tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const double time)
 {
     tng_trajectory_frame_set_t frame_set;
@@ -11319,18 +10259,20 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
     }
     tng_block_destroy(&block);
 
-    if(fread(&first_frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
+    if(tng_file_input_numerical(tng_data, &first_frame,
+                                sizeof(first_frame),
+                                TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot read first frame of frame set. %s: %d\n",
-               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
-    if(fread(&n_frames, sizeof(int64_t), 1, tng_data->input_file) == 0)
+
+    if(tng_file_input_numerical(tng_data, &n_frames,
+                                sizeof(n_frames),
+                                TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot read n frames of frame set. %s: %d\n",
-               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
+
     fseeko(tng_data->input_file, file_pos, SEEK_SET);
 
     *n = first_frame + n_frames;
@@ -11350,7 +10292,7 @@ tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const double precision)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -11361,7 +10303,7 @@ tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t n)
 {
     tng_molecule_t mol;
@@ -11582,9 +10524,15 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
                 (const tng_trajectory_t tng_data,
                  const int64_t n)
 {
+    tng_trajectory_frame_set_t frame_set;
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
     tng_data->frame_set_n_frames = n;
+    frame_set = &tng_data->current_trajectory_frame_set;
+    if(frame_set)
+    {
+        frame_set->n_frames = n;
+    }
 
     return(TNG_SUCCESS);
 }
@@ -11619,8 +10567,8 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
 
     tng_block_init(&block);
     fseeko(tng_data->input_file,
-          file_pos,
-          SEEK_SET);
+           file_pos,
+           SEEK_SET);
     tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
     /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
@@ -11682,8 +10630,8 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
         {
             cnt += medium_stride_length;
             fseeko(tng_data->input_file,
-                  file_pos,
-                  SEEK_SET);
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11712,8 +10660,8 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
         {
             ++cnt;
             fseeko(tng_data->input_file,
-                  file_pos,
-                  SEEK_SET);
+                   file_pos,
+                   SEEK_SET);
             /* Read block headers first to see what block is found. */
             stat = tng_block_header_read(tng_data, block);
             if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -11765,7 +10713,7 @@ tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t nr)
 {
     int64_t long_stride_length, medium_stride_length;
@@ -12089,7 +11037,7 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame)
 {
     int64_t first_frame, last_frame, n_frames_per_frame_set;
@@ -12504,3500 +11452,2421 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
 {
     (void)tng_data;
 
-    TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
-    TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
-
-    *pos = frame_set->prev_frame_set_file_pos;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
-                (const tng_trajectory_t tng_data,
-                 const tng_trajectory_frame_set_t frame_set,
-                 int64_t *first_frame,
-                 int64_t *last_frame)
-{
-    (void)tng_data;
-
-    TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
-    TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
-    TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
-
-    *first_frame = frame_set->first_frame;
-    *last_frame = *first_frame + frame_set->n_frames - 1;
-
-    return(TNG_SUCCESS);
-}
-
-/** Translate from the particle numbering used in a frame set to the real
- *  particle numbering - used in the molecule description.
- * @param frame_set is the frame_set containing the mappings to use.
- * @param local is the index number of the atom in this frame set
- * @param real is set to the index of the atom in the molecular system.
- * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
- * cannot be found.
- */
-static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
-                (const tng_trajectory_frame_set_t frame_set,
-                 const int64_t local,
-                 int64_t *real)
-{
-    int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
-    tng_particle_mapping_t mapping;
-    if(n_blocks <= 0)
-    {
-        *real = local;
-        return(TNG_SUCCESS);
-    }
-    for(i = 0; i < n_blocks; i++)
-    {
-        mapping = &frame_set->mappings[i];
-        first = mapping->num_first_particle;
-        if(local < first ||
-           local >= first + mapping->n_particles)
-        {
-            continue;
-        }
-        *real = mapping->real_particle_numbers[local-first];
-        return(TNG_SUCCESS);
-    }
-    *real = local;
-    return(TNG_FAILURE);
-}
-
-/** Translate from the real particle numbering to the particle numbering
- *  used in a frame set.
- * @param frame_set is the frame_set containing the mappings to use.
- * @param real is the index number of the atom in the molecular system.
- * @param local is set to the index of the atom in this frame set.
- * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
- * cannot be found.
- */
-/*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
-                (const tng_trajectory_frame_set_t frame_set,
-                 const int64_t real,
-                 int64_t *local)
-{
-    int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
-    tng_particle_mapping_t mapping;
-    if(n_blocks <= 0)
-    {
-        *local = real;
-        return(TNG_SUCCESS);
-    }
-    for(i = 0; i < n_blocks; i++)
-    {
-        mapping = &frame_set->mappings[i];
-        for(j = mapping->n_particles; j--;)
-        {
-            if(mapping->real_particle_numbers[j] == real)
-            {
-                *local = j;
-                return(TNG_SUCCESS);
-            }
-        }
-    }
-    return(TNG_FAILURE);
-}
-*/
-
-static tng_function_status tng_file_headers_len_get
-                (tng_trajectory_t tng_data,
-                 int64_t *len)
-{
-    int64_t orig_pos;
-    tng_gen_block_t block;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    *len = 0;
-
-    orig_pos = ftello(tng_data->input_file);
-
-    if(!tng_data->input_file_len)
-    {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
-    }
-    fseeko(tng_data->input_file, 0, SEEK_SET);
-
-    tng_block_init(&block);
-    /* Read through the headers of non-trajectory blocks (they come before the
-     * trajectory blocks in the file) */
-    while (*len < tng_data->input_file_len &&
-           tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
-           block->id != -1 &&
-           block->id != TNG_TRAJECTORY_FRAME_SET)
-    {
-        *len += block->header_contents_size + block->block_contents_size;
-        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-    }
-
-    fseeko(tng_data->input_file, orig_pos, SEEK_SET);
-
-    tng_block_destroy(&block);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int64_t prev_pos = 0;
-    tng_gen_block_t block;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    tng_data->n_trajectory_frame_sets = 0;
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    if(!tng_data->input_file_len)
-    {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
-    }
-    fseeko(tng_data->input_file, 0, SEEK_SET);
-
-    tng_block_init(&block);
-    /* Non trajectory blocks (they come before the trajectory
-     * blocks in the file) */
-    while (prev_pos < tng_data->input_file_len &&
-           tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
-           block->id != -1 &&
-           block->id != TNG_TRAJECTORY_FRAME_SET)
-    {
-        tng_block_read_next(tng_data, block, hash_mode);
-        prev_pos = ftello(tng_data->input_file);
-    }
-
-    /* Go back if a trajectory block was encountered */
-    if(block->id == TNG_TRAJECTORY_FRAME_SET)
-    {
-        fseeko(tng_data->input_file, prev_pos, SEEK_SET);
-    }
-
-    tng_block_destroy(&block);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int i;
-    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.");
-
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
-    {
-        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. */
-
-    if(tng_general_info_block_write(tng_data, hash_mode)
-       != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
-                tng_data->input_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    if(tng_molecules_block_write(tng_data, hash_mode)
-        != TNG_SUCCESS)
-    {
-        fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
-                tng_data->input_file_path, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-
-    /* FIXME: Currently writing non-trajectory data blocks here.
-     * Should perhaps be moved. */
-    tng_block_init(&block);
-    for(i = 0; i < tng_data->n_data_blocks; i++)
-    {
-        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++)
-    {
-        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(&block);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_block_read_next(tng_trajectory_t tng_data,
-                                        tng_gen_block_t block,
-                                        const char hash_mode)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
-
-    switch(block->id)
-    {
-    case TNG_TRAJECTORY_FRAME_SET:
-        return(tng_frame_set_block_read(tng_data, block, hash_mode));
-    case TNG_PARTICLE_MAPPING:
-        return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
-    case TNG_GENERAL_INFO:
-        return(tng_general_info_block_read(tng_data, block, hash_mode));
-    case TNG_MOLECULES:
-        return(tng_molecules_block_read(tng_data, block, hash_mode));
-    default:
-        if(block->id >= TNG_TRAJ_BOX_SHAPE)
-        {
-            return(tng_data_block_contents_read(tng_data, block, hash_mode));
-        }
-        else
-        {
-            /* Skip to the next block */
-            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-            return(TNG_FAILURE);
-        }
-    }
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int64_t file_pos;
-    tng_gen_block_t block;
-    tng_function_status stat;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    file_pos = ftello(tng_data->input_file);
-
-    tng_block_init(&block);
-
-    if(!tng_data->input_file_len)
-    {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
-        fseeko(tng_data->input_file, file_pos, SEEK_SET);
-    }
-
-    /* Read block headers first to see what block is found. */
-    stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
-       block->id == -1)
-    {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
-
-    if(tng_block_read_next(tng_data, block,
-                           hash_mode) == TNG_SUCCESS)
-    {
-        tng_data->n_trajectory_frame_sets++;
-        file_pos = ftello(tng_data->input_file);
-        /* Read all blocks until next frame set block */
-        stat = tng_block_header_read(tng_data, block);
-        while(file_pos < tng_data->input_file_len &&
-              stat != TNG_CRITICAL &&
-              block->id != TNG_TRAJECTORY_FRAME_SET &&
-              block->id != -1)
-        {
-            stat = tng_block_read_next(tng_data, block,
-                                       hash_mode);
-            if(stat != TNG_CRITICAL)
-            {
-                file_pos = ftello(tng_data->input_file);
-                if(file_pos < tng_data->input_file_len)
-                {
-                    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",
-                   file_pos, __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(stat);
-        }
-
-        if(block->id == TNG_TRAJECTORY_FRAME_SET)
-        {
-            fseeko(tng_data->input_file, file_pos, SEEK_SET);
-        }
-    }
-
-    tng_block_destroy(&block);
-
-    return(TNG_SUCCESS);
-}
-
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
-                (tng_trajectory_t tng_data,
-                 const char hash_mode,
-                 const int64_t block_id)
-{
-    int64_t file_pos;
-    tng_gen_block_t block;
-    tng_function_status stat;
-    int found_flag = 1;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
-
-    if(file_pos < 0)
-    {
-        /* No current frame set. This means that the first frame set must be
-         * read */
-        found_flag = 0;
-        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
-    }
-
-    if(file_pos > 0)
-    {
-        fseeko(tng_data->input_file,
-              file_pos,
-              SEEK_SET);
-    }
-    else
-    {
-        return(TNG_FAILURE);
-    }
-
-    tng_block_init(&block);
-
-    if(!tng_data->input_file_len)
-    {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
-        fseeko(tng_data->input_file, file_pos, SEEK_SET);
-    }
-
-    /* Read block headers first to see what block is found. */
-    stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
-    {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-    /* If the current frame set had already been read skip its block contents */
-    if(found_flag)
-    {
-        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-    }
-    /* Otherwiese read the frame set block */
-    else
-    {
-        stat = tng_block_read_next(tng_data, block,
-                                   hash_mode);
-        if(stat != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(stat);
-        }
-    }
-    file_pos = ftello(tng_data->input_file);
-
-    found_flag = 0;
-
-    /* Read only blocks of the requested ID
-        * until next frame set block */
-    stat = tng_block_header_read(tng_data, block);
-    while(file_pos < tng_data->input_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET &&
-            block->id != -1)
-    {
-        if(block->id == block_id)
-        {
-            stat = tng_block_read_next(tng_data, block,
-                                       hash_mode);
-            if(stat != TNG_CRITICAL)
-            {
-                file_pos = ftello(tng_data->input_file);
-                found_flag = 1;
-                if(file_pos < tng_data->input_file_len)
-                {
-                    stat = tng_block_header_read(tng_data, block);
-                }
-            }
-        }
-        else
-        {
-            file_pos += (block->block_contents_size + block->header_contents_size);
-            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-            if(file_pos < tng_data->input_file_len)
-            {
-                stat = tng_block_header_read(tng_data, block);
-            }
-        }
-    }
-    if(stat == TNG_CRITICAL)
-    {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(stat);
-    }
-
-    if(block->id == TNG_TRAJECTORY_FRAME_SET)
-    {
-        fseeko(tng_data->input_file, file_pos, SEEK_SET);
-    }
-
-    tng_block_destroy(&block);
-
-    if(found_flag)
-    {
-        return(TNG_SUCCESS);
-    }
-    else
-    {
-        return(TNG_FAILURE);
-    }
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    int64_t file_pos;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
-
-    if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
-    {
-        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
-    }
-
-    if(file_pos > 0)
-    {
-        fseeko(tng_data->input_file,
-              file_pos,
-              SEEK_SET);
-    }
-    else
-    {
-        return(TNG_FAILURE);
-    }
-
-    return(tng_frame_set_read(tng_data, hash_mode));
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
-                (tng_trajectory_t tng_data,
-                 const char hash_mode,
-                 const int64_t block_id)
-{
-    int64_t file_pos;
-    tng_gen_block_t block;
-    tng_function_status stat;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
-    {
-        return(TNG_CRITICAL);
-    }
-
-    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
-
-    if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
-    {
-        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
-    }
-
-    if(file_pos > 0)
-    {
-        fseeko(tng_data->input_file,
-              file_pos,
-              SEEK_SET);
-    }
-    else
-    {
-        return(TNG_FAILURE);
-    }
-
-    tng_block_init(&block);
-
-    if(!tng_data->input_file_len)
-    {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
-        fseeko(tng_data->input_file, file_pos, SEEK_SET);
-    }
-
-    /* Read block headers first to see what block is found. */
-    stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
-    {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-
-    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
-
-    if(tng_block_read_next(tng_data, block,
-                           hash_mode) == TNG_SUCCESS)
-    {
-        stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
-    }
-
-    tng_block_destroy(&block);
-
-    return(stat);
-}
-
-tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
-                                        const char hash_mode)
-{
-    int i, j;
-    tng_gen_block_t block;
-    tng_trajectory_frame_set_t frame_set;
-    tng_function_status stat;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    if(frame_set->n_written_frames == frame_set->n_frames)
-    {
-        return(TNG_SUCCESS);
-    }
-
-    tng_data->current_trajectory_frame_set_output_file_pos =
-    ftello(tng_data->output_file);
-    tng_data->last_trajectory_frame_set_output_file_pos =
-    tng_data->current_trajectory_frame_set_output_file_pos;
-
-    if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
-    {
-        return(TNG_FAILURE);
-    }
-
-    if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
-    {
-        tng_data->first_trajectory_frame_set_output_file_pos =
-        tng_data->current_trajectory_frame_set_output_file_pos;
-    }
-
-    tng_block_init(&block);
-
-    if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
-    {
-        tng_block_destroy(&block);
-        return(TNG_FAILURE);
-    }
-
-    /* Write non-particle data blocks */
-    for(i = 0; i<frame_set->n_data_blocks; i++)
-    {
-        block->id = frame_set->tr_data[i].block_id;
-        tng_data_block_write(tng_data, block, i, hash_mode);
-    }
-    /* Write the mapping blocks and particle data blocks*/
-    if(frame_set->n_mapping_blocks)
-    {
-        for(i = 0; i < frame_set->n_mapping_blocks; i++)
-        {
-            block->id = TNG_PARTICLE_MAPPING;
-            if(frame_set->mappings[i].n_particles > 0)
-            {
-                tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
-                for(j = 0; j<frame_set->n_particle_data_blocks; j++)
-                {
-                    block->id = frame_set->tr_particle_data[j].block_id;
-                    tng_particle_data_block_write(tng_data, block,
-                                                  j, &frame_set->mappings[i],
-                                                  hash_mode);
-                }
-            }
-        }
-    }
-    else
-    {
-        for(i = 0; i<frame_set->n_particle_data_blocks; i++)
-        {
-            block->id = frame_set->tr_particle_data[i].block_id;
-            tng_particle_data_block_write(tng_data, block,
-                                          i, 0, hash_mode);
-        }
-    }
-
-
-    /* Update pointers in the general info block */
-    stat = tng_header_pointers_update(tng_data, hash_mode);
-
-    if(stat == TNG_SUCCESS)
-    {
-        stat = tng_frame_set_pointers_update(tng_data, hash_mode);
-    }
-
-    tng_block_destroy(&block);
-
-    frame_set->n_unwritten_frames = 0;
-
-    fflush(tng_data->output_file);
-
-    return(stat);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
-                (tng_trajectory_t tng_data,
-                 const char hash_mode)
-{
-    tng_trajectory_frame_set_t frame_set;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    if(frame_set->n_unwritten_frames == 0)
-    {
-        return(TNG_SUCCESS);
-    }
-    frame_set->n_frames = frame_set->n_unwritten_frames;
-
-    return(tng_frame_set_write(tng_data, hash_mode));
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
-                (tng_trajectory_t tng_data,
-                 const int64_t first_frame,
-                 const int64_t n_frames)
-{
-    tng_gen_block_t block;
-    tng_trajectory_frame_set_t frame_set;
-    FILE *temp = tng_data->input_file;
-    int64_t curr_pos;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
-    TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    curr_pos = ftello(tng_data->output_file);
-
-    if(curr_pos <= 10)
-    {
-        tng_file_headers_write(tng_data, TNG_USE_HASH);
-    }
-
-    /* Set pointer to previous frame set to the one that was loaded
-     * before.
-     * FIXME: This is a bit risky. If they are not added in order
-     * it will be wrong. */
-    if(tng_data->n_trajectory_frame_sets)
-    {
-        frame_set->prev_frame_set_file_pos =
-        tng_data->current_trajectory_frame_set_output_file_pos;
-    }
-
-    tng_data->current_trajectory_frame_set_output_file_pos =
-    ftello(tng_data->output_file);
-
-    tng_data->n_trajectory_frame_sets++;
-
-    /* Set the medium range pointers */
-    if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
-    {
-        frame_set->medium_stride_prev_frame_set_file_pos =
-        tng_data->first_trajectory_frame_set_output_file_pos;
-    }
-    else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
-    {
-        /* FIXME: Currently only working if the previous frame set has its
-         * medium stride pointer already set. This might need some fixing. */
-        if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
-           frame_set->medium_stride_prev_frame_set_file_pos != 0)
-        {
-            tng_block_init(&block);
-            tng_data->input_file = tng_data->output_file;
-
-            curr_pos = ftello(tng_data->output_file);
-            fseeko(tng_data->output_file,
-                   frame_set->medium_stride_prev_frame_set_file_pos,
-                   SEEK_SET);
-
-            if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
-            {
-                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 next frame set from the previous frame set and one
-             * medium stride step back */
-            fseeko(tng_data->output_file, block->block_contents_size - (6 *
-            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-            if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
-               sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
-               1, tng_data->output_file) == 0)
-            {
-                fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-                tng_data->input_file = temp;
-                tng_block_destroy(&block);
-                return(TNG_CRITICAL);
-            }
-
-            if(tng_data->input_endianness_swap_func_64)
-            {
-                if(tng_data->input_endianness_swap_func_64(tng_data,
-                   &frame_set->medium_stride_prev_frame_set_file_pos)
-                    != TNG_SUCCESS)
-                {
-                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                            __FILE__, __LINE__);
-                }
-            }
-
-            tng_block_destroy(&block);
-
-            /* Set the long range pointers */
-            if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
-            {
-                frame_set->long_stride_prev_frame_set_file_pos =
-                tng_data->first_trajectory_frame_set_output_file_pos;
-            }
-            else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
-            {
-                /* FIXME: Currently only working if the previous frame set has its
-                * long stride pointer already set. This might need some fixing. */
-                if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
-                frame_set->long_stride_prev_frame_set_file_pos != 0)
-                {
-                    tng_block_init(&block);
-                    tng_data->input_file = tng_data->output_file;
-
-                    fseeko(tng_data->output_file,
-                           frame_set->long_stride_prev_frame_set_file_pos,
-                           SEEK_SET);
-
-                    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
-                    {
-                        fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
-                            __FILE__, __LINE__);
-                        tng_data->input_file = temp;
-                        tng_block_destroy(&block);
-                        return(TNG_CRITICAL);
-                    }
-
-                    /* Read the next frame set from the previous frame set and one
-                    * long stride step back */
-                    fseeko(tng_data->output_file, block->block_contents_size - (6 *
-                          sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
-                    tng_block_destroy(&block);
-
-                    if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
-                    sizeof(frame_set->long_stride_prev_frame_set_file_pos),
-                    1, tng_data->output_file) == 0)
-                    {
-                        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
-                        tng_data->input_file = temp;
-                        return(TNG_CRITICAL);
-                    }
-
-                    if(tng_data->input_endianness_swap_func_64)
-                    {
-                        if(tng_data->input_endianness_swap_func_64(tng_data,
-                           &frame_set->long_stride_prev_frame_set_file_pos)
-                            != TNG_SUCCESS)
-                        {
-                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                                    __FILE__, __LINE__);
-                        }
-                    }
-
-                }
-            }
-
-            tng_data->input_file = temp;
-            fseeko(tng_data->output_file, curr_pos, SEEK_SET);
-        }
-    }
-
-    frame_set->first_frame = first_frame;
-    frame_set->n_frames = n_frames;
-    frame_set->n_written_frames = 0;
-    frame_set->n_unwritten_frames = 0;
-    frame_set->first_frame_time = -1;
-
-    if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
-       tng_data->first_trajectory_frame_set_output_file_pos == 0)
-    {
-        tng_data->first_trajectory_frame_set_output_file_pos =
-        tng_data->current_trajectory_frame_set_output_file_pos;
-    }
-    /* FIXME: Should check the frame number instead of the file_pos,
-     * in case frame sets are not in order */
-    if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
-       tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
-       tng_data->last_trajectory_frame_set_output_file_pos <
-       tng_data->current_trajectory_frame_set_output_file_pos)
-    {
-        tng_data->last_trajectory_frame_set_output_file_pos =
-        tng_data->current_trajectory_frame_set_output_file_pos;
-    }
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
-                (tng_trajectory_t tng_data,
-                 const int64_t first_frame,
-                 const int64_t n_frames,
-                 const double first_frame_time)
-{
-    tng_function_status stat;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
-    TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
-    TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
-
-
-    stat = tng_frame_set_new(tng_data, first_frame, n_frames);
-    if(stat != TNG_SUCCESS)
-    {
-        return(stat);
-    }
-    stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
-
-    return(stat);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
-                (tng_trajectory_t tng_data,
-                 const double first_frame_time)
-{
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
-
-    tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
-                (const tng_trajectory_t tng_data,
-                 int64_t *frame)
-{
-    int64_t file_pos, next_frame_set_file_pos;
-    tng_gen_block_t block;
-    tng_function_status stat;
-
-    tng_trajectory_frame_set_t frame_set;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
-    TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
-
-    file_pos = ftello(tng_data->input_file);
-
-    if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
-    {
-        next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
-    }
-    else
-    {
-        frame_set = &tng_data->current_trajectory_frame_set;
-        next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
-    }
-
-    if(next_frame_set_file_pos <= 0)
-    {
-        return(TNG_FAILURE);
-    }
-
-    fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
-    /* Read block headers first to see that a frame set block is found. */
-    tng_block_init(&block);
-    stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
-    {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-/*    if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
-    {
-        tng_block_read_next(tng_data, block, TNG_USE_HASH);
-    }*/
-    tng_block_destroy(&block);
-
-    if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
-    {
-        fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-    }
-    fseeko(tng_data->input_file, file_pos, SEEK_SET);
-
-    return(TNG_SUCCESS);
-}
-
-tng_function_status DECLSPECDLLEXPORT tng_data_block_add
-                (tng_trajectory_t tng_data,
-                 const int64_t id,
-                 const char *block_name,
-                 const char datatype,
-                 const char block_type_flag,
-                 int64_t n_frames,
-                 const int64_t n_values_per_frame,
-                 int64_t stride_length,
-                 const int64_t codec_id,
-                 void *new_data)
-{
-    int i, j, size, len;
-    tng_trajectory_frame_set_t frame_set;
-    tng_non_particle_data_t data;
-    char **first_dim_values;
-    char *new_data_c=new_data;
-    int64_t n_frames_div;
-
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    if(stride_length <= 0)
-    {
-        stride_length = 1;
-    }
-
-    /* If the block does not exist, create it */
-    if(tng_data_find(tng_data, id, &data) != TNG_SUCCESS)
-    {
-        if(tng_data_block_create(tng_data, block_type_flag) !=
-            TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-        if(block_type_flag == TNG_TRAJECTORY_BLOCK)
-        {
-            data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
-        }
-        else
-        {
-            data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
-        }
-        data->block_id = id;
-
-        data->block_name = malloc(strlen(block_name) + 1);
-        if(!data->block_name)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block_name)+1, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-        strncpy(data->block_name, block_name, strlen(block_name) + 1);
-
-        data->values = 0;
-        /* FIXME: Memory leak from strings. */
-        data->strings = 0;
-        data->last_retrieved_frame = -1;
-    }
-
-    data->datatype = datatype;
-    data->stride_length = tng_max_i64(stride_length, 1);
-    data->n_values_per_frame = n_values_per_frame;
-    data->n_frames = n_frames;
-    data->codec_id = codec_id;
-    data->compression_multiplier = 1.0;
-    /* FIXME: This can cause problems. */
-    data->first_frame_with_data = frame_set->first_frame;
-
-    switch(datatype)
-    {
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int64_t);
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-        break;
-    }
-
-    if(new_data_c)
-    {
-        /* Allocate memory */
-        if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
-                                 n_values_per_frame) !=
-        TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate data memory. %s: %d\n",
-                __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
-
-        if(n_frames > frame_set->n_unwritten_frames)
-        {
-            frame_set->n_unwritten_frames = n_frames;
-        }
-
-        n_frames_div = (n_frames % stride_length) ?
-                     n_frames / stride_length + 1:
-                     n_frames / stride_length;
+    TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
+    TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
 
-        if(datatype == TNG_CHAR_DATA)
-        {
-            for(i = 0; i < n_frames_div; i++)
-            {
-                first_dim_values = data->strings[i];
-                for(j = 0; j < n_values_per_frame; j++)
-                {
-                    len = tng_min_i((int)strlen(new_data_c) + 1,
-                                TNG_MAX_STR_LEN);
-                    if(first_dim_values[j])
-                    {
-                        free(first_dim_values[j]);
-                    }
-                    first_dim_values[j] = malloc(len);
-                    if(!first_dim_values[j])
-                    {
-                        fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                            len, __FILE__, __LINE__);
-                        return(TNG_CRITICAL);
-                    }
-                    strncpy(first_dim_values[j],
-                            new_data_c, len);
-                    new_data_c += len;
-                }
-            }
-        }
-        else
-        {
-            memcpy(data->values, new_data, size * n_frames_div *
-                   n_values_per_frame);
-        }
-    }
+    *pos = frame_set->prev_frame_set_file_pos;
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
-                (tng_trajectory_t tng_data,
-                 const int64_t id,
-                 const char *block_name,
-                 const char datatype,
-                 const char block_type_flag,
-                 int64_t n_frames,
-                 const int64_t n_values_per_frame,
-                 int64_t stride_length,
-                 const int64_t num_first_particle,
-                 const int64_t n_particles,
-                 const int64_t codec_id,
-                 void *new_data)
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
+                (const tng_trajectory_t tng_data,
+                 const tng_trajectory_frame_set_t frame_set,
+                 int64_t *first_frame,
+                 int64_t *last_frame)
 {
-    int i, size, len;
-    int64_t j, k;
-    int64_t tot_n_particles, n_frames_div;
-    char ***first_dim_values, **second_dim_values;
-    tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t data;
-    char *new_data_c=new_data;
+    (void)tng_data;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
-    TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
-    TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
+    TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
+    TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
+    TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
 
+    *first_frame = frame_set->first_frame;
+    *last_frame = *first_frame + frame_set->n_frames - 1;
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    return(TNG_SUCCESS);
+}
 
-    if(stride_length <= 0)
+/**
+ * @brief Translate from the particle numbering used in a frame set to the real
+ *  particle numbering - used in the molecule description.
+ * @param frame_set is the frame_set containing the mappings to use.
+ * @param local is the index number of the atom in this frame set
+ * @param real is set to the index of the atom in the molecular system.
+ * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
+ * cannot be found.
+ */
+static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
+                (const tng_trajectory_frame_set_t frame_set,
+                 const int64_t local,
+                 int64_t *real)
+{
+    int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
+    tng_particle_mapping_t mapping;
+    if(n_blocks <= 0)
     {
-        stride_length = 1;
+        *real = local;
+        return(TNG_SUCCESS);
     }
-
-    /* If the block does not exist, create it */
-    if(tng_particle_data_find(tng_data, id, &data) != TNG_SUCCESS)
+    for(i = 0; i < n_blocks; i++)
     {
-        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
+        mapping = &frame_set->mappings[i];
+        first = mapping->num_first_particle;
+        if(local < first ||
+           local >= first + mapping->n_particles)
         {
-            data = &tng_data->non_tr_particle_data[tng_data->
-                                                   n_particle_data_blocks - 1];
+            continue;
         }
-        data->block_id = id;
+        *real = mapping->real_particle_numbers[local-first];
+        return(TNG_SUCCESS);
+    }
+    *real = local;
+    return(TNG_FAILURE);
+}
 
-        data->block_name = malloc(strlen(block_name) + 1);
-        if(!data->block_name)
+/**
+ * @brief Translate from the real particle numbering to the particle numbering
+ *  used in a frame set.
+ * @param frame_set is the frame_set containing the mappings to use.
+ * @param real is the index number of the atom in the molecular system.
+ * @param local is set to the index of the atom in this frame set.
+ * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
+ * cannot be found.
+ */
+/*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
+                (const tng_trajectory_frame_set_t frame_set,
+                 const int64_t real,
+                 int64_t *local)
+{
+    int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
+    tng_particle_mapping_t mapping;
+    if(n_blocks <= 0)
+    {
+        *local = real;
+        return(TNG_SUCCESS);
+    }
+    for(i = 0; i < n_blocks; i++)
+    {
+        mapping = &frame_set->mappings[i];
+        for(j = mapping->n_particles; j--;)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
-                   (int)strlen(block_name)+1, __FILE__, __LINE__);
-            return(TNG_CRITICAL);
+            if(mapping->real_particle_numbers[j] == real)
+            {
+                *local = j;
+                return(TNG_SUCCESS);
+            }
         }
-        strncpy(data->block_name, block_name, strlen(block_name) + 1);
-
-        data->datatype = datatype;
-
-        data->values = 0;
-        /* FIXME: Memory leak from strings. */
-        data->strings = 0;
-        data->last_retrieved_frame = -1;
     }
+    return(TNG_FAILURE);
+}
+*/
 
-    data->stride_length = tng_max_i64(stride_length, 1);
-    data->n_values_per_frame = n_values_per_frame;
-    data->n_frames = n_frames;
-    data->codec_id = codec_id;
-    data->compression_multiplier = 1.0;
-    /* FIXME: This can cause problems. */
-    data->first_frame_with_data = frame_set->first_frame;
+static tng_function_status tng_file_headers_len_get
+                (const 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(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        tot_n_particles = frame_set->n_particles;
+        return(TNG_CRITICAL);
     }
-    else
+
+    *len = 0;
+
+    orig_pos = ftello(tng_data->input_file);
+
+    fseeko(tng_data->input_file, 0, SEEK_SET);
+
+    tng_block_init(&block);
+    /* Read through the headers of non-trajectory blocks (they come before the
+     * trajectory blocks in the file) */
+    while (*len < tng_data->input_file_len &&
+           tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
+           block->id != -1 &&
+           block->id != TNG_TRAJECTORY_FRAME_SET)
     {
-        tot_n_particles = tng_data->n_particles;
+        *len += block->header_contents_size + block->block_contents_size;
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
     }
 
-    /* If data values are supplied add that data to the data block. */
-    if(new_data_c)
-    {
-        /* Allocate memory */
-        if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
-                                          stride_length, tot_n_particles,
-                                          n_values_per_frame) !=
-        TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
-                __FILE__, __LINE__);
-            return(TNG_CRITICAL);
-        }
+    fseeko(tng_data->input_file, orig_pos, SEEK_SET);
 
-        if(n_frames > frame_set->n_unwritten_frames)
-        {
-            frame_set->n_unwritten_frames = n_frames;
-        }
+    tng_block_destroy(&block);
 
-        n_frames_div = (n_frames % stride_length) ?
-                     n_frames / stride_length + 1:
-                     n_frames / stride_length;
+    return(TNG_SUCCESS);
+}
 
-        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++)
-                {
-                    second_dim_values = first_dim_values[j];
-                    for(k = 0; k < n_values_per_frame; k++)
-                    {
-                        len = tng_min_i((int)strlen(new_data_c) + 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],
-                                new_data_c, len);
-                        new_data_c += len;
-                    }
-                }
-            }
-        }
-        else
-        {
-            switch(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);
-            }
+tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode)
+{
+    int64_t prev_pos = 0;
+    tng_gen_block_t block;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-            memcpy(data->values, new_data, size * n_frames_div *
-                   n_particles * n_values_per_frame);
-        }
+    tng_data->n_trajectory_frame_sets = 0;
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
+
+    fseeko(tng_data->input_file, 0, SEEK_SET);
+
+    tng_block_init(&block);
+    /* Non trajectory blocks (they come before the trajectory
+     * blocks in the file) */
+    while (prev_pos < tng_data->input_file_len &&
+           tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
+           block->id != -1 &&
+           block->id != TNG_TRAJECTORY_FRAME_SET)
+    {
+        tng_block_read_next(tng_data, block, hash_mode);
+        prev_pos = ftello(tng_data->input_file);
+    }
+
+    /* Go back if a trajectory block was encountered */
+    if(block->id == TNG_TRAJECTORY_FRAME_SET)
+    {
+        fseeko(tng_data->input_file, prev_pos, SEEK_SET);
     }
 
+    tng_block_destroy(&block);
+
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
-                (tng_trajectory_t tng_data,
-                 int64_t block_id,
-                 char *name,
-                 int max_len)
+tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode)
 {
-    int64_t i;
-    tng_trajectory_frame_set_t frame_set;
+    int i;
+    int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
     tng_function_status stat;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
-    int block_type = -1;
+    tng_gen_block_t block;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
 
-    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        p_data = &tng_data->non_tr_particle_data[i];
-        if(p_data->block_id == block_id)
-        {
-            strncpy(name, p_data->block_name, max_len);
-            name[max_len - 1] = '\0';
-            return(TNG_SUCCESS);
-        }
+        return(TNG_CRITICAL);
     }
-    for(i = 0; i < tng_data->n_data_blocks; i++)
+
+    if(tng_data->n_trajectory_frame_sets > 0)
     {
-        np_data = &tng_data->non_tr_data[i];
-        if(np_data->block_id == block_id)
+        stat = tng_file_headers_len_get(tng_data, &orig_len);
+        if(stat != TNG_SUCCESS)
         {
-            strncpy(name, np_data->block_name, max_len);
-            name[max_len - 1] = '\0';
-            return(TNG_SUCCESS);
+            return(stat);
         }
-    }
-
-    frame_set = &tng_data->current_trajectory_frame_set;
 
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
-    if(stat == TNG_SUCCESS)
-    {
-        block_type = TNG_PARTICLE_BLOCK_DATA;
-    }
-    else
-    {
-        stat = tng_data_find(tng_data, block_id, &np_data);
-        if(stat == TNG_SUCCESS)
+        tng_block_init(&block);
+        block->name = malloc(TNG_MAX_STR_LEN);
+        if(!block->name)
         {
-            block_type = TNG_NON_PARTICLE_BLOCK_DATA;
+            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);
         }
-        else
+        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++)
         {
-            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-            if(stat != TNG_SUCCESS)
-            {
-                return(stat);
-            }
-            stat = tng_particle_data_find(tng_data, block_id, &p_data);
-            if(stat == TNG_SUCCESS)
-            {
-                block_type = TNG_PARTICLE_BLOCK_DATA;
-            }
-            else
-            {
-                stat = tng_data_find(tng_data, block_id, &np_data);
-                if(stat == TNG_SUCCESS)
-                {
-                    block_type = TNG_NON_PARTICLE_BLOCK_DATA;
-                }
-            }
+            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_data_t)&tng_data->non_tr_data[i],
+                                         TNG_FALSE, 1, 1, 1, 0, 1,
+                                         &data_start_pos,
+                                         &len);
+            tot_len += len;
         }
-    }
-    if(block_type == TNG_PARTICLE_BLOCK_DATA)
-    {
-        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
+        for(i = 0; i < tng_data->n_particle_data_blocks; i++)
         {
-            p_data = &frame_set->tr_particle_data[i];
-            if(p_data->block_id == block_id)
-            {
-                strncpy(name, p_data->block_name, max_len);
-                name[max_len - 1] = '\0';
-                return(TNG_SUCCESS);
-            }
+            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,
+                                         &data_start_pos,
+                                         &len);
+            tot_len += len;
         }
-    }
-    else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
-    {
-        for(i = 0; i < frame_set->n_data_blocks; i++)
+        tng_block_destroy(&block);
+
+        if(tot_len > orig_len)
         {
-            np_data = &frame_set->tr_data[i];
-            if(np_data->block_id == block_id)
-            {
-                strncpy(name, np_data->block_name, max_len);
-                name[max_len - 1] = '\0';
-                return(TNG_SUCCESS);
-            }
+            tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
         }
-    }
 
-    return(TNG_FAILURE);
-}
+        stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
+        if(stat == TNG_CRITICAL)
+        {
+            fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
+                    __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
 
-tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
-                (const tng_trajectory_t tng_data,
-                 int64_t block_id,
-                 int *block_dependency)
-{
-    int64_t i;
-    tng_function_status stat;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+        /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
+         * must temporarily be reset */
+        temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
+        tng_data->current_trajectory_frame_set_output_file_pos = -1;
+    }
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
+    if(tng_general_info_block_write(tng_data, hash_mode)
+       != TNG_SUCCESS)
+    {
+        fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
+                tng_data->input_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
 
-    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
+    if(tng_molecules_block_write(tng_data, hash_mode)
+        != TNG_SUCCESS)
     {
-        p_data = &tng_data->non_tr_particle_data[i];
-        if(p_data->block_id == block_id)
-        {
-            *block_dependency = TNG_PARTICLE_DEPENDENT;
-            return(TNG_SUCCESS);
-        }
+        fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
+                tng_data->input_file_path, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
+
+    /* FIXME: Currently writing non-trajectory data blocks here.
+     * Should perhaps be moved. */
+    tng_block_init(&block);
     for(i = 0; i < tng_data->n_data_blocks; i++)
     {
-        np_data = &tng_data->non_tr_data[i];
-        if(np_data->block_id == block_id)
-        {
-            *block_dependency = 0;
-            return(TNG_SUCCESS);
-        }
+        block->id = tng_data->non_tr_data[i].block_id;
+        tng_data_block_write(tng_data, block,
+                             i, TNG_FALSE, 0, hash_mode);
     }
 
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
-    if(stat == TNG_SUCCESS)
+    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
     {
-        *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
-        return(TNG_SUCCESS);
+        block->id = tng_data->non_tr_particle_data[i].block_id;
+        tng_data_block_write(tng_data, block,
+                             i, TNG_TRUE, 0, hash_mode);
     }
-    else
+
+    tng_block_destroy(&block);
+
+    /* Continue writing at the end of the file. */
+    fseeko(tng_data->output_file, 0, SEEK_END);
+    if(temp_pos > 0)
     {
-        stat = tng_data_find(tng_data, block_id, &np_data);
-        if(stat == TNG_SUCCESS)
-        {
-            *block_dependency = TNG_FRAME_DEPENDENT;
-            return(TNG_SUCCESS);
-        }
-        else
-        {
-            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-            if(stat != TNG_SUCCESS)
-            {
-                return(stat);
-            }
-            stat = tng_particle_data_find(tng_data, block_id, &p_data);
-            if(stat == TNG_SUCCESS)
-            {
-                *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
-                return(TNG_SUCCESS);
-            }
-            else
-            {
-                stat = tng_data_find(tng_data, block_id, &np_data);
-                if(stat == TNG_SUCCESS)
-                {
-                    *block_dependency = TNG_FRAME_DEPENDENT;
-                    return(TNG_SUCCESS);
-                }
-            }
-        }
+        tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
     }
 
-    return(TNG_FAILURE);
+    return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
+tng_function_status DECLSPECDLLEXPORT tng_block_read_next
                 (const tng_trajectory_t tng_data,
-                 int64_t block_id,
-                 int64_t *n_values_per_frame)
+                 const tng_gen_block_t block,
+                 const char hash_mode)
 {
-    int64_t i;
-    tng_function_status stat;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
-
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-
-    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
-    {
-        p_data = &tng_data->non_tr_particle_data[i];
-        if(p_data->block_id == block_id)
-        {
-            *n_values_per_frame = p_data->n_values_per_frame;
-            return(TNG_SUCCESS);
-        }
-    }
-    for(i = 0; i < tng_data->n_data_blocks; i++)
-    {
-        np_data = &tng_data->non_tr_data[i];
-        if(np_data->block_id == block_id)
-        {
-            *n_values_per_frame = np_data->n_values_per_frame;
-            return(TNG_SUCCESS);
-        }
-    }
+    TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
 
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
-    if(stat == TNG_SUCCESS)
-    {
-        *n_values_per_frame = p_data->n_values_per_frame;
-        return(TNG_SUCCESS);
-    }
-    else
+    switch(block->id)
     {
-        stat = tng_data_find(tng_data, block_id, &np_data);
-        if(stat == TNG_SUCCESS)
+    case TNG_TRAJECTORY_FRAME_SET:
+        return(tng_frame_set_block_read(tng_data, block, hash_mode));
+    case TNG_PARTICLE_MAPPING:
+        return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
+    case TNG_GENERAL_INFO:
+        return(tng_general_info_block_read(tng_data, block, hash_mode));
+    case TNG_MOLECULES:
+        return(tng_molecules_block_read(tng_data, block, hash_mode));
+    default:
+        if(block->id >= TNG_TRAJ_BOX_SHAPE)
         {
-            *n_values_per_frame = np_data->n_values_per_frame;
-            return(TNG_SUCCESS);
+            return(tng_data_block_contents_read(tng_data, block, hash_mode));
         }
         else
         {
-            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
-            if(stat != TNG_SUCCESS)
-            {
-                return(stat);
-            }
-            stat = tng_particle_data_find(tng_data, block_id, &p_data);
-            if(stat == TNG_SUCCESS)
-            {
-                *n_values_per_frame = p_data->n_values_per_frame;
-                return(TNG_SUCCESS);
-            }
-            else
-            {
-                stat = tng_data_find(tng_data, block_id, &np_data);
-                if(stat == TNG_SUCCESS)
-                {
-                    *n_values_per_frame = np_data->n_values_per_frame;
-                    return(TNG_SUCCESS);
-                }
-            }
+            /* Skip to the next block */
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+            return(TNG_FAILURE);
         }
     }
-
-    return(TNG_FAILURE);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
-                (tng_trajectory_t tng_data,
-                 const int64_t frame_nr,
-                 const int64_t block_id,
-                 const void *values,
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
+                (const tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    int64_t header_pos, file_pos;
-    int64_t output_file_len, n_values_per_frame, size, contents_size;
-    int64_t header_size, temp_first, temp_last;
-    int64_t i, last_frame, temp_current;
+    int64_t file_pos;
     tng_gen_block_t block;
-    tng_trajectory_frame_set_t frame_set;
-    FILE *temp = tng_data->input_file;
-    struct tng_non_particle_data data;
     tng_function_status stat;
-    char dependency, sparse_data, datatype;
-    void *copy;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
-    TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
-               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
-    temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
-    temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
-    temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
-    tng_data->first_trajectory_frame_set_input_file_pos =
-    tng_data->first_trajectory_frame_set_output_file_pos;
-    tng_data->last_trajectory_frame_set_input_file_pos =
-    tng_data->last_trajectory_frame_set_output_file_pos;
-    tng_data->current_trajectory_frame_set_input_file_pos =
-    tng_data->current_trajectory_frame_set_output_file_pos;
+    file_pos = ftello(tng_data->input_file);
 
-    tng_data->input_file = tng_data->output_file;
+    tng_block_init(&block);
 
-    stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
+    /* 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 ||
+       block->id == -1)
+    {
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+               file_pos, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
 
-    if(stat != TNG_SUCCESS)
+    if(tng_block_read_next(tng_data, block,
+                           hash_mode) == TNG_SUCCESS)
     {
-        last_frame = frame_set->first_frame +
-                     frame_set->n_frames - 1;
-        /* If the wanted frame would be in the frame set after the last
-            * frame set create a new frame set. */
-        if(stat == TNG_FAILURE &&
-            last_frame < frame_nr)
-/*           (last_frame < frame_nr &&
-            tng_data->current_trajectory_frame_set.first_frame +
-            tng_data->frame_set_n_frames >= frame_nr))*/
+        tng_data->n_trajectory_frame_sets++;
+        file_pos = ftello(tng_data->input_file);
+        /* Read all blocks until next frame set block */
+        stat = tng_block_header_read(tng_data, block);
+        while(file_pos < tng_data->input_file_len &&
+              stat != TNG_CRITICAL &&
+              block->id != TNG_TRAJECTORY_FRAME_SET &&
+              block->id != -1)
         {
-            if(last_frame + tng_data->frame_set_n_frames < frame_nr)
-            {
-                last_frame = frame_nr - 1;
-            }
-            tng_frame_set_new(tng_data,
-                              last_frame+1,
-                              tng_data->frame_set_n_frames);
-            file_pos = ftello(tng_data->output_file);
-            fseeko(tng_data->output_file, 0, SEEK_END);
-            output_file_len = ftello(tng_data->output_file);
-            fseeko(tng_data->output_file, file_pos, SEEK_SET);
-
-            /* Read mapping blocks from the last frame set */
-            tng_block_init(&block);
-
-            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 != -1)
+            stat = tng_block_read_next(tng_data, block,
+                                       hash_mode);
+            if(stat != TNG_CRITICAL)
             {
-                if(block->id == TNG_PARTICLE_MAPPING)
-                {
-                    tng_trajectory_mapping_block_read(tng_data, block,
-                                                      hash_mode);
-                }
-                else
-                {
-                    fseeko(tng_data->output_file, block->block_contents_size,
-                           SEEK_CUR);
-                }
-                file_pos = ftello(tng_data->output_file);
-                if(file_pos < output_file_len)
+                file_pos = ftello(tng_data->input_file);
+                if(file_pos < tng_data->input_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
                 }
             }
-
-            tng_block_destroy(&block);
-            /* Write the frame set to disk */
-            if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
-                return(TNG_CRITICAL);
-            }
         }
-        else
+        if(stat == TNG_CRITICAL)
         {
-            tng_data->input_file = temp;
-            tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-            tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-            tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+                   file_pos, __FILE__, __LINE__);
+            tng_block_destroy(&block);
             return(stat);
         }
+
+        if(block->id == TNG_TRAJECTORY_FRAME_SET)
+        {
+            fseeko(tng_data->input_file, file_pos, SEEK_SET);
+        }
     }
 
-    tng_block_init(&block);
+    tng_block_destroy(&block);
 
-    file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
+    return(TNG_SUCCESS);
+}
 
-    fseeko(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftello(tng_data->output_file);
-    fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
-    /* Read past the frame set block first */
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode,
+                 const int64_t block_id)
+{
+    int64_t file_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
+    int found_flag = 1;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
+
+    file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
+
+    if(file_pos < 0)
+    {
+        /* No current frame set. This means that the first frame set must be
+         * read */
+        found_flag = 0;
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
+    }
+
+    if(file_pos > 0)
+    {
+        fseeko(tng_data->input_file,
+              file_pos,
+              SEEK_SET);
+    }
+    else
+    {
+        return(TNG_FAILURE);
+    }
+
+    tng_block_init(&block);
+
+    /* Read block headers first to see what block is found. */
     stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL)
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
         fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
                file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
-        tng_data->input_file = temp;
-
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-        return(stat);
+        return(TNG_CRITICAL);
     }
-    fseeko(tng_data->output_file, block->block_contents_size,
-           SEEK_CUR);
+    /* If the current frame set had already been read skip its block contents */
+    if(found_flag)
+    {
+        fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+    }
+    /* Otherwise read the frame set block */
+    else
+    {
+        stat = tng_block_read_next(tng_data, block,
+                                   hash_mode);
+        if(stat != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            return(stat);
+        }
+    }
+    file_pos = ftello(tng_data->input_file);
 
-    /* Read all block headers until next frame set block or
-     * until the wanted block id is found */
+    found_flag = 0;
+
+    /* Read only blocks of the requested ID
+        * until next frame set block */
     stat = tng_block_header_read(tng_data, block);
-    while(file_pos < output_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != block_id &&
-            block->id != TNG_TRAJECTORY_FRAME_SET &&
-            block->id != -1)
+    while(file_pos < tng_data->input_file_len &&
+          stat != TNG_CRITICAL &&
+          block->id != TNG_TRAJECTORY_FRAME_SET &&
+          block->id != -1)
     {
-        fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
-        file_pos = ftello(tng_data->output_file);
-        if(file_pos < output_file_len)
+        if(block->id == block_id)
         {
-            stat = tng_block_header_read(tng_data, block);
+            stat = tng_block_read_next(tng_data, block,
+                                       hash_mode);
+            if(stat != TNG_CRITICAL)
+            {
+                file_pos = ftello(tng_data->input_file);
+                found_flag = 1;
+                if(file_pos < tng_data->input_file_len)
+                {
+                    stat = tng_block_header_read(tng_data, block);
+                }
+            }
+        }
+        else
+        {
+            file_pos += block->block_contents_size + block->header_contents_size;
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+            if(file_pos < tng_data->input_file_len)
+            {
+                stat = tng_block_header_read(tng_data, block);
+            }
         }
     }
     if(stat == TNG_CRITICAL)
     {
         fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
+                file_pos, __FILE__, __LINE__);
         tng_block_destroy(&block);
-        tng_data->input_file = temp;
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
         return(stat);
     }
 
-    contents_size = block->block_contents_size;
-    header_size = block->header_contents_size;
+    if(block->id == TNG_TRAJECTORY_FRAME_SET)
+    {
+        fseeko(tng_data->input_file, file_pos, SEEK_SET);
+    }
 
-    header_pos = ftello(tng_data->output_file) - header_size;
-    frame_set = &tng_data->current_trajectory_frame_set;
+    tng_block_destroy(&block);
 
-    if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
+    if(found_flag)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        return(TNG_SUCCESS);
     }
-    if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
+    else
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
-    data.datatype = datatype;
+}
 
-    if(!(dependency & TNG_FRAME_DEPENDENT) ||
-       (dependency & TNG_PARTICLE_DEPENDENT))
-    {
-        tng_block_destroy(&block);
-        tng_data->input_file = temp;
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode)
+{
+    int64_t file_pos;
 
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-        return(TNG_FAILURE);
-    }
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
 
-    if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
 
-    if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
-             tng_data->input_file) == 0)
+    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
+
+    if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
-    if(tng_data->output_endianness_swap_func_64)
+
+    if(file_pos > 0)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &data.n_values_per_frame)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        fseeko(tng_data->input_file,
+               file_pos,
+               SEEK_SET);
+    }
+    else
+    {
+        return(TNG_FAILURE);
     }
 
-    if(fread(&data.codec_id, sizeof(data.codec_id), 1,
-             tng_data->input_file) == 0)
+    return(tng_frame_set_read(tng_data, hash_mode));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode,
+                 const int64_t block_id)
+{
+    int64_t file_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
-    if(tng_data->output_endianness_swap_func_64)
+
+    file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
+
+    if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &data.codec_id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
 
-    if(data.codec_id != TNG_UNCOMPRESSED)
+    if(file_pos > 0)
     {
-        if(fread(&data.compression_multiplier,
-                 sizeof(data.compression_multiplier), 1, tng_data->input_file)
-            == 0)
-        {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                (int64_t *)&data.compression_multiplier)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
+        fseeko(tng_data->input_file,
+               file_pos,
+               SEEK_SET);
     }
     else
     {
-        data.compression_multiplier = 1;
+        return(TNG_FAILURE);
     }
 
-    if(sparse_data)
-    {
-        if(fread(&data.first_frame_with_data, sizeof(data.first_frame_with_data),
-                 1, tng_data->input_file) == 0)
-        {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                &data.first_frame_with_data)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
+    tng_block_init(&block);
 
-        if(fread(&data.stride_length, sizeof(data.stride_length),
-                 1, tng_data->input_file) == 0)
-        {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
-        }
-        if(tng_data->output_endianness_swap_func_64)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                &data.stride_length)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
+    /* Read block headers first to see what block is found. */
+    stat = tng_block_header_read(tng_data, block);
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+    {
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+                file_pos, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
     }
-    else
+
+    tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
+
+    if(tng_block_read_next(tng_data, block,
+                           hash_mode) == TNG_SUCCESS)
     {
-        data.first_frame_with_data = 0;
-        data.stride_length = 1;
+        stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
     }
-    data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
 
-    tng_data->input_file = temp;
+    tng_block_destroy(&block);
 
-    tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-    tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-    tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+    return(stat);
+}
 
-    switch(data.datatype)
+tng_function_status tng_frame_set_write
+                (const tng_trajectory_t tng_data,
+                 const char hash_mode)
+{
+    int i, j;
+    tng_gen_block_t block;
+    tng_trajectory_frame_set_t frame_set;
+    tng_function_status stat;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    if(frame_set->n_written_frames == frame_set->n_frames)
     {
-        case(TNG_INT_DATA):
-            size = sizeof(int64_t);
-            break;
-        case(TNG_FLOAT_DATA):
-            size = sizeof(float);
-            break;
-        case(TNG_DOUBLE_DATA):
-            size = sizeof(double);
-            break;
-        default:
-            fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
-                   __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_FAILURE);
+        return(TNG_SUCCESS);
     }
 
-    n_values_per_frame = data.n_values_per_frame;
+    tng_data->current_trajectory_frame_set_output_file_pos =
+    ftello(tng_data->output_file);
+    tng_data->last_trajectory_frame_set_output_file_pos =
+    tng_data->current_trajectory_frame_set_output_file_pos;
 
-    file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
-                               data.first_frame_with_data)) /
-                data.stride_length;
-    file_pos *= size * n_values_per_frame;
+    if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
+    {
+        return(TNG_FAILURE);
+    }
 
-    if(file_pos > contents_size)
+    if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
+    {
+        tng_data->first_trajectory_frame_set_output_file_pos =
+        tng_data->current_trajectory_frame_set_output_file_pos;
+    }
+
+    tng_block_init(&block);
+
+    if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
-               __LINE__);
         tng_block_destroy(&block);
         return(TNG_FAILURE);
     }
 
-    fseeko(tng_data->output_file, file_pos, SEEK_CUR);
-
-    /* If the endianness is not big endian the data needs to be swapped */
-    if((data.datatype == TNG_INT_DATA ||
-        data.datatype == TNG_DOUBLE_DATA) &&
-       tng_data->output_endianness_swap_func_64)
+    /* Write non-particle data blocks */
+    for(i = 0; i<frame_set->n_data_blocks; i++)
     {
-        copy = malloc(n_values_per_frame * size);
-        memcpy(copy, values, n_values_per_frame * size);
-        for(i = 0; i < n_values_per_frame; i++)
-        {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                (int64_t *)copy+i)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
-        }
-        fwrite(copy, n_values_per_frame, size,
-               tng_data->output_file);
-        free(copy);
+        block->id = frame_set->tr_data[i].block_id;
+        tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
     }
-    else if(data.datatype == TNG_FLOAT_DATA &&
-            tng_data->output_endianness_swap_func_32)
+    /* Write the mapping blocks and particle data blocks*/
+    if(frame_set->n_mapping_blocks)
     {
-        copy = malloc(n_values_per_frame * size);
-        memcpy(copy, values, n_values_per_frame * size);
-        for(i = 0; i < n_values_per_frame; i++)
+        for(i = 0; i < frame_set->n_mapping_blocks; i++)
         {
-            if(tng_data->output_endianness_swap_func_32(tng_data,
-                (int32_t *)copy+i)
-                != TNG_SUCCESS)
+            block->id = TNG_PARTICLE_MAPPING;
+            if(frame_set->mappings[i].n_particles > 0)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
+                for(j = 0; j<frame_set->n_particle_data_blocks; j++)
+                {
+                    block->id = frame_set->tr_particle_data[j].block_id;
+                    tng_data_block_write(tng_data, block,
+                                         j, TNG_TRUE, &frame_set->mappings[i],
+                                         hash_mode);
+                }
             }
         }
-        fwrite(copy, n_values_per_frame, size,
-               tng_data->output_file);
-        free(copy);
     }
-
     else
     {
-        fwrite(values, n_values_per_frame, size, tng_data->output_file);
+        for(i = 0; i<frame_set->n_particle_data_blocks; i++)
+        {
+            block->id = frame_set->tr_particle_data[i].block_id;
+            tng_data_block_write(tng_data, block,
+                                 i, TNG_TRUE, 0, hash_mode);
+        }
     }
 
-    fflush(tng_data->output_file);
 
-    /* Update the number of written frames in the frame set. */
-    if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
-    {
-        frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
-    }
+    /* Update pointers in the general info block */
+    stat = tng_header_pointers_update(tng_data, hash_mode);
 
-    /* If the last frame has been written update the hash */
-    if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
-       data.first_frame_with_data) >=
-       frame_set->n_frames)
+    if(stat == TNG_SUCCESS)
     {
-        tng_md5_hash_update(tng_data, block, header_pos, header_pos +
-                            header_size);
+        stat = tng_frame_set_pointers_update(tng_data, hash_mode);
     }
 
     tng_block_destroy(&block);
 
-    return(TNG_SUCCESS);
+    frame_set->n_unwritten_frames = 0;
+
+    fflush(tng_data->output_file);
+
+    return(stat);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
-                (tng_trajectory_t tng_data,
-                 const int64_t frame_nr,
-                 const int64_t block_id,
-                 const int64_t val_first_particle,
-                 const int64_t val_n_particles,
-                 const void *values,
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
+                (const tng_trajectory_t tng_data,
                  const char hash_mode)
 {
-    int64_t header_pos, file_pos, tot_n_particles;
-    int64_t output_file_len, n_values_per_frame, size, contents_size;
-    int64_t header_size, temp_first, temp_last;
-    int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
-    int64_t i, last_frame, temp_current;
+    tng_trajectory_frame_set_t frame_set;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    if(frame_set->n_unwritten_frames == 0)
+    {
+        return(TNG_SUCCESS);
+    }
+    frame_set->n_frames = frame_set->n_unwritten_frames;
+
+    return(tng_frame_set_write(tng_data, hash_mode));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
+                (const tng_trajectory_t tng_data,
+                 const int64_t first_frame,
+                 const int64_t n_frames)
+{
     tng_gen_block_t block;
     tng_trajectory_frame_set_t frame_set;
     FILE *temp = tng_data->input_file;
-    struct tng_particle_data data;
-    tng_function_status stat;
-    tng_particle_mapping_t mapping;
-    char dependency, sparse_data, datatype;
-    void *copy;
+    int64_t curr_file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
-    TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
-    TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
-    TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
+    TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
+    TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
 
-    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    curr_file_pos = ftello(tng_data->output_file);
+
+    if(curr_file_pos <= 10)
     {
-        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
+        tng_file_headers_write(tng_data, TNG_USE_HASH);
     }
 
-    temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
-    temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
-    temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
-    tng_data->first_trajectory_frame_set_input_file_pos =
-    tng_data->first_trajectory_frame_set_output_file_pos;
-    tng_data->last_trajectory_frame_set_input_file_pos =
-    tng_data->last_trajectory_frame_set_output_file_pos;
-    tng_data->current_trajectory_frame_set_input_file_pos =
-    tng_data->current_trajectory_frame_set_output_file_pos;
+    /* Set pointer to previous frame set to the one that was loaded
+     * before.
+     * FIXME: This is a bit risky. If they are not added in order
+     * it will be wrong. */
+    if(tng_data->n_trajectory_frame_sets)
+    {
+        frame_set->prev_frame_set_file_pos =
+        tng_data->last_trajectory_frame_set_output_file_pos;
+    }
 
-    tng_data->input_file = tng_data->output_file;
+    frame_set->next_frame_set_file_pos = -1;
 
-    stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
+    tng_data->current_trajectory_frame_set_output_file_pos =
+    ftello(tng_data->output_file);
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    tng_data->n_trajectory_frame_sets++;
 
-    if(stat != TNG_SUCCESS)
+    /* Set the medium range pointers */
+    if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
     {
-        last_frame = frame_set->first_frame +
-                     frame_set->n_frames - 1;
-/*         fprintf(stderr, "TNG library: Frame %"PRId64" not found. Last frame: %"PRId64"\n", frame_nr,
-                  last_frame); */
-        /* If the wanted frame would be in the frame set after the last
-         * frame set create a new frame set. */
-        if(stat == TNG_FAILURE &&
-           (last_frame < frame_nr &&
-            last_frame + tng_data->frame_set_n_frames >= frame_nr))
+        frame_set->medium_stride_prev_frame_set_file_pos =
+        tng_data->first_trajectory_frame_set_output_file_pos;
+    }
+    else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
+    {
+        /* FIXME: Currently only working if the previous frame set has its
+         * medium stride pointer already set. This might need some fixing. */
+        if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
+           frame_set->medium_stride_prev_frame_set_file_pos != 0)
         {
-            if(last_frame + tng_data->frame_set_n_frames < frame_nr)
+            tng_block_init(&block);
+            tng_data->input_file = tng_data->output_file;
+
+            curr_file_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file,
+                   frame_set->medium_stride_prev_frame_set_file_pos,
+                   SEEK_SET);
+
+            if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
             {
-                last_frame = frame_nr - 1;
+                fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                    __FILE__, __LINE__);
+                tng_data->input_file = temp;
+                tng_block_destroy(&block);
+                return(TNG_CRITICAL);
             }
-            tng_frame_set_new(tng_data,
-                              last_frame+1,
-                              tng_data->frame_set_n_frames);
-
-            file_pos = ftello(tng_data->output_file);
-            fseeko(tng_data->output_file, 0, SEEK_END);
-            output_file_len = ftello(tng_data->output_file);
-            fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
-            /* Read mapping blocks from the last frame set */
-            tng_block_init(&block);
+            /* Read the next frame set from the previous frame set and one
+             * medium stride step back */
+            fseeko(tng_data->output_file, block->block_contents_size - (6 *
+            sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+            if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
+               sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
+               1, tng_data->output_file) == 0)
+            {
+                fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+                tng_data->input_file = temp;
+                tng_block_destroy(&block);
+                return(TNG_CRITICAL);
+            }
 
-            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 != -1)
+            if(tng_data->input_endianness_swap_func_64)
             {
-                if(block->id == TNG_PARTICLE_MAPPING)
-                {
-                    tng_trajectory_mapping_block_read(tng_data, block,
-                                                      hash_mode);
-                }
-                else
-                {
-                    fseeko(tng_data->output_file, block->block_contents_size,
-                        SEEK_CUR);
-                }
-                file_pos = ftello(tng_data->output_file);
-                if(file_pos < output_file_len)
+                if(tng_data->input_endianness_swap_func_64(tng_data,
+                   &frame_set->medium_stride_prev_frame_set_file_pos)
+                    != TNG_SUCCESS)
                 {
-                    stat = tng_block_header_read(tng_data, block);
+                    fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                            __FILE__, __LINE__);
                 }
             }
 
             tng_block_destroy(&block);
-            /* Write the frame set to disk */
-            if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
+
+            /* Set the long range pointers */
+            if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
             {
-                fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
-                exit(1);
+                frame_set->long_stride_prev_frame_set_file_pos =
+                tng_data->first_trajectory_frame_set_output_file_pos;
             }
-        }
-        else
-        {
+            else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
+            {
+                /* FIXME: Currently only working if the previous frame set has its
+                * long stride pointer already set. This might need some fixing. */
+                if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
+                frame_set->long_stride_prev_frame_set_file_pos != 0)
+                {
+                    tng_block_init(&block);
+                    tng_data->input_file = tng_data->output_file;
+
+                    fseeko(tng_data->output_file,
+                           frame_set->long_stride_prev_frame_set_file_pos,
+                           SEEK_SET);
+
+                    if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+                    {
+                        fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+                            __FILE__, __LINE__);
+                        tng_data->input_file = temp;
+                        tng_block_destroy(&block);
+                        return(TNG_CRITICAL);
+                    }
+
+                    /* Read the next frame set from the previous frame set and one
+                    * long stride step back */
+                    fseeko(tng_data->output_file, block->block_contents_size - (6 *
+                          sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+                    tng_block_destroy(&block);
+
+                    if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
+                    sizeof(frame_set->long_stride_prev_frame_set_file_pos),
+                    1, tng_data->output_file) == 0)
+                    {
+                        fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+                        tng_data->input_file = temp;
+                        return(TNG_CRITICAL);
+                    }
+
+                    if(tng_data->input_endianness_swap_func_64)
+                    {
+                        if(tng_data->input_endianness_swap_func_64(tng_data,
+                           &frame_set->long_stride_prev_frame_set_file_pos)
+                            != TNG_SUCCESS)
+                        {
+                            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                                    __FILE__, __LINE__);
+                        }
+                    }
+
+                }
+            }
+
             tng_data->input_file = temp;
-            tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-            tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-            tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-            return(stat);
+            fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
         }
     }
 
+    frame_set->first_frame = first_frame;
+    frame_set->n_frames = n_frames;
+    frame_set->n_written_frames = 0;
+    frame_set->n_unwritten_frames = 0;
+    frame_set->first_frame_time = -1;
+
+    if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
+       tng_data->first_trajectory_frame_set_output_file_pos == 0)
+    {
+        tng_data->first_trajectory_frame_set_output_file_pos =
+        tng_data->current_trajectory_frame_set_output_file_pos;
+    }
+    /* FIXME: Should check the frame number instead of the file_pos,
+     * in case frame sets are not in order */
+    if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
+       tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
+       tng_data->last_trajectory_frame_set_output_file_pos <
+       tng_data->current_trajectory_frame_set_output_file_pos)
+    {
+        tng_data->last_trajectory_frame_set_output_file_pos =
+        tng_data->current_trajectory_frame_set_output_file_pos;
+    }
+
+    return(TNG_SUCCESS);
+}
 
-    tng_block_init(&block);
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
+                (const tng_trajectory_t tng_data,
+                 const int64_t first_frame,
+                 const int64_t n_frames,
+                 const double first_frame_time)
+{
+    tng_function_status stat;
 
-    file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
+    TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
+    TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
 
-    fseeko(tng_data->output_file, 0, SEEK_END);
-    output_file_len = ftello(tng_data->output_file);
-    fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
-    /* Read past the frame set block first */
-    stat = tng_block_header_read(tng_data, block);
-    if(stat == TNG_CRITICAL)
+    stat = tng_frame_set_new(tng_data, first_frame, n_frames);
+    if(stat != TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-               file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        tng_data->input_file = temp;
-
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
         return(stat);
     }
-    fseeko(tng_data->output_file, block->block_contents_size,
-            SEEK_CUR);
+    stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
 
-    if(tng_data->var_num_atoms_flag)
+    return(stat);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
+                (const tng_trajectory_t tng_data,
+                 const double first_frame_time)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
+
+    tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
+
+    return(TNG_SUCCESS);
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
+                (const tng_trajectory_t tng_data,
+                 int64_t *frame)
+{
+    int64_t file_pos, next_frame_set_file_pos;
+    tng_gen_block_t block;
+    tng_function_status stat;
+
+    tng_trajectory_frame_set_t frame_set;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
+    TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
+
+    file_pos = ftello(tng_data->input_file);
+
+    if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
     {
-        tot_n_particles = frame_set->n_particles;
+        next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
     }
     else
     {
-        tot_n_particles = tng_data->n_particles;
+        frame_set = &tng_data->current_trajectory_frame_set;
+        next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
     }
 
-    if(val_n_particles < tot_n_particles)
+    if(next_frame_set_file_pos <= 0)
     {
-        mapping_block_end_pos = -1;
-        /* Read all mapping blocks to find the right place to put the data */
-        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 != -1)
-        {
-            if(block->id == TNG_PARTICLE_MAPPING)
-            {
-                tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
-            }
-            else
-            {
-                fseeko(tng_data->output_file, block->block_contents_size,
-                      SEEK_CUR);
-            }
-            file_pos = ftello(tng_data->output_file);
-            if(block->id == TNG_PARTICLE_MAPPING)
-            {
-                mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
-                if(val_first_particle >= mapping->num_first_particle &&
-                   val_first_particle < mapping->num_first_particle +
-                   mapping->n_particles &&
-                   val_first_particle + val_n_particles <=
-                   mapping->num_first_particle + mapping->n_particles)
-                {
-                    mapping_block_end_pos = file_pos;
-                }
-            }
-            if(file_pos < output_file_len)
-            {
-                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",
-                   file_pos, __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            tng_data->input_file = temp;
-
-            tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-            tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-            tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-            return(stat);
-        }
-        if(mapping_block_end_pos < 0)
-        {
-            tng_block_destroy(&block);
-            tng_data->input_file = temp;
-
-            tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-            tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-            tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-            return(TNG_FAILURE);
-        }
-        fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
+        return(TNG_FAILURE);
     }
 
-    /* Read all block headers until next frame set block or
-     * until the wanted block id is found */
+    fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
+    /* Read block headers first to see that a frame set block is found. */
+    tng_block_init(&block);
     stat = tng_block_header_read(tng_data, block);
-    while(file_pos < output_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != block_id &&
-            block->id != TNG_PARTICLE_MAPPING &&
-            block->id != TNG_TRAJECTORY_FRAME_SET &&
-            block->id != -1)
-    {
-        fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
-        file_pos = ftello(tng_data->output_file);
-        if(file_pos < output_file_len)
-        {
-            stat = tng_block_header_read(tng_data, block);
-        }
-    }
-    if(stat == TNG_CRITICAL)
+    if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
     {
         fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                file_pos, __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        tng_data->input_file = temp;
-
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-        return(stat);
+               file_pos, __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
+/*    if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
+    {
+        tng_block_read_next(tng_data, block, TNG_USE_HASH);
+    }*/
+    tng_block_destroy(&block);
 
-    contents_size = block->block_contents_size;
-    header_size = block->header_contents_size;
-
-    header_pos = ftello(tng_data->output_file) - header_size;
-    frame_set = &tng_data->current_trajectory_frame_set;
-
-    if(fread(&datatype, sizeof(datatype), 1, tng_data->input_file) == 0)
+    if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
+        fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
+    fseeko(tng_data->input_file, file_pos, SEEK_SET);
 
-    data.datatype = datatype;
+    return(TNG_SUCCESS);
+}
 
-    if(fread(&dependency, sizeof(dependency), 1, tng_data->input_file) == 0)
-    {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
+static tng_function_status tng_gen_data_block_add
+                (const tng_trajectory_t tng_data,
+                 const int64_t id,
+                 const tng_bool is_particle_data,
+                 const char *block_name,
+                 const char datatype,
+                 const char block_type_flag,
+                 int64_t n_frames,
+                 const int64_t n_values_per_frame,
+                 int64_t stride_length,
+                 const int64_t num_first_particle,
+                 const int64_t n_particles,
+                 const int64_t codec_id,
+                 void *new_data)
+{
+    int i, size, len;
+    int64_t j, k;
+    int64_t tot_n_particles, n_frames_div;
+    char ***first_dim_values, **second_dim_values;
+    tng_trajectory_frame_set_t frame_set;
+    tng_data_t data;
+    char *new_data_c=new_data;
+    tng_function_status stat;
 
-    if(!(dependency & TNG_FRAME_DEPENDENT) ||
-       !(dependency & TNG_PARTICLE_DEPENDENT))
-    {
-        tng_block_destroy(&block);
-        tng_data->input_file = temp;
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
-        return(TNG_FAILURE);
+    if(stride_length <= 0)
+    {
+        stride_length = 1;
     }
 
-    if(fread(&sparse_data, sizeof(sparse_data), 1, tng_data->input_file) == 0)
+    if(is_particle_data)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        stat = tng_particle_data_find(tng_data, id, &data);
     }
-
-    if(fread(&data.n_values_per_frame, sizeof(data.n_values_per_frame), 1,
-             tng_data->input_file) == 0)
+    else
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        stat = tng_data_find(tng_data, id, &data);
     }
-    if(tng_data->output_endianness_swap_func_64)
+    /* If the block does not exist, create it */
+    if(stat != TNG_SUCCESS)
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &data.n_values_per_frame)
-            != TNG_SUCCESS)
+        if(is_particle_data)
+        {
+            stat = tng_particle_data_block_create(tng_data, block_type_flag);
+        }
+        else
+        {
+            stat = tng_data_block_create(tng_data, block_type_flag);
+        }
+
+        if(stat != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(TNG_CRITICAL);
+        }
+        if(is_particle_data)
+        {
+            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];
+            }
+        }
+        else
+        {
+            if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+            {
+                data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+            }
+            else
+            {
+                data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
+            }
+        }
+        data->block_id = id;
+
+        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 (%ud bytes). %s: %d\n",
+                   (unsigned int)strlen(block_name)+1, __FILE__, __LINE__);
+            return(TNG_CRITICAL);
         }
+        strncpy(data->block_name, block_name, strlen(block_name) + 1);
+
+        data->values = 0;
+        /* FIXME: Memory leak from strings. */
+        data->strings = 0;
+        data->last_retrieved_frame = -1;
     }
 
-    if(fread(&data.codec_id, sizeof(data.codec_id), 1,
-             tng_data->input_file) == 0)
+    data->datatype = datatype;
+    data->stride_length = tng_max_i64(stride_length, 1);
+    data->n_values_per_frame = n_values_per_frame;
+    data->n_frames = n_frames;
+    if(is_particle_data)
     {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
+        data->dependency = TNG_PARTICLE_DEPENDENT;
     }
-    if(tng_data->output_endianness_swap_func_64)
+    else
     {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &data.codec_id)
-            != TNG_SUCCESS)
-        {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
-        }
+        data->dependency = 0;
+    }
+    if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+                          (n_frames > 1 ||
+                           frame_set->n_frames == n_frames ||
+                           stride_length > 1))
+    {
+        data->dependency += TNG_FRAME_DEPENDENT;
     }
+    data->codec_id = codec_id;
+    data->compression_multiplier = 1.0;
+    /* FIXME: This can cause problems. */
+    data->first_frame_with_data = frame_set->first_frame;
 
-    if(data.codec_id != TNG_UNCOMPRESSED)
+    if(is_particle_data)
     {
-        if(fread(&data.compression_multiplier,
-                 sizeof(data.compression_multiplier), 1, tng_data->input_file)
-            == 0)
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
         {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
+            tot_n_particles = frame_set->n_particles;
         }
-
-        if(tng_data->output_endianness_swap_func_64)
+        else
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-               (int64_t *)&data.compression_multiplier)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            tot_n_particles = tng_data->n_particles;
         }
     }
+    /* This is just to keep the compiler happy - avoid it considering tot_n_particles
+     * uninitialized. */
     else
     {
-        data.compression_multiplier = 1;
+        tot_n_particles = 0;
     }
 
-    if(sparse_data)
+    /* If data values are supplied add that data to the data block. */
+    if(new_data_c)
     {
-        if(fread(&data.first_frame_with_data,
-                 sizeof(data.first_frame_with_data),
-                 1, tng_data->input_file) == 0)
+        /* Allocate memory */
+        if(is_particle_data)
         {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_CRITICAL);
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
+                                            stride_length, tot_n_particles,
+                                            n_values_per_frame);
         }
-        if(tng_data->output_endianness_swap_func_64)
+        else
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                &data.first_frame_with_data)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
+                                 n_values_per_frame);
         }
-
-        if(fread(&data.stride_length, sizeof(data.stride_length),
-                 1, tng_data->input_file) == 0)
+        if(stat != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-            tng_block_destroy(&block);
+            fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
+                __FILE__, __LINE__);
             return(TNG_CRITICAL);
         }
-        if(tng_data->output_endianness_swap_func_64)
+
+        if(n_frames > frame_set->n_unwritten_frames)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                &data.stride_length)
-                != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
-            }
+            frame_set->n_unwritten_frames = n_frames;
         }
-    }
-    else
-    {
-        data.first_frame_with_data = 0;
-        data.stride_length = 1;
-    }
-    data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
 
-    if(fread(&num_first_particle, sizeof(num_first_particle), 1,
-             tng_data->input_file) == 0)
-    {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &num_first_particle)
-            != TNG_SUCCESS)
+        n_frames_div = (n_frames % stride_length) ?
+                     n_frames / stride_length + 1:
+                     n_frames / stride_length;
+
+        if(datatype == TNG_CHAR_DATA)
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            if(is_particle_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++)
+                    {
+                        second_dim_values = first_dim_values[j];
+                        for(k = 0; k < n_values_per_frame; k++)
+                        {
+                            len = tng_min_size(strlen(new_data_c) + 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],
+                                    new_data_c, len);
+                            new_data_c += len;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for(i = 0; i < n_frames_div; i++)
+                {
+                    second_dim_values = data->strings[0][i];
+                    for(j = 0; j < n_values_per_frame; j++)
+                    {
+                        len = tng_min_size(strlen(new_data_c) + 1,
+                                    TNG_MAX_STR_LEN);
+                        if(second_dim_values[j])
+                        {
+                            free(second_dim_values[j]);
+                        }
+                        second_dim_values[j] = malloc(len);
+                        if(!second_dim_values[j])
+                        {
+                            fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+                                len, __FILE__, __LINE__);
+                            return(TNG_CRITICAL);
+                        }
+                        strncpy(second_dim_values[j],
+                                new_data_c, len);
+                        new_data_c += len;
+                    }
+                }
+            }
         }
-    }
-
-    if(fread(&block_n_particles, sizeof(block_n_particles), 1,
-             tng_data->input_file) == 0)
-    {
-        fprintf(stderr, "TNG library: Error reading file. %s: %d\n", __FILE__, __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_CRITICAL);
-    }
-    if(tng_data->output_endianness_swap_func_64)
-    {
-        if(tng_data->output_endianness_swap_func_64(tng_data,
-            &block_n_particles)
-            != TNG_SUCCESS)
+        else
         {
-            fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                    __FILE__, __LINE__);
+            switch(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);
+            }
+
+            if(is_particle_data)
+            {
+                memcpy(data->values, new_data, size * n_frames_div *
+                    n_particles * n_values_per_frame);
+            }
+            else
+            {
+                memcpy(data->values, new_data, size * n_frames_div *
+                    n_values_per_frame);
+            }
         }
     }
 
+    return(TNG_SUCCESS);
+}
 
-    tng_data->input_file = temp;
+tng_function_status DECLSPECDLLEXPORT tng_data_block_add
+                (const tng_trajectory_t tng_data,
+                 const int64_t id,
+                 const char *block_name,
+                 const char datatype,
+                 const char block_type_flag,
+                 int64_t n_frames,
+                 const int64_t n_values_per_frame,
+                 int64_t stride_length,
+                 const int64_t codec_id,
+                 void *new_data)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
 
-    tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
-    tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
-    tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+    return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
+                                  block_type_flag, n_frames, n_values_per_frame,
+                                  stride_length, 0, 0, codec_id, new_data));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
+                (const tng_trajectory_t tng_data,
+                 const int64_t id,
+                 const char *block_name,
+                 const char datatype,
+                 const char block_type_flag,
+                 int64_t n_frames,
+                 const int64_t n_values_per_frame,
+                 int64_t stride_length,
+                 const int64_t num_first_particle,
+                 const int64_t n_particles,
+                 const int64_t codec_id,
+                 void *new_data)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
+    TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
+    TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
 
+    return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
+                                  block_type_flag, n_frames, n_values_per_frame,
+                                  stride_length, num_first_particle, n_particles,
+                                  codec_id, new_data));
+}
 
-    switch(data.datatype)
+tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 char *name,
+                 const int max_len)
+{
+    int64_t i;
+    tng_trajectory_frame_set_t frame_set;
+    tng_function_status stat;
+    tng_data_t data;
+    int block_type = -1;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+
+    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
     {
-        case(TNG_INT_DATA):
-            size = sizeof(int64_t);
-            break;
-        case(TNG_FLOAT_DATA):
-            size = sizeof(float);
-            break;
-        case(TNG_DOUBLE_DATA):
-            size = sizeof(double);
-            break;
-        default:
-            fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
-                   __LINE__);
-            tng_block_destroy(&block);
-            return(TNG_FAILURE);
+        data = &tng_data->non_tr_particle_data[i];
+        if(data->block_id == block_id)
+        {
+            strncpy(name, data->block_name, max_len);
+            name[max_len - 1] = '\0';
+            return(TNG_SUCCESS);
+        }
+    }
+    for(i = 0; i < tng_data->n_data_blocks; i++)
+    {
+        data = &tng_data->non_tr_data[i];
+        if(data->block_id == block_id)
+        {
+            strncpy(name, data->block_name, max_len);
+            name[max_len - 1] = '\0';
+            return(TNG_SUCCESS);
+        }
     }
 
-    n_values_per_frame = data.n_values_per_frame;
-
-    file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
-                               data.first_frame_with_data)) /
-                data.stride_length;
-    file_pos *= block_n_particles * size * n_values_per_frame;
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-    if(file_pos > contents_size)
+    stat = tng_particle_data_find(tng_data, block_id, &data);
+    if(stat == TNG_SUCCESS)
     {
-        fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
-               __LINE__);
-        tng_block_destroy(&block);
-        return(TNG_FAILURE);
+        block_type = TNG_PARTICLE_BLOCK_DATA;
     }
-
-    fseeko(tng_data->output_file, file_pos, SEEK_CUR);
-
-    /* If the endianness is not big endian the data needs to be swapped */
-    if((data.datatype == TNG_INT_DATA ||
-        data.datatype == TNG_DOUBLE_DATA) &&
-       tng_data->output_endianness_swap_func_64)
+    else
     {
-        copy = malloc(val_n_particles * n_values_per_frame * size);
-        memcpy(copy, values, val_n_particles * n_values_per_frame * size);
-        for(i = 0; i < val_n_particles * n_values_per_frame; i++)
+        stat = tng_data_find(tng_data, block_id, &data);
+        if(stat == TNG_SUCCESS)
         {
-            if(tng_data->output_endianness_swap_func_64(tng_data,
-                (int64_t *) copy+i)
-                != TNG_SUCCESS)
+            block_type = TNG_NON_PARTICLE_BLOCK_DATA;
+        }
+        else
+        {
+            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
+            if(stat != TNG_SUCCESS)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                return(stat);
+            }
+            stat = tng_particle_data_find(tng_data, block_id, &data);
+            if(stat == TNG_SUCCESS)
+            {
+                block_type = TNG_PARTICLE_BLOCK_DATA;
+            }
+            else
+            {
+                stat = tng_data_find(tng_data, block_id, &data);
+                if(stat == TNG_SUCCESS)
+                {
+                    block_type = TNG_NON_PARTICLE_BLOCK_DATA;
+                }
             }
         }
-        fwrite(copy, val_n_particles * n_values_per_frame, size,
-               tng_data->output_file);
-        free(copy);
     }
-    else if(data.datatype == TNG_FLOAT_DATA &&
-       tng_data->output_endianness_swap_func_32)
+    if(block_type == TNG_PARTICLE_BLOCK_DATA)
     {
-        copy = malloc(val_n_particles * n_values_per_frame * size);
-        memcpy(copy, values, val_n_particles * n_values_per_frame * size);
-        for(i = 0; i < val_n_particles * n_values_per_frame; i++)
+        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
         {
-            if(tng_data->output_endianness_swap_func_32(tng_data,
-                (int32_t *) copy+i)
-                != TNG_SUCCESS)
+            data = &frame_set->tr_particle_data[i];
+            if(data->block_id == block_id)
             {
-                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
-                        __FILE__, __LINE__);
+                strncpy(name, data->block_name, max_len);
+                name[max_len - 1] = '\0';
+                return(TNG_SUCCESS);
             }
         }
-        fwrite(copy, val_n_particles * n_values_per_frame, size,
-               tng_data->output_file);
-        free(copy);
-    }
-
-    else
-    {
-        fwrite(values, val_n_particles * n_values_per_frame, size,
-               tng_data->output_file);
-    }
-    fflush(tng_data->output_file);
-
-    /* Update the number of written frames in the frame set. */
-    if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
-    {
-        frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
     }
-
-    /* If the last frame has been written update the hash */
-    if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
-       data.first_frame_with_data) >=
-       frame_set->n_frames)
+    else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
     {
-        tng_md5_hash_update(tng_data, block, header_pos, header_pos +
-                            header_size);
+        for(i = 0; i < frame_set->n_data_blocks; i++)
+        {
+            data = &frame_set->tr_data[i];
+            if(data->block_id == block_id)
+            {
+                strncpy(name, data->block_name, max_len);
+                name[max_len - 1] = '\0';
+                return(TNG_SUCCESS);
+            }
+        }
     }
 
-    tng_block_destroy(&block);
-    return(TNG_SUCCESS);
+    return(TNG_FAILURE);
 }
 
-static tng_function_status tng_data_values_alloc
+tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
                 (const tng_trajectory_t tng_data,
-                 union data_values ***values,
-                 const int64_t n_frames,
-                 const int64_t n_values_per_frame,
-                 const char type)
+                 const int64_t block_id,
+                 int *block_dependency)
 {
     int64_t i;
     tng_function_status stat;
+    tng_data_t data;
 
-    if(n_frames <= 0 || n_values_per_frame <= 0)
-    {
-        return(TNG_FAILURE);
-    }
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
 
-    if(*values)
+    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
     {
-        stat = tng_data_values_free(tng_data, *values, n_frames,
-                                    n_values_per_frame,
-                                    type);
-        if(stat != TNG_SUCCESS)
+        data = &tng_data->non_tr_particle_data[i];
+        if(data->block_id == block_id)
         {
-            fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(stat);
+            *block_dependency = TNG_PARTICLE_DEPENDENT;
+            return(TNG_SUCCESS);
         }
     }
-    *values = malloc(sizeof(union data_values *) * n_frames);
-    if(!*values)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(union data_values **) * n_frames,
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-
-    }
-
-    for(i = 0; i < n_frames; i++)
+    for(i = 0; i < tng_data->n_data_blocks; i++)
     {
-        (*values)[i] = malloc(sizeof(union data_values) *
-                           n_values_per_frame);
-        if(!(*values)[i])
+        data = &tng_data->non_tr_data[i];
+        if(data->block_id == block_id)
         {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-                   sizeof(union data_values) * n_values_per_frame,
-                   __FILE__, __LINE__);
-            free(values);
-            values = 0;
-            return(TNG_CRITICAL);
+            *block_dependency = 0;
+            return(TNG_SUCCESS);
         }
     }
-    return(TNG_SUCCESS);
-}
-
-/* FIXME: This needs ***values */
-tng_function_status DECLSPECDLLEXPORT tng_data_values_free
-                (const tng_trajectory_t tng_data,
-                 union data_values **values,
-                 const int64_t n_frames,
-                 const int64_t n_values_per_frame,
-                 const char type)
-{
-    int64_t i, j;
-    (void)tng_data;
 
-    if(values)
+    stat = tng_particle_data_find(tng_data, block_id, &data);
+    if(stat == TNG_SUCCESS)
     {
-        for(i = 0; i < n_frames; i++)
+        *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
+        return(TNG_SUCCESS);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &data);
+        if(stat == TNG_SUCCESS)
         {
-            if(values[i])
+            *block_dependency = TNG_FRAME_DEPENDENT;
+            return(TNG_SUCCESS);
+        }
+        else
+        {
+            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
+            if(stat != TNG_SUCCESS)
             {
-                if(type == TNG_CHAR_DATA)
+                return(stat);
+            }
+            stat = tng_particle_data_find(tng_data, block_id, &data);
+            if(stat == TNG_SUCCESS)
+            {
+                *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
+                return(TNG_SUCCESS);
+            }
+            else
+            {
+                stat = tng_data_find(tng_data, block_id, &data);
+                if(stat == TNG_SUCCESS)
                 {
-                    for(j = 0; j < n_values_per_frame; j++)
-                    {
-                        if(values[i][j].c)
-                        {
-                            free(values[i][j].c);
-                            values[i][j].c = 0;
-                        }
-                    }
+                    *block_dependency = TNG_FRAME_DEPENDENT;
+                    return(TNG_SUCCESS);
                 }
-                free(values[i]);
-                values[i] = 0;
             }
         }
-        free(values);
-        values = 0;
     }
 
-    return(TNG_SUCCESS);
+    return(TNG_FAILURE);
 }
 
-static tng_function_status tng_particle_data_values_alloc
+tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
                 (const tng_trajectory_t tng_data,
-                 union data_values ****values,
-                 const int64_t n_frames,
-                 const int64_t n_particles,
-                 const int64_t n_values_per_frame,
-                 const char type)
+                 const int64_t block_id,
+                 int64_t *n_values_per_frame)
 {
-    int64_t i, j;
+    int64_t i;
     tng_function_status stat;
+    tng_data_t data;
 
-    if(n_particles == 0 || n_values_per_frame == 0)
-    {
-        return(TNG_FAILURE);
-    }
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
 
-    if(*values)
+    for(i = 0; i < tng_data->n_particle_data_blocks; i++)
     {
-        stat = tng_particle_data_values_free(tng_data, *values, n_frames,
-                                             n_particles, n_values_per_frame,
-                                             type);
-        if(stat != TNG_SUCCESS)
+        data = &tng_data->non_tr_particle_data[i];
+        if(data->block_id == block_id)
         {
-            fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
-                   __FILE__, __LINE__);
-            return(stat);
+            *n_values_per_frame = data->n_values_per_frame;
+            return(TNG_SUCCESS);
         }
     }
-    *values = malloc(sizeof(union data_values **) * n_frames);
-    if(!*values)
-    {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-               sizeof(union data_values **) * n_frames,
-               __FILE__, __LINE__);
-        return(TNG_CRITICAL);
-
-    }
-
-    for(i = 0; i < n_frames; i++)
-    {
-        (*values)[i] = malloc(sizeof(union data_values *) *
-                           n_particles);
-        if(!(*values)[i])
-        {
-            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-                   sizeof(union data_values *) * n_particles,
-                   __FILE__, __LINE__);
-            free(*values);
-            *values = 0;
-            return(TNG_CRITICAL);
-        }
-        for(j = 0; j < n_particles; j++)
-        {
-            (*values)[i][j] = malloc(sizeof(union data_values) *
-                                  n_values_per_frame);
-            if(!(*values)[i][j])
-            {
-                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
-                    sizeof(union data_values *) * n_particles,
-                    __FILE__, __LINE__);
-                tng_particle_data_values_free(tng_data, *values, n_frames,
-                                              n_particles, n_values_per_frame,
-                                              type);
-                *values = 0;
-                return(TNG_CRITICAL);
-            }
+    for(i = 0; i < tng_data->n_data_blocks; i++)
+    {
+        data = &tng_data->non_tr_data[i];
+        if(data->block_id == block_id)
+        {
+            *n_values_per_frame = data->n_values_per_frame;
+            return(TNG_SUCCESS);
         }
     }
-    return(TNG_SUCCESS);
-}
-
-/* FIXME: This needs ****values */
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
-                (const tng_trajectory_t tng_data,
-                 union data_values ***values,
-                 const int64_t n_frames,
-                 const int64_t n_particles,
-                 const int64_t n_values_per_frame,
-                 const char type)
-{
-    int64_t i, j, k;
-    (void)tng_data;
 
-    if(values)
+    stat = tng_particle_data_find(tng_data, block_id, &data);
+    if(stat == TNG_SUCCESS)
     {
-        for(i = 0; i < n_frames; i++)
+        *n_values_per_frame = data->n_values_per_frame;
+        return(TNG_SUCCESS);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &data);
+        if(stat == TNG_SUCCESS)
         {
-            if(values[i])
+            *n_values_per_frame = data->n_values_per_frame;
+            return(TNG_SUCCESS);
+        }
+        else
+        {
+            stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
+            if(stat != TNG_SUCCESS)
             {
-                for(j = 0; j < n_particles; j++)
+                return(stat);
+            }
+            stat = tng_particle_data_find(tng_data, block_id, &data);
+            if(stat == TNG_SUCCESS)
+            {
+                *n_values_per_frame = data->n_values_per_frame;
+                return(TNG_SUCCESS);
+            }
+            else
+            {
+                stat = tng_data_find(tng_data, block_id, &data);
+                if(stat == TNG_SUCCESS)
                 {
-                    if(type == TNG_CHAR_DATA)
-                    {
-                        for(k = 0; k < n_values_per_frame; k++)
-                        {
-                            if(values[i][j][k].c)
-                            {
-                                free(values[i][j][k].c);
-                                values[i][j][k].c = 0;
-                            }
-                        }
-                    }
-                    free(values[i][j]);
-                    values[i][j] = 0;
+                    *n_values_per_frame = data->n_values_per_frame;
+                    return(TNG_SUCCESS);
                 }
-                free(values[i]);
-                values[i] = 0;
             }
         }
-        free(values);
-        values = 0;
     }
 
-    return(TNG_SUCCESS);
+    return(TNG_FAILURE);
 }
 
-
-tng_function_status DECLSPECDLLEXPORT tng_data_get
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
-                 union data_values ***values,
-                 int64_t *n_frames,
-                 int64_t *n_values_per_frame,
-                 char *type)
+                 int64_t *n_frames)
 {
-    int64_t i, j, file_pos, block_index;
-    int size;
-    size_t len;
-    tng_non_particle_data_t data;
-    tng_trajectory_frame_set_t frame_set;
     tng_gen_block_t block;
     tng_function_status stat;
+    char datatype, dependency, sparse_data;
+    int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
+    int64_t num_first_particle, block_n_particles;
+    double multiplier;
+    md5_state_t md5_state;
+    int found = TNG_FALSE;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
-    frame_set = &tng_data->current_trajectory_frame_set;
 
-    block_index = -1;
-    data = 0;
+    tng_block_init(&block);
 
-    if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
+    stat = tng_block_header_read(tng_data, block);
+    /* If the block header could not be read the reading position might not have been
+     * at the start of a block. Try again from the file position of the current frame
+     * set. */
+    if(stat != TNG_SUCCESS)
     {
-        tng_block_init(&block);
-        file_pos = ftello(tng_data->input_file);
-        /* Read all blocks until next frame set block */
+        fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
         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 != -1)
+        if(stat != TNG_SUCCESS)
         {
-            /* Use hash by default */
-            stat = tng_block_read_next(tng_data, block,
-                                    TNG_USE_HASH);
-            if(stat != TNG_CRITICAL)
-            {
-                file_pos = ftello(tng_data->input_file);
-                if(file_pos < tng_data->input_file_len)
-                {
-                    stat = tng_block_header_read(tng_data, block);
-                }
-            }
+            tng_block_destroy(&block);
+            return(stat);
         }
-        tng_block_destroy(&block);
-        if(stat == TNG_CRITICAL)
+    }
+    if(block->id == TNG_TRAJECTORY_FRAME_SET)
+    {
+        stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
+        if(stat != TNG_SUCCESS)
         {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                    file_pos, __FILE__, __LINE__);
+            tng_block_destroy(&block);
             return(stat);
         }
-
-        for(i = 0; i < frame_set->n_data_blocks; i++)
+        stat = tng_block_header_read(tng_data, block);
+    }
+    while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
+    {
+        if(block->id == block_id)
         {
-            data = &frame_set->tr_data[i];
-            if(data->block_id == block_id)
+            stat = tng_data_block_meta_information_read(tng_data, &datatype,
+                                                        &dependency, &sparse_data,
+                                                        &n_values, &codec_id,
+                                                        &first_frame_with_data,
+                                                        &stride_length, &curr_n_frames,
+                                                        &num_first_particle,
+                                                        &block_n_particles,
+                                                        &multiplier, TNG_SKIP_HASH,
+                                                        &md5_state);
+            if(stat == TNG_SUCCESS)
             {
-                block_index = i;
-                break;
+                found = TNG_TRUE;
             }
         }
-        if(block_index < 0)
+        else
         {
-            return(TNG_FAILURE);
+            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+            stat = tng_block_header_read(tng_data, block);
         }
     }
+    if(found == TNG_TRUE)
+    {
+        *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
+                     (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
+    }
+    else if(stat == TNG_SUCCESS)
+    {
+        *n_frames = 0;
+    }
 
-    *n_frames = tng_max_i64(1, data->n_frames);
-    *n_values_per_frame = data->n_values_per_frame;
-    *type = data->datatype;
+    tng_block_destroy(&block);
 
-    if(*values == 0)
+    return(stat);
+}
+
+static tng_function_status tng_frame_gen_data_write
+                (const tng_trajectory_t tng_data,
+                 const int64_t frame_nr,
+                 const int64_t block_id,
+                 const tng_bool is_particle_data,
+                 const int64_t val_first_particle,
+                 const int64_t val_n_particles,
+                 const void *values,
+                 const char hash_mode)
+{
+    int64_t header_pos, file_pos, tot_n_particles;
+    int64_t output_file_len, n_values_per_frame, size, contents_size;
+    int64_t header_size, temp_first, temp_last;
+    int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
+    int64_t i, last_frame, temp_current, write_n_particles;
+    tng_gen_block_t block;
+    tng_trajectory_frame_set_t frame_set;
+    FILE *temp = tng_data->input_file;
+    struct tng_data data;
+    tng_function_status stat;
+    tng_particle_mapping_t mapping;
+    char dependency, sparse_data, datatype;
+    void *copy;
+
+    if(tng_output_file_init(tng_data) != TNG_SUCCESS)
     {
-        if(tng_data_values_alloc(tng_data, values, *n_frames,
-                                 *n_values_per_frame,
-                                 *type)
-        != TNG_SUCCESS)
-        {
-            return(TNG_CRITICAL);
-        }
+        fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
     }
 
-    switch(*type)
+    temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
+    temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
+    temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
+    tng_data->first_trajectory_frame_set_input_file_pos =
+    tng_data->first_trajectory_frame_set_output_file_pos;
+    tng_data->last_trajectory_frame_set_input_file_pos =
+    tng_data->last_trajectory_frame_set_output_file_pos;
+    tng_data->current_trajectory_frame_set_input_file_pos =
+    tng_data->current_trajectory_frame_set_output_file_pos;
+
+    tng_data->input_file = tng_data->output_file;
+
+    stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
+
+    frame_set = &tng_data->current_trajectory_frame_set;
+
+    if(stat != TNG_SUCCESS)
     {
-    case TNG_CHAR_DATA:
-        for(i = 0; i < *n_frames; i++)
+        last_frame = frame_set->first_frame +
+                     frame_set->n_frames - 1;
+        /* If the wanted frame would be in the frame set after the last
+            * frame set create a new frame set. */
+        if(stat == TNG_FAILURE &&
+            last_frame < frame_nr)
+/*           (last_frame < frame_nr &&
+            tng_data->current_trajectory_frame_set.first_frame +
+            tng_data->frame_set_n_frames >= frame_nr))*/
         {
-            for(j = 0; j < *n_values_per_frame; j++)
+            if(last_frame + tng_data->frame_set_n_frames < frame_nr)
             {
-                len = strlen(data->strings[i][j]) + 1;
-                (*values)[i][j].c = malloc(len);
-                strncpy((*values)[i][j].c, data->strings[i][j], len);
+                last_frame = frame_nr - 1;
             }
-        }
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int);
-        for(i = 0; i < *n_frames; i++)
-        {
-            for(j = 0; j < *n_values_per_frame; j++)
+            tng_frame_set_new(tng_data,
+                              last_frame+1,
+                              tng_data->frame_set_n_frames);
+            file_pos = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, 0, SEEK_END);
+            output_file_len = ftello(tng_data->output_file);
+            fseeko(tng_data->output_file, file_pos, SEEK_SET);
+
+            /* Read mapping blocks from the last frame set */
+            tng_block_init(&block);
+
+            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 != -1)
             {
-                (*values)[i][j].i = *(int *)((char *)data->values + size *
-                                             (i*(*n_values_per_frame) + j));
+                if(block->id == TNG_PARTICLE_MAPPING)
+                {
+                    tng_trajectory_mapping_block_read(tng_data, block,
+                                                      hash_mode);
+                }
+                else
+                {
+                    fseeko(tng_data->output_file, block->block_contents_size,
+                        SEEK_CUR);
+                }
+                file_pos = ftello(tng_data->output_file);
+                if(file_pos < output_file_len)
+                {
+                    stat = tng_block_header_read(tng_data, block);
+                }
             }
-        }
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        for(i = 0; i < *n_frames; i++)
-        {
-            for(j = 0; j < *n_values_per_frame; j++)
+
+            tng_block_destroy(&block);
+            /* Write the frame set to disk */
+            if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
             {
-                (*values)[i][j].f = *(float *)((char *)data->values + size *
-                                               (i*(*n_values_per_frame) + j));
+                fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
+                return(TNG_CRITICAL);
             }
         }
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-        for(i = 0; i < *n_frames; i++)
+        else
         {
-            for(j = 0; j < *n_values_per_frame; j++)
-            {
-                (*values)[i][j].d = *(double *)((char *)data->values + size *
-                                                (i*(*n_values_per_frame) + j));
-            }
+            tng_data->input_file = temp;
+            tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+            tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+            tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+            return(stat);
         }
     }
 
-    data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
-
-    return(TNG_SUCCESS);
-}
+    tng_block_init(&block);
 
-tng_function_status tng_data_vector_get(tng_trajectory_t tng_data,
-                                        const int64_t block_id,
-                                        void **values,
-                                        int64_t *n_frames,
-                                        int64_t *stride_length,
-                                        int64_t *n_values_per_frame,
-                                        char *type)
-{
-    int64_t file_pos, data_size, n_frames_div, block_index;
-    int i, size;
-    tng_non_particle_data_t data;
-    tng_trajectory_frame_set_t frame_set;
-    tng_gen_block_t block;
-    void *temp;
-    tng_function_status stat;
+    file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
-    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+    fseeko(tng_data->output_file, 0, SEEK_END);
+    output_file_len = ftello(tng_data->output_file);
+    fseeko(tng_data->output_file, file_pos, SEEK_SET);
 
-    frame_set = &tng_data->current_trajectory_frame_set;
+    /* Read past the frame set block first */
+    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",
+               file_pos, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        tng_data->input_file = temp;
 
-    block_index = -1;
-    data = 0;
+        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+        return(stat);
+    }
+    fseeko(tng_data->output_file, block->block_contents_size,
+            SEEK_CUR);
 
-    if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
+    if(is_particle_data == TNG_TRUE)
     {
-        tng_block_init(&block);
-        file_pos = ftello(tng_data->input_file);
-        /* Read all blocks until next frame set block */
-        stat = tng_block_header_read(tng_data, block);
-        while(file_pos < tng_data->input_file_len &&
-                stat != TNG_CRITICAL &&
-                block->id != TNG_TRAJECTORY_FRAME_SET &&
-                block->id != -1)
+        if(tng_data->var_num_atoms_flag)
         {
-            /* Use hash by default */
-            stat = tng_block_read_next(tng_data, block,
-                                    TNG_USE_HASH);
-            if(stat != TNG_CRITICAL)
+            tot_n_particles = frame_set->n_particles;
+        }
+        else
+        {
+            tot_n_particles = tng_data->n_particles;
+        }
+
+        if(val_n_particles < tot_n_particles)
+        {
+            mapping_block_end_pos = -1;
+            /* Read all mapping blocks to find the right place to put the data */
+            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 != -1)
             {
-                file_pos = ftello(tng_data->input_file);
-                if(file_pos < tng_data->input_file_len)
+                if(block->id == TNG_PARTICLE_MAPPING)
+                {
+                    tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
+                }
+                else
+                {
+                    fseeko(tng_data->output_file, block->block_contents_size,
+                           SEEK_CUR);
+                }
+                file_pos = ftello(tng_data->output_file);
+                if(block->id == TNG_PARTICLE_MAPPING)
+                {
+                    mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
+                    if(val_first_particle >= mapping->num_first_particle &&
+                       val_first_particle < mapping->num_first_particle +
+                       mapping->n_particles &&
+                       val_first_particle + val_n_particles <=
+                       mapping->num_first_particle + mapping->n_particles)
+                    {
+                        mapping_block_end_pos = file_pos;
+                    }
+                }
+                if(file_pos < output_file_len)
                 {
                     stat = tng_block_header_read(tng_data, block);
                 }
             }
-        }
-        tng_block_destroy(&block);
-        if(stat == TNG_CRITICAL)
-        {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                    file_pos, __FILE__, __LINE__);
-            return(stat);
-        }
+            if(stat == TNG_CRITICAL)
+            {
+                fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+                       file_pos, __FILE__, __LINE__);
+                tng_block_destroy(&block);
+                tng_data->input_file = temp;
 
-        for(i = 0; i < frame_set->n_data_blocks; i++)
-        {
-            data = &frame_set->tr_data[i];
-            if(data->block_id == block_id)
+                tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+                tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+                tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+                return(stat);
+            }
+            if(mapping_block_end_pos < 0)
             {
-                block_index = i;
-                break;
+                tng_block_destroy(&block);
+                tng_data->input_file = temp;
+
+                tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+                tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+                tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+                return(TNG_FAILURE);
             }
+            fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
         }
-        if(block_index < 0)
+    }
+
+    /* Read all block headers until next frame set block or
+     * until the wanted block id is found */
+    stat = tng_block_header_read(tng_data, block);
+    while(file_pos < output_file_len &&
+            stat != TNG_CRITICAL &&
+            block->id != block_id &&
+            (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
+            block->id != TNG_TRAJECTORY_FRAME_SET &&
+            block->id != -1)
+    {
+        fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
+        file_pos = ftello(tng_data->output_file);
+        if(file_pos < output_file_len)
         {
-            return(TNG_FAILURE);
+            stat = tng_block_header_read(tng_data, block);
         }
     }
-
-    *type = data->datatype;
-
-    switch(*type)
+    if(stat == TNG_CRITICAL)
     {
-    case TNG_CHAR_DATA:
-        return(TNG_FAILURE);
-    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);
+        fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+               file_pos, __FILE__, __LINE__);
+        tng_block_destroy(&block);
+        tng_data->input_file = temp;
+        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+        return(stat);
     }
 
-    *n_frames = data->n_frames;
-    *n_values_per_frame = data->n_values_per_frame;
-    *stride_length = data->stride_length;
-    n_frames_div = (*n_frames % *stride_length) ? *n_frames / *stride_length + 1:
-                   *n_frames / *stride_length;
+    contents_size = block->block_contents_size;
+    header_size = block->header_contents_size;
 
-    data_size = n_frames_div * size *
-                *n_values_per_frame;
+    header_pos = ftello(tng_data->output_file) - header_size;
+    frame_set = &tng_data->current_trajectory_frame_set;
 
-    temp = realloc(*values, data_size);
-    if(!temp)
+    if(tng_file_input_numerical(tng_data, &datatype,
+                                 sizeof(datatype),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
-        free(*values);
-        *values = 0;
+        tng_block_destroy(&block);
         return(TNG_CRITICAL);
     }
+    if(tng_file_input_numerical(tng_data, &dependency,
+                                 sizeof(dependency),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+    {
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
+    data.datatype = datatype;
 
-    *values = temp;
-
-    memcpy(*values, data->values, data_size);
-
-    data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
-
-    return(TNG_SUCCESS);
-}
+    if(!(dependency & TNG_FRAME_DEPENDENT) ||
+       (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
+       (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
+    {
+        tng_block_destroy(&block);
+        tng_data->input_file = temp;
 
-tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
-                (tng_trajectory_t tng_data,
-                 const int64_t block_id,
-                 const int64_t start_frame_nr,
-                 const int64_t end_frame_nr,
-                 const char hash_mode,
-                 union data_values ***values,
-                 int64_t *n_values_per_frame,
-                 char *type)
-{
-    int64_t i, j, n_frames, file_pos, current_frame_pos, first_frame;
-    int64_t block_index;
-    int size;
-    size_t len;
-    tng_non_particle_data_t data;
-    tng_trajectory_frame_set_t frame_set;
-    tng_gen_block_t block;
-    tng_function_status stat;
+        tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+        tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+        tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+        return(TNG_FAILURE);
+    }
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+    if(tng_file_input_numerical(tng_data, &sparse_data,
+                                 sizeof(sparse_data),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+    {
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-    block_index = -1;
+    if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
+                                 sizeof(data.n_values_per_frame),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+    {
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-    frame_set = &tng_data->current_trajectory_frame_set;
-    first_frame = frame_set->first_frame;
+    if(tng_file_input_numerical(tng_data, &data.codec_id,
+                                 sizeof(data.codec_id),
+                                 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+    {
+        tng_block_destroy(&block);
+        return(TNG_CRITICAL);
+    }
 
-    stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
-    if(stat != TNG_SUCCESS)
+    if(data.codec_id != TNG_UNCOMPRESSED)
     {
-        return(stat);
+        if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
+                                     sizeof(data.compression_multiplier),
+                                     TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+        {
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+    }
+    else
+    {
+        data.compression_multiplier = 1;
     }
 
+    if(sparse_data)
+    {
+        if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
+                                     sizeof(data.first_frame_with_data),
+                                     TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+        {
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
 
-    /* Do not re-read the frame set. */
-    if(first_frame != frame_set->first_frame ||
-       frame_set->n_data_blocks <= 0)
+        if(tng_file_input_numerical(tng_data, &data.stride_length,
+                                     sizeof(data.stride_length),
+                                     TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
+        {
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+    }
+    else
+    {
+        data.first_frame_with_data = 0;
+        data.stride_length = 1;
+    }
+    data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
+
+    if(is_particle_data == TNG_TRUE)
     {
-        tng_block_init(&block);
-        file_pos = ftello(tng_data->input_file);
-        /* Read all blocks until next frame set block */
-        stat = tng_block_header_read(tng_data, block);
-        while(file_pos < tng_data->input_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET &&
-            block->id != -1)
+        if(tng_file_input_numerical(tng_data, &num_first_particle,
+                                     sizeof(num_first_particle),
+                                     TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
         {
-            stat = tng_block_read_next(tng_data, block,
-                                    hash_mode);
-            if(stat != TNG_CRITICAL)
-            {
-                file_pos = ftello(tng_data->input_file);
-                if(file_pos < tng_data->input_file_len)
-                {
-                    stat = tng_block_header_read(tng_data, block);
-                }
-            }
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
         }
-        tng_block_destroy(&block);
-        if(stat == TNG_CRITICAL)
+
+        if(tng_file_input_numerical(tng_data, &block_n_particles,
+                                     sizeof(block_n_particles),
+                                     TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
         {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                    file_pos, __FILE__, __LINE__);
-            return(stat);
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
         }
     }
 
+    tng_data->input_file = temp;
 
-    /* See if there is a data block of this ID.
-     * Start checking the last read frame set */
-    for(i = 0; i < frame_set->n_data_blocks; i++)
+    tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
+    tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
+    tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
+
+    switch(data.datatype)
     {
-        data = &frame_set->tr_data[i];
-        if(data->block_id == block_id)
-        {
-            block_index = i;
+        case(TNG_INT_DATA):
+            size = sizeof(int64_t);
             break;
-        }
+        case(TNG_FLOAT_DATA):
+            size = sizeof(float);
+            break;
+        case(TNG_DOUBLE_DATA):
+            size = sizeof(double);
+            break;
+        default:
+            fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
+                   __LINE__);
+            tng_block_destroy(&block);
+            return(TNG_FAILURE);
     }
 
-    if(block_index < 0)
+    n_values_per_frame = data.n_values_per_frame;
+
+    file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
+                               data.first_frame_with_data)) /
+                data.stride_length;
+    if(is_particle_data == TNG_TRUE)
     {
-        fprintf(stderr, "TNG library: Could not find non-particle data block with id %"PRId64". %s: %d\n",
-                block_id, __FILE__, __LINE__);
+        file_pos *= block_n_particles * size * n_values_per_frame;
+    }
+    else
+    {
+        file_pos *= size * n_values_per_frame;
+    }
+
+    if(file_pos > contents_size)
+    {
+        fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
+               __LINE__);
+        tng_block_destroy(&block);
         return(TNG_FAILURE);
     }
 
-    n_frames = end_frame_nr - start_frame_nr + 1;
-    *n_values_per_frame = data->n_values_per_frame;
-    *type = data->datatype;
+    fseeko(tng_data->output_file, file_pos, SEEK_CUR);
 
-    if(*values == 0)
+    if(is_particle_data == TNG_TRUE)
     {
-        if(tng_data_values_alloc(tng_data, values, n_frames,
-                                 *n_values_per_frame,
-                                 *type) != TNG_SUCCESS)
-        {
-            return(TNG_CRITICAL);
-        }
+        write_n_particles = val_n_particles;
+    }
+    else
+    {
+        write_n_particles = 1;
     }
 
-    current_frame_pos = start_frame_nr - frame_set->first_frame;
-    /* It's not very elegant to reuse so much of the code in the different case
-     * statements, but it's unnecessarily slow to have the switch-case block
-     * inside the for loops. */
-    switch(*type)
+    /* If the endianness is not big endian the data needs to be swapped */
+    if((data.datatype == TNG_INT_DATA ||
+        data.datatype == TNG_DOUBLE_DATA) &&
+       tng_data->output_endianness_swap_func_64)
     {
-    case TNG_CHAR_DATA:
-        for(i=0; i<n_frames; i++)
-        {
-            if(current_frame_pos == frame_set->n_frames)
-            {
-                stat = tng_frame_set_read_next(tng_data, hash_mode);
-                if(stat != TNG_SUCCESS)
-                {
-                    return(stat);
-                }
-                current_frame_pos = 0;
-            }
-            for(j = 0; j < *n_values_per_frame; j++)
-            {
-                len = strlen(data->strings[current_frame_pos][j]) + 1;
-                (*values)[i][j].c = malloc(len);
-                strncpy((*values)[i][j].c, data->strings[current_frame_pos][j], len);
-            }
-            current_frame_pos++;
-        }
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int);
-        for(i=0; i<n_frames; i++)
-        {
-            if(current_frame_pos == frame_set->n_frames)
-            {
-                stat = tng_frame_set_read_next(tng_data, hash_mode);
-                if(stat != TNG_SUCCESS)
-                {
-                    return(stat);
-                }
-                current_frame_pos = 0;
-            }
-            for(j = 0; j < *n_values_per_frame; j++)
-            {
-                (*values)[i][j].i = *(int *)((char *)data->values + size *
-                                            (current_frame_pos *
-                                             (*n_values_per_frame) + j));
-            }
-            current_frame_pos++;
-        }
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        for(i=0; i<n_frames; i++)
+        copy = malloc(write_n_particles * n_values_per_frame * size);
+        memcpy(copy, values, write_n_particles * n_values_per_frame * size);
+        for(i = 0; i < write_n_particles * n_values_per_frame; i++)
         {
-            if(current_frame_pos == frame_set->n_frames)
-            {
-                stat = tng_frame_set_read_next(tng_data, hash_mode);
-                if(stat != TNG_SUCCESS)
-                {
-                    return(stat);
-                }
-                current_frame_pos = 0;
-            }
-            for(j = 0; j < *n_values_per_frame; j++)
+            if(tng_data->output_endianness_swap_func_64(tng_data,
+                (int64_t *) copy+i)
+                != TNG_SUCCESS)
             {
-                (*values)[i][j].f = *(float *)((char *)data->values + size *
-                                               (current_frame_pos *
-                                                (*n_values_per_frame) + j));
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
-            current_frame_pos++;
         }
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-        for(i=0; i<n_frames; i++)
+        fwrite(copy, write_n_particles * n_values_per_frame, size,
+               tng_data->output_file);
+        free(copy);
+    }
+    else if(data.datatype == TNG_FLOAT_DATA &&
+            tng_data->output_endianness_swap_func_32)
+    {
+        copy = malloc(write_n_particles * n_values_per_frame * size);
+        memcpy(copy, values, write_n_particles * n_values_per_frame * size);
+        for(i = 0; i < write_n_particles * n_values_per_frame; i++)
         {
-            if(current_frame_pos == frame_set->n_frames)
-            {
-                stat = tng_frame_set_read_next(tng_data, hash_mode);
-                if(stat != TNG_SUCCESS)
-                {
-                    return(stat);
-                }
-                current_frame_pos = 0;
-            }
-            for(j = 0; j < *n_values_per_frame; j++)
+            if(tng_data->output_endianness_swap_func_32(tng_data,
+                (int32_t *) copy+i)
+                != TNG_SUCCESS)
             {
-                (*values)[i][j].d = *(double *)((char *)data->values + size *
-                                                (current_frame_pos *
-                                                 (*n_values_per_frame) + j));
+                fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+                        __FILE__, __LINE__);
             }
-            current_frame_pos++;
         }
+        fwrite(copy, write_n_particles * n_values_per_frame, size,
+               tng_data->output_file);
+        free(copy);
     }
 
-    data->last_retrieved_frame = end_frame_nr;
+    else
+    {
+        fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
+    }
+
+    fflush(tng_data->output_file);
+
+    /* Update the number of written frames in the frame set. */
+    if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
+    {
+        frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
+    }
+
+    /* If the last frame has been written update the hash */
+    if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
+       data.first_frame_with_data) >=
+       frame_set->n_frames)
+    {
+        tng_md5_hash_update(tng_data, block, header_pos, header_pos +
+                            header_size);
+    }
+
+    tng_block_destroy(&block);
 
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
+                (const tng_trajectory_t tng_data,
+                 const int64_t frame_nr,
                  const int64_t block_id,
-                 const int64_t start_frame_nr,
-                 const int64_t end_frame_nr,
-                 const char hash_mode,
-                 void **values,
-                 int64_t *stride_length,
-                 int64_t *n_values_per_frame,
-                 char *type)
+                 const void *values,
+                 const char hash_mode)
 {
-    int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
-    int64_t file_pos, current_frame_pos, data_size, frame_size;
-    int64_t last_frame_pos;
-    int size;
-    tng_trajectory_frame_set_t frame_set;
-    tng_non_particle_data_t np_data;
-    tng_gen_block_t block;
-    void *current_values = 0, *temp;
-    tng_function_status stat;
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
+    TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
+
+    /* This is now just calling the generic data writing function. This
+     * function must keep its signature to let the API be backwards
+     * compatible. */
+    return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
+                                    TNG_FALSE, 0, 0, values, hash_mode));
+}
 
+tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
+                (const tng_trajectory_t tng_data,
+                 const int64_t frame_nr,
+                 const int64_t block_id,
+                 const int64_t val_first_particle,
+                 const int64_t val_n_particles,
+                 const void *values,
+                 const char hash_mode)
+{
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
-    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
+    TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
+    TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
+    TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
 
-    frame_set = &tng_data->current_trajectory_frame_set;
-    first_frame = frame_set->first_frame;
+    /* This is now just calling the generic data writing function. This
+     * function must keep its signature to let the API be backwards
+     * compatible. */
+    return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
+                                    TNG_TRUE, val_first_particle, val_n_particles,
+                                    values, hash_mode));
+}
 
-    stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
-    if(stat != TNG_SUCCESS)
+static tng_function_status tng_data_values_alloc
+                (const tng_trajectory_t tng_data,
+                 union data_values ***values,
+                 const int64_t n_frames,
+                 const int64_t n_values_per_frame,
+                 const char type)
+{
+    int64_t i;
+    tng_function_status stat;
+
+    if(n_frames <= 0 || n_values_per_frame <= 0)
     {
-        return(stat);
+        return(TNG_FAILURE);
     }
 
-    /* Do not re-read the frame set and only need the requested block. */
-    /* TODO: Test that blocks are read correctly now that not all of them are read at the same time. */
-    stat = tng_data_find(tng_data, block_id, &np_data);
-    if(first_frame != frame_set->first_frame ||
-       stat != TNG_SUCCESS)
+    if(*values)
     {
-        tng_block_init(&block);
+        stat = tng_data_values_free(tng_data, *values, n_frames,
+                                    n_values_per_frame,
+                                    type);
         if(stat != TNG_SUCCESS)
         {
-            fseeko(tng_data->input_file,
-                   tng_data->current_trajectory_frame_set_input_file_pos,
-                   SEEK_SET);
-            stat = tng_block_header_read(tng_data, block);
-            if(stat != TNG_SUCCESS)
-            {
-                fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
-                        __FILE__, __LINE__);
-                return(stat);
-            }
-
-            fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-        }
-        file_pos = ftello(tng_data->input_file);
-        /* Read until next frame set block */
-        stat = tng_block_header_read(tng_data, block);
-        while(file_pos < tng_data->input_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET &&
-            block->id != -1)
-        {
-            if(block->id == block_id)
-            {
-                stat = tng_block_read_next(tng_data, block,
-                                        hash_mode);
-                if(stat != TNG_CRITICAL)
-                {
-                    file_pos = ftello(tng_data->input_file);
-                    if(file_pos < tng_data->input_file_len)
-                    {
-                        stat = tng_block_header_read(tng_data, block);
-                    }
-                }
-            }
-            else
-            {
-                file_pos += block->block_contents_size + block->header_contents_size;
-                fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
-                if(file_pos < tng_data->input_file_len)
-                {
-                    stat = tng_block_header_read(tng_data, block);
-                }
-            }
-        }
-        tng_block_destroy(&block);
-        if(stat == TNG_CRITICAL)
-        {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
-                    file_pos, __FILE__, __LINE__);
+            fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
+                   __FILE__, __LINE__);
             return(stat);
         }
     }
-
-    stat = tng_data_find(tng_data, block_id, &np_data);
-    if(stat != TNG_SUCCESS)
+    *values = malloc(sizeof(union data_values *) * n_frames);
+    if(!*values)
     {
-        return(stat);
-    }
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(union data_values **) * n_frames,
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
 
-    stat = tng_data_vector_get(tng_data, block_id, &current_values,
-                               &n_frames, stride_length,
-                               n_values_per_frame, type);
+    }
 
-    if(stat != TNG_SUCCESS)
+    for(i = 0; i < n_frames; i++)
     {
-        if(current_values)
+        (*values)[i] = malloc(sizeof(union data_values) *
+                           n_values_per_frame);
+        if(!(*values)[i])
         {
-            free(current_values);
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                   sizeof(union data_values) * n_values_per_frame,
+                   __FILE__, __LINE__);
+            free(values);
+            values = 0;
+            return(TNG_CRITICAL);
         }
-        return(stat);
     }
+    return(TNG_SUCCESS);
+}
 
-    if(n_frames == 1 && n_frames < frame_set->n_frames)
-    {
-        tot_n_frames = 1;
-    }
-    else
-    {
-        tot_n_frames = end_frame_nr - start_frame_nr + 1;
-    }
+/* FIXME: This needs ***values */
+tng_function_status DECLSPECDLLEXPORT tng_data_values_free
+                (const tng_trajectory_t tng_data,
+                 union data_values **values,
+                 const int64_t n_frames,
+                 const int64_t n_values_per_frame,
+                 const char type)
+{
+    int64_t i, j;
+    (void)tng_data;
 
-    switch(*type)
+    if(values)
     {
-    case TNG_CHAR_DATA:
-        return(TNG_FAILURE);
-    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);
+        for(i = 0; i < n_frames; i++)
+        {
+            if(values[i])
+            {
+                if(type == TNG_CHAR_DATA)
+                {
+                    for(j = 0; j < n_values_per_frame; j++)
+                    {
+                        if(values[i][j].c)
+                        {
+                            free(values[i][j].c);
+                            values[i][j].c = 0;
+                        }
+                    }
+                }
+                free(values[i]);
+                values[i] = 0;
+            }
+        }
+        free(values);
+        values = 0;
     }
 
-    n_frames_div = (tot_n_frames % *stride_length) ?
-                 tot_n_frames / *stride_length + 1:
-                 tot_n_frames / *stride_length;
-    data_size = n_frames_div * size * (*n_values_per_frame);
+    return(TNG_SUCCESS);
+}
 
-/*     fprintf(stderr, "TNG library: size: %d, n_frames_div: %"PRId64", data_size: %"PRId64"\n",
-              size, n_frames_div, data_size);
-*/
-    temp = realloc(*values, data_size);
-    if(!temp)
+static tng_function_status tng_particle_data_values_alloc
+                (const tng_trajectory_t tng_data,
+                 union data_values ****values,
+                 const int64_t n_frames,
+                 const int64_t n_particles,
+                 const int64_t n_values_per_frame,
+                 const char type)
+{
+    int64_t i, j;
+    tng_function_status stat;
+
+    if(n_particles == 0 || n_values_per_frame == 0)
     {
-        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
-        free(*values);
-        *values = 0;
-        return(TNG_CRITICAL);
+        return(TNG_FAILURE);
     }
 
-    *values = temp;
-
-    if( n_frames == 1 && n_frames < frame_set->n_frames)
+    if(*values)
     {
-        memcpy(*values, current_values, size * (*n_values_per_frame));
+        stat = tng_particle_data_values_free(tng_data, *values, n_frames,
+                                             n_particles, n_values_per_frame,
+                                             type);
+        if(stat != TNG_SUCCESS)
+        {
+            fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
+                   __FILE__, __LINE__);
+            return(stat);
+        }
     }
-    else
+    *values = malloc(sizeof(union data_values **) * n_frames);
+    if(!*values)
     {
-        current_frame_pos = start_frame_nr - frame_set->first_frame;
-
-        frame_size = size * (*n_values_per_frame);
-
-        last_frame_pos = tng_min_i64(n_frames,
-                                     end_frame_nr - start_frame_nr);
-
-        n_frames_div = current_frame_pos / *stride_length;
-        n_frames_div_2 = (last_frame_pos % *stride_length) ?
-                       last_frame_pos / *stride_length + 1:
-                       last_frame_pos / *stride_length;
-        n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
-
-        memcpy(*values, (char *)current_values + n_frames_div * frame_size,
-               n_frames_div_2 * frame_size);
+        fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+               sizeof(union data_values **) * n_frames,
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
 
-        current_frame_pos += n_frames - current_frame_pos;
+    }
 
-        while(current_frame_pos <= end_frame_nr - start_frame_nr)
+    for(i = 0; i < n_frames; i++)
+    {
+        (*values)[i] = malloc(sizeof(union data_values *) *
+                           n_particles);
+        if(!(*values)[i])
         {
-            stat = tng_frame_set_read_next(tng_data, hash_mode);
-            if(stat != TNG_SUCCESS)
+            fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                   sizeof(union data_values *) * n_particles,
+                   __FILE__, __LINE__);
+            free(*values);
+            *values = 0;
+            return(TNG_CRITICAL);
+        }
+        for(j = 0; j < n_particles; j++)
+        {
+            (*values)[i][j] = malloc(sizeof(union data_values) *
+                                  n_values_per_frame);
+            if(!(*values)[i][j])
             {
-                if(current_values)
-                {
-                    free(current_values);
-                }
-                free(*values);
+                fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
+                    sizeof(union data_values *) * n_particles,
+                    __FILE__, __LINE__);
+                tng_particle_data_values_free(tng_data, *values, n_frames,
+                                              n_particles, n_values_per_frame,
+                                              type);
                 *values = 0;
-                return(stat);
+                return(TNG_CRITICAL);
             }
+        }
+    }
+    return(TNG_SUCCESS);
+}
 
-            stat = tng_data_vector_get(tng_data, block_id, &current_values,
-                                    &n_frames, stride_length,
-                                    n_values_per_frame, type);
+/* FIXME: This needs ****values */
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
+                (const tng_trajectory_t tng_data,
+                 union data_values ***values,
+                 const int64_t n_frames,
+                 const int64_t n_particles,
+                 const int64_t n_values_per_frame,
+                 const char type)
+{
+    int64_t i, j, k;
+    (void)tng_data;
 
-            if(stat != TNG_SUCCESS)
+    if(values)
+    {
+        for(i = 0; i < n_frames; i++)
+        {
+            if(values[i])
             {
-                if(current_values)
+                for(j = 0; j < n_particles; j++)
                 {
-                    free(current_values);
+                    if(type == TNG_CHAR_DATA)
+                    {
+                        for(k = 0; k < n_values_per_frame; k++)
+                        {
+                            if(values[i][j][k].c)
+                            {
+                                free(values[i][j][k].c);
+                                values[i][j][k].c = 0;
+                            }
+                        }
+                    }
+                    free(values[i][j]);
+                    values[i][j] = 0;
                 }
-                free(*values);
-                *values = 0;
-                return(stat);
+                free(values[i]);
+                values[i] = 0;
             }
-
-            last_frame_pos = tng_min_i64(n_frames,
-                                         end_frame_nr - current_frame_pos);
-
-            n_frames_div = current_frame_pos / *stride_length;
-            n_frames_div_2 = (last_frame_pos % *stride_length) ?
-                           last_frame_pos / *stride_length + 1:
-                           last_frame_pos / *stride_length;
-            n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
-
-            memcpy(((char *)*values) + n_frames_div * frame_size,
-                   current_values,
-                   n_frames_div_2 * frame_size);
-
-            current_frame_pos += n_frames;
         }
+        free(values);
+        values = 0;
     }
 
-    if(current_values)
-    {
-        free(current_values);
-    }
-
-    np_data->last_retrieved_frame = end_frame_nr;
-
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
-                (tng_trajectory_t tng_data,
+static tng_function_status tng_gen_data_get
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
+                 const tng_bool is_particle_data,
                  union data_values ****values,
                  int64_t *n_frames,
                  int64_t *n_particles,
@@ -16007,34 +13876,37 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     int64_t i, j, k, mapping, file_pos, i_step, block_index;
     int size;
     size_t len;
-    tng_particle_data_t data;
+    tng_data_t data;
     tng_trajectory_frame_set_t frame_set;
     tng_gen_block_t block;
     char block_type_flag;
     tng_function_status stat;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
-    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
     frame_set = &tng_data->current_trajectory_frame_set;
 
     block_index = -1;
     data = 0;
 
-    if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
+    if(is_particle_data == TNG_TRUE)
     {
-        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;
-        }
+        stat = tng_particle_data_find(tng_data, block_id, &data);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &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(stat != TNG_SUCCESS)
+    {
         tng_block_init(&block);
         file_pos = ftello(tng_data->input_file);
         /* Read all blocks until next frame set block */
@@ -16064,14 +13936,29 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
             return(stat);
         }
 
-        for(i = 0; i < frame_set->n_particle_data_blocks; i++)
+        if(is_particle_data == TNG_TRUE)
         {
-            data = &frame_set->tr_particle_data[i];
-            if(data->block_id == block_id)
+            for(i = 0; i < frame_set->n_particle_data_blocks; i++)
             {
-                block_index = i;
-                block_type_flag = TNG_TRAJECTORY_BLOCK;
-                break;
+                data = &frame_set->tr_particle_data[i];
+                if(data->block_id == block_id)
+                {
+                    block_index = i;
+                    block_type_flag = TNG_TRAJECTORY_BLOCK;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            for(i = 0; i < frame_set->n_data_blocks; i++)
+            {
+                data = &frame_set->tr_data[i];
+                if(data->block_id == block_id)
+                {
+                    block_index = i;
+                    break;
+                }
             }
         }
         if(block_index < 0)
@@ -16079,115 +13966,167 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
             return(TNG_FAILURE);
         }
     }
-    else
+
+    if(is_particle_data == TNG_TRUE)
     {
-        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+           tng_data->var_num_atoms_flag)
         {
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
+            *n_particles = frame_set->n_particles;
         }
         else
         {
-            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+            *n_particles = tng_data->n_particles;
         }
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
-       tng_data->var_num_atoms_flag)
-    {
-        *n_particles = frame_set->n_particles;
-    }
-    else
-    {
-        *n_particles = tng_data->n_particles;
-    }
-
     *n_frames = tng_max_i64(1, data->n_frames);
     *n_values_per_frame = data->n_values_per_frame;
     *type = data->datatype;
 
-    if(*values == 0)
+    if(is_particle_data == TNG_TRUE)
     {
-        if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
-                                         *n_particles, *n_values_per_frame,
-                                         *type)
-            != TNG_SUCCESS)
+        if(*values == 0)
         {
-            return(TNG_CRITICAL);
+            if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
+                                             *n_particles, *n_values_per_frame,
+                                             *type) != TNG_SUCCESS)
+            {
+                return(TNG_CRITICAL);
+            }
         }
-    }
 
-    /* It's not very elegant to reuse so much of the code in the different case
-     * statements, but it's unnecessarily slow to have the switch-case block
-     * inside the for loops. */
-    switch(*type)
-    {
-    case TNG_CHAR_DATA:
-        for(i = 0; i < *n_frames; i++)
+        i_step = (*n_particles) * (*n_values_per_frame);
+
+        /* It's not very elegant to reuse so much of the code in the different case
+         * statements, but it's unnecessarily slow to have the switch-case block
+         * inside the for loops. */
+        switch(*type)
         {
-            for(j = 0; j < *n_particles; j++)
+        case TNG_CHAR_DATA:
+            for(i = 0; i < *n_frames; i++)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                for(j = 0; j < *n_particles; j++)
                 {
-                    len = strlen(data->strings[i][j][k]) + 1;
-                    (*values)[i][mapping][k].c = malloc(len);
-                    strncpy((*values)[i][mapping][k].c,
-                            data->strings[i][j][k], len);
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k = 0; k < *n_values_per_frame; k++)
+                    {
+                        len = strlen(data->strings[i][j][k]) + 1;
+                        (*values)[i][mapping][k].c = malloc(len);
+                        strncpy((*values)[i][mapping][k].c,
+                                data->strings[i][j][k], len);
+                    }
                 }
             }
-        }
-        break;
-    case TNG_INT_DATA:
-        size = sizeof(int);
-        i_step = (*n_particles) * (*n_values_per_frame);
-        for(i = 0; i < *n_frames; i++)
-        {
-            for(j = 0; j < *n_particles; j++)
+            break;
+        case TNG_INT_DATA:
+            size = sizeof(int);
+            for(i = 0; i < *n_frames; i++)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                for(j = 0; j < *n_particles; j++)
                 {
-                    (*values)[i][mapping][k].i = *(int *)
-                                                 ((char *)data->values + size *
-                                                 (i * i_step + j *
-                                                  (*n_values_per_frame) + k));
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k = 0; k < *n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].i = *(int *)
+                                                     ((char *)data->values + size *
+                                                     (i * i_step + j *
+                                                      (*n_values_per_frame) + k));
+                    }
                 }
             }
-        }
-        break;
-    case TNG_FLOAT_DATA:
-        size = sizeof(float);
-        i_step = (*n_particles) * (*n_values_per_frame);
-        for(i = 0; i < *n_frames; i++)
-        {
-            for(j = 0; j < *n_particles; j++)
+            break;
+        case TNG_FLOAT_DATA:
+            size = sizeof(float);
+            for(i = 0; i < *n_frames; i++)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                for(j = 0; j < *n_particles; j++)
+                {
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k = 0; k < *n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].f = *(float *)
+                                                     ((char *)data->values + size *
+                                                     (i * i_step + j *
+                                                      (*n_values_per_frame) + k));
+                    }
+                }
+            }
+            break;
+        case TNG_DOUBLE_DATA:
+        default:
+            size = sizeof(double);
+            for(i = 0; i < *n_frames; i++)
+            {
+                for(j = 0; j < *n_particles; j++)
                 {
-                    (*values)[i][mapping][k].f = *(float *)
-                                                 ((char *)data->values + size *
-                                                 (i * i_step + j *
-                                                  (*n_values_per_frame) + k));
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k = 0; k < *n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].d = *(double *)
+                                                     ((char *)data->values + size *
+                                                     (i * i_step + j *
+                                                      (*n_values_per_frame) + k));
+                    }
                 }
             }
         }
-        break;
-    case TNG_DOUBLE_DATA:
-    default:
-        size = sizeof(double);
-        i_step = (*n_particles) * (*n_values_per_frame);
-        for(i = 0; i < *n_frames; i++)
+    }
+    else
+    {
+        if(*(values[0]) == 0)
         {
-            for(j = 0; j < *n_particles; j++)
+            if(tng_data_values_alloc(tng_data, values[0], *n_frames,
+                                     *n_values_per_frame,
+                                     *type) != TNG_SUCCESS)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                return(TNG_CRITICAL);
+            }
+        }
+        switch(*type)
+        {
+        case TNG_CHAR_DATA:
+            for(i = 0; i < *n_frames; i++)
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
+                {
+                    len = strlen(data->strings[0][i][j]) + 1;
+                    (*values)[0][i][j].c = malloc(len);
+                    strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
+                }
+            }
+            break;
+        case TNG_INT_DATA:
+            size = sizeof(int);
+            for(i = 0; i < *n_frames; i++)
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
+                {
+                    (*values)[0][i][j].i = *(int *)((char *)data->values + size *
+                                                    (i*(*n_values_per_frame) + j));
+                }
+            }
+            break;
+        case TNG_FLOAT_DATA:
+            size = sizeof(float);
+            for(i = 0; i < *n_frames; i++)
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
+                {
+                    (*values)[0][i][j].f = *(float *)((char *)data->values + size *
+                                                   (i*(*n_values_per_frame) + j));
+                }
+            }
+            break;
+        case TNG_DOUBLE_DATA:
+        default:
+            size = sizeof(double);
+            for(i = 0; i < *n_frames; i++)
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
                 {
-                    (*values)[i][mapping][k].d = *(double *)
-                                                 ((char *)data->values + size *
-                                                 (i * i_step + j *
-                                                  (*n_values_per_frame) + k));
+                    (*values)[0][i][j].d = *(double *)((char *)data->values + size *
+                                                       (i*(*n_values_per_frame) + j));
                 }
             }
         }
@@ -16198,9 +14137,27 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_data_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 union data_values ***values,
+                 int64_t *n_frames,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
+                            n_values_per_frame, type));
+}
+
+static tng_function_status tng_gen_data_vector_get
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
+                 const tng_bool is_particle_data,
                  void **values,
                  int64_t *n_frames,
                  int64_t *stride_length,
@@ -16208,28 +14165,31 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
                  int64_t *n_values_per_frame,
                  char *type)
 {
-    int64_t i, j, mapping, file_pos, i_step, data_size, n_frames_div;
+    int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
     int64_t block_index;
     int size;
-    tng_particle_data_t data;
+    tng_data_t data;
     tng_trajectory_frame_set_t frame_set;
     tng_gen_block_t block;
     void *temp;
     char block_type_flag;
     tng_function_status stat;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
-    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
     frame_set = &tng_data->current_trajectory_frame_set;
 
     block_index = -1;
     data = 0;
 
-    if(tng_particle_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
+    if(is_particle_data == TNG_TRUE)
+    {
+        stat = tng_particle_data_find(tng_data, block_id, &data);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &data);
+    }
+
+    if(stat != TNG_SUCCESS)
     {
         tng_block_init(&block);
         file_pos = ftello(tng_data->input_file);
@@ -16275,23 +14235,26 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
         }
     }
 
-    if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
-    {
-        block_type_flag = TNG_TRAJECTORY_BLOCK;
-    }
-    else
+    if(is_particle_data == TNG_TRUE)
     {
-        block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
-    }
+        if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
+        {
+            block_type_flag = TNG_TRAJECTORY_BLOCK;
+        }
+        else
+        {
+            block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+        }
 
-   if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
-      tng_data->var_num_atoms_flag)
-    {
-        *n_particles = frame_set->n_particles;
-    }
-    else
-    {
-        *n_particles = tng_data->n_particles;
+       if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+          tng_data->var_num_atoms_flag)
+        {
+            *n_particles = frame_set->n_particles;
+        }
+        else
+        {
+            *n_particles = tng_data->n_particles;
+        }
     }
 
     *type = data->datatype;
@@ -16319,14 +14282,18 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
                    *n_frames / *stride_length + 1:
                    *n_frames / *stride_length;
 
-    data_size = n_frames_div * size * (*n_particles) *
+    full_data_len = n_frames_div * size *
                 (*n_values_per_frame);
+    if(is_particle_data == TNG_TRUE)
+    {
+        full_data_len *= (*n_particles);
+    }
 
-    temp = realloc(*values, data_size);
+    temp = realloc(*values, full_data_len);
     if(!temp)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
+               full_data_len, __FILE__, __LINE__);
         free(*values);
         *values = 0;
         return(TNG_CRITICAL);
@@ -16334,9 +14301,9 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
 
     *values = temp;
 
-    if(frame_set->n_mapping_blocks <= 0)
+    if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
     {
-        memcpy(*values, data->values, data_size);
+        memcpy(*values, data->values, full_data_len);
     }
     else
     {
@@ -16360,9 +14327,30 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 void **values,
+                 int64_t *n_frames,
+                 int64_t *stride_length,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
+    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
+                                   n_frames, stride_length, 0, n_values_per_frame,
+                                   type));
+}
+
+static tng_function_status tng_gen_data_interval_get
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
+                 const tng_bool is_particle_data,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
                  const char hash_mode,
@@ -16375,18 +14363,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
     int64_t first_frame, block_index;
     int size;
     size_t len;
-    tng_particle_data_t data;
+    tng_data_t data;
     tng_trajectory_frame_set_t frame_set;
     tng_gen_block_t block;
     char block_type_flag;
     tng_function_status stat;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
-    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
     block_index = -1;
 
     frame_set = &tng_data->current_trajectory_frame_set;
@@ -16399,8 +14381,12 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
     }
 
     /* Do not re-read the frame set. */
-    if(first_frame != frame_set->first_frame ||
-       frame_set->n_particle_data_blocks <= 0)
+    if((is_particle_data == TNG_TRUE &&
+       (first_frame != frame_set->first_frame ||
+        frame_set->n_particle_data_blocks <= 0)) ||
+       (is_particle_data == TNG_FALSE &&
+       (first_frame != frame_set->first_frame ||
+        frame_set->n_data_blocks <= 0)))
     {
         tng_block_init(&block);
         file_pos = ftello(tng_data->input_file);
@@ -16433,14 +14419,29 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
 
     /* See if there is already a data block of this ID.
      * Start checking the last read frame set */
-    for(i = frame_set->n_particle_data_blocks; i-- ;)
+    if(is_particle_data == TNG_TRUE)
     {
-        data = &frame_set->tr_particle_data[i];
-        if(data->block_id == block_id)
+        for(i = frame_set->n_particle_data_blocks; i-- ;)
         {
-            block_index = i;
-            block_type_flag = TNG_TRAJECTORY_BLOCK;
-            break;
+            data = &frame_set->tr_particle_data[i];
+            if(data->block_id == block_id)
+            {
+                block_index = i;
+                block_type_flag = TNG_TRAJECTORY_BLOCK;
+                break;
+            }
+        }
+    }
+    else
+    {
+        for(i = 0; i < frame_set->n_data_blocks; i++)
+        {
+            data = &frame_set->tr_data[i];
+            if(data->block_id == block_id)
+            {
+                block_index = i;
+                break;
+            }
         }
     }
 
@@ -16451,14 +14452,17 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
         return(TNG_FAILURE);
     }
 
-    if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
-       tng_data->var_num_atoms_flag)
-    {
-        *n_particles = frame_set->n_particles;
-    }
-    else
+    if(is_particle_data ==  TNG_TRUE)
     {
-        *n_particles = tng_data->n_particles;
+        if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
+           tng_data->var_num_atoms_flag)
+        {
+            *n_particles = frame_set->n_particles;
+        }
+        else
+        {
+            *n_particles = tng_data->n_particles;
+        }
     }
 
     n_frames = end_frame_nr - start_frame_nr + 1;
@@ -16467,16 +14471,36 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
 
     if(*values == 0)
     {
-        if(tng_particle_data_values_alloc(tng_data, values, n_frames,
-                                         *n_particles, *n_values_per_frame,
-                                         *type)
-            != TNG_SUCCESS)
+        if(is_particle_data == TNG_TRUE)
         {
-            return(TNG_CRITICAL);
+            if(tng_particle_data_values_alloc(tng_data, values, n_frames,
+                                             *n_particles, *n_values_per_frame,
+                                             *type) != TNG_SUCCESS)
+            {
+                return(TNG_CRITICAL);
+            }
+        }
+        else
+        {
+            if(tng_data_values_alloc(tng_data, *values, n_frames,
+                                     *n_values_per_frame,
+                                     *type) != TNG_SUCCESS)
+            {
+                return(TNG_CRITICAL);
+            }
         }
     }
 
     current_frame_pos = start_frame_nr - frame_set->first_frame;
+
+    if(is_particle_data == TNG_TRUE)
+    {
+        i_step = (*n_particles) * (*n_values_per_frame);
+    }
+    else
+    {
+        i_step = (*n_values_per_frame);
+    }
     /* It's not very elegant to reuse so much of the code in the different case
      * statements, but it's unnecessarily slow to have the switch-case block
      * inside the for loops. */
@@ -16494,14 +14518,26 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j = 0; j < *n_particles; j++)
+            if(is_particle_data == TNG_TRUE)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                for(j = 0; j < *n_particles; j++)
+                {
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    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);
+                        strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
+                    }
+                }
+            }
+            else
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
                 {
-                    len = strlen(data->strings[current_frame_pos][j][k]) + 1;
-                    (*values)[i][mapping][k].c = malloc(len);
-                    strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
+                    len = strlen(data->strings[0][current_frame_pos][j]) + 1;
+                    (*values)[0][i][j].c = malloc(len);
+                    strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
                 }
             }
             current_frame_pos++;
@@ -16509,7 +14545,6 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
         break;
     case TNG_INT_DATA:
         size = sizeof(int);
-        i_step = (*n_particles) * (*n_values_per_frame);
         for(i=0; i<n_frames; i++)
         {
             if(current_frame_pos == frame_set->n_frames)
@@ -16521,24 +14556,35 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j = 0; j < *n_particles; j++)
+            if(is_particle_data == TNG_TRUE)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k = 0; k < *n_values_per_frame; k++)
+                for(j = 0; j < *n_particles; j++)
                 {
-                    (*values)[i][mapping][k].i = *(int *)
-                                                 ((char *)data->values + size *
-                                                  (current_frame_pos *
-                                                   i_step + j *
-                                                   (*n_values_per_frame) + k));
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k = 0; k < *n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].i = *(int *)
+                                                     ((char *)data->values + size *
+                                                      (current_frame_pos *
+                                                       i_step + j *
+                                                       (*n_values_per_frame) + k));
+                    }
+                }
+                current_frame_pos++;
+            }
+            else
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
+                {
+                    (*values)[0][i][j].i = *(int *)((char *)data->values + size *
+                                                (current_frame_pos *
+                                                 i_step + j));
                 }
             }
-            current_frame_pos++;
         }
         break;
     case TNG_FLOAT_DATA:
         size = sizeof(float);
-        i_step = (*n_particles) * (*n_values_per_frame);
         for(i=0; i<n_frames; i++)
         {
             if(current_frame_pos == frame_set->n_frames)
@@ -16550,16 +14596,28 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=0; j<*n_particles; j++)
+            if(is_particle_data == TNG_TRUE)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=0; k<*n_values_per_frame; k++)
+                for(j=0; j<*n_particles; j++)
+                {
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k=0; k<*n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].f = *(float *)
+                                                     ((char *)data->values + size *
+                                                      (current_frame_pos *
+                                                       i_step + j *
+                                                       (*n_values_per_frame) + k));
+                    }
+                }
+            }
+            else
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
                 {
-                    (*values)[i][mapping][k].f = *(float *)
-                                                 ((char *)data->values + size *
-                                                  (current_frame_pos *
-                                                   i_step + j *
-                                                   (*n_values_per_frame) + k));
+                    (*values)[0][i][j].f = *(float *)((char *)data->values + size *
+                                                   (current_frame_pos *
+                                                    i_step + j));
                 }
             }
             current_frame_pos++;
@@ -16568,7 +14626,6 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
     case TNG_DOUBLE_DATA:
     default:
         size = sizeof(double);
-        i_step = (*n_particles) * (*n_values_per_frame);
         for(i=0; i<n_frames; i++)
         {
             if(current_frame_pos == frame_set->n_frames)
@@ -16580,16 +14637,28 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
                 }
                 current_frame_pos = 0;
             }
-            for(j=0; j<*n_particles; j++)
+            if(is_particle_data == TNG_TRUE)
             {
-                tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
-                for(k=0; k<*n_values_per_frame; k++)
+                for(j=0; j<*n_particles; j++)
                 {
-                    (*values)[i][mapping][k].d = *(double *)
-                                                 ((char *)data->values + size *
-                                                  (current_frame_pos *
-                                                   i_step + j *
-                                                   (*n_values_per_frame) + k));
+                    tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
+                    for(k=0; k<*n_values_per_frame; k++)
+                    {
+                        (*values)[i][mapping][k].d = *(double *)
+                                                     ((char *)data->values + size *
+                                                      (current_frame_pos *
+                                                       i_step + j *
+                                                       (*n_values_per_frame) + k));
+                    }
+                }
+            }
+            else
+            {
+                for(j = 0; j < *n_values_per_frame; j++)
+                {
+                    (*values)[0][i][j].d = *(double *)((char *)data->values + size *
+                                                    (current_frame_pos *
+                                                     i_step + j));
                 }
             }
             current_frame_pos++;
@@ -16601,9 +14670,30 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
     return(TNG_SUCCESS);
 }
 
-tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
-                (tng_trajectory_t tng_data,
+tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 const int64_t start_frame_nr,
+                 const int64_t end_frame_nr,
+                 const char hash_mode,
+                 union data_values ***values,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
+                                     end_frame_nr, hash_mode, &values, 0,
+                                     n_values_per_frame, type));
+}
+
+static tng_function_status tng_gen_data_vector_interval_get
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
+                 const tng_bool is_particle_data,
                  const int64_t start_frame_nr,
                  const int64_t end_frame_nr,
                  const char hash_mode,
@@ -16614,21 +14704,14 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
                  char *type)
 {
     int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
-    int64_t file_pos, current_frame_pos, last_frame_pos, data_size, frame_size;
+    int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
     int size;
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data;
+    tng_data_t data;
     tng_gen_block_t block;
     void *current_values = 0, *temp;
     tng_function_status stat;
 
-    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
-    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
-    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
-    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
-    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
-
     frame_set = &tng_data->current_trajectory_frame_set;
     first_frame = frame_set->first_frame;
 
@@ -16640,7 +14723,15 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
 
     /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
     /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
+    if(is_particle_data == TNG_TRUE)
+    {
+        stat = tng_particle_data_find(tng_data, block_id, &data);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &data);
+    }
+
     if(first_frame != frame_set->first_frame ||
        stat != TNG_SUCCESS)
     {
@@ -16648,8 +14739,8 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
         if(stat != TNG_SUCCESS)
         {
             fseeko(tng_data->input_file,
-                   tng_data->current_trajectory_frame_set_input_file_pos,
-                   SEEK_SET);
+                  tng_data->current_trajectory_frame_set_input_file_pos,
+                  SEEK_SET);
             stat = tng_block_header_read(tng_data, block);
             if(stat != TNG_SUCCESS)
             {
@@ -16699,17 +14790,24 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
             return(stat);
         }
     }
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
+    if(is_particle_data == TNG_TRUE)
+    {
+        stat = tng_particle_data_find(tng_data, block_id, &data);
+    }
+    else
+    {
+        stat = tng_data_find(tng_data, block_id, &data);
+    }
     if(stat != TNG_SUCCESS)
     {
         return(stat);
     }
 
-    stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
-                                        &n_frames, stride_length, n_particles,
-                                        n_values_per_frame, type);
+    stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
+                                   &current_values, &n_frames, stride_length,
+                                   n_particles, n_values_per_frame, type);
 
-    if(stat != TNG_SUCCESS || *n_particles == 0)
+    if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
     {
         if(current_values)
         {
@@ -16746,14 +14844,17 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
                  tot_n_frames / *stride_length + 1:
                  tot_n_frames / *stride_length;
 
-    data_size = n_frames_div * size * (*n_particles) *
-                (*n_values_per_frame);
+    full_data_len = n_frames_div * size * (*n_values_per_frame);
+    if(is_particle_data)
+    {
+        full_data_len *= (*n_particles);
+    }
 
-    temp = realloc(*values, data_size);
+    temp = realloc(*values, full_data_len);
     if(!temp)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
+               full_data_len, __FILE__, __LINE__);
         free(*values);
         *values = 0;
         return(TNG_CRITICAL);
@@ -16763,14 +14864,25 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
 
     if( n_frames == 1 && n_frames < frame_set->n_frames)
     {
-        memcpy(*values, current_values, size * (*n_particles) *
-               (*n_values_per_frame));
+        if(is_particle_data)
+        {
+            memcpy(*values, current_values, size * (*n_particles) *
+                   (*n_values_per_frame));
+        }
+        else
+        {
+            memcpy(*values, current_values, size * (*n_values_per_frame));
+        }
     }
     else
     {
         current_frame_pos = start_frame_nr - frame_set->first_frame;
 
-        frame_size = size * (*n_particles) * (*n_values_per_frame);
+        frame_size = size * (*n_values_per_frame);
+        if(is_particle_data)
+        {
+            frame_size *= (*n_particles);
+        }
 
         last_frame_pos = tng_min_i64(n_frames,
                                      end_frame_nr - start_frame_nr);
@@ -16800,9 +14912,10 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
                 return(stat);
             }
 
-            stat = tng_particle_data_vector_get(tng_data, block_id, &current_values,
-                                                &n_frames, stride_length, n_particles,
-                                                n_values_per_frame, type);
+            stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
+                                           &current_values, &n_frames,
+                                           stride_length, n_particles,
+                                           n_values_per_frame, type);
 
             if(stat != TNG_SUCCESS)
             {
@@ -16837,9 +14950,121 @@ tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
         free(current_values);
     }
 
-    p_data->last_retrieved_frame = end_frame_nr;
+    data->last_retrieved_frame = end_frame_nr;
+
+    return(TNG_SUCCESS);
+}
+
+
+tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 const int64_t start_frame_nr,
+                 const int64_t end_frame_nr,
+                 const char hash_mode,
+                 void **values,
+                 int64_t *stride_length,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
+    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
+                                            start_frame_nr, end_frame_nr,
+                                            hash_mode, values, 0, stride_length,
+                                            n_values_per_frame, type));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 union data_values ****values,
+                 int64_t *n_frames,
+                 int64_t *n_particles,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
+    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
+                            n_values_per_frame, type));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 void **values,
+                 int64_t *n_frames,
+                 int64_t *stride_length,
+                 int64_t *n_particles,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
+    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
+                                   n_frames, stride_length, n_particles,
+                                   n_values_per_frame, type));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 const int64_t start_frame_nr,
+                 const int64_t end_frame_nr,
+                 const char hash_mode,
+                 union data_values ****values,
+                 int64_t *n_particles,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
+    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
+
+    return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
+                                     end_frame_nr, hash_mode, values, n_particles,
+                                     n_values_per_frame, type));
+}
+
+tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 const int64_t start_frame_nr,
+                 const int64_t end_frame_nr,
+                 const char hash_mode,
+                 void **values,
+                 int64_t *n_particles,
+                 int64_t *stride_length,
+                 int64_t *n_values_per_frame,
+                 char *type)
+{
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+    TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
+    TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
+    TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
+    TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
+    TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
 
-    return(TNG_SUCCESS);
+    return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
+                                            start_frame_nr, end_frame_nr,
+                                            hash_mode, values, n_particles,
+                                            stride_length, n_values_per_frame,
+                                            type));
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
@@ -16849,8 +15074,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
                  int64_t *stride_length)
 {
     tng_function_status stat;
-    tng_non_particle_data_t np_data;
-    tng_particle_data_t p_data;
+    tng_data_t data;
     int64_t orig_file_pos, file_pos;
     int is_particle_data;
 
@@ -16868,10 +15092,10 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
         }
     }
     orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
-    stat = tng_data_find(tng_data, block_id, &np_data);
+    stat = tng_data_find(tng_data, block_id, &data);
     if(stat != TNG_SUCCESS)
     {
-        stat = tng_particle_data_find(tng_data, block_id, &p_data);
+        stat = tng_particle_data_find(tng_data, block_id, &data);
         if(stat != TNG_SUCCESS)
         {
             stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
@@ -16891,10 +15115,10 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
 
                 return(stat);
             }
-            stat = tng_data_find(tng_data, block_id, &np_data);
+            stat = tng_data_find(tng_data, block_id, &data);
             if(stat != TNG_SUCCESS)
             {
-                stat = tng_particle_data_find(tng_data, block_id, &p_data);
+                stat = tng_particle_data_find(tng_data, block_id, &data);
                 if(stat != TNG_SUCCESS)
                 {
                     tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
@@ -16922,11 +15146,11 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
     }
     if(is_particle_data)
     {
-        *stride_length = p_data->stride_length;
+        *stride_length = data->stride_length;
     }
     else
     {
-        *stride_length = np_data->stride_length;
+        *stride_length = data->stride_length;
     }
     tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
 
@@ -16992,7 +15216,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
 
     if(mode == 'w')
     {
-        tng_output_file_set(*tng_data_p, filename);
+        stat = tng_output_file_set(*tng_data_p, filename);
     }
     else if(mode == 'a')
     {
@@ -17002,8 +15226,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         }
         (*tng_data_p)->output_file = (*tng_data_p)->input_file;
         fseeko((*tng_data_p)->input_file,
-               (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
-               SEEK_SET);
+                (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
+                SEEK_SET);
 
         stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
@@ -17034,7 +15258,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         fseeko((*tng_data_p)->output_file, 0, SEEK_END);
     }
 
-    return(TNG_SUCCESS);
+    return(stat);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
@@ -17066,7 +15290,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  double *time)
 {
@@ -17100,7 +15324,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
 
 /*
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *n_mols,
                  int64_t **molecule_cnt_list,
                  tng_molecule_t *mols)
@@ -17129,7 +15353,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
 */
 /*
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const char *name,
                  const int64_t cnt,
                  tng_molecule_t *mol)
@@ -17150,7 +15374,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
 }
 */
 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const tng_molecule_t mol,
                  int64_t *n_particles,
                  char ***names,
@@ -17196,8 +15420,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
-                (tng_trajectory_t tng_data,
-                 tng_molecule_t mol,
+                (const tng_trajectory_t tng_data,
+                 const tng_molecule_t mol,
                  const int64_t n_particles,
                  const char **names,
                  const char **types,
@@ -17252,7 +15476,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **positions, int64_t *stride_length)
 {
     int64_t n_frames, n_particles, n_values_per_frame;
@@ -17281,7 +15505,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **velocities, int64_t *stride_length)
 {
     int64_t n_frames, n_particles, n_values_per_frame;
@@ -17310,7 +15534,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **forces, int64_t *stride_length)
 {
     int64_t n_frames, n_particles, n_values_per_frame;
@@ -17339,7 +15563,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_read
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  float **box_shape,
                  int64_t *stride_length)
 {
@@ -17368,7 +15592,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  char *data_type,
@@ -17376,11 +15600,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
                  double *retrieved_time)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t data = 0;
+    tng_data_t data = 0;
     tng_function_status stat;
     int size;
-    int64_t i, data_size, n_particles, file_pos;
+    int64_t i, full_data_len, n_particles;
     void *temp;
+    int64_t file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
@@ -17413,8 +15638,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     if(data->last_retrieved_frame < 0)
     {
         fseeko(tng_data->input_file,
-               tng_data->first_trajectory_frame_set_input_file_pos,
-               SEEK_SET);
+              tng_data->first_trajectory_frame_set_input_file_pos,
+              SEEK_SET);
         stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
         {
@@ -17430,7 +15655,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     }
     else
     {
-        if(data->n_frames == 1)
+        if(data->n_frames == 1 && frame_set->n_frames == 1)
         {
             i = data->last_retrieved_frame + 1;
         }
@@ -17508,16 +15733,16 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
         size = sizeof(double);
     }
 
-    data_size = size * n_particles * data->n_values_per_frame;
+    full_data_len = size * n_particles * data->n_values_per_frame;
 
-//     fprintf(stderr, "TNG library: TEMP: i = %"PRId64", data_size = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
-//            i, data_size, size, n_particles, data->n_values_per_frame);
+//     fprintf(stderr, "TNG library: TEMP: i = %"PRId64", full_data_len = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
+//            i, full_data_len, size, n_particles, data->n_values_per_frame);
 
-    temp = realloc(*values, data_size);
+    temp = realloc(*values, full_data_len);
     if(!temp)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
+               full_data_len, __FILE__, __LINE__);
         free(*values);
         *values = 0;
         return(TNG_CRITICAL);
@@ -17525,13 +15750,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
 
     *values = temp;
 
-    memcpy(*values, (char *)data->values + i * data_size, data_size);
+    memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
 
     return(TNG_SUCCESS);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  void **values,
                  char *data_type,
@@ -17539,11 +15764,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
                  double *retrieved_time)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_non_particle_data_t data = 0;
+    tng_data_t data = 0;
     tng_function_status stat;
     int size;
-    int64_t i, data_size, file_pos;
+    int64_t i, full_data_len;
     void *temp;
+    int64_t file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
@@ -17576,8 +15802,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     if(data->last_retrieved_frame < 0)
     {
         fseeko(tng_data->input_file,
-               tng_data->first_trajectory_frame_set_input_file_pos,
-               SEEK_SET);
+                tng_data->first_trajectory_frame_set_input_file_pos,
+                SEEK_SET);
         stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
         if(stat != TNG_SUCCESS)
         {
@@ -17593,7 +15819,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     }
     else
     {
-        if(data->n_frames == 1)
+        if(data->n_frames == 1 && frame_set->n_frames == 1)
         {
             i = data->last_retrieved_frame + 1;
         }
@@ -17669,13 +15895,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
         size = sizeof(double);
     }
 
-    data_size = size * data->n_values_per_frame;
+    full_data_len = size * data->n_values_per_frame;
 
-    temp = realloc(*values, data_size);
+    temp = realloc(*values, full_data_len);
     if(!temp)
     {
         fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
-               data_size, __FILE__, __LINE__);
+               full_data_len, __FILE__, __LINE__);
         free(*values);
         *values = 0;
         return(TNG_CRITICAL);
@@ -17683,13 +15909,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
 
     *values = temp;
 
-    memcpy(*values, (char *)data->values + i * data_size, data_size);
+    memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
 
     return(TNG_SUCCESS);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **positions,
@@ -17713,11 +15939,16 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
                                                  &n_values_per_frame,
                                                  &type);
 
+    if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
+    {
+        return(TNG_FAILURE);
+    }
+
     return(stat);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **velocities,
@@ -17741,11 +15972,16 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
                                                  &n_values_per_frame,
                                                  &type);
 
+    if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
+    {
+        return(TNG_FAILURE);
+    }
+
     return(stat);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **forces,
@@ -17769,11 +16005,16 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
                                                  &n_values_per_frame,
                                                  &type);
 
+    if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
+    {
+        return(TNG_FAILURE);
+    }
+
     return(stat);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t first_frame,
                  const int64_t last_frame,
                  float **box_shape,
@@ -17796,11 +16037,16 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
                                         &n_values_per_frame,
                                         &type);
 
+    if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
+    {
+        return(TNG_FAILURE);
+    }
+
     return(stat);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -17809,8 +16055,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
                  const char compression)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+    tng_data_t data;
     int64_t n_particles, n_frames;
     tng_function_status stat;
 
@@ -17851,7 +16096,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
             return(TNG_FAILURE);
         }
 
-        if(tng_particle_data_find(tng_data, block_id, &p_data)
+        if(tng_particle_data_find(tng_data, block_id, &data)
         != TNG_SUCCESS)
         {
             stat = tng_particle_data_block_add(tng_data, block_id,
@@ -17867,9 +16112,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
                        __FILE__, __LINE__);
                 return(stat);
             }
-            p_data = &frame_set->tr_particle_data[frame_set->
+            data = &frame_set->tr_particle_data[frame_set->
                                                   n_particle_data_blocks - 1];
-            stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
                                                   i, n_particles,
                                                   n_values_per_frame);
             if(stat != TNG_SUCCESS)
@@ -17881,10 +16126,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
         }
         else
         {
-            if(p_data->stride_length != i)
+            if(data->stride_length != i)
             {
-                p_data->stride_length = i;
-                stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
+                data->stride_length = i;
+                stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
                                                       i, n_particles,
                                                       n_values_per_frame);
                 if(stat != TNG_SUCCESS)
@@ -17898,7 +16143,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
     }
     else
     {
-        if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
+        if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
         {
             stat = tng_data_block_add(tng_data, block_id, block_name,
                                       TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
@@ -17910,9 +16155,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
                        __FILE__, __LINE__);
                 return(stat);
             }
-            np_data = &frame_set->tr_data[frame_set->
+            data = &frame_set->tr_data[frame_set->
                                           n_data_blocks - 1];
-            stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
                                          i, n_values_per_frame);
             if(stat != TNG_SUCCESS)
             {
@@ -17923,10 +16168,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
         }
         else
         {
-            if(np_data->stride_length != i)
+            if(data->stride_length != i)
             {
-                np_data->stride_length = i;
-                stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
+                data->stride_length = i;
+                stat = tng_allocate_data_mem(tng_data, data, n_frames,
                                              i, n_values_per_frame);
                 if(stat != TNG_SUCCESS)
                 {
@@ -17942,7 +16187,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -17951,8 +16196,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
                  const char compression)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+    tng_data_t data;
     int64_t n_particles, n_frames;
     tng_function_status stat;
 
@@ -17994,7 +16238,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
             return(TNG_FAILURE);
         }
 
-        if(tng_particle_data_find(tng_data, block_id, &p_data)
+        if(tng_particle_data_find(tng_data, block_id, &data)
         != TNG_SUCCESS)
         {
             stat = tng_particle_data_block_add(tng_data, block_id,
@@ -18010,9 +16254,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
                        __FILE__, __LINE__);
                 return(stat);
             }
-            p_data = &frame_set->tr_particle_data[frame_set->
+            data = &frame_set->tr_particle_data[frame_set->
                                                   n_particle_data_blocks - 1];
-            stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
                                                   i, n_particles,
                                                   n_values_per_frame);
             if(stat != TNG_SUCCESS)
@@ -18024,12 +16268,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
         }
         else
         {
-            p_data->stride_length = i;
+            data->stride_length = i;
         }
     }
     else
     {
-        if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
+        if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
         {
             stat = tng_data_block_add(tng_data, block_id, block_name,
                                       TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
@@ -18041,9 +16285,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
                        __FILE__, __LINE__);
                 return(stat);
             }
-            np_data = &frame_set->tr_data[frame_set->
+            data = &frame_set->tr_data[frame_set->
                                           n_data_blocks - 1];
-            stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
                                          i, n_values_per_frame);
             if(stat != TNG_SUCCESS)
             {
@@ -18054,7 +16298,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
         }
         else
         {
-            np_data->stride_length = i;
+            data->stride_length = i;
         }
     }
 
@@ -18062,7 +16306,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i,
                  const int64_t n_values_per_frame,
                  const int64_t block_id,
@@ -18078,7 +16322,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
                                                compression));
 }
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18092,7 +16336,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18106,7 +16350,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
@@ -18115,7 +16359,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18129,7 +16373,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18143,7 +16387,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
@@ -18152,7 +16396,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18166,7 +16410,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18180,7 +16424,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
@@ -18189,7 +16433,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18203,7 +16447,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
@@ -18217,7 +16461,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_s
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t i)
 {
     fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
@@ -18226,7 +16470,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *values,
                  const int64_t n_values_per_frame,
@@ -18236,8 +16480,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
                  const char compression)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+    tng_data_t data;
     int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
     int64_t last_frame;
     int is_first_frame_flag = 0;
@@ -18245,7 +16488,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
     tng_function_status stat;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
 
     if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
@@ -18316,7 +16558,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
 
     if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
     {
-        if(tng_particle_data_find(tng_data, block_id, &p_data)
+        if(tng_particle_data_find(tng_data, block_id, &data)
         != TNG_SUCCESS)
         {
             stat = tng_particle_data_block_add(tng_data, block_id,
@@ -18335,15 +16577,15 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
             }
             if(block_type_flag == TNG_TRAJECTORY_BLOCK)
             {
-                p_data = &frame_set->tr_particle_data[frame_set->
+                data = &frame_set->tr_particle_data[frame_set->
                                                     n_particle_data_blocks - 1];
             }
             else
             {
-                p_data = &tng_data->non_tr_particle_data[tng_data->
-                                                    n_particle_data_blocks - 1];
+                data = &tng_data->non_tr_particle_data[tng_data->
+                                                       n_particle_data_blocks - 1];
             }
-            stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
                                                   stride_length, n_particles,
                                                   n_values_per_frame);
             if(stat != TNG_SUCCESS)
@@ -18353,14 +16595,27 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
                 return(stat);
             }
         }
+        /* FIXME: Here we must be able to handle modified n_particles as well. */
+        else if(n_frames > data->n_frames)
+        {
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
+                                                  data->stride_length, n_particles,
+                                                  n_values_per_frame);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(stat);
+            }
+        }
 
         if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            stride_length = p_data->stride_length;
+            stride_length = data->stride_length;
 
-            if(is_first_frame_flag || p_data->first_frame_with_data < frame_set->first_frame)
+            if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
             {
-                p_data->first_frame_with_data = frame_nr;
+                data->first_frame_with_data = frame_nr;
                 frame_pos = 0;
             }
             else
@@ -18368,19 +16623,19 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
                 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
             }
 
-            memcpy((char *)p_data->values + sizeof(float) * frame_pos * n_particles *
+            memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
                    n_values_per_frame, values, sizeof(float) *
                    n_particles * n_values_per_frame);
         }
         else
         {
-            memcpy(p_data->values, values, sizeof(float) * n_particles *
+            memcpy(data->values, values, sizeof(float) * n_particles *
                    n_values_per_frame);
         }
     }
     else
     {
-        if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
+        if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
         {
             stat = tng_data_block_add(tng_data, block_id, block_name,
                                       TNG_FLOAT_DATA, block_type_flag,
@@ -18394,15 +16649,15 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
             }
             if(block_type_flag == TNG_TRAJECTORY_BLOCK)
             {
-                np_data = &frame_set->tr_data[frame_set->
+                data = &frame_set->tr_data[frame_set->
                                               n_data_blocks - 1];
             }
             else
             {
-                np_data = &tng_data->non_tr_data[tng_data->
+                data = &tng_data->non_tr_data[tng_data->
                                                  n_data_blocks - 1];
             }
-            stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
                                          stride_length, n_values_per_frame);
             if(stat != TNG_SUCCESS)
             {
@@ -18411,14 +16666,26 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
                 return(stat);
             }
         }
+        /* FIXME: Here we must be able to handle modified n_particles as well. */
+        else if(n_frames > data->n_frames)
+        {
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
+                                         data->stride_length, n_values_per_frame);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(stat);
+            }
+        }
 
         if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            stride_length = np_data->stride_length;
+            stride_length = data->stride_length;
 
-            if(is_first_frame_flag || np_data->first_frame_with_data < frame_set->first_frame)
+            if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
             {
-                np_data->first_frame_with_data = frame_nr;
+                data->first_frame_with_data = frame_nr;
                 frame_pos = 0;
             }
             else
@@ -18426,13 +16693,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
                 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
             }
 
-            memcpy((char *)np_data->values + sizeof(float) * frame_pos *
+            memcpy((char *)data->values + sizeof(float) * frame_pos *
                    n_values_per_frame, values, sizeof(float) *
                    n_values_per_frame);
         }
         else
         {
-            memcpy(np_data->values, values, sizeof(float) * n_values_per_frame);
+            memcpy(data->values, values, sizeof(float) * n_values_per_frame);
         }
     }
 
@@ -18440,7 +16707,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *values,
                  const int64_t n_values_per_frame,
@@ -18450,8 +16717,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                  const char compression)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+    tng_data_t data;
     int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
     int64_t last_frame;
     int is_first_frame_flag = 0;
@@ -18459,7 +16725,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
     tng_function_status stat;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
 
     if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
@@ -18484,11 +16749,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
     {
         block_type_flag = TNG_TRAJECTORY_BLOCK;
 
-        n_frames = tng_data->frame_set_n_frames;
-
         if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
         {
-            stat = tng_frame_set_new(tng_data, 0, n_frames);
+            stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
             if(stat != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot create frame set.  %s: %d\n", __FILE__,
@@ -18496,10 +16759,6 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                 return(stat);
             }
         }
-        else
-        {
-            n_frames = frame_set->n_frames;
-        }
         last_frame = frame_set->first_frame +
                      frame_set->n_frames - 1;
         if(frame_nr > last_frame)
@@ -18515,7 +16774,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
             {
                 last_frame = frame_nr - 1;
             }
-            stat = tng_frame_set_new(tng_data, last_frame + 1, n_frames);
+            stat = tng_frame_set_new(tng_data, last_frame + 1,
+                                     tng_data->frame_set_n_frames);
             if(stat != TNG_SUCCESS)
             {
                 fprintf(stderr, "TNG library: Cannot create frame set.  %s: %d\n", __FILE__,
@@ -18529,11 +16789,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
         }
         frame_set->n_unwritten_frames = frame_nr -
                                         frame_set->first_frame + 1;
+
+        n_frames = frame_set->n_frames;
     }
 
+
     if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
     {
-        if(tng_particle_data_find(tng_data, block_id, &p_data)
+        if(tng_particle_data_find(tng_data, block_id, &data)
         != TNG_SUCCESS)
         {
             stat = tng_particle_data_block_add(tng_data, block_id,
@@ -18552,15 +16815,15 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
             }
             if(block_type_flag == TNG_TRAJECTORY_BLOCK)
             {
-                p_data = &frame_set->tr_particle_data[frame_set->
+                data = &frame_set->tr_particle_data[frame_set->
                                                     n_particle_data_blocks - 1];
             }
             else
             {
-                p_data = &tng_data->non_tr_particle_data[tng_data->
+                data = &tng_data->non_tr_particle_data[tng_data->
                                                     n_particle_data_blocks - 1];
             }
-            stat = tng_allocate_particle_data_mem(tng_data, p_data, n_frames,
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
                                                   stride_length, n_particles,
                                                   n_values_per_frame);
             if(stat != TNG_SUCCESS)
@@ -18570,14 +16833,27 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                 return(stat);
             }
         }
+        /* FIXME: Here we must be able to handle modified n_particles as well. */
+        else if(n_frames > data->n_frames)
+        {
+            stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
+                                                  data->stride_length, n_particles,
+                                                  n_values_per_frame);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(stat);
+            }
+        }
 
         if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            stride_length = p_data->stride_length;
+            stride_length = data->stride_length;
 
-            if(is_first_frame_flag)
+            if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
             {
-                p_data->first_frame_with_data = frame_nr;
+                data->first_frame_with_data = frame_nr;
                 frame_pos = 0;
             }
             else
@@ -18585,19 +16861,19 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
             }
 
-            memcpy((char *)p_data->values + sizeof(double) * frame_pos * n_particles *
+            memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
                    n_values_per_frame, values, sizeof(double) *
                    n_particles * n_values_per_frame);
         }
         else
         {
-            memcpy(p_data->values, values, sizeof(double) * n_particles *
+            memcpy(data->values, values, sizeof(double) * n_particles *
                    n_values_per_frame);
         }
     }
     else
     {
-        if(tng_data_find(tng_data, block_id, &np_data) != TNG_SUCCESS)
+        if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
         {
             stat = tng_data_block_add(tng_data, block_id, block_name,
                                       TNG_DOUBLE_DATA, block_type_flag,
@@ -18611,15 +16887,15 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
             }
             if(block_type_flag == TNG_TRAJECTORY_BLOCK)
             {
-                np_data = &frame_set->tr_data[frame_set->
+                data = &frame_set->tr_data[frame_set->
                                               n_data_blocks - 1];
             }
             else
             {
-                np_data = &tng_data->non_tr_data[tng_data->
+                data = &tng_data->non_tr_data[tng_data->
                                                  n_data_blocks - 1];
             }
-            stat = tng_allocate_data_mem(tng_data, np_data, n_frames,
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
                                          stride_length, n_values_per_frame);
             if(stat != TNG_SUCCESS)
             {
@@ -18628,14 +16904,26 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                 return(stat);
             }
         }
+        /* FIXME: Here we must be able to handle modified n_particles as well. */
+        else if(n_frames > data->n_frames)
+        {
+            stat = tng_allocate_data_mem(tng_data, data, n_frames,
+                                         data->stride_length, n_values_per_frame);
+            if(stat != TNG_SUCCESS)
+            {
+                fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(stat);
+            }
+        }
 
         if(block_type_flag == TNG_TRAJECTORY_BLOCK)
         {
-            stride_length = np_data->stride_length;
+            stride_length = data->stride_length;
 
-            if(is_first_frame_flag)
+            if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
             {
-                np_data->first_frame_with_data = frame_nr;
+                data->first_frame_with_data = frame_nr;
                 frame_pos = 0;
             }
             else
@@ -18643,13 +16931,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
                 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
             }
 
-            memcpy((char *)np_data->values + sizeof(double) * frame_pos *
+            memcpy((char *)data->values + sizeof(double) * frame_pos *
                    n_values_per_frame, values, sizeof(double) *
                    n_values_per_frame);
         }
         else
         {
-            memcpy(np_data->values, values, sizeof(double) * n_values_per_frame);
+            memcpy(data->values, values, sizeof(double) * n_values_per_frame);
         }
     }
 
@@ -18657,12 +16945,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *positions)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
 
     return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
@@ -18672,12 +16959,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *positions)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
 
     return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
@@ -18687,12 +16973,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *velocities)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
 
     return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
@@ -18702,12 +16987,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *velocities)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
 
     return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
@@ -18717,12 +17001,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *forces)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
 
     return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
@@ -18732,12 +17015,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *forces)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
 
     return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
@@ -18747,12 +17029,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const float *box_shape)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
 
     return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
@@ -18762,12 +17043,11 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double *box_shape)
 {
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
-    TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
     TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
 
     return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
@@ -18777,7 +17057,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *values,
@@ -18827,7 +17107,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *values,
@@ -18877,7 +17157,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *positions)
@@ -18894,7 +17174,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *positions)
@@ -18913,7 +17193,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *velocities)
@@ -18932,7 +17212,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *velocities)
@@ -18951,7 +17231,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *forces)
@@ -18968,7 +17248,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *forces)
@@ -18986,7 +17266,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const float *box_shape)
@@ -19003,7 +17283,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t frame_nr,
                  const double time,
                  const double *box_shape)
@@ -19022,14 +17302,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t block_id,
                  int64_t *codec_id,
                  double *factor)
 {
     tng_trajectory_frame_set_t frame_set;
-    tng_particle_data_t p_data = 0;
-    tng_non_particle_data_t np_data = 0;
+    tng_data_t data = 0;
     tng_function_status stat;
     int64_t i;
     int block_type = -1;
@@ -19040,14 +17319,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
 
     frame_set = &tng_data->current_trajectory_frame_set;
 
-    stat = tng_particle_data_find(tng_data, block_id, &p_data);
+    stat = tng_particle_data_find(tng_data, block_id, &data);
     if(stat == TNG_SUCCESS)
     {
         block_type = TNG_PARTICLE_BLOCK_DATA;
     }
     else
     {
-        stat = tng_data_find(tng_data, block_id, &np_data);
+        stat = tng_data_find(tng_data, block_id, &data);
         if(stat == TNG_SUCCESS)
         {
             block_type = TNG_NON_PARTICLE_BLOCK_DATA;
@@ -19059,14 +17338,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
             {
                 return(stat);
             }
-            stat = tng_particle_data_find(tng_data, block_id, &p_data);
+            stat = tng_particle_data_find(tng_data, block_id, &data);
             if(stat == TNG_SUCCESS)
             {
                 block_type = TNG_PARTICLE_BLOCK_DATA;
             }
             else
             {
-                stat = tng_data_find(tng_data, block_id, &np_data);
+                stat = tng_data_find(tng_data, block_id, &data);
                 if(stat == TNG_SUCCESS)
                 {
                     block_type = TNG_NON_PARTICLE_BLOCK_DATA;
@@ -19080,24 +17359,24 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
     }
     if(block_type == TNG_PARTICLE_BLOCK_DATA)
     {
-        if(p_data->last_retrieved_frame < 0)
+        if(data->last_retrieved_frame < 0)
         {
-            i = p_data->first_frame_with_data;
+            i = data->first_frame_with_data;
         }
         else
         {
-            i = p_data->last_retrieved_frame;
+            i = data->last_retrieved_frame;
         }
     }
     else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
     {
-        if(np_data->last_retrieved_frame < 0)
+        if(data->last_retrieved_frame < 0)
         {
-            i = np_data->first_frame_with_data;
+            i = data->first_frame_with_data;
         }
         else
         {
-            i = np_data->last_retrieved_frame;
+            i = data->last_retrieved_frame;
         }
     }
     else
@@ -19121,19 +17400,19 @@ tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
     }
     if(block_type == TNG_PARTICLE_BLOCK_DATA)
     {
-        *codec_id = p_data->codec_id;
-        *factor   = p_data->compression_multiplier;
+        *codec_id = data->codec_id;
+        *factor   = data->compression_multiplier;
     }
     else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
     {
-        *codec_id = np_data->codec_id;
-        *factor   = np_data->compression_multiplier;
+        *codec_id = data->codec_id;
+        *factor   = data->compression_multiplier;
     }
     return(TNG_SUCCESS);
 }
 
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t current_frame,
                  const int64_t n_requested_data_block_ids,
                  const int64_t *requested_data_block_ids,
@@ -19143,13 +17422,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
 {
     tng_trajectory_frame_set_t frame_set;
     tng_function_status stat;
-    tng_particle_data_t p_data;
-    tng_non_particle_data_t np_data;
+    tng_data_t data;
     tng_gen_block_t block;
     int64_t i, j, block_id, *temp;
     int64_t data_frame, frame_diff, min_diff;
-    int64_t size, frame_set_file_pos, file_pos;
+    int64_t size, frame_set_file_pos;
     int found, read_all = 0;
+    int64_t file_pos;
 
     TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
     TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
@@ -19238,8 +17517,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
 
     for(i = 0; i < frame_set->n_particle_data_blocks; i++)
     {
-        p_data = &frame_set->tr_particle_data[i];
-        block_id = p_data->block_id;
+        data = &frame_set->tr_particle_data[i];
+        block_id = data->block_id;
 
         if(n_requested_data_block_ids > 0)
         {
@@ -19258,8 +17537,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
             }
         }
 
-        if(!read_all && (p_data->last_retrieved_frame < frame_set->first_frame ||
-           p_data->last_retrieved_frame >=
+        if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
+           data->last_retrieved_frame >=
            frame_set->first_frame + frame_set->n_frames))
         {
             stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
@@ -19276,13 +17555,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
             }
         }
         if(frame_set->first_frame != current_frame &&
-           p_data->last_retrieved_frame >= 0)
+           data->last_retrieved_frame >= 0)
         {
-            data_frame = p_data->last_retrieved_frame + p_data->stride_length;
+            data_frame = data->last_retrieved_frame + data->stride_length;
         }
         else
         {
-            data_frame = p_data->first_frame_with_data;
+            data_frame = data->first_frame_with_data;
         }
         frame_diff = data_frame - current_frame;
         if(frame_diff < 0)
@@ -19325,8 +17604,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
     }
     for(i = 0; i < frame_set->n_data_blocks; i++)
     {
-        np_data = &frame_set->tr_data[i];
-        block_id = np_data->block_id;
+        data = &frame_set->tr_data[i];
+        block_id = data->block_id;
 
         if(n_requested_data_block_ids > 0)
         {
@@ -19345,8 +17624,8 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
             }
         }
 
-        if(!read_all && (np_data->last_retrieved_frame < frame_set->first_frame ||
-           np_data->last_retrieved_frame >=
+        if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
+           data->last_retrieved_frame >=
            frame_set->first_frame + frame_set->n_frames))
         {
             stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
@@ -19363,13 +17642,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
             }
         }
         if(frame_set->first_frame != current_frame &&
-           np_data->last_retrieved_frame >= 0)
+           data->last_retrieved_frame >= 0)
         {
-            data_frame = np_data->last_retrieved_frame + np_data->stride_length;
+            data_frame = data->last_retrieved_frame + data->stride_length;
         }
         else
         {
-            data_frame = np_data->first_frame_with_data;
+            data_frame = data->first_frame_with_data;
         }
         frame_diff = data_frame - current_frame;
         if(frame_diff < 0)
@@ -19421,7 +17700,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
 
 /*
 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  int64_t *n_data_blocks,
                  int64_t **data_block_ids,
                  char ***data_block_names,
@@ -19440,14 +17719,13 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
     TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
     TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
 
-    orig_file_pos = ftello(tng_data->input_file);
-
-    if(!tng_data->input_file_len)
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
     {
-        fseeko(tng_data->input_file, 0, SEEK_END);
-        tng_data->input_file_len = ftello(tng_data->input_file);
+        return(TNG_CRITICAL);
     }
 
+    orig_file_pos = ftello(tng_data->input_file);
+
     fseeko(tng_data->input_file, 0, SEEK_SET);
     file_pos = 0;
 
@@ -19472,7 +17750,7 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_g
 }
 */
 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
-                (tng_trajectory_t tng_data,
+                (const tng_trajectory_t tng_data,
                  const int64_t prev_frame)
 {
     tng_function_status stat;
@@ -19496,3 +17774,46 @@ tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
 
     return(TNG_SUCCESS);
 }
+
+tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
+                (const tng_trajectory_t tng_data,
+                 const int64_t block_id,
+                 int64_t *n_frames)
+{
+    int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
+    tng_function_status stat;
+
+    TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+    *n_frames = 0;
+
+    if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+    {
+        return(TNG_CRITICAL);
+    }
+
+    first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
+    curr_file_pos = ftello(tng_data->input_file);
+    fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
+
+    stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
+
+    while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
+    {
+        *n_frames += curr_n_frames;
+        fseeko(tng_data->input_file,
+               tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
+               SEEK_SET);
+        stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
+    }
+    if(stat == TNG_SUCCESS)
+    {
+        *n_frames += curr_n_frames;
+    }
+    fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
+    if(stat == TNG_CRITICAL)
+    {
+        return(TNG_CRITICAL);
+    }
+    return(TNG_SUCCESS);
+}
index aac8b3b7bd2d73b481cd42257767f4dfbc01aa25..d500167e152d644bad8b4e3088bcc3ab7dceb288 100644 (file)
@@ -1,11 +1,11 @@
 #ifdef TNG_BUILD_OPENMP_EXAMPLES
 
+#include "tng/tng_io.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <time.h>
 #include <math.h>
 #include <omp.h>
-#include "tng/tng_io.h"
 
 int main ();
 void compute ( int np, int nd, double pos[], double vel[],
index 9fe6c91b60ce6b11ebcabdd69a1544bc600b5171..11a7fa0c70e049aeffe079678904211f0ad70e1d 100644 (file)
@@ -1,11 +1,11 @@
 #ifdef TNG_BUILD_OPENMP_EXAMPLES
 
+#include "tng/tng_io.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <time.h>
 #include <math.h>
 #include <omp.h>
-#include "tng/tng_io.h"
 
 int main ();
 void compute ( int np, int nd, float pos[], float vel[],
index b29cec7cd11352883d7dfd5987701594e18da0de..8e3d266fcc2464497653c27eb1d8b3c44674376f 100644 (file)
@@ -9,13 +9,14 @@
  * modify it under the terms of the Revised BSD License.
  */
 
+#include "tng/tng_io.h"
+
 #ifdef USE_STD_INTTYPES_H
 #include <inttypes.h>
 #endif
 
 #include <stdlib.h>
 #include <stdio.h>
-#include "tng/tng_io.h"
 
 int main(int argc, char **argv)
 {
index b237dad03ddc52a226c04c9182760ae5fdf93a90..699f52db876604cc18901adc300052a89a3110ab 100644 (file)
  * modify it under the terms of the Revised BSD License.
  */
 
+#include "tng/tng_io.h"
+
 #ifdef USE_STD_INTTYPES_H
 #include <inttypes.h>
 #endif
 
 #include <stdlib.h>
 #include <stdio.h>
-#include "tng/tng_io.h"
 
 int main(int argc, char **argv)
 {
index e1e2726db15c1de35876cc251d37ccc33660c9eb..28f8f4777eb78c9df311e91d44c47c0f1af924eb 100644 (file)
@@ -9,21 +9,37 @@
  * modify it under the terms of the Revised BSD License.
  */
 
+#include "tng/tng_io.h"
+
 #ifdef USE_STD_INTTYPES_H
 #include <inttypes.h>
 #endif
 
 #include <stdlib.h>
 #include <string.h>
-#include "tng/tng_io.h"
+#include <math.h>
 #include "tng/version.h"
 
+#define BOX_SHAPE_X 150.0
+#define BOX_SHAPE_Y 145.5
+#define BOX_SHAPE_Z 155.5
+#define N_FRAME_SETS 100
+#define MEDIUM_STRIDE_LEN 5
+#define LONG_STRIDE_LEN 25
+#define TIME_PER_FRAME 2e-15
+#define COMPRESSION_PRECISION 1000
+#define USER_NAME "USER 1"
+#define PROGRAM_NAME "tng_testing"
+#define COMPUTER_NAME "Unknown computer"
+#define FORCEFIELD_NAME "No forcefield"
+
 static tng_function_status tng_test_setup_molecules(tng_trajectory_t traj)
 {
     tng_molecule_t molecule;
     tng_chain_t chain;
     tng_residue_t residue;
     tng_atom_t atom;
+    tng_bond_t bond;
     int64_t cnt;
 
     tng_molecule_add(traj, "water", &molecule);
@@ -41,8 +57,15 @@ static tng_function_status tng_test_setup_molecules(tng_trajectory_t traj)
     {
         return(TNG_CRITICAL);
     }
+    tng_molecule_bond_add(traj, molecule, 0, 1, &bond);
+    tng_molecule_bond_add(traj, molecule, 0, 2, &bond);
     tng_molecule_cnt_set(traj, molecule, 200);
     tng_molecule_cnt_get(traj, molecule, &cnt);
+
+    if(cnt != 200)
+    {
+        return(TNG_CRITICAL);
+    }
 /*     printf("Created %"PRId64" %s molecules.\n", cnt, molecule->name); */
 
 /*     traj->molecule_cnt_list[traj->n_molecules-1] = 5;
@@ -106,50 +129,353 @@ static tng_function_status tng_test_setup_molecules(tng_trajectory_t traj)
     return(TNG_SUCCESS);
 }
 
+static tng_function_status tng_test_molecules(tng_trajectory_t traj)
+{
+    tng_molecule_t molecule, molecule_new;
+    tng_chain_t chain;
+    tng_residue_t residue;
+    tng_atom_t atom;
+    int64_t cnt, *bonds_to, *bonds_from;
+    char var_atoms, str[TNG_MAX_STR_LEN];
+    tng_function_status stat;
+
+    stat = tng_num_molecule_types_get(traj, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 1)
+    {
+        printf("Molecule reading error. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_num_molecules_get(traj, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 200)
+    {
+        printf("Molecule reading error. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_num_particles_variable_get(traj, &var_atoms);
+    if(stat != TNG_SUCCESS || var_atoms)
+    {
+        printf("Molecule reading error. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_molecule_of_index_get(traj, 0, &molecule);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot find molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_find(traj, "water", -1, &molecule);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot find molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat =tng_molecule_name_get(traj, molecule, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get molecule name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_num_chains_get(traj, molecule, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 1)
+    {
+        printf("Cannot get number of chains in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_molecule_chain_of_index_get(traj, molecule, 0, &chain);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get chain in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_chain_find(traj, molecule, "W", -1, &chain);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get chain in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_num_residues_get(traj, molecule, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 1)
+    {
+        printf("Cannot get number of residues in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_molecule_residue_of_index_get(traj, molecule, 0, &residue);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get residue in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_num_atoms_get(traj, molecule, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 3)
+    {
+        printf("Cannot get number of atoms in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_molecule_atom_of_index_get(traj, molecule, 0, &atom);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get atom in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_atom_find(traj, molecule, "O", -1, &atom);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get atom in molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat =tng_chain_name_get(traj, chain, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get name of chain. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_chain_num_residues_get(traj, chain, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 1)
+    {
+        printf("Cannot get number of residues in chain. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_chain_residue_of_index_get(traj, chain, 0, &residue);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get residue in chain. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_chain_residue_find(traj, chain, "WAT", -1, &residue);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get residue in chain. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_residue_name_get(traj, residue, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get name of residue. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_residue_num_atoms_get(traj, residue, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 3)
+    {
+        printf("Cannot get number of atoms in residue. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_residue_atom_of_index_get(traj, residue, 0, &atom);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get residue of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_atom_name_get(traj, atom, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get name of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_atom_type_get(traj, atom, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get atom type of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_molecule_id_of_particle_nr_get(traj, 0, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 1)
+    {
+        printf("Cannot get molecule id of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_residue_id_of_particle_nr_get(traj, 0, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 0)
+    {
+        printf("Cannot get residue id of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_global_residue_id_of_particle_nr_get(traj, 599, &cnt);
+    if(stat != TNG_SUCCESS || cnt != 199)
+    {
+        printf("Cannot get global residue id of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_molecule_name_of_particle_nr_get(traj, 0, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get molecule name of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_chain_name_of_particle_nr_get(traj, 0, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get chain name of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_residue_name_of_particle_nr_get(traj, 0, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get residue name of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_atom_name_of_particle_nr_get(traj, 0, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get atom name of atom. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_molecule_alloc(traj, &molecule_new);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot setup new molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_name_set(traj, molecule_new, "TEST");
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot set name of new molecule. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_molecule_existing_add(traj, &molecule_new);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot add new molecule to molecule system. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_molsystem_bonds_get(traj, &cnt, &bonds_from, &bonds_to);
+    if(stat != TNG_SUCCESS || cnt != 400)
+    {
+        printf("Cannot get bonds in molecule system. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    free(bonds_from);
+    free(bonds_to);
+
+    return(TNG_SUCCESS);
+}
+
 static tng_function_status tng_test_read_and_write_file
-                (tng_trajectory_t traj)
+                (tng_trajectory_t traj, const char hash_mode)
 {
+    char file_name[TNG_MAX_STR_LEN];
     tng_function_status stat;
 
-    stat = tng_file_headers_read(traj, TNG_USE_HASH);
-    if(stat == TNG_CRITICAL)
+    stat = tng_input_file_get(traj, file_name, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
     {
+        printf("Could not get name of input file. %s: %d\n",
+               __FILE__, __LINE__);
         return(stat);
     }
-    stat = tng_file_headers_write(traj, TNG_USE_HASH);
-    if(stat == TNG_CRITICAL)
+    stat = tng_output_file_get(traj, file_name, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Could not get name of output file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_file_headers_read(traj, hash_mode);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Could not read headers. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_file_headers_write(traj, hash_mode);
+    if(stat != TNG_SUCCESS)
     {
+        printf("Could not write headers. %s: %d\n",
+               __FILE__, __LINE__);
         return(stat);
     }
 
     while(stat == TNG_SUCCESS)
     {
-        stat = tng_frame_set_read_next(traj, TNG_USE_HASH);
-        if(stat != TNG_SUCCESS)
+        stat = tng_frame_set_read_next(traj, hash_mode);
+        if(stat == TNG_CRITICAL)
         {
+            printf("Could not read frame set. %s: %d\n",
+                   __FILE__, __LINE__);
             return(stat);
         }
-        stat = tng_frame_set_write(traj, TNG_USE_HASH);
+        if(stat == TNG_FAILURE)
+        {
+            return(TNG_SUCCESS);
+        }
+        stat = tng_frame_set_write(traj, hash_mode);
     }
 
     return(stat);
 }
 
-static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
+static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj,
+                                                        const char hash_mode)
 {
-    int i, j, k, nr, cnt;
+    int i, j, k, nr, cnt, dependency;
     float *data, *molpos, *charges;
     int64_t mapping[300], n_particles, n_frames_per_frame_set, tot_n_mols;
+    int64_t codec_id;
+    int64_t dist_exp = -9, temp_int, temp_int2;
 //     int64_t frame_nr;
-    double box_shape[9];
+    double box_shape[9], temp_double;
     char atom_type[16], annotation[128];
+    char temp_str[TNG_MAX_STR_LEN];
+    tng_trajectory_frame_set_t frame_set;
     tng_function_status stat = TNG_SUCCESS;
 
-    tng_medium_stride_length_set(*traj, 10);
-    tng_long_stride_length_set(*traj, 100);
+    tng_medium_stride_length_set(*traj, MEDIUM_STRIDE_LEN);
+    tng_long_stride_length_set(*traj, LONG_STRIDE_LEN);
+
+    tng_first_user_name_set(*traj, USER_NAME);
+    tng_first_program_name_set(*traj, PROGRAM_NAME);
+    tng_first_computer_name_set(*traj, COMPUTER_NAME);
+    tng_forcefield_name_set(*traj, FORCEFIELD_NAME);
 
-    tng_first_user_name_set(*traj, "User1");
-    tng_first_program_name_set(*traj, "tng_testing");
+    tng_compression_precision_set(*traj, COMPRESSION_PRECISION);
+
+    tng_distance_unit_exponential_set(*traj, dist_exp);
+
+    tng_time_per_frame_set(*traj, TIME_PER_FRAME);
 
     /* Create molecules */
     if(tng_test_setup_molecules(*traj) == TNG_CRITICAL)
@@ -160,9 +486,9 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
     /* Set the box shape */
     box_shape[1] = box_shape[2] = box_shape[3] = box_shape[5] = box_shape[6] =
     box_shape[7] = 0;
-    box_shape[0] = 150.0;
-    box_shape[4] = 145.5;
-    box_shape[8] = 155.5;
+    box_shape[0] = BOX_SHAPE_X;
+    box_shape[4] = BOX_SHAPE_Y;
+    box_shape[8] = BOX_SHAPE_Z;
     if(tng_data_block_add(*traj, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE", TNG_DOUBLE_DATA,
                        TNG_NON_TRAJECTORY_BLOCK, 1, 9, 1, TNG_UNCOMPRESSED,
                        box_shape) == TNG_CRITICAL)
@@ -195,7 +521,8 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
     if(stat == TNG_CRITICAL)
     {
         free(charges);
-        printf("Failed setting partial charges.\n");
+        printf("Failed setting partial charges. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
@@ -206,7 +533,8 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
     free(charges);
     if(stat != TNG_SUCCESS)
     {
-        printf("Failed adding partial charges\n");
+        printf("Failed adding partial charges. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
@@ -218,14 +546,16 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
                           TNG_NON_TRAJECTORY_BLOCK, 1, 1, 1, TNG_UNCOMPRESSED,
                           annotation) != TNG_SUCCESS)
     {
-        printf("Failed adding details annotation data block.\n");
+        printf("Failed adding details annotation data block. %s: %d\n",
+               __FILE__, __LINE__);
         return(TNG_CRITICAL);
     }
 
     /* Write file headers (includes non trajectory data blocks */
-    if(tng_file_headers_write(*traj, TNG_SKIP_HASH) == TNG_CRITICAL)
+    if(tng_file_headers_write(*traj, hash_mode) == TNG_CRITICAL)
     {
-        printf("Cannot write file headers.\n");
+        printf("Cannot write file headers. %s: %d\n",
+               __FILE__, __LINE__);
     }
 
 
@@ -253,10 +583,18 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
         molpos[nr+2] = 100.0 * rand() / (RAND_MAX + 1.0);
     }
 
-    /* Generate 200 frame sets - each with 100 frames (by default) */
-    for(i = 0; i < 200; i++)
+    /* Generate frame sets - each with 100 frames (by default) */
+    for(i = 0; i < N_FRAME_SETS; i++)
     {
         cnt = 0;
+        if(i < N_FRAME_SETS/2)
+        {
+            codec_id = TNG_GZIP_COMPRESSION;
+        }
+        else
+        {
+            codec_id = TNG_TNG_COMPRESSION;
+        }
         for(j = 0; j < n_frames_per_frame_set; j++)
         {
             for(k = 0; k < tot_n_mols; k++)
@@ -278,8 +616,8 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
                 data[cnt++] = molpos[nr + 2] - 1;
             }
         }
-        if(tng_frame_set_new(*traj, i * n_frames_per_frame_set,
-            n_frames_per_frame_set) != TNG_SUCCESS)
+        if(tng_frame_set_with_time_new(*traj, i * n_frames_per_frame_set,
+                                       n_frames_per_frame_set, 2e-15 * (i*n_frames_per_frame_set)) != TNG_SUCCESS)
         {
             printf("Error creating frame set %d. %s: %d\n",
                    i, __FILE__, __LINE__);
@@ -349,7 +687,7 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
                                        n_frames_per_frame_set, 3,
                                        1, 0, n_particles,
 /*                                        TNG_UNCOMPRESSED, */
-                                       TNG_GZIP_COMPRESSION,
+                                       codec_id,
                                        data) != TNG_SUCCESS)
         {
             printf("Error adding data. %s: %d\n", __FILE__, __LINE__);
@@ -358,7 +696,7 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
             return(TNG_CRITICAL);
         }
         /* Write the frame set */
-        if(tng_frame_set_write(*traj, TNG_SKIP_HASH) != TNG_SUCCESS)
+        if(tng_frame_set_write(*traj, hash_mode) != TNG_SUCCESS)
         {
             printf("Error writing frame set. %s: %d\n", __FILE__, __LINE__);
             free(molpos);
@@ -367,125 +705,214 @@ static tng_function_status tng_test_write_and_read_traj(tng_trajectory_t *traj)
         }
     }
 
-    /* Write two more frame sets one frame at a time */
+    free(molpos);
+    free(data);
+
+    tng_trajectory_destroy(traj);
+    tng_trajectory_init(traj);
+    tng_input_file_set(*traj, TNG_EXAMPLE_FILES_DIR "tng_test.tng");
+
+    stat = tng_file_headers_read(*traj, hash_mode);
 
-    /* Make a new frame set - if always using the same mapping blocks
-     * it is not necessary to explicitly add a new frame set - it will
-     * be added automatically when adding data for a frame */
-/*    if(tng_frame_set_new(*traj, i * n_frames_per_frame_set,
-        n_frames_per_frame_set) != TNG_SUCCESS)
+    tng_first_user_name_get(*traj, temp_str, TNG_MAX_STR_LEN);
+    if(strcmp(USER_NAME, temp_str) != 0)
     {
-        printf("Error creating frame set %d. %s: %d\n",
-                i, __FILE__, __LINE__);
-        free(molpos);
-        free(data);
-        return(TNG_CRITICAL);
+        printf("User name does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    frame_nr = i * n_frames_per_frame_set;
+    tng_first_program_name_get(*traj, temp_str, TNG_MAX_STR_LEN);
+    if(strcmp(PROGRAM_NAME, temp_str) != 0)
+    {
+        printf("Program name does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
 
-    for(k=0; k<300; k++)
+    tng_first_computer_name_get(*traj, temp_str, TNG_MAX_STR_LEN);
+    if(strcmp(COMPUTER_NAME, temp_str) != 0)
     {
-        mapping[k]=k;
+        printf("Computer name does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
-    *//* Just use two particle mapping blocks in this frame set *//*
-    if(tng_particle_mapping_add(*traj, 0, 300, mapping) != TNG_SUCCESS)
+
+    tng_forcefield_name_get(*traj, temp_str, TNG_MAX_STR_LEN);
+    if(strcmp(FORCEFIELD_NAME, temp_str) != 0)
     {
-        printf("Error creating particle mapping. %s: %d\n",
-                __FILE__, __LINE__);
-        free(molpos);
-        free(data);
-        return(TNG_CRITICAL);
+        printf("Forcefield name does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
-    for(k=0; k<300; k++)
+
+    tng_medium_stride_length_get(*traj, &temp_int);
+    if(temp_int != MEDIUM_STRIDE_LEN)
     {
-        mapping[k]=599-k;
+        printf("Stride length does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
-    if(tng_particle_mapping_add(*traj, 300, 300, mapping) != TNG_SUCCESS)
+
+    tng_long_stride_length_get(*traj, &temp_int);
+    if(temp_int != LONG_STRIDE_LEN)
     {
-        printf("Error creating particle mapping. %s: %d\n",
-                __FILE__, __LINE__);
-        free(molpos);
-        free(data);
-        return(TNG_CRITICAL);
+        printf("Stride length does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    *//* Add the data block to the current frame set *//*
-    if(tng_particle_data_block_add(*traj, TNG_TRAJ_POSITIONS,
-                                    "POSITIONS",
-                                    TNG_FLOAT_DATA,
-                                    TNG_TRAJECTORY_BLOCK,
-                                    n_frames_per_frame_set, 3,
-                                    1, 0, n_particles,
-                                    TNG_UNCOMPRESSED,
-                                    0) != TNG_SUCCESS)
+    tng_compression_precision_get(*traj, &temp_double);
+    if(temp_double != COMPRESSION_PRECISION)
     {
-        printf("Error adding data. %s: %d\n", __FILE__, __LINE__);
-        free(molpos);
-        free(data);
-        return(TNG_CRITICAL);
+        printf("Compression precision does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    *//* Write the frame set to disk *//*
-    if(tng_frame_set_write(*traj, TNG_SKIP_HASH) != TNG_SUCCESS)
+    tng_distance_unit_exponential_get(*traj, &temp_int);
+    if(temp_int != dist_exp)
     {
-        printf("Error writing frame set. %s: %d\n", __FILE__, __LINE__);
-        free(molpos);
-        free(data);
-        return(TNG_CRITICAL);
+        printf("Distance unit exponential does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
     }
 
-    *//* Write particle data to disk - one frame at a time *//*
-    for(i = 0; i < n_frames_per_frame_set * 2; i++)
+    stat = tng_test_molecules(*traj);
+    if(stat != TNG_SUCCESS)
     {
-        for(j = 0; j < 2; j++)
+        return(stat);
+    }
+
+    i = 0;
+    while(stat == TNG_SUCCESS)
+    {
+        stat = tng_frame_set_read_next(*traj, hash_mode);
+        tng_current_frame_set_get(*traj, &frame_set);
+        tng_frame_set_prev_frame_set_file_pos_get(*traj, frame_set, &temp_int);
+        tng_frame_set_next_frame_set_file_pos_get(*traj, frame_set, &temp_int2);
+        if(i > 0)
         {
-            cnt = 0;
-            for(k = 0; k < tot_n_mols/2; k++)
+            if(temp_int == -1)
             {
-                nr = k * 3;
-                *//* Move -1 to 1 *//*
-                molpos[nr] += 2 * (rand() / (RAND_MAX + 1.0)) - 1;
-                molpos[nr+1] += 2 * (rand() / (RAND_MAX + 1.0)) - 1;
-                molpos[nr+2] += 2 * (rand() / (RAND_MAX + 1.0)) - 1;
-
-                data[cnt++] = molpos[nr];
-                data[cnt++] = molpos[nr + 1];
-                data[cnt++] = molpos[nr + 2];
-                data[cnt++] = molpos[nr] + 1;
-                data[cnt++] = molpos[nr + 1] + 1;
-                data[cnt++] = molpos[nr + 2] + 1;
-                data[cnt++] = molpos[nr] - 1;
-                data[cnt++] = molpos[nr + 1] - 1;
-                data[cnt++] = molpos[nr + 2] - 1;
+                printf("File position of previous frame set not correct. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(TNG_FAILURE);
             }
-            if(tng_frame_particle_data_write(*traj, frame_nr + i,
-                                          TNG_TRAJ_POSITIONS, j * 300, 300,
-                                          data, TNG_SKIP_HASH) != TNG_SUCCESS)
+        }
+        else if(temp_int != -1)
+        {
+            printf("File position of previous frame set not correct. %s: %d\n",
+                    __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
+        if(i < N_FRAME_SETS -1)
+        {
+            if(temp_int2 == -1)
             {
-                printf("Error adding data. %s: %d\n", __FILE__, __LINE__);
-                free(molpos);
-                free(data);
-                return(TNG_CRITICAL);
+                printf("File position of next frame set not correct. %s: %d\n",
+                       __FILE__, __LINE__);
+                return(TNG_FAILURE);
             }
         }
+        else if(temp_int2 != -1)
+        {
+            printf("File position of previous next set not correct. %s: %d\n",
+                    __FILE__, __LINE__);
+            return(TNG_FAILURE);
+        }
+        i++;
+    }
+    if(stat == TNG_CRITICAL)
+    {
+        return(stat);
     }
-*/
-    free(molpos);
-    free(data);
 
-    tng_trajectory_destroy(traj);
-    tng_trajectory_init(traj);
-    tng_input_file_set(*traj, TNG_EXAMPLE_FILES_DIR "tng_test.tng");
+    tng_time_per_frame_get(*traj, &temp_double);
+    if(fabs(TIME_PER_FRAME - temp_double) > 0.000001)
+    {
+        printf("Time per frame does not match when reading written file. %s: %d\n",
+               __FILE__, __LINE__);
+        printf("Value: %e, expected value: %e\n", temp_double, TIME_PER_FRAME);
+        return(TNG_FAILURE);
+    }
 
-    stat = tng_file_headers_read(*traj, TNG_SKIP_HASH);
+    stat = tng_frame_set_nr_find(*traj, (int64_t)(0.30*N_FRAME_SETS));
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Could not find frame set %"PRId64". %s: %d\n", (int64_t)0.30*N_FRAME_SETS,
+               __FILE__, __LINE__);
+        return(stat);
+    }
 
-    while(stat == TNG_SUCCESS)
+    stat = tng_frame_set_nr_find(*traj, (int64_t)(0.75*N_FRAME_SETS));
+    if(stat != TNG_SUCCESS)
     {
-        stat = tng_frame_set_read_next(*traj, TNG_SKIP_HASH);
+        printf("Could not find frame set %"PRId64". %s: %d\n", (int64_t)0.75*N_FRAME_SETS,
+               __FILE__, __LINE__);
+        return(stat);
     }
 
-    return(stat);
+    tng_current_frame_set_get(*traj, &frame_set);
+    tng_frame_set_frame_range_get(*traj, frame_set, &temp_int, &temp_int2);
+    if(temp_int !=  75 * n_frames_per_frame_set)
+    {
+        printf("Unexpected first frame in frame set. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_frame_set_read_current_only_data_from_block_id(*traj, hash_mode, TNG_TRAJ_POSITIONS);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot read positions in current frame set. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_frame_set_read_next_only_data_from_block_id(*traj, hash_mode, TNG_TRAJ_POSITIONS);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot read positions in next frame set. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_data_block_name_get(*traj, TNG_TRAJ_POSITIONS, temp_str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS || strcmp("POSITIONS", temp_str) != 0)
+    {
+        printf("Cannot get name of data block or unexpected name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_data_block_name_get(*traj, TNG_TRAJ_FORCES, temp_str, TNG_MAX_STR_LEN);
+    if(stat != TNG_FAILURE)
+    {
+        printf("Trying to retrieve name of non-existent data block did not return failure. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_data_block_dependency_get(*traj, TNG_TRAJ_POSITIONS, &dependency);
+    if(stat != TNG_SUCCESS || dependency != TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT)
+    {
+        printf("Cannot get dependency of data block or unexpected dependency. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_data_block_num_values_per_frame_get(*traj, TNG_TRAJ_POSITIONS, &temp_int);
+    if(stat != TNG_SUCCESS || temp_int != 3)
+    {
+        printf("Cannot get number of values per frame of data block or unexpected value. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+    stat = tng_data_get_stride_length(*traj, TNG_TRAJ_POSITIONS, 100, &temp_int);
+    if(stat != TNG_SUCCESS || temp_int != 1)
+    {
+        printf("Cannot get stride length of data block or unexpected value. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    return(TNG_SUCCESS);
 }
 
 /* This test relies on knowing that the box shape is stored as double */
@@ -502,18 +929,13 @@ tng_function_status tng_test_get_box_data(tng_trajectory_t traj)
         return(TNG_CRITICAL);
     }
 
-/*
-//     int64_t i, j;
-//     printf("Box shape:");
-//     for(i=0; i<n_frames; i++)
-//     {
-//         for(j=0; j<n_values_per_frame; j++)
-//         {
-//             printf("\t%f", (values[i][j]).d);
-//         }
-//         printf("\n");
-//     }
-*/
+    /* The X dimension in the example file is 50 */
+    if(fabs(values[0][0].d - 50) > 0.000001)
+    {
+        printf("Unexpected value in box shape. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
     tng_data_values_free(traj, values, n_frames, n_values_per_frame, type);
 
     return(TNG_SUCCESS);
@@ -522,9 +944,10 @@ tng_function_status tng_test_get_box_data(tng_trajectory_t traj)
 /* This test relies on knowing that the positions are stored as float
  * and that the data is not sparse (i.e. as many frames in the data
  * as in the frame set */
-tng_function_status tng_test_get_positions_data(tng_trajectory_t traj)
+tng_function_status tng_test_get_positions_data(tng_trajectory_t traj,
+                                                const char hash_mode)
 {
-    int64_t n_frames, n_particles, n_values_per_frame;
+    int64_t i, j, k, n_frames, n_particles, n_values_per_frame;
     union data_values ***values = 0;
     char type;
 
@@ -536,57 +959,317 @@ tng_function_status tng_test_get_positions_data(tng_trajectory_t traj)
         return(TNG_CRITICAL);
     }
 
-/*
-//     int64_t i, j, k;
-//     struct tng_trajectory_frame_set *frame_set =
-//     &traj->current_trajectory_frame_set;
-//     for(i = 0; i<n_frames; i++)
-//     {
-//         printf("Frame %"PRId64"\n", frame_set->first_frame + i);
-//         for(j = 0; j<n_particles; j++)
-//         {
-//             printf("Particle %"PRId64":", j);
-//             for(k=0; k<n_values_per_frame; k++)
-//             {
-//                 printf("\t%f", (values[i][j][k]).f);
-//             }
+    if(n_values_per_frame != 3)
+    {
+        printf("Number of values per frame does not match expected value. %s: %d\n",
+               __FILE__, __LINE__);
+        tng_particle_data_values_free(traj, values, n_frames, n_particles,
+                                      n_values_per_frame, type);
+        return(TNG_FAILURE);
+    }
+
+    for(i = 0; i < n_frames; i++)
+    {
+//         printf("%"PRId64"\n", i);
+        for(j = 0; j < n_particles; j++)
+        {
+            for(k = 0; k < n_values_per_frame; k++)
+            {
+//                 printf("%f ", values[i][j][k].f);
+                if(values[i][j][k].f < -500 || values[i][j][k].f > 500)
+                {
+                    printf("Coordinates not in range. %s: %d\n",
+                           __FILE__, __LINE__);
+                    tng_particle_data_values_free(traj, values, n_frames, n_particles,
+                                                  n_values_per_frame, type);
+                    return(TNG_FAILURE);
+                }
+            }
 //             printf("\n");
-//         }
-//     }
-*/
+        }
+    }
+
+    if(tng_particle_data_interval_get(traj, TNG_TRAJ_POSITIONS, 111000, 111499,
+                                      hash_mode, &values, &n_particles,
+                                      &n_values_per_frame, &type) == TNG_SUCCESS)
+    {
+        printf("Getting particle positions succeeded when it should have failed. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    if(tng_particle_data_interval_get(traj, TNG_TRAJ_POSITIONS, 1000, 1050,
+                                      hash_mode, &values, &n_particles,
+                                      &n_values_per_frame, &type) != TNG_SUCCESS)
+    {
+        printf("Failed getting particle positions. %s: %d\n", __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    for(i = 0; i < 50; i++)
+    {
+//         printf("%"PRId64"\n", i);
+        for(j = 0; j < n_particles; j++)
+        {
+            for(k = 0; k < n_values_per_frame; k++)
+            {
+//                 printf("%f ", values[i][j][k].f);
+                if(values[i][j][k].f < -500 || values[i][j][k].f > 500)
+                {
+                    printf("Coordinates not in range. %s: %d\n",
+                           __FILE__, __LINE__);
+                    tng_particle_data_values_free(traj, values, n_frames, n_particles,
+                                                  n_values_per_frame, type);
+                    return(TNG_FAILURE);
+                }
+            }
+//             printf("\n");
+        }
+    }
+
     tng_particle_data_values_free(traj, values, n_frames, n_particles,
                                   n_values_per_frame, type);
 
-    values = 0;
+    return(TNG_SUCCESS);
+}
 
-    tng_particle_data_interval_get(traj, TNG_TRAJ_POSITIONS, 11000, 11499,
-                                   TNG_SKIP_HASH, &values, &n_particles,
-                                   &n_values_per_frame, &type);
+tng_function_status tng_test_utility_functions(tng_trajectory_t traj, const char hash_mode)
+{
+    tng_function_status stat;
+    int64_t n_particles, i, j, k, codec_id, n_frames, n_frames_per_frame_set;
+    int64_t n_frames_to_read=30, stride_len, next_frame, n_blocks, *block_ids = 0;
+    double time, multiplier;
+    float *positions = 0;
 
-    /* Here the particle positions can be printed */
+    stat = tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_test.tng", 'r', &traj);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
 
-    tng_particle_data_values_free(traj, values, 500, n_particles,
-                                  n_values_per_frame, type);
+    stat = tng_util_time_of_frame_get(traj, 50, &time);
+    if(stat != TNG_SUCCESS || fabs(time - 100e-13) > 0.000001)
+    {
+        printf("Unexpected time at frame 50. %s: %d\n", __FILE__, __LINE__);
+        printf("Value: %e, expected value: %e\n", time, 100e-13);
+        return(stat);
+    }
+    stat = tng_util_time_of_frame_get(traj, 100, &time);
+    if(stat != TNG_SUCCESS || fabs(time - 200e-13) > 0.000001)
+    {
+        printf("Unexpected time at frame 100. %s: %d\n", __FILE__, __LINE__);
+        printf("Value: %e, expected value: %e\n", time, 100e-13);
+        return(stat);
+    }
+
+    tng_num_frames_per_frame_set_get(traj, &n_frames_per_frame_set);
+
+    stat = tng_util_num_frames_with_data_of_block_id_get(traj, TNG_TRAJ_POSITIONS, &n_frames);
+    if(stat != TNG_SUCCESS || n_frames != n_frames_per_frame_set * N_FRAME_SETS)
+    {
+        printf("Unexpected number of frames with positions data. %s: %d\n",
+               __FILE__, __LINE__);
+        printf("Value: %"PRId64", expected value: %"PRId64"\n", n_frames,
+               n_frames_per_frame_set * N_FRAME_SETS);
+        return(stat);
+    }
+
+    tng_num_frames_per_frame_set_get(traj, &n_frames_per_frame_set);
+
+    stat = tng_util_num_frames_with_data_of_block_id_get(traj, TNG_TRAJ_POSITIONS, &n_frames);
+    if(stat != TNG_SUCCESS || n_frames != n_frames_per_frame_set * N_FRAME_SETS)
+    {
+        return(stat);
+    }
+
+    tng_num_particles_get(traj, &n_particles);
+
+    stat = tng_util_pos_read_range(traj, 1, n_frames_to_read, &positions, &stride_len);
+    if(stat != TNG_SUCCESS)
+    {
+        if(positions)
+        {
+            free(positions);
+        }
+        return(stat);
+    }
+
+    for(i = 0; i < n_frames_to_read / stride_len; i++)
+    {
+        for(j = 0; j < n_particles; j++)
+        {
+            for(k = 0; k < 3; k++)
+            {
+                if(positions[i*n_particles + j*3 + k] < -500 || positions[i*n_particles + j*3 + k] > 500)
+                {
+                    printf("Coordinates not in range. %s: %d\n",
+                           __FILE__, __LINE__);
+                    free(positions);
+                    return(TNG_FAILURE);
+                }
+            }
+        }
+    }
+
+    free(positions);
+
+    stat=tng_util_trajectory_next_frame_present_data_blocks_find(traj, n_frames_to_read,
+                                                                 0, 0, &next_frame,
+                                                                 &n_blocks, &block_ids);
+    if(block_ids)
+    {
+        free(block_ids);
+    }
+    if(stat != TNG_SUCCESS || n_blocks != 1 || next_frame != n_frames_to_read + stride_len)
+    {
+        printf("Unexpected data blocks in next frame. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_util_frame_current_compression_get(traj, TNG_TRAJ_POSITIONS, &codec_id, &multiplier);
+    if(stat != TNG_SUCCESS || codec_id != TNG_GZIP_COMPRESSION)
+    {
+        printf("Could not get compression. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_FAILURE);
+    }
+
+    stat = tng_util_trajectory_close(&traj);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
 
     return(TNG_SUCCESS);
 }
 
 
-tng_function_status tng_test_append(tng_trajectory_t traj)
+tng_function_status tng_test_append(tng_trajectory_t traj, const char hash_mode)
 {
+    char str[TNG_MAX_STR_LEN];
+    int64_t n_frames, n_particles, i;
+    double time, *velocities;
     tng_function_status stat;
 
     stat = tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_test.tng", 'a', &traj);
     if(stat != TNG_SUCCESS)
     {
+        printf("Cannot open trajectory. %s: %d\n",
+               __FILE__, __LINE__);
         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_last_user_name_set(traj, USER_NAME);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot set last user name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_last_user_name_get(traj, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get last user name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_last_program_name_set(traj, PROGRAM_NAME);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot set last program name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_last_program_name_get(traj, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get last program name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_last_computer_name_set(traj, "Still " COMPUTER_NAME);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot set last computer name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+    stat = tng_last_computer_name_get(traj, str, TNG_MAX_STR_LEN);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot get last computer name. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_file_headers_write(traj, hash_mode);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot write file headers. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    tng_num_frames_get(traj, &n_frames);
+    tng_frame_set_of_frame_find(traj, n_frames - 1);
+    tng_util_time_of_frame_get(traj, n_frames - 1, &time);
+    time += TIME_PER_FRAME;
+    tng_num_particles_get(traj, &n_particles);
+
+    velocities = malloc(sizeof(double) * n_particles * 3);
+    if(!velocities)
+    {
+        printf("Cannot allocate memory. %s: %d\n",
+               __FILE__, __LINE__);
+        return(TNG_CRITICAL);
+    }
+
+    for(i = 0; i < n_particles * 3; i++)
+    {
+        velocities[i] = i;
+    }
+
+    stat = tng_util_vel_with_time_double_write(traj, n_frames, time, velocities);
+
+    free(velocities);
+
+    stat = tng_util_trajectory_close(&traj);
+
+    return(stat);
+}
+
+tng_function_status tng_test_copy_container(tng_trajectory_t traj, const char hash_mode)
+{
+    tng_trajectory_t dest;
+    tng_function_status stat;
+
+    stat = tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_test.tng", 'r', &traj);
+    if(stat != TNG_SUCCESS)
+    {
+        printf("Cannot open trajectory. %s: %d\n",
+               __FILE__, __LINE__);
+        return(stat);
+    }
+
+    stat = tng_trajectory_init_from_src(traj, &dest);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
+
+    stat = tng_molecule_system_copy(traj, dest);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
 
     stat = tng_util_trajectory_close(&traj);
+    if(stat != TNG_SUCCESS)
+    {
+        return(stat);
+    }
+    stat = tng_util_trajectory_close(&dest);
 
     return(stat);
 }
@@ -594,28 +1277,29 @@ tng_function_status tng_test_append(tng_trajectory_t traj)
 int main()
 {
     tng_trajectory_t traj;
-    tng_function_status stat;
     char time_str[TNG_MAX_DATE_STR_LEN];
     char version_str[TNG_MAX_STR_LEN];
+    char hash_mode = TNG_USE_HASH;
 
     tng_version(traj, version_str, TNG_MAX_STR_LEN);
+    printf("Test version control:\t\t\t\t");
     if(strncmp(TNG_VERSION, version_str, TNG_MAX_STR_LEN) == 0)
     {
-        printf("Test version control: \t\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
     else
     {
-        printf("Test version control: \t\t\t\tFailed.\n");
+        printf("Failed.\n");
     }
 
+    printf("Test Init trajectory:\t\t\t\t");
     if(tng_trajectory_init(&traj) != TNG_SUCCESS)
     {
         tng_trajectory_destroy(&traj);
-        printf("Test Init trajectory:\t\t\t\tFailed. %s: %d.\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d.\n", __FILE__, __LINE__);
         exit(1);
     }
-    printf("Test Init trajectory:\t\t\t\tSucceeded.\n");
+    printf("Succeeded.\n");
 
     tng_time_get_str(traj, time_str);
 
@@ -624,107 +1308,101 @@ int main()
     tng_input_file_set(traj, TNG_EXAMPLE_FILES_DIR "tng_example.tng");
     tng_output_file_set(traj, TNG_EXAMPLE_FILES_DIR "tng_example_out.tng");
 
-
-    if(tng_test_read_and_write_file(traj) == TNG_CRITICAL)
+    printf("Test Read and write file:\t\t\t");
+    if(tng_test_read_and_write_file(traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Read and write file:\t\t\tFailed. %s: %d\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Read and write file:\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
+    printf("Test Get data:\t\t\t\t\t");
     if(tng_test_get_box_data(traj) != TNG_SUCCESS)
     {
-        printf("Test Get data:\t\t\t\t\tFailed. %s: %d\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Get data:\t\t\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-    if(tng_trajectory_destroy(&traj) == TNG_CRITICAL ||
-       tng_trajectory_init(&traj) == TNG_CRITICAL)
+    printf("Test Destroy and init trajectory:\t\t");
+    if(tng_trajectory_destroy(&traj) != TNG_SUCCESS ||
+       tng_trajectory_init(&traj) != TNG_SUCCESS)
     {
-        printf("Test Destroy and init trajectory:\t\tFailed. %s: %d\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Destroy and init trajectory:\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
 
     tng_output_file_set(traj, TNG_EXAMPLE_FILES_DIR "tng_test.tng");
 
-    if(tng_test_write_and_read_traj(&traj) == TNG_CRITICAL)
+    printf("Test Write and read file:\t\t\t");
+    if(tng_test_write_and_read_traj(&traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Write and read file:\t\t\tFailed. %s: %d\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Write and read file:\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-    if(tng_test_get_positions_data(traj) != TNG_SUCCESS)
+    printf("Test Get particle data:\t\t\t\t");
+    if(tng_test_get_positions_data(traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Get particle data:\t\t\t\tFailed. %s: %d\n",
+        printf("Failed. %s: %d\n",
                __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Get particle data:\t\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-    if(tng_trajectory_destroy(&traj) == TNG_CRITICAL)
+    printf("Test Destroy trajectory:\t\t\t");
+    if(tng_trajectory_destroy(&traj) != TNG_SUCCESS)
     {
-        printf("Test Destroy trajectory:\t\t\tFailed. %s: %d.\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d.\n", __FILE__, __LINE__);
         exit(1);
     }
     else
     {
-        printf("Test Destroy trajectory:\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-
-    stat = tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_test.tng", 'r', &traj);
-
-    if(stat != TNG_SUCCESS)
+    printf("Test Utility functions:\t\t\t\t");
+    if(tng_test_utility_functions(traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Utility function open:\t\t\tFailed. %s: %d.\n",
-               __FILE__, __LINE__);
+        printf("Failed. %s: %d.\n", __FILE__, __LINE__);
         exit(1);
     }
     else
     {
-        printf("Test Utility function open:\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-    stat = tng_util_trajectory_close(&traj);
-    if(stat != TNG_SUCCESS)
+    printf("Test Append:\t\t\t\t\t");
+    if(tng_test_append(traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Utility function close:\t\t\tFailed. %s: %d.\n",
-               __FILE__, __LINE__);
-        exit(1);
+        printf("Failed. %s: %d.\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Utility function close:\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
-    if(tng_test_append(traj) != TNG_SUCCESS)
+    printf("Test Copy trajectory container:\t\t\t");
+    if(tng_test_copy_container(traj, hash_mode) != TNG_SUCCESS)
     {
-        printf("Test Append:\t\t\t\t\tFailed. %s: %d.\n",
-               __FILE__, __LINE__);
-        exit(1);
+        printf("Failed. %s: %d.\n", __FILE__, __LINE__);
     }
     else
     {
-        printf("Test Append:\t\t\t\t\tSucceeded.\n");
+        printf("Succeeded.\n");
     }
 
     printf("Tests finished\n");
index 44e8f796b712762586fbea1376b6764cdabdacf6..c2ef2d6254af5fe4c73774a28bb681addf4c4f52 100644 (file)
  * modify it under the terms of the Revised BSD License.
  */
 
+#include "tng/tng_io.h"
+
 #include <stdlib.h>
 #include <stdio.h>
-#include "tng/tng_io.h"
 
 
 /* N.B. this code is for testing parallel reading of trajectory frame sets. The