/* This code is part of the tng binary trajectory format.
- *
- * VERSION 1.5
*
* Written by Magnus Lundborg
- * Copyright (c) 2012-2013, The GROMACS development team.
+ * Copyright (c) 2012-2014, The GROMACS development team.
* Check out http://www.gromacs.org for more information.
*
*
#include "../../include/tng_io.h"
#include "../../include/md5.h"
#include "../../include/compression/tng_compress.h"
+#include "../include/version.h"
struct tng_bond {
};
/* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
+/* FIXME: Make only one data block struct */
struct tng_particle_data {
/** The block ID of the data block containing this particle data.
* This is used to determine the kind of data that is stored */
/** A 1-dimensional array of values of length
* [sizeof (datatype)] * n_frames * n_values_per_frame */
void *values;
- /** If storing character data store it in a 3-dimensional array */
+ /** If storing character data store it in a 2-dimensional array */
char ***strings;
};
* cannot be trusted to be up-to-date */
int64_t n_trajectory_frame_sets;
- /** The number of trajectory blocks in the file */
- int64_t n_trajectory_blocks;
-
/* These data blocks are non-trajectory data blocks */
/** The number of non-frame dependent particle dependent data blocks */
int n_particle_data_blocks;
/* Reset the md5_hash */
memcpy(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN);
block->name = 0;
- block->block_version = TNG_VERSION;
+ block->block_version = TNG_API_VERSION;
block->header_contents = 0;
block->header_contents_size = 0;
block->block_contents = 0;
/** Read the header of a data block, regardless of its type
* @param tng_data is a trajectory data container.
* @param block is a general block container.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
+ * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
+ * error has occured (not able to read the header size, thus skipping
+ * the block) or TNG_CRITICAL (2) if a major error has occured.
*/
static tng_function_status tng_block_header_read
(tng_trajectory_t tng_data, tng_gen_block_t block)
return(TNG_CRITICAL);
}
+ if(block->header_contents_size == 0)
+ {
+ block->id = -1;
+ return(TNG_FAILURE);
+ }
+
/* If this was the size of the general info block check the endianness */
if(ftell(tng_data->input_file) < 9)
{
// }
*/
-static tng_function_status tng_reread_frame_set_at_file_pos
- (tng_trajectory_t tng_data,
- const int64_t pos)
+/** Update the md5 hash of a block already written to the file
+ * @param tng_data is a trajectory data container.
+ * @param block is the block, of which to update the md5 hash.
+ * @param header_start_pos is the file position where the block header starts.
+ * @param contents_start_pos is the file position where the block contents
+ * start.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ const int64_t header_start_pos,
+ const int64_t contents_start_pos)
{
- tng_gen_block_t block;
- tng_function_status stat;
-
- tng_block_init(&block);
+ if(block->block_contents)
+ {
+ free(block->block_contents);
+ }
- fseek(tng_data->input_file, pos, SEEK_SET);
- if(pos > 0)
+ block->block_contents = malloc(block->block_contents_size);
+ if(!block->block_contents)
{
- stat = tng_block_header_read(tng_data, block);
- if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
- {
- fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
- __FILE__, __LINE__);
- tng_block_destroy(&block);
- return(TNG_FAILURE);
- }
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- if(tng_block_read_next(tng_data, block,
- TNG_SKIP_HASH) != TNG_SUCCESS)
- {
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
+ fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
+ if(fread(block->block_contents, block->block_contents_size, 1,
+ tng_data->output_file) == 0)
+ {
+ fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- tng_block_destroy(&block);
+ tng_block_md5_hash_generate(block);
+
+ fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
+ SEEK_SET);
+ fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
return(TNG_SUCCESS);
}
-/** Write the header of a data block, regardless of its type
+/** Update the frame set pointers in the file header (general info block),
+ * already written to disk
* @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @param hash_mode specifies whether to update the block md5 hash when
+ * updating the pointers.
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_block_header_write
- (tng_trajectory_t tng_data,
- tng_gen_block_t block,
- const char hash_mode)
+static tng_function_status tng_header_pointers_update
+ (tng_trajectory_t tng_data, const char hash_mode)
{
- int name_len, offset = 0;
-
- TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
+ tng_gen_block_t block;
+ FILE *temp = tng_data->input_file;
+ int64_t output_file_pos, pos, contents_start_pos;
if(tng_output_file_init(tng_data) != TNG_SUCCESS)
{
return(TNG_CRITICAL);
}
- if(!block->name)
- {
- block->name = malloc(1);
- if(!block->name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- block->name[0] = 0;
- }
+ tng_data->input_file = tng_data->output_file;
- name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+ tng_block_init(&block);
- if(hash_mode == TNG_USE_HASH)
+ output_file_pos = ftell(tng_data->output_file);
+ fseek(tng_data->output_file, 0, SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
{
- tng_block_md5_hash_generate(block);
+ fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
}
- /* Calculate the size of the header to write */
- block->header_contents_size = sizeof(block->header_contents_size) +
- sizeof(block->block_contents_size) +
- sizeof(block->id) +
- sizeof(block->block_version) +
- TNG_MD5_HASH_LEN +
- name_len;
+ contents_start_pos = ftell(tng_data->output_file);
- if(block->header_contents)
- {
- free(block->header_contents);
- }
+ fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
+ sizeof(int64_t), SEEK_CUR);
- block->header_contents = malloc(block->header_contents_size);
- if(!block->header_contents)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->header_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
+ tng_data->input_file = temp;
- /* First copy all data into the header_contents block and finally write
- * the whole block at once. */
- memcpy(block->header_contents, &block->header_contents_size,
- sizeof(block->header_contents_size));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- offset += sizeof(block->header_contents_size);
+ pos = tng_data->first_trajectory_frame_set_output_file_pos;
- memcpy(block->header_contents+offset, &block->block_contents_size,
- sizeof(block->block_contents_size));
- if(tng_data->output_endianness_swap_func_64)
+ if(tng_data->input_endianness_swap_func_64)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
- offset += sizeof(block->block_contents_size);
- memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
- if(tng_data->output_endianness_swap_func_64)
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
}
- offset += sizeof(block->id);
-
- memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
- offset += TNG_MD5_HASH_LEN;
- strncpy(block->header_contents+offset, block->name, name_len);
- offset += name_len;
+ pos = tng_data->last_trajectory_frame_set_output_file_pos;
- memcpy(block->header_contents+offset, &block->block_version,
- sizeof(block->block_version));
- if(tng_data->output_endianness_swap_func_64)
+ if(tng_data->input_endianness_swap_func_64)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
}
}
- if(fwrite(block->header_contents, block->header_contents_size,
- 1, tng_data->output_file) != 1)
+ if(fwrite(&pos,
+ sizeof(int64_t), 1, tng_data->output_file) != 1)
{
- fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
+ tng_block_destroy(&block);
return(TNG_CRITICAL);
}
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
+ }
+
+ tng_block_destroy(&block);
+
+ fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+
return(TNG_SUCCESS);
}
-/** Read a general info block. This is the first block of a TNG file.
- * Populate the fields in tng_data.
+/** Update the frame set pointers in the current frame set block, already
+ * written to disk. It also updates the pointers of the blocks pointing to
+ * the current frame set block.
* @param tng_data is a trajectory data container.
- * @param block is a general block container.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
- * compared to the md5 hash of the read contents to ensure valid data.
+ * @param hash_mode specifies whether to update the block md5 hash when
+ * updating the pointers.
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_general_info_block_read
- (tng_trajectory_t tng_data, tng_gen_block_t block,
- const char hash_mode)
+static tng_function_status tng_frame_set_pointers_update
+ (tng_trajectory_t tng_data, const char hash_mode)
{
- int len, offset = 0;
- tng_bool same_hash;
-
- void *temp;
-
- TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
+ tng_gen_block_t block;
+ tng_trajectory_frame_set_t frame_set;
+ FILE *temp = tng_data->input_file;
+ int64_t pos, output_file_pos, contents_start_pos;
- if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+ if(tng_output_file_init(tng_data) != TNG_SUCCESS)
{
+ fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
+ __FILE__, __LINE__);
return(TNG_CRITICAL);
}
- temp = realloc(block->block_contents, block->block_contents_size);
- if(!temp)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- free(block->block_contents);
- block->block_contents = 0;
- return(TNG_CRITICAL);
- }
- block->block_contents = temp;
+ tng_block_init(&block);
+ output_file_pos = ftell(tng_data->output_file);
- /* Read the whole block into block_contents to be able to write it to disk
- * even if it cannot be interpreted. */
- if(fread(block->block_contents, block->block_contents_size, 1,
- tng_data->input_file) == 0)
- {
- fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
+ tng_data->input_file = tng_data->output_file;
- /* FIXME: Does not check if the size of the contents matches the expected
- * size or if the contents can be read. */
+ frame_set = &tng_data->current_trajectory_frame_set;
- if(hash_mode == TNG_USE_HASH)
+ pos = tng_data->current_trajectory_frame_set_output_file_pos;
+
+ /* Update next frame set */
+ if(frame_set->next_frame_set_file_pos > 0)
{
- tng_md5_hash_match_verify(block, &same_hash);
- if(same_hash != TNG_TRUE)
- {
- fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
+ fseek(tng_data->output_file, (long)frame_set->next_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (5 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
+ contents_start_pos);
+ }
+ fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+ }
+ /* Update previous frame set */
+ if(frame_set->prev_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
+ contents_start_pos);
+ }
+ fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+ }
+
+ /* Update the frame set one medium stride step after */
+ if(frame_set->medium_stride_next_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->output_file,
+ (long)frame_set->medium_stride_next_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (3 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block,
+ frame_set->medium_stride_next_frame_set_file_pos,
+ contents_start_pos);
+ }
+ }
+ /* Update the frame set one medium stride step before */
+ if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->output_file,
+ (long)frame_set->medium_stride_prev_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block,
+ frame_set->medium_stride_prev_frame_set_file_pos,
+ contents_start_pos);
+ }
+ }
+
+ /* Update the frame set one long stride step after */
+ if(frame_set->long_stride_next_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->output_file,
+ (long)frame_set->long_stride_next_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (1 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block,
+ frame_set->long_stride_next_frame_set_file_pos,
+ contents_start_pos);
+ }
+ }
+ /* Update the frame set one long stride step before */
+ if(frame_set->long_stride_prev_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->output_file,
+ (long)frame_set->long_stride_prev_frame_set_file_pos,
+ SEEK_SET);
+
+ if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ contents_start_pos = ftell(tng_data->output_file);
+
+ fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ &pos)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_update(tng_data, block,
+ frame_set->long_stride_prev_frame_set_file_pos,
+ contents_start_pos);
+ }
+ }
+
+ fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
+
+ tng_data->input_file = temp;
+
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_reread_frame_set_at_file_pos
+ (tng_trajectory_t tng_data,
+ const int64_t pos)
+{
+ tng_gen_block_t block;
+ tng_function_status stat;
+
+ tng_block_init(&block);
+
+ fseek(tng_data->input_file, pos, SEEK_SET);
+ if(pos > 0)
+ {
+ stat = tng_block_header_read(tng_data, block);
+ if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_FAILURE);
+ }
+
+ if(tng_block_read_next(tng_data, block,
+ TNG_SKIP_HASH) != TNG_SUCCESS)
+ {
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+ }
+
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
+ (tng_trajectory_t tng_data,
+ int64_t *pos)
+{
+ int64_t orig_pos, curr_frame_set_pos;
+ tng_gen_block_t block;
+ tng_function_status stat;
+ tng_trajectory_frame_set_t frame_set =
+ &tng_data->current_trajectory_frame_set;
+
+ orig_pos = ftell(tng_data->input_file);
+ curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
+
+ *pos = tng_data->first_trajectory_frame_set_input_file_pos;
+
+ if(*pos <= 0)
+ {
+ return(TNG_SUCCESS);
+ }
+
+ fseek(tng_data->input_file, *pos, SEEK_SET);
+
+ tng_block_init(&block);
+ /* Read block headers first to see that a frame set block is found. */
+ stat = tng_block_header_read(tng_data, block);
+ if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_FAILURE);
+ }
+
+ if(tng_block_read_next(tng_data, block,
+ TNG_SKIP_HASH) != TNG_SUCCESS)
+ {
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
+ /* Read all frame set blocks (not the blocks between them) */
+ while(frame_set->next_frame_set_file_pos > 0)
+ {
+ fseek(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
+ stat = tng_block_header_read(tng_data, block);
+ if(stat == TNG_CRITICAL)
+ {
+ fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+ if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ return(TNG_FAILURE);
+ }
+
+ stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
+ if(stat != TNG_SUCCESS)
+ {
+ tng_block_destroy(&block);
+ return(stat);
+ }
+ /* Update *pos if this is the earliest frame set so far (after orig_pos) */
+ if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
+ tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
+ {
+ *pos = tng_data->current_trajectory_frame_set_input_file_pos;
+ }
+ }
+
+ /* Re-read the frame set that used to be the current one */
+ tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
+
+ fseek(tng_data->input_file, orig_pos, SEEK_SET);
+
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_frame_set_complete_migrate
+ (tng_trajectory_t tng_data,
+ int64_t block_start_pos,
+ int64_t block_len,
+ int64_t new_pos)
+{
+ int64_t i;
+ tng_bool updated = TNG_FALSE;
+
+ char *contents;
+
+ if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
+
+ fseek(tng_data->input_file, block_start_pos, SEEK_SET);
+
+ contents = malloc(block_len);
+ if(!contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block_len, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ if(fread(contents, block_len, 1, tng_data->input_file) == 0)
+ {
+ fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
+ __FILE__, __LINE__);
+ free(contents);
+ return(TNG_CRITICAL);
+ }
+ fseek(tng_data->output_file, new_pos, SEEK_SET);
+
+ if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
+ {
+ fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
+ __FILE__, __LINE__);
+ free(contents);
+ return(TNG_CRITICAL);
+ }
+
+ tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
+
+ tng_frame_set_pointers_update(tng_data, TNG_USE_HASH);
+
+ /* Update the general info block if needed */
+ if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
+ {
+ tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
+ updated = TNG_TRUE;
+ }
+ if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
+ {
+ tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
+ updated = TNG_TRUE;
+ }
+ if(updated)
+ {
+ tng_header_pointers_update(tng_data, TNG_USE_HASH);
+ }
+
+ /* Fill the block with NULL to avoid confusion. */
+ for(i = 0; i < block_len; i++)
+ {
+ contents[i] = '\0';
+ }
+ fseek(tng_data->output_file, block_start_pos, SEEK_SET);
+
+ /* FIXME: casting block_len to size_t is dangerous */
+ fwrite(contents, 1, block_len, tng_data->output_file);
+
+ free(contents);
+
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_length_of_current_frame_set_contents_get
+ (tng_trajectory_t tng_data,
+ int64_t *len)
+{
+ int64_t orig_pos, pos, curr_frame_set_pos;
+ tng_gen_block_t block;
+ tng_function_status stat;
+
+ orig_pos = ftell(tng_data->input_file);
+ curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
+
+ *len = 0;
+
+ fseek(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
+
+ tng_block_init(&block);
+ /* Read block headers first to see that a frame set block is found. */
+ stat = tng_block_header_read(tng_data, block);
+ if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
+ curr_frame_set_pos, __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_FAILURE);
+ }
+
+ /* Read the headers of all blocks in the frame set (not the actual contents of them) */
+ while(stat == TNG_SUCCESS)
+ {
+ fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+ *len += block->header_contents_size + block->block_contents_size;
+ pos += block->header_contents_size + block->block_contents_size;
+ if(pos >= tng_data->input_file_len)
+ {
+ break;
+ }
+ stat = tng_block_header_read(tng_data, block);
+ if(block->id == TNG_TRAJECTORY_FRAME_SET)
+ {
+ break;
+ }
+ }
+
+ /* Re-read the frame set that used to be the current one */
+ tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
+
+ fseek(tng_data->input_file, orig_pos, SEEK_SET);
+
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
+/** Migrate blocks in the file to make room for new data in a block. This
+ * is required e.g. when adding data to a block or extending strings in a
+ * block.
+ * @param tng_data is a trajectory data container.
+ * @param start_pos is the position from which to start moving data, usually
+ * the byte after the end of the block to which data was added.
+ * @param offset is the number of bytes that were inserted.
+ * @details Trajectory blocks (frame sets and their related blocks) are moved
+ * to the end of the file (if needed) in order to make room for non-trajectory
+ * data.
+ */
+static tng_function_status tng_migrate_data_in_file
+ (tng_trajectory_t tng_data,
+ int64_t start_pos,
+ int64_t offset)
+{
+ int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
+ tng_gen_block_t block;
+ tng_function_status stat;
+ FILE *temp;
+
+ if(offset <= 0)
+ {
+ return(TNG_SUCCESS);
+ }
+
+ temp = tng_data->input_file;
+
+ stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
+ if(stat != TNG_SUCCESS)
+ {
+ tng_data->input_file = temp;
+ return(stat);
+ }
+
+ tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
+
+ empty_space = traj_start_pos - (start_pos - 1);
+
+ if(empty_space >= offset)
+ {
+ return(TNG_SUCCESS);
+ }
+
+ orig_file_pos = ftell(tng_data->input_file);
+ tng_block_init(&block);
+
+ while(empty_space < offset)
+ {
+ fseek(tng_data->input_file, traj_start_pos, SEEK_SET);
+ stat = tng_block_header_read(tng_data, block);
+ if(stat == TNG_CRITICAL)
+ {
+ fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ tng_data->input_file = temp;
+ return(TNG_CRITICAL);
+ }
+ if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(TNG_FAILURE);
+ }
+ stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
+ if(stat != TNG_SUCCESS)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(stat);
+ }
+ stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
+ frame_set_length, tng_data->input_file_len);
+ if(stat != TNG_SUCCESS)
+ {
+ tng_data->input_file = temp;
+ tng_block_destroy(&block);
+ return(stat);
+ }
+
+ empty_space += frame_set_length;
+ }
+ fseek(tng_data->input_file, orig_file_pos, SEEK_SET);
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_block_header_len_calculate
+ (const tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ int64_t *len)
+{
+ int name_len;
+ (void)tng_data;
+
+ /* If the string is unallocated allocate memory for just string
+ * termination */
+ if(!block->name)
+ {
+ block->name = malloc(1);
+ if(!block->name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ block->name[0] = 0;
+ }
+
+ name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+
+ /* Calculate the size of the header to write */
+ *len = sizeof(block->header_contents_size) +
+ sizeof(block->block_contents_size) +
+ sizeof(block->id) +
+ sizeof(block->block_version) +
+ TNG_MD5_HASH_LEN +
+ name_len;
+
+ return (TNG_SUCCESS);
+}
+
+/** Write the header of a data block, regardless of its type
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_block_header_write
+ (tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ const char hash_mode)
+{
+ int name_len, offset = 0;
+
+ TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
+
+ if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
+ TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_block_md5_hash_generate(block);
+ }
+
+ if(block->header_contents)
+ {
+ free(block->header_contents);
+ }
+
+ block->header_contents = malloc(block->header_contents_size);
+ if(!block->header_contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->header_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ name_len = tng_min_i((int)strlen(block->name) + 1, TNG_MAX_STR_LEN);
+
+ /* First copy all data into the header_contents block and finally write
+ * the whole block at once. */
+ memcpy(block->header_contents, &block->header_contents_size,
+ sizeof(block->header_contents_size));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ offset += sizeof(block->header_contents_size);
+
+ memcpy(block->header_contents+offset, &block->block_contents_size,
+ sizeof(block->block_contents_size));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ offset += sizeof(block->block_contents_size);
+
+ memcpy(block->header_contents+offset, &block->id, sizeof(block->id));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ offset += sizeof(block->id);
+
+ memcpy(block->header_contents+offset, block->md5_hash, TNG_MD5_HASH_LEN);
+ offset += TNG_MD5_HASH_LEN;
+
+ strncpy(block->header_contents+offset, block->name, name_len);
+ offset += name_len;
+
+ memcpy(block->header_contents+offset, &block->block_version,
+ sizeof(block->block_version));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if(fwrite(block->header_contents, block->header_contents_size,
+ 1, tng_data->output_file) != 1)
+ {
+ fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n", __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_general_info_block_len_calculate
+ (tng_trajectory_t tng_data,
+ int64_t *len)
+{
+ int first_program_name_len, first_user_name_len;
+ int first_computer_name_len, first_pgp_signature_len;
+ int last_program_name_len, last_user_name_len;
+ int last_computer_name_len, last_pgp_signature_len;
+ int forcefield_name_len;
+
+ /* If the strings are unallocated allocate memory for just string
+ * termination */
+ if(!tng_data->first_program_name)
+ {
+ tng_data->first_program_name = malloc(1);
+ if(!tng_data->first_program_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->first_program_name[0] = 0;
+ }
+ if(!tng_data->last_program_name)
+ {
+ tng_data->last_program_name = malloc(1);
+ if(!tng_data->last_program_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->last_program_name[0] = 0;
+ }
+ if(!tng_data->first_user_name)
+ {
+ tng_data->first_user_name = malloc(1);
+ if(!tng_data->first_user_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->first_user_name[0] = 0;
+ }
+ if(!tng_data->last_user_name)
+ {
+ tng_data->last_user_name = malloc(1);
+ if(!tng_data->last_user_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->last_user_name[0] = 0;
+ }
+ if(!tng_data->first_computer_name)
+ {
+ tng_data->first_computer_name = malloc(1);
+ if(!tng_data->first_computer_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->first_computer_name[0] = 0;
+ }
+ if(!tng_data->last_computer_name)
+ {
+ tng_data->last_computer_name = malloc(1);
+ if(!tng_data->last_computer_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->last_computer_name[0] = 0;
+ }
+ if(!tng_data->first_pgp_signature)
+ {
+ tng_data->first_pgp_signature = malloc(1);
+ if(!tng_data->first_pgp_signature)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->first_pgp_signature[0] = 0;
+ }
+ if(!tng_data->last_pgp_signature)
+ {
+ tng_data->last_pgp_signature = malloc(1);
+ if(!tng_data->last_pgp_signature)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->last_pgp_signature[0] = 0;
+ }
+ if(!tng_data->forcefield_name)
+ {
+ tng_data->forcefield_name = malloc(1);
+ if(!tng_data->forcefield_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ tng_data->forcefield_name[0] = 0;
+ }
+
+ first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
+ TNG_MAX_STR_LEN);
+ last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
+ TNG_MAX_STR_LEN);
+ first_user_name_len = tng_min_i((int)strlen(tng_data->first_user_name) + 1,
+ TNG_MAX_STR_LEN);
+ last_user_name_len = tng_min_i((int)strlen(tng_data->last_user_name) + 1,
+ TNG_MAX_STR_LEN);
+ first_computer_name_len = tng_min_i((int)strlen(tng_data->first_computer_name) + 1,
+ TNG_MAX_STR_LEN);
+ last_computer_name_len = tng_min_i((int)strlen(tng_data->last_computer_name) + 1,
+ TNG_MAX_STR_LEN);
+ first_pgp_signature_len = tng_min_i((int)strlen(tng_data->first_pgp_signature) + 1,
+ TNG_MAX_STR_LEN);
+ last_pgp_signature_len = tng_min_i((int)strlen(tng_data->last_pgp_signature) + 1,
+ TNG_MAX_STR_LEN);
+ forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
+ TNG_MAX_STR_LEN);
+
+ *len = sizeof(tng_data->time) +
+ sizeof(tng_data->var_num_atoms_flag) +
+ sizeof(tng_data->frame_set_n_frames) +
+ sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
+ sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
+ sizeof(tng_data->medium_stride_length) +
+ sizeof(tng_data->long_stride_length) +
+ sizeof(tng_data->distance_unit_exponential) +
+ first_program_name_len +
+ last_program_name_len +
+ first_user_name_len +
+ last_user_name_len +
+ first_computer_name_len +
+ last_computer_name_len +
+ first_pgp_signature_len +
+ last_pgp_signature_len +
+ forcefield_name_len;
+
+ return(TNG_SUCCESS);
+}
+
+/** Read a general info block. This is the first block of a TNG file.
+ * Populate the fields in tng_data.
+ * @param tng_data is a trajectory data container.
+ * @param block is a general block container.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
+ * compared to the md5 hash of the read contents to ensure valid data.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_general_info_block_read
+ (tng_trajectory_t tng_data, tng_gen_block_t block,
+ const char hash_mode)
+{
+ int len, offset = 0;
+ tng_bool same_hash;
+
+ void *temp;
+
+ TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
+
+ if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
+
+ temp = realloc(block->block_contents, block->block_contents_size);
+ if(!temp)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ free(block->block_contents);
+ block->block_contents = 0;
+ return(TNG_CRITICAL);
+ }
+ block->block_contents = temp;
+
+ /* Read the whole block into block_contents to be able to write it to disk
+ * even if it cannot be interpreted. */
+ if(fread(block->block_contents, block->block_contents_size, 1,
+ tng_data->input_file) == 0)
+ {
+ fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ /* FIXME: Does not check if the size of the contents matches the expected
+ * size or if the contents can be read. */
+
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_match_verify(block, &same_hash);
+ if(same_hash != TNG_TRUE)
+ {
+ fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
"%s: %d\n",
__FILE__, __LINE__);
/* return(TNG_FAILURE); */
/** Write a general info block. This is the first block of a TNG file.
* @param tng_data is a trajectory data container.
* @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_general_info_block_write
- (tng_trajectory_t tng_data,
- const char hash_mode)
-{
- int first_program_name_len, first_user_name_len;
- int first_computer_name_len, first_pgp_signature_len;
- int last_program_name_len, last_user_name_len;
- int last_computer_name_len, last_pgp_signature_len;
- int forcefield_name_len, name_len;
- int offset = 0;
- tng_gen_block_t block;
-
- if(tng_output_file_init(tng_data) != TNG_SUCCESS)
- {
- return(TNG_CRITICAL);
- }
-
- fseek(tng_data->output_file, 0, SEEK_SET);
-
- /* If the strings are unallocated allocate memory for just string
- * termination */
- if(!tng_data->first_program_name)
- {
- tng_data->first_program_name = malloc(1);
- if(!tng_data->first_program_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->first_program_name[0] = 0;
- }
- if(!tng_data->last_program_name)
- {
- tng_data->last_program_name = malloc(1);
- if(!tng_data->last_program_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->last_program_name[0] = 0;
- }
- if(!tng_data->first_user_name)
- {
- tng_data->first_user_name = malloc(1);
- if(!tng_data->first_user_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->first_user_name[0] = 0;
- }
- if(!tng_data->last_user_name)
- {
- tng_data->last_user_name = malloc(1);
- if(!tng_data->last_user_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->last_user_name[0] = 0;
- }
- if(!tng_data->first_computer_name)
- {
- tng_data->first_computer_name = malloc(1);
- if(!tng_data->first_computer_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->first_computer_name[0] = 0;
- }
- if(!tng_data->last_computer_name)
- {
- tng_data->last_computer_name = malloc(1);
- if(!tng_data->last_computer_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->last_computer_name[0] = 0;
- }
- if(!tng_data->first_pgp_signature)
- {
- tng_data->first_pgp_signature = malloc(1);
- if(!tng_data->first_pgp_signature)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->first_pgp_signature[0] = 0;
- }
- if(!tng_data->last_pgp_signature)
- {
- tng_data->last_pgp_signature = malloc(1);
- if(!tng_data->last_pgp_signature)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->last_pgp_signature[0] = 0;
- }
- if(!tng_data->forcefield_name)
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_general_info_block_write
+ (tng_trajectory_t tng_data,
+ const char hash_mode)
+{
+ int first_program_name_len, first_user_name_len;
+ int first_computer_name_len, first_pgp_signature_len;
+ int last_program_name_len, last_user_name_len;
+ int last_computer_name_len, last_pgp_signature_len;
+ int forcefield_name_len, name_len;
+ int offset = 0;
+ tng_gen_block_t block;
+
+ if(tng_output_file_init(tng_data) != TNG_SUCCESS)
{
- tng_data->forcefield_name = malloc(1);
- if(!tng_data->forcefield_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- tng_data->forcefield_name[0] = 0;
+ return(TNG_CRITICAL);
}
+ fseek(tng_data->output_file, 0, SEEK_SET);
+
tng_block_init(&block);
name_len = (int)strlen("GENERAL INFO");
strcpy(block->name, "GENERAL INFO");
block->id = TNG_GENERAL_INFO;
+ if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
+ TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
+ }
+
first_program_name_len = tng_min_i((int)strlen(tng_data->first_program_name) + 1,
TNG_MAX_STR_LEN);
last_program_name_len = tng_min_i((int)strlen(tng_data->last_program_name) + 1,
forcefield_name_len = tng_min_i((int)strlen(tng_data->forcefield_name) + 1,
TNG_MAX_STR_LEN);
- block->block_contents_size = sizeof(tng_data->time) +
- sizeof(tng_data->var_num_atoms_flag) +
- sizeof(tng_data->frame_set_n_frames) +
- sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
- sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
- sizeof(tng_data->medium_stride_length) +
- sizeof(tng_data->long_stride_length) +
- sizeof(tng_data->distance_unit_exponential) +
- first_program_name_len +
- last_program_name_len +
- first_user_name_len +
- last_user_name_len +
- first_computer_name_len +
- last_computer_name_len +
- first_pgp_signature_len +
- last_pgp_signature_len +
- forcefield_name_len;
-
if(block->block_contents)
{
free(block->block_contents);
offset += sizeof(tng_data->frame_set_n_frames);
memcpy(block->block_contents+offset,
- &tng_data->first_trajectory_frame_set_input_file_pos,
- sizeof(tng_data->first_trajectory_frame_set_input_file_pos));
+ &tng_data->first_trajectory_frame_set_output_file_pos,
+ sizeof(tng_data->first_trajectory_frame_set_output_file_pos));
if(tng_data->output_endianness_swap_func_64)
{
if(tng_data->output_endianness_swap_func_64(tng_data,
__FILE__, __LINE__);
}
}
- offset += sizeof(tng_data->first_trajectory_frame_set_input_file_pos);
+ offset += sizeof(tng_data->first_trajectory_frame_set_output_file_pos);
memcpy(block->block_contents+offset,
- &tng_data->last_trajectory_frame_set_input_file_pos,
- sizeof(tng_data->last_trajectory_frame_set_input_file_pos));
+ &tng_data->last_trajectory_frame_set_output_file_pos,
+ sizeof(tng_data->last_trajectory_frame_set_output_file_pos));
if(tng_data->output_endianness_swap_func_64)
{
if(tng_data->output_endianness_swap_func_64(tng_data,
__FILE__, __LINE__);
}
}
- offset += sizeof(tng_data->last_trajectory_frame_set_input_file_pos);
+ offset += sizeof(tng_data->last_trajectory_frame_set_output_file_pos);
memcpy(block->block_contents+offset, &tng_data->medium_stride_length,
sizeof(tng_data->medium_stride_length));
return(TNG_SUCCESS);
}
+static tng_function_status tng_molecules_block_len_calculate
+ (const tng_trajectory_t tng_data,
+ int64_t *len)
+{
+ int64_t i, j;
+ tng_molecule_t molecule;
+ tng_chain_t chain;
+ tng_residue_t residue;
+ tng_atom_t atom;
+ tng_bond_t bond;
+
+ *len = 0;
+
+ for(i = 0; i < tng_data->n_molecules; i++)
+ {
+ molecule = &tng_data->molecules[i];
+ if(!molecule->name)
+ {
+ molecule->name = malloc(1);
+ if(!molecule->name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ molecule->name[0] = 0;
+ }
+ *len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
+
+ chain = molecule->chains;
+ for(j = 0; j < molecule->n_chains; j++)
+ {
+ *len += sizeof(chain->id);
+
+ if(!chain->name)
+ {
+ chain->name = malloc(1);
+ if(!chain->name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ chain->name[0] = 0;
+ }
+ *len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
+
+ *len += sizeof(chain->n_residues);
+
+ chain++;
+ }
+
+ residue = molecule->residues;
+ for(j = 0; j < molecule->n_residues; j++)
+ {
+ *len += sizeof(residue->id);
+
+ if(!residue->name)
+ {
+ residue->name = malloc(1);
+ if(!residue->name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ residue->name[0] = 0;
+ }
+ *len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
+
+ *len += sizeof(residue->n_atoms);
+
+ residue++;
+ }
+
+ atom = molecule->atoms;
+ for(j = 0; j < molecule->n_atoms; j++)
+ {
+ *len += sizeof(atom->id);
+ if(!atom->name)
+ {
+ atom->name = malloc(1);
+ if(!atom->name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ atom->name[0] = 0;
+ }
+ *len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
+
+ if(!atom->atom_type)
+ {
+ atom->atom_type = malloc(1);
+ if(!atom->atom_type)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ atom->atom_type[0] = 0;
+ }
+ *len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
+
+ atom++;
+ }
+
+ for(j = 0; j < molecule->n_bonds; j++)
+ {
+ *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
+ }
+ }
+ *len += sizeof(tng_data->n_molecules) +
+ (sizeof(molecule->id) +
+ sizeof(molecule->quaternary_str) +
+ sizeof(molecule->n_chains) +
+ sizeof(molecule->n_residues) +
+ sizeof(molecule->n_atoms) +
+ sizeof(molecule->n_bonds)) *
+ tng_data->n_molecules;
+
+ if(!tng_data->var_num_atoms_flag)
+ {
+ *len += tng_data->n_molecules * sizeof(int64_t);
+ }
+
+ return(TNG_SUCCESS);
+}
+
/** Read a molecules block. Contains chain, residue and atom data
* @param tng_data is a trajectory data container.
* @param block is a general block container.
if(tng_data->molecules)
{
- for(i=tng_data->n_molecules; i--;)
+ for(i=0; i<tng_data->n_molecules; i++)
{
tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
}
if(molecule->n_chains > 0)
{
/* Read the chains of the molecule */
- for(j=molecule->n_chains; j--;)
+ for(j=0; j<molecule->n_chains; j++)
{
chain->molecule = molecule;
residue = chain->residues;
/* Read the residues of the chain */
- for(k=chain->n_residues; k--;)
+ for(k=0; k<chain->n_residues; k++)
{
residue->chain = chain;
residue->atoms_offset = atom - molecule->atoms;
/* Read the atoms of the residue */
- for(l=residue->n_atoms; l--;)
+ for(l=0; l<residue->n_atoms; l++)
{
atom->residue = residue;
{
if(molecule->n_residues > 0)
{
- for(k=molecule->n_residues; k--;)
+ for(k=0; k<molecule->n_residues; k++)
{
residue->chain = 0;
residue->atoms_offset = atom - molecule->atoms;
/* Read the atoms of the residue */
- for(l=residue->n_atoms; l--;)
+ for(l=0; l<residue->n_atoms; l++)
{
atom->residue = residue;
}
else
{
- for(l=molecule->n_atoms; l--;)
+ for(l=0; l<molecule->n_atoms; l++)
{
atom->residue = 0;
bond = molecule->bonds;
- for(j=molecule->n_bonds; j--;)
+ for(j=0; j<molecule->n_bonds; j++)
{
memcpy(&bond->from_atom_id, block->block_contents+offset,
sizeof(bond->from_atom_id));
return(TNG_CRITICAL);
}
- /* First predict the size of the block */
- for(i = 0; i < tng_data->n_molecules; i++)
- {
- molecule = &tng_data->molecules[i];
- if(!molecule->name)
- {
- molecule->name = malloc(1);
- if(!molecule->name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- molecule->name[0] = 0;
- }
- len += tng_min_i((int)strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
-
- chain = molecule->chains;
- for(j = molecule->n_chains; j--;)
- {
- len += sizeof(chain->id);
-
- if(!chain->name)
- {
- chain->name = malloc(1);
- if(!chain->name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- chain->name[0] = 0;
- }
- len += tng_min_i((int)strlen(chain->name) + 1, TNG_MAX_STR_LEN);
-
- len += sizeof(chain->n_residues);
-
- chain++;
- }
-
- residue = molecule->residues;
- for(j = molecule->n_residues; j--;)
- {
- len += sizeof(residue->id);
-
- if(!residue->name)
- {
- residue->name = malloc(1);
- if(!residue->name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- residue->name[0] = 0;
- }
- len += tng_min_i((int)strlen(residue->name) + 1, TNG_MAX_STR_LEN);
-
- len += sizeof(residue->n_atoms);
-
- residue++;
- }
-
- atom = molecule->atoms;
- for(j = molecule->n_atoms; j--;)
- {
- len += sizeof(atom->id);
- if(!atom->name)
- {
- atom->name = malloc(1);
- if(!atom->name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- atom->name[0] = 0;
- }
- len += tng_min_i((int)strlen(atom->name) + 1, TNG_MAX_STR_LEN);
-
- if(!atom->atom_type)
- {
- atom->atom_type = malloc(1);
- if(!atom->atom_type)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- atom->atom_type[0] = 0;
- }
- len += tng_min_i((int)strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
-
- atom++;
- }
-
- for(j = molecule->n_bonds; j--;)
- {
- len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
- }
- }
-
tng_block_init(&block);
name_len = (int)strlen("MOLECULES");
strcpy(block->name, "MOLECULES");
block->id = TNG_MOLECULES;
- block->block_contents_size = sizeof(tng_data->n_molecules) +
- (sizeof(molecule->id) +
- sizeof(molecule->quaternary_str) +
- sizeof(molecule->n_chains) +
- sizeof(molecule->n_residues) +
- sizeof(molecule->n_atoms) +
- sizeof(molecule->n_bonds)) *
- tng_data->n_molecules +
- len;
-
- if(!tng_data->var_num_atoms_flag)
+ if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
+ TNG_SUCCESS)
{
- block->block_contents_size += tng_data->n_molecules * sizeof(int64_t);
+ fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
+ __FILE__, __LINE__);
+ tng_block_destroy(&block);
+ return(TNG_CRITICAL);
}
block->block_contents = malloc(block->block_contents_size);
if(molecule->n_chains > 0)
{
chain = molecule->chains;
- for(j = molecule->n_chains; j--;)
+ for(j = 0; j < molecule->n_chains; j++)
{
tng_chain_data_write(tng_data, block, chain, &offset);
residue = chain->residues;
- for(k = chain->n_residues; k--;)
+ for(k = 0; k < chain->n_residues; k++)
{
tng_residue_data_write(tng_data, block, residue, &offset);
atom = molecule->atoms + residue->atoms_offset;
- for(l = residue->n_atoms; l--;)
+ for(l = 0; l < residue->n_atoms; l++)
{
tng_atom_data_write(tng_data, block, atom, &offset);
if(molecule->n_residues > 0)
{
residue = molecule->residues;
- for(k = molecule->n_residues; k--;)
+ for(k = 0; k < molecule->n_residues; k++)
{
tng_residue_data_write(tng_data, block, residue, &offset);
atom = molecule->atoms + residue->atoms_offset;
- for(l = residue->n_atoms; l--;)
+ for(l = 0; l < residue->n_atoms; l++)
{
tng_atom_data_write(tng_data, block, atom, &offset);
else
{
atom = molecule->atoms;
- for(l = molecule->n_atoms; l--;)
+ for(l = 0; l < molecule->n_atoms; l++)
{
tng_atom_data_write(tng_data, block, atom, &offset);
offset += sizeof(molecule->n_bonds);
bond = molecule->bonds;
- for(j = molecule->n_bonds; j--;)
+ for(j = 0; j < molecule->n_bonds; j++)
{
memcpy(block->block_contents+offset, &bond->from_atom_id,
sizeof(bond->from_atom_id));
return(TNG_SUCCESS);
}
+static tng_function_status tng_frame_set_block_len_calculate
+ (const tng_trajectory_t tng_data,
+ int64_t *len)
+{
+ *len = sizeof(int64_t) * 8;
+ *len += sizeof(double) * 2;
+
+ if(tng_data->var_num_atoms_flag)
+ {
+ *len += sizeof(int64_t) * tng_data->n_molecules;
+ }
+ return(TNG_SUCCESS);
+}
+
/** Read a frame set block. Update tng_data->current_trajectory_frame_set
* @param tng_data is a trajectory data container.
* @param block is a general block container.
tng_data->time_per_frame = -1;
}
- frame_set->n_written_frames = frame_set->n_frames;
+ /* If the output file and the input files are the same the number of
+ * frames in the file are the same number as has just been read.
+ * This is updated here to later on see if there have been new frames
+ * added and thereby the frame set needs to be rewritten. */
+ if(tng_data->output_file == tng_data->input_file)
+ {
+ frame_set->n_written_frames = frame_set->n_frames;
+ }
return(TNG_SUCCESS);
}
strcpy(block->name, "TRAJECTORY FRAME SET");
block->id = TNG_TRAJECTORY_FRAME_SET;
- block->block_contents_size = sizeof(int64_t) * 8;
- block->block_contents_size += sizeof(double) * 2;
-
- if(tng_data->var_num_atoms_flag)
+ if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
+ TNG_SUCCESS)
{
- block->block_contents_size += sizeof(int64_t) * tng_data->n_molecules;
+ fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
if(block->block_contents)
return(TNG_SUCCESS);
}
+static tng_function_status tng_trajectory_mapping_block_len_calculate
+ (const tng_trajectory_t tng_data,
+ const int64_t n_particles,
+ int64_t *len)
+{
+ (void)tng_data;
+ *len = sizeof(int64_t) * (2 + n_particles);
+
+ return(TNG_SUCCESS);
+}
/** Read an atom mappings block (translating between real atom indexes and how
* the atom info is written in this frame set).
strcpy(block->name, "PARTICLE MAPPING");
block->id = TNG_PARTICLE_MAPPING;
- block->block_contents_size = sizeof(int64_t) * (2 + mapping->n_particles);
+ if(tng_trajectory_mapping_block_len_calculate(tng_data,
+ mapping->n_particles,
+ &block->block_contents_size) !=
+ TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
if(block->block_contents)
{
temp = realloc(block->block_contents, block->block_contents_size);
if(!temp)
{
- free(block->block_contents);
- free(dest);
- block->block_contents = 0;
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- block->block_contents = temp;
-
- memcpy(temp + offset, dest, max_len);
-
- free(dest);
-
- return(TNG_SUCCESS);
-}
-
-static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- void *start_pos,
- unsigned long uncompressed_len)
-{
- Bytef *dest;
- char *temp;
- unsigned long stat;
- int offset;
- (void)tng_data;
-
- offset = (char *)start_pos - (char *)block->block_contents;
-
- dest = malloc(uncompressed_len);
- if(!dest)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
- uncompressed_len, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
- block->block_contents_size - offset);
-
- if(stat != Z_OK)
- {
- free(dest);
- if(stat == (unsigned long)Z_MEM_ERROR)
- {
- fprintf(stderr, "TNG library: Not enough memory. ");
- }
- else if(stat == (unsigned long)Z_BUF_ERROR)
- {
- fprintf(stderr, "TNG library: Destination buffer too small. ");
- }
- else if(stat == (unsigned long)Z_DATA_ERROR)
- {
- fprintf(stderr, "TNG library: Data corrupt. ");
- }
- fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
- __LINE__);
- return(TNG_FAILURE);
- }
-
-
- block->block_contents_size = uncompressed_len + offset;
-
- temp = realloc(block->block_contents, uncompressed_len + offset);
- if(!temp)
- {
- free(block->block_contents);
- block->block_contents = 0;
- free(dest);
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- memcpy(temp + offset, dest, uncompressed_len);
-
- block->block_contents = temp;
-
- free(dest);
- return(TNG_SUCCESS);
-}
-#endif
-
-/** Allocate memory for storing particle data.
- * The allocated block will be refered to by data->values.
- * @param tng_data is a trajectory data container.
- * @param data is the data struct, which will contain the allocated memory in
- * data->values.
- * @param n_frames is the number of frames of data to store.
- * @param n_particles is the number of particles with data.
- * @param n_values_per_frame is the number of data values per particle and
- * frame.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_allocate_particle_data_mem
- (tng_trajectory_t tng_data,
- tng_particle_data_t data,
- int64_t n_frames,
- int64_t stride_length,
- const int64_t n_particles,
- const int64_t n_values_per_frame)
-{
- void ***values;
- int64_t i, j, k, size, frame_alloc;
- (void)tng_data;
-
- if(n_particles == 0 || n_values_per_frame == 0)
- {
- return(TNG_FAILURE);
- }
-
- if(data->strings && data->datatype == TNG_CHAR_DATA)
- {
- for(i = data->n_frames; i--;)
- {
- for(j = n_particles; j--;)
- {
- for(k = data->n_values_per_frame; k--;)
- {
- if(data->strings[i][j][k])
- {
- free(data->strings[i][j][k]);
- }
- }
- free(data->strings[i][j]);
- }
- free(data->strings[i]);
- }
- free(data->strings);
- }
- data->n_frames = n_frames;
- n_frames = tng_max_i64(1, n_frames);
- data->stride_length = tng_max_i64(1, stride_length);
- data->n_values_per_frame = n_values_per_frame;
- frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
-
- if(data->datatype == TNG_CHAR_DATA)
- {
- data->strings = malloc(sizeof(char ***) * frame_alloc);
- for(i = frame_alloc; i-- ;)
- {
- data->strings[i] = malloc(sizeof(char **) *
- n_particles);
- if(!data->strings[i])
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- sizeof(union data_values *) * n_particles,
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- for(j = n_particles; j--;)
- {
- data->strings[i][j] = malloc(sizeof(char *) *
- n_values_per_frame);
- if(!data->strings[i][j])
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- sizeof(union data_values) * n_values_per_frame,
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- for(k = n_values_per_frame; k--;)
- {
- data->strings[i][j][k] = 0;
- }
- }
- }
- }
- else
- {
- switch(data->datatype)
- {
- case TNG_INT_DATA:
- size = sizeof(int64_t);
- break;
- case TNG_FLOAT_DATA:
- size = sizeof(float);
- break;
- case TNG_DOUBLE_DATA:
- default:
- size = sizeof(double);
- }
-
- values = realloc(data->values,
- size * frame_alloc *
- n_particles * n_values_per_frame);
- if(!values)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- size * frame_alloc *
- n_particles * n_values_per_frame,
- __FILE__, __LINE__);
- free(data->values);
- data->values = 0;
- return(TNG_CRITICAL);
- }
- data->values = values;
- }
- return(TNG_SUCCESS);
-}
-
-static tng_function_status tng_particle_data_find
- (tng_trajectory_t tng_data,
- const int64_t id,
- tng_particle_data_t *data)
-{
- int64_t block_index, i;
- tng_trajectory_frame_set_t frame_set = &tng_data->
- current_trajectory_frame_set;
- char block_type_flag;
-
- if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
- tng_data->current_trajectory_frame_set_output_file_pos > 0)
- {
- block_type_flag = TNG_TRAJECTORY_BLOCK;
- }
- else
- {
- block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
- }
-
- block_index = -1;
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
- {
- for(i = frame_set->n_particle_data_blocks; i-- ;)
- {
- *data = &frame_set->tr_particle_data[i];
- if((*data)->block_id == id)
- {
- block_index = i;
- break;
- }
- }
- }
- else
- {
- for(i = tng_data->n_particle_data_blocks; i-- ;)
- {
- *data = &tng_data->non_tr_particle_data[i];
- if((*data)->block_id == id)
- {
- block_index = i;
- break;
- }
- }
- }
- if(block_index == -1)
- {
- return(TNG_FAILURE);
+ free(block->block_contents);
+ free(dest);
+ block->block_contents = 0;
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+
+ block->block_contents = temp;
+
+ memcpy(temp + offset, dest, max_len);
+
+ free(dest);
+
return(TNG_SUCCESS);
}
-static tng_function_status tng_data_find
- (tng_trajectory_t tng_data,
- const int64_t id,
- tng_non_particle_data_t *data)
+static tng_function_status tng_gzip_uncompress(tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ void *start_pos,
+ unsigned long uncompressed_len)
{
- int64_t block_index, i;
- tng_trajectory_frame_set_t frame_set = &tng_data->
- current_trajectory_frame_set;
- char block_type_flag;
+ Bytef *dest;
+ char *temp;
+ unsigned long stat;
+ int offset;
+ (void)tng_data;
- if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
- tng_data->current_trajectory_frame_set_output_file_pos > 0)
- {
- block_type_flag = TNG_TRAJECTORY_BLOCK;
- }
- else
+ offset = (char *)start_pos - (char *)block->block_contents;
+
+ dest = malloc(uncompressed_len);
+ if(!dest)
{
- block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+ fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n",
+ uncompressed_len, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- block_index = -1;
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ stat = uncompress(dest, &uncompressed_len, (Bytef *) start_pos,
+ block->block_contents_size - offset);
+
+ if(stat != Z_OK)
{
- for(i = frame_set->n_data_blocks; i-- ;)
+ free(dest);
+ if(stat == (unsigned long)Z_MEM_ERROR)
{
- *data = &frame_set->tr_data[i];
- if((*data)->block_id == id)
- {
- block_index = i;
- break;
- }
+ fprintf(stderr, "TNG library: Not enough memory. ");
}
- if(block_index == -1)
+ else if(stat == (unsigned long)Z_BUF_ERROR)
{
- for(i = tng_data->n_data_blocks; i-- ;)
- {
- *data = &tng_data->non_tr_data[i];
- if((*data)->block_id == id)
- {
- block_index = i;
- break;
- }
- }
+ fprintf(stderr, "TNG library: Destination buffer too small. ");
}
- }
- else
- {
- for(i = tng_data->n_data_blocks; i-- ;)
+ else if(stat == (unsigned long)Z_DATA_ERROR)
{
- *data = &tng_data->non_tr_data[i];
- if((*data)->block_id == id)
- {
- block_index = i;
- break;
- }
+ fprintf(stderr, "TNG library: Data corrupt. ");
}
+ fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
+ __LINE__);
+ return(TNG_FAILURE);
}
- if(block_index == -1)
+
+
+ block->block_contents_size = uncompressed_len + offset;
+
+ temp = realloc(block->block_contents, uncompressed_len + offset);
+ if(!temp)
{
- return(TNG_FAILURE);
+ free(block->block_contents);
+ block->block_contents = 0;
+ free(dest);
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+
+ memcpy(temp + offset, dest, uncompressed_len);
+
+ block->block_contents = temp;
+
+ free(dest);
return(TNG_SUCCESS);
}
+#endif
-/** Read the values of a particle data block
+/** Allocate memory for storing particle data.
+ * The allocated block will be refered to by data->values.
* @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param offset is the reading offset to point at the place where the actual
- * values are stored, starting from the beginning of the block_contents. The
- * offset is changed during the reading.
- * @param datatype is the type of data of the data block (char, int, float or
- * double).
- * @param num_first_particle is the number of the first particle in the data
- * block. This should be the same as in the corresponding particle mapping
- * block.
- * @param n_particles is the number of particles in the data block. This should
- * be the same as in the corresponding particle mapping block.
- * @param first_frame_with_data is the frame number of the first frame with data
- * in this data block.
- * @param stride_length is the number of frames between each data entry.
- * @param n_frames is the number of frames in this data block.
- * @param n_values is the number of values per particle and frame stored in this
- * data block.
- * @param codec_id is the ID of the codec to compress the data.
- * @param multiplier is the multiplication factor applied to each data value
- * before compression. This factor is applied since some compression algorithms
- * work only on integers.
+ * @param data is the data struct, which will contain the allocated memory in
+ * data->values.
+ * @param n_frames is the number of frames of data to store.
+ * @param n_particles is the number of particles with data.
+ * @param n_values_per_frame is the number of data values per particle and
+ * frame.
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_particle_data_read
+static tng_function_status tng_allocate_particle_data_mem
(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- int *offset,
- const char datatype,
- const int64_t num_first_particle,
- const int64_t n_particles,
- const int64_t first_frame_with_data,
- const int64_t stride_length,
+ tng_particle_data_t data,
int64_t n_frames,
- const int64_t n_values,
- const int64_t codec_id,
- const double multiplier)
+ int64_t stride_length,
+ const int64_t n_particles,
+ const int64_t n_values_per_frame)
{
- int64_t i, j, k, tot_n_particles, n_frames_div;
- int size, len;
- unsigned long data_size;
- char ***first_dim_values, **second_dim_values;
- tng_particle_data_t data;
- tng_trajectory_frame_set_t frame_set =
- &tng_data->current_trajectory_frame_set;
- char block_type_flag;
-
- TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+ void ***values;
+ int64_t i, j, k, size, frame_alloc;
+ (void)tng_data;
- switch(datatype)
+ if(n_particles == 0 || n_values_per_frame == 0)
{
- case TNG_CHAR_DATA:
- size = 1;
- break;
- case TNG_INT_DATA:
- size = sizeof(int64_t);
- break;
- case TNG_FLOAT_DATA:
- size = sizeof(float);
- break;
- case TNG_DOUBLE_DATA:
- default:
- size = sizeof(double);
+ return(TNG_FAILURE);
}
- /* If the block does not exist, create it */
- if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+ if(data->strings && data->datatype == TNG_CHAR_DATA)
{
- if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
- {
- block_type_flag = TNG_TRAJECTORY_BLOCK;
- }
- else
- {
- block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
- }
-
- if(tng_particle_data_block_create(tng_data, block_type_flag) !=
- TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
- {
- data = &frame_set->tr_particle_data[frame_set->
- n_particle_data_blocks - 1];
- }
- else
- {
- data = &tng_data->non_tr_particle_data[tng_data->
- n_particle_data_blocks - 1];
- }
- data->block_id = block->id;
-
- data->block_name = malloc(strlen(block->name) + 1);
- if(!data->block_name)
+ for(i = 0; i < data->n_frames; i++)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
- (int)strlen(block->name)+1, __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ for(j = 0; j < n_particles; j++)
+ {
+ for(k = 0; k < data->n_values_per_frame; k++)
+ {
+ if(data->strings[i][j][k])
+ {
+ free(data->strings[i][j][k]);
+ }
+ }
+ free(data->strings[i][j]);
+ }
+ free(data->strings[i]);
}
- strcpy(data->block_name, block->name);
-
- data->datatype = datatype;
-
- data->values = 0;
- /* FIXME: Memory leak from strings. */
- data->strings = 0;
- data->n_frames = 0;
- data->codec_id = codec_id;
- data->compression_multiplier = multiplier;
- data->last_retrieved_frame = -1;
- }
-
- if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
- tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
- tng_data->var_num_atoms_flag)
- {
- tot_n_particles = frame_set->n_particles;
- }
- else
- {
- tot_n_particles = tng_data->n_particles;
+ free(data->strings);
}
+ data->n_frames = n_frames;
+ n_frames = tng_max_i64(1, n_frames);
+ data->stride_length = tng_max_i64(1, stride_length);
+ data->n_values_per_frame = n_values_per_frame;
+ frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
- n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
-
- if(codec_id != TNG_UNCOMPRESSED)
+ if(data->datatype == TNG_CHAR_DATA)
{
- data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
- switch(codec_id)
+ data->strings = malloc(sizeof(char ***) * frame_alloc);
+ for(i = 0; i < frame_alloc; i++)
{
- case TNG_XTC_COMPRESSION:
- fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
- break;
- case TNG_TNG_COMPRESSION:
-/* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
- if(tng_uncompress(tng_data, block, datatype,
- block->block_contents + *offset,
- data_size) != TNG_SUCCESS)
+ data->strings[i] = malloc(sizeof(char **) *
+ n_particles);
+ if(!data->strings[i])
{
- fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
- __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ sizeof(union data_values *) * n_particles,
+ __FILE__, __LINE__);
return(TNG_CRITICAL);
}
-/* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
- break;
-#ifdef USE_ZLIB
- case TNG_GZIP_COMPRESSION:
-/* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
- if(tng_gzip_uncompress(tng_data, block,
- block->block_contents + *offset,
- data_size) != TNG_SUCCESS)
+ for(j = 0; j < n_particles; j++)
{
- fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
- __LINE__);
- return(TNG_CRITICAL);
+ data->strings[i][j] = malloc(sizeof(char *) *
+ n_values_per_frame);
+ if(!data->strings[i][j])
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ sizeof(union data_values) * n_values_per_frame,
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ for(k = 0; k < n_values_per_frame; k++)
+ {
+ data->strings[i][j][k] = 0;
+ }
}
-/* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
- break;
-#endif
}
}
- /* Allocate memory */
- if(!data->values || data->n_frames != n_frames ||
- data->n_values_per_frame != n_values)
+ else
{
- if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
- stride_length,
- tot_n_particles, n_values) !=
- TNG_SUCCESS)
+ switch(data->datatype)
{
- fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
+ }
+
+ values = realloc(data->values,
+ size * frame_alloc *
+ n_particles * n_values_per_frame);
+ if(!values)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ size * frame_alloc *
+ n_particles * n_values_per_frame,
__FILE__, __LINE__);
+ free(data->values);
+ data->values = 0;
return(TNG_CRITICAL);
}
+ data->values = values;
}
+ return(TNG_SUCCESS);
+}
- data->first_frame_with_data = first_frame_with_data;
+static tng_function_status tng_particle_data_find
+ (tng_trajectory_t tng_data,
+ const int64_t id,
+ tng_particle_data_t *data)
+{
+ int64_t block_index, i;
+ tng_trajectory_frame_set_t frame_set = &tng_data->
+ current_trajectory_frame_set;
+ char block_type_flag;
- if(datatype == TNG_CHAR_DATA)
+ if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
+ tng_data->current_trajectory_frame_set_output_file_pos > 0)
{
- for(i = 0; i < n_frames_div; i++)
+ block_type_flag = TNG_TRAJECTORY_BLOCK;
+ }
+ else
+ {
+ block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+ }
+
+ block_index = -1;
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ {
+ for(i = 0; i < frame_set->n_particle_data_blocks; i++)
{
- first_dim_values = data->strings[i];
- for(j = num_first_particle; j < num_first_particle + n_particles;
- j++)
+ *data = &frame_set->tr_particle_data[i];
+ if((*data)->block_id == id)
{
- second_dim_values = first_dim_values[j];
- for(k = 0; k < n_values; k++)
- {
- len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
- TNG_MAX_STR_LEN);
- if(second_dim_values[k])
- {
- free(second_dim_values[k]);
- }
- second_dim_values[k] = malloc(len);
- if(!second_dim_values[k])
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
- len, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- strncpy(second_dim_values[k],
- block->block_contents+*offset, len);
- *offset += len;
- }
+ block_index = i;
+ break;
}
}
}
else
{
- memcpy((char *)data->values + n_frames_div * size * n_values *
- num_first_particle,
- block->block_contents + *offset,
- block->block_contents_size - *offset);
- switch(datatype)
+ for(i = 0; i < tng_data->n_particle_data_blocks; i++)
{
- case TNG_FLOAT_DATA:
- if(tng_data->input_endianness_swap_func_32)
- {
- for(i = 0; i < (block->block_contents_size - *offset); i+=size)
- {
- if(tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)((char *)data->values + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- }
- break;
- case TNG_INT_DATA:
- case TNG_DOUBLE_DATA:
- if(tng_data->input_endianness_swap_func_64)
+ *data = &tng_data->non_tr_particle_data[i];
+ if((*data)->block_id == id)
{
- for(i = 0; i < (block->block_contents_size - *offset); i+=size)
- {
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)((char *)data->values + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
+ block_index = i;
+ break;
}
- break;
- case TNG_CHAR_DATA:
- break;
}
}
+ if(block_index == -1)
+ {
+ return(TNG_FAILURE);
+ }
return(TNG_SUCCESS);
}
-/** Write a particle data block
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param block_index is the index number of the data block in the frame set.
- * @param mapping is the particle mapping that is relevant for the data block.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_particle_data_block_write
+static tng_function_status tng_data_find
(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- const int64_t block_index,
- const tng_particle_mapping_t mapping,
- const char hash_mode)
+ const int64_t id,
+ tng_non_particle_data_t *data)
{
- int64_t n_particles, num_first_particle, n_frames, stride_length;
- int64_t frame_step, data_start_pos;
- int64_t i, j, k;
- int size;
- size_t len, offset = 0;
- char dependency, temp, *temp_name;
- double multiplier;
- char ***first_dim_values, **second_dim_values;
- tng_trajectory_frame_set_t frame_set;
- tng_function_status stat;
-
- tng_particle_data_t data;
+ int64_t block_index, i;
+ tng_trajectory_frame_set_t frame_set = &tng_data->
+ current_trajectory_frame_set;
char block_type_flag;
- frame_set = &tng_data->current_trajectory_frame_set;
-
- /* If we have already started writing frame sets it is too late to write
- * non-trajectory data blocks */
- if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
+ if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
+ tng_data->current_trajectory_frame_set_output_file_pos > 0)
{
block_type_flag = TNG_TRAJECTORY_BLOCK;
}
block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
}
- if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+ block_index = -1;
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- return(TNG_CRITICAL);
+ for(i = 0; i < frame_set->n_data_blocks; i++)
+ {
+ *data = &frame_set->tr_data[i];
+ if((*data)->block_id == id)
+ {
+ block_index = i;
+ break;
+ }
+ }
+ if(block_index == -1)
+ {
+ for(i = 0; i < tng_data->n_data_blocks; i++)
+ {
+ *data = &tng_data->non_tr_data[i];
+ if((*data)->block_id == id)
+ {
+ block_index = i;
+ break;
+ }
+ }
+ }
}
-
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ else
{
- data = &frame_set->tr_particle_data[block_index];
-
- /* If this data block has not had any data added in this frame set
- * do not write it. */
- if(data->first_frame_with_data < frame_set->first_frame)
+ for(i = 0; i < tng_data->n_data_blocks; i++)
{
- return(TNG_SUCCESS);
+ *data = &tng_data->non_tr_data[i];
+ if((*data)->block_id == id)
+ {
+ block_index = i;
+ break;
+ }
}
-
- stride_length = tng_max_i64(1, data->stride_length);
}
- else
+ if(block_index == -1)
{
- data = &tng_data->non_tr_particle_data[block_index];
- stride_length = 1;
+ return(TNG_FAILURE);
+ }
+ return(TNG_SUCCESS);
+}
+
+static tng_function_status tng_data_block_len_calculate
+ (const tng_trajectory_t tng_data,
+ const tng_particle_data_t data,
+ const tng_bool is_particle_data,
+ const int64_t n_frames,
+ const int64_t frame_step,
+ const int64_t stride_length,
+ const int64_t num_first_particle,
+ const int64_t n_particles,
+ const char dependency,
+ int64_t *data_start_pos,
+ int64_t *len)
+{
+ int size;
+ int64_t i, j, k;
+ char ***first_dim_values, **second_dim_values;
+ (void)tng_data;
+
+ if(data == 0)
+ {
+ return(TNG_SUCCESS);
}
switch(data->datatype)
size = sizeof(double);
}
- len = strlen(data->block_name) + 1;
-
- if(!block->name || strlen(block->name) < len)
- {
- temp_name = realloc(block->name, len);
- if(!temp_name)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
- __FILE__, __LINE__);
- free(block->name);
- block->name = 0;
- return(TNG_CRITICAL);
- }
- block->name = temp_name;
- }
- strncpy(block->name, data->block_name, len);
- block->id = data->block_id;
-
- /* If writing frame independent data data->n_frames is 0, but n_frames
- is used for the loop writing the data (and reserving memory) and needs
- to be at least 1 */
- n_frames = tng_max_i64(1, data->n_frames);
-
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
- {
- /* If the frame set is finished before writing the full number of frames
- make sure the data block is not longer than the frame set. */
- n_frames = tng_min_i64(n_frames, frame_set->n_frames);
-
- n_frames -= (data->first_frame_with_data - frame_set->first_frame);
- }
-
- frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
- n_frames / stride_length;
-
- /* TNG compression will use compression precision to get integers from
- * floating point data. The compression multiplier stores that information
- * to be able to return the precision of the compressed data. */
- if(data->codec_id == TNG_TNG_COMPRESSION)
- {
- data->compression_multiplier = tng_data->compression_precision;
- }
- /* Uncompressed data blocks do not use compression multipliers at all.
- * GZip compression does not need it either. */
- else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
- {
- data->compression_multiplier = 1.0;
- }
-
- if(mapping && mapping->n_particles != 0)
- {
- n_particles = mapping->n_particles;
- num_first_particle = mapping->num_first_particle;
- }
- else
+ *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
+ sizeof(data->codec_id);
+ if(is_particle_data)
{
- num_first_particle = 0;
- if(tng_data->var_num_atoms_flag)
- {
- n_particles = frame_set->n_particles;
- }
- else
- {
- n_particles = tng_data->n_particles;
- }
+ *len += sizeof(num_first_particle) + sizeof(n_particles);
}
- block->block_contents_size = sizeof(char) * 2 +
- sizeof(data->n_values_per_frame) +
- sizeof(data->codec_id) +
- sizeof(num_first_particle) +
- sizeof(n_particles);
-
if(stride_length > 1)
{
- block->block_contents_size += sizeof(data->first_frame_with_data) +
- sizeof(data->stride_length);
+ *len += sizeof(data->first_frame_with_data) +
+ sizeof(data->stride_length);
}
if(data->codec_id != TNG_UNCOMPRESSED)
{
- block->block_contents_size += sizeof(data->compression_multiplier);
+ *len += sizeof(data->compression_multiplier);
}
- if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
- {
- dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
- }
- else
- {
- dependency = TNG_PARTICLE_DEPENDENT;
- }
if(dependency & TNG_FRAME_DEPENDENT)
{
- block->block_contents_size += sizeof(char);
+ *len += sizeof(char);
}
- data_start_pos = block->block_contents_size;
+ *data_start_pos = *len;
if(data->datatype == TNG_CHAR_DATA)
{
- for(i = n_frames; i--;)
+ if(is_particle_data)
{
- first_dim_values = data->strings[i];
- for(j = num_first_particle; j < num_first_particle + n_particles;
- j++)
+ for(i = 0; i < n_frames; i++)
{
- second_dim_values = first_dim_values[j];
- for(k = data->n_values_per_frame; k--;)
+ first_dim_values = data->strings[i];
+ for(j = num_first_particle; j < num_first_particle + n_particles;
+ j++)
{
- block->block_contents_size +=
- strlen(second_dim_values[k]) + 1;
+ second_dim_values = first_dim_values[j];
+ for(k = 0; k < data->n_values_per_frame; k++)
+ {
+ *len += strlen(second_dim_values[k]) + 1;
+ }
}
}
}
- }
- else
- {
- block->block_contents_size += size * frame_step *
- n_particles * data->n_values_per_frame;
- }
-
- if(block->block_contents)
- {
- free(block->block_contents);
- }
- block->block_contents = malloc(block->block_contents_size);
- if(!block->block_contents)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
-
- memcpy(block->block_contents, &data->datatype, sizeof(char));
- offset += sizeof(char);
-
- memcpy(block->block_contents+offset, &dependency, sizeof(char));
- offset += sizeof(char);
-
- if(dependency & TNG_FRAME_DEPENDENT)
- {
- if(stride_length > 1)
- {
- temp = 1;
- }
else
{
- temp = 0;
+ for(i = 0; i < n_frames; i++)
+ {
+ second_dim_values = ((tng_non_particle_data_t)data)->strings[i];
+ for(j = 0; j < data->n_values_per_frame; j++)
+ {
+ *len += strlen(second_dim_values[j]) + 1;
+ }
+ }
}
- memcpy(block->block_contents+offset, &temp, sizeof(char));
- offset += sizeof(char);
}
-
- memcpy(block->block_contents+offset, &data->n_values_per_frame,
- sizeof(data->n_values_per_frame));
- if(tng_data->output_endianness_swap_func_64)
+ else
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ *len += size * frame_step * n_particles * data->n_values_per_frame;
}
- offset += sizeof(data->n_values_per_frame);
- memcpy(block->block_contents+offset, &data->codec_id,
- sizeof(data->codec_id));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- offset += sizeof(data->codec_id);
+ return(TNG_SUCCESS);
+}
- if(data->codec_id != TNG_UNCOMPRESSED)
+/** Read the values of a particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers and the block contents).
+ * @param offset is the reading offset to point at the place where the actual
+ * values are stored, starting from the beginning of the block_contents. The
+ * offset is changed during the reading.
+ * @param datatype is the type of data of the data block (char, int, float or
+ * double).
+ * @param num_first_particle is the number of the first particle in the data
+ * block. This should be the same as in the corresponding particle mapping
+ * block.
+ * @param n_particles is the number of particles in the data block. This should
+ * be the same as in the corresponding particle mapping block.
+ * @param first_frame_with_data is the frame number of the first frame with data
+ * in this data block.
+ * @param stride_length is the number of frames between each data entry.
+ * @param n_frames is the number of frames in this data block.
+ * @param n_values is the number of values per particle and frame stored in this
+ * data block.
+ * @param codec_id is the ID of the codec to compress the data.
+ * @param multiplier is the multiplication factor applied to each data value
+ * before compression. This factor is applied since some compression algorithms
+ * work only on integers.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_particle_data_read
+ (tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ int *offset,
+ const char datatype,
+ const int64_t num_first_particle,
+ const int64_t n_particles,
+ const int64_t first_frame_with_data,
+ const int64_t stride_length,
+ int64_t n_frames,
+ const int64_t n_values,
+ const int64_t codec_id,
+ const double multiplier)
+{
+ int64_t i, j, k, tot_n_particles, n_frames_div;
+ int size, len;
+ unsigned long data_size;
+ char ***first_dim_values, **second_dim_values;
+ tng_particle_data_t data;
+ tng_trajectory_frame_set_t frame_set =
+ &tng_data->current_trajectory_frame_set;
+ char block_type_flag;
+
+ TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+
+ switch(datatype)
{
- memcpy(block->block_contents+offset, &data->compression_multiplier,
- sizeof(data->compression_multiplier));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- offset += sizeof(data->compression_multiplier);
+ case TNG_CHAR_DATA:
+ size = 1;
+ break;
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
}
- if(data->n_frames > 0 && stride_length > 1)
+ /* If the block does not exist, create it */
+ if(tng_particle_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
{
- /* FIXME: first_frame_with_data is not reliably set */
- if(data->first_frame_with_data == 0)
+ if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
{
- data->first_frame_with_data = frame_set->first_frame;
+ block_type_flag = TNG_TRAJECTORY_BLOCK;
}
- memcpy(block->block_contents+offset, &data->first_frame_with_data,
- sizeof(data->first_frame_with_data));
- if(tng_data->output_endianness_swap_func_64)
+ else
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
}
- offset += sizeof(data->first_frame_with_data);
- memcpy(block->block_contents+offset, &stride_length,
- sizeof(stride_length));
- if(tng_data->output_endianness_swap_func_64)
+ if(tng_particle_data_block_create(tng_data, block_type_flag) !=
+ TNG_SUCCESS)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- offset += sizeof(stride_length);
- }
-
-
- memcpy(block->block_contents+offset, &num_first_particle,
- sizeof(num_first_particle));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ data = &frame_set->tr_particle_data[frame_set->
+ n_particle_data_blocks - 1];
}
- }
- offset += sizeof(num_first_particle);
+ else
+ {
+ data = &tng_data->non_tr_particle_data[tng_data->
+ n_particle_data_blocks - 1];
+ }
+ data->block_id = block->id;
- memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
+ data->block_name = malloc(strlen(block->name) + 1);
+ if(!data->block_name)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+ (int)strlen(block->name)+1, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+ strcpy(data->block_name, block->name);
+
+ data->datatype = datatype;
+
+ data->values = 0;
+ /* FIXME: Memory leak from strings. */
+ data->strings = 0;
+ data->n_frames = 0;
+ data->codec_id = codec_id;
+ data->compression_multiplier = multiplier;
+ data->last_retrieved_frame = -1;
}
- offset += sizeof(n_particles);
- if(data->datatype == TNG_CHAR_DATA)
+ if(/*block_type_flag == TNG_TRAJECTORY_BLOCK &&*/
+ tng_data->current_trajectory_frame_set_input_file_pos > 0 &&
+ tng_data->var_num_atoms_flag)
{
- if(data->strings)
- {
- for(i = 0; i < frame_step; i++)
- {
- first_dim_values = data->strings[i];
- for(j = num_first_particle; j < num_first_particle + n_particles;
- j++)
- {
- second_dim_values = first_dim_values[j];
- for(k = 0; k < data->n_values_per_frame; k++)
- {
- len = (unsigned int)strlen(second_dim_values[k]) + 1;
- strncpy(block->block_contents+offset,
- second_dim_values[k], len);
- offset += len;
- }
- }
- }
- }
+ tot_n_particles = frame_set->n_particles;
}
- else if(data->values)
+ else
{
- memcpy(block->block_contents + offset, data->values,
- block->block_contents_size - offset);
+ tot_n_particles = tng_data->n_particles;
+ }
- switch(data->datatype)
+ n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+
+ if(codec_id != TNG_UNCOMPRESSED)
+ {
+ data_size = (unsigned long)(n_frames_div * size * n_particles * n_values);
+ switch(codec_id)
{
- case TNG_FLOAT_DATA:
- if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
- data->codec_id == TNG_TNG_COMPRESSION)
- {
- if(tng_data->input_endianness_swap_func_32)
- {
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- if(tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- }
- }
- else
- {
- multiplier = data->compression_multiplier;
- if(fabs(multiplier - 1.0) > 0.00001 ||
- tng_data->input_endianness_swap_func_32)
- {
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- *(float *)(block->block_contents + i) *= (float)multiplier;
- if(tng_data->input_endianness_swap_func_32 &&
- tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- }
- }
+ case TNG_XTC_COMPRESSION:
+ fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
break;
- case TNG_INT_DATA:
- if(tng_data->input_endianness_swap_func_64)
+ case TNG_TNG_COMPRESSION:
+/* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
+ if(tng_uncompress(tng_data, block, datatype,
+ block->block_contents + *offset,
+ data_size) != TNG_SUCCESS)
{
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
+ fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+/* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
break;
- case TNG_DOUBLE_DATA:
- if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
- data->codec_id == TNG_TNG_COMPRESSION)
+#ifdef USE_ZLIB
+ case TNG_GZIP_COMPRESSION:
+/* fprintf(stderr, "TNG library: Before GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
+ if(tng_gzip_uncompress(tng_data, block,
+ block->block_contents + *offset,
+ data_size) != TNG_SUCCESS)
{
- if(tng_data->input_endianness_swap_func_64)
- {
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- }
+ fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
+ __LINE__);
+ return(TNG_CRITICAL);
}
- else
+/* fprintf(stderr, "TNG library: After GZIP uncompression: %"PRId64"\n", block->block_contents_size);*/
+ break;
+#endif
+ }
+ }
+ /* Allocate memory */
+ if(!data->values || data->n_frames != n_frames ||
+ data->n_values_per_frame != n_values)
+ {
+ if(tng_allocate_particle_data_mem(tng_data, data, n_frames,
+ stride_length,
+ tot_n_particles, n_values) !=
+ TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory for particle data. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ }
+
+ data->first_frame_with_data = first_frame_with_data;
+
+ if(datatype == TNG_CHAR_DATA)
+ {
+ for(i = 0; i < n_frames_div; i++)
+ {
+ first_dim_values = data->strings[i];
+ for(j = num_first_particle; j < num_first_particle + n_particles;
+ j++)
{
- multiplier = data->compression_multiplier;
- if(fabs(multiplier - 1.0) > 0.00001 ||
- tng_data->input_endianness_swap_func_64)
+ second_dim_values = first_dim_values[j];
+ for(k = 0; k < n_values; k++)
{
- for(i = offset; i < block->block_contents_size; i+=size)
+ len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+ TNG_MAX_STR_LEN);
+ if(second_dim_values[k])
{
- *(double *)(block->block_contents + i) *= multiplier;
- if(tng_data->input_endianness_swap_func_64 &&
- tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ free(second_dim_values[k]);
+ }
+ second_dim_values[k] = malloc(len);
+ if(!second_dim_values[k])
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+ len, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+ strncpy(second_dim_values[k],
+ block->block_contents+*offset, len);
+ *offset += len;
}
}
- break;
- case TNG_CHAR_DATA:
- break;
}
}
else
{
- memset(block->block_contents+offset, 0, block->block_contents_size - offset);
- }
-
- frame_set->n_written_frames += frame_set->n_unwritten_frames;
- frame_set->n_unwritten_frames = 0;
-
- if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
- {
- switch(data->codec_id)
+ memcpy((char *)data->values + n_frames_div * size * n_values *
+ num_first_particle,
+ block->block_contents + *offset,
+ block->block_contents_size - *offset);
+ switch(datatype)
{
- case TNG_XTC_COMPRESSION:
- fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
- data->codec_id = TNG_UNCOMPRESSED;
- break;
- case TNG_TNG_COMPRESSION:
- stat = tng_compress(tng_data, block, frame_step,
- n_particles, data->datatype,
- block->block_contents + data_start_pos);
- if(stat != TNG_SUCCESS)
+ case TNG_FLOAT_DATA:
+ if(tng_data->input_endianness_swap_func_32)
{
- fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
- __FILE__, __LINE__);
- if(stat == TNG_CRITICAL)
+ for(i = 0; i < (block->block_contents_size - *offset); i+=size)
{
- return(TNG_CRITICAL);
+ if(tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)((char *)data->values + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
- /* Set the data again, but with no compression (to write only
- * the relevant data) */
- data->codec_id = TNG_UNCOMPRESSED;
- stat = tng_particle_data_block_write(tng_data, block,
- block_index, mapping,
- hash_mode);
- return(stat);
}
break;
-#ifdef USE_ZLIB
- case TNG_GZIP_COMPRESSION:
- /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
- stat = tng_gzip_compress(tng_data, block,
- block->block_contents + data_start_pos,
- block->block_contents_size - data_start_pos);
- if(stat != TNG_SUCCESS)
+ case TNG_INT_DATA:
+ case TNG_DOUBLE_DATA:
+ if(tng_data->input_endianness_swap_func_64)
{
- fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
- __LINE__);
- if(stat == TNG_CRITICAL)
+ for(i = 0; i < (block->block_contents_size - *offset); i+=size)
{
- return(TNG_CRITICAL);
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)((char *)data->values + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
- /* Set the data again, but with no compression (to write only
- * the relevant data) */
- data->codec_id = TNG_UNCOMPRESSED;
- stat = tng_particle_data_block_write(tng_data, block,
- block_index, mapping,
- hash_mode);
- return(stat);
}
- /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
break;
-#endif
+ case TNG_CHAR_DATA:
+ break;
}
}
-
- if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
- tng_data->output_file_path, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- if(fwrite(block->block_contents, block->block_contents_size, 1,
- tng_data->output_file) != 1)
- {
- fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
- __LINE__);
- return(TNG_CRITICAL);
- }
-
return(TNG_SUCCESS);
}
-/* TEST: */
-/** Create a non-particle data block
+/** Write a particle data block
* @param tng_data is a trajectory data container.
- * @param block_type_flag specifies if this is a trajectory block or a
- * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
+ * @param block is the block to store the data (should already contain
+ * the block headers and the block contents).
+ * @param block_index is the index number of the data block in the frame set.
+ * @param mapping is the particle mapping that is relevant for the data block.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_data_block_create
+static tng_function_status tng_particle_data_block_write
(tng_trajectory_t tng_data,
- const char block_type_flag)
+ tng_gen_block_t block,
+ const int64_t block_index,
+ const tng_particle_mapping_t mapping,
+ const char hash_mode)
{
- tng_trajectory_frame_set_t frame_set =
- &tng_data->current_trajectory_frame_set;
+ int64_t n_particles, num_first_particle, n_frames, stride_length;
+ int64_t frame_step, data_start_pos;
+ int64_t i, j, k;
+ int size;
+ size_t len, offset = 0;
+ char dependency, temp, *temp_name;
+ double multiplier;
+ char ***first_dim_values, **second_dim_values;
+ tng_trajectory_frame_set_t frame_set;
+ tng_function_status stat;
- tng_non_particle_data_t data;
+ tng_particle_data_t data;
+ char block_type_flag;
+
+ frame_set = &tng_data->current_trajectory_frame_set;
+
+ /* If we have already started writing frame sets it is too late to write
+ * non-trajectory data blocks */
+ if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
+ {
+ block_type_flag = TNG_TRAJECTORY_BLOCK;
+ }
+ else
+ {
+ block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+ }
+
+ if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- frame_set->n_data_blocks++;
- data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
- frame_set->n_data_blocks);
- if(!data)
+ data = &frame_set->tr_particle_data[block_index];
+
+ /* If this data block has not had any data added in this frame set
+ * do not write it. */
+ if(data->first_frame_with_data < frame_set->first_frame)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
- sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
- __FILE__, __LINE__);
- free(frame_set->tr_data);
- frame_set->tr_data = 0;
- return(TNG_CRITICAL);
+ return(TNG_SUCCESS);
}
- frame_set->tr_data = data;
+
+ stride_length = tng_max_i64(1, data->stride_length);
}
else
{
- tng_data->n_data_blocks++;
- data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
- tng_data->n_data_blocks);
- if(!data)
+ data = &tng_data->non_tr_particle_data[block_index];
+ stride_length = 1;
+ }
+
+ switch(data->datatype)
+ {
+ case TNG_CHAR_DATA:
+ size = 1;
+ break;
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
+ }
+
+ len = strlen(data->block_name) + 1;
+
+ if(!block->name || strlen(block->name) < len)
+ {
+ temp_name = realloc(block->name, len);
+ if(!temp_name)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
- sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
- __FILE__, __LINE__);
- free(tng_data->non_tr_data);
- tng_data->non_tr_data = 0;
+ fprintf(stderr, "TNG library: Cannot allocate memory (%lud bytes). %s: %d\n", len,
+ __FILE__, __LINE__);
+ free(block->name);
+ block->name = 0;
return(TNG_CRITICAL);
}
- tng_data->non_tr_data = data;
+ block->name = temp_name;
}
+ strncpy(block->name, data->block_name, len);
+ block->id = data->block_id;
- return(TNG_SUCCESS);
-}
+ /* If writing frame independent data data->n_frames is 0, but n_frames
+ is used for the loop writing the data (and reserving memory) and needs
+ to be at least 1 */
+ n_frames = tng_max_i64(1, data->n_frames);
-/* TEST: */
-/** Allocate memory for storing non-particle data.
- * The allocated block will be refered to by data->values.
- * @param tng_data is a trajectory data container.
- * @param data is the data struct, which will contain the allocated memory in
- * data->values.
- * @param n_frames is the number of frames of data to store.
- * @param n_values_per_frame is the number of data values per frame.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_allocate_data_mem
- (tng_trajectory_t tng_data,
- tng_non_particle_data_t data,
- int64_t n_frames,
- int64_t stride_length,
- const int64_t n_values_per_frame)
-{
- void **values;
- int64_t i, j, size, frame_alloc;
- (void)tng_data;
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ {
+ /* If the frame set is finished before writing the full number of frames
+ make sure the data block is not longer than the frame set. */
+ n_frames = tng_min_i64(n_frames, frame_set->n_frames);
+
+ n_frames -= (data->first_frame_with_data - frame_set->first_frame);
+ }
+
+ frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
+ n_frames / stride_length;
- if(n_values_per_frame == 0)
+ /* TNG compression will use compression precision to get integers from
+ * floating point data. The compression multiplier stores that information
+ * to be able to return the precision of the compressed data. */
+ if(data->codec_id == TNG_TNG_COMPRESSION)
{
- return(TNG_FAILURE);
+ data->compression_multiplier = tng_data->compression_precision;
}
-
- if(data->strings && data->datatype == TNG_CHAR_DATA)
+ /* Uncompressed data blocks do not use compression multipliers at all.
+ * GZip compression does not need it either. */
+ else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
{
- for(i = data->n_frames; i--;)
- {
- for(j = data->n_values_per_frame; j--;)
- {
- if(data->strings[i][j])
- {
- free(data->strings[i][j]);
- data->strings[i][j] = 0;
- }
- }
- free(data->strings[i]);
- data->strings[i] = 0;
- }
- free(data->strings);
+ data->compression_multiplier = 1.0;
}
- data->n_frames = n_frames;
- data->stride_length = tng_max_i64(1, stride_length);
- n_frames = tng_max_i64(1, n_frames);
- data->n_values_per_frame = n_values_per_frame;
- frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
- if(data->datatype == TNG_CHAR_DATA)
+ if(mapping && mapping->n_particles != 0)
{
- data->strings = malloc(sizeof(char **) * frame_alloc);
- for(i = frame_alloc; i-- ;)
- {
- data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
- if(!data->strings[i])
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- n_values_per_frame,
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
- for(j = n_values_per_frame; j--;)
- {
- data->strings[i][j] = 0;
- }
- }
+ n_particles = mapping->n_particles;
+ num_first_particle = mapping->num_first_particle;
}
else
{
- switch(data->datatype)
+ num_first_particle = 0;
+ if(tng_data->var_num_atoms_flag)
{
- case TNG_INT_DATA:
- size = sizeof(int64_t);
- break;
- case TNG_FLOAT_DATA:
- size = sizeof(float);
- break;
- case TNG_DOUBLE_DATA:
- default:
- size = sizeof(double);
+ n_particles = frame_set->n_particles;
}
-
- values = realloc(data->values,
- size * frame_alloc *
- n_values_per_frame);
- if(!values)
+ else
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- size * frame_alloc *
- n_values_per_frame,
- __FILE__, __LINE__);
- free(data->values);
- data->values = 0;
- return(TNG_CRITICAL);
+ n_particles = tng_data->n_particles;
}
- data->values = values;
}
- return(TNG_SUCCESS);
-}
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+ {
+ dependency = TNG_FRAME_DEPENDENT + TNG_PARTICLE_DEPENDENT;
+ }
+ else
+ {
+ dependency = TNG_PARTICLE_DEPENDENT;
+ }
-/** Read the values of a non-particle data block
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param offset is the reading offset to point at the place where the actual
- * values are stored, starting from the beginning of the block_contents. The
- * offset is changed during the reading.
- * @param datatype is the type of data of the data block (char, int, float or
- * double).
- * @param first_frame_with_data is the frame number of the first frame with data
- * in this data block.
- * @param stride_length is the number of frames between each data entry.
- * @param n_frames is the number of frames in this data block.
- * @param n_values is the number of values per frame stored in this data block.
- * @param codec_id is the ID of the codec to compress the data.
- * @param multiplier is the multiplication factor applied to each data value
- * before compression. This factor is applied since some compression algorithms
- * work only on integers.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_data_read(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- int *offset,
- const char datatype,
- const int64_t first_frame_with_data,
- const int64_t stride_length,
- int64_t n_frames,
- const int64_t n_values,
- const int64_t codec_id,
- const double multiplier)
-{
- int64_t i, j, n_frames_div;
- int size, len;
-#ifdef USE_ZLIB
- unsigned long data_size;
-#endif
- tng_non_particle_data_t data;
- tng_trajectory_frame_set_t frame_set =
- &tng_data->current_trajectory_frame_set;
- char block_type_flag;
+ if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
+ frame_step, stride_length, num_first_particle,
+ n_particles, dependency, &data_start_pos,
+ &block->block_contents_size) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
+ if(block->block_contents)
+ {
+ free(block->block_contents);
+ }
+ block->block_contents = malloc(block->block_contents_size);
+ if(!block->block_contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
-/* fprintf(stderr, "TNG library: %s\n", block->name);*/
- switch(datatype)
+ memcpy(block->block_contents, &data->datatype, sizeof(char));
+ offset += sizeof(char);
+
+ memcpy(block->block_contents+offset, &dependency, sizeof(char));
+ offset += sizeof(char);
+
+ if(dependency & TNG_FRAME_DEPENDENT)
{
- case TNG_CHAR_DATA:
- size = 1;
- break;
- case TNG_INT_DATA:
- size = sizeof(int64_t);
- break;
- case TNG_FLOAT_DATA:
- size = sizeof(float);
- break;
- case TNG_DOUBLE_DATA:
- default:
- size = sizeof(double);
+ if(stride_length > 1)
+ {
+ temp = 1;
+ }
+ else
+ {
+ temp = 0;
+ }
+ memcpy(block->block_contents+offset, &temp, sizeof(char));
+ offset += sizeof(char);
}
- /* If the block does not exist, create it */
- if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
+ memcpy(block->block_contents+offset, &data->n_values_per_frame,
+ sizeof(data->n_values_per_frame));
+ if(tng_data->output_endianness_swap_func_64)
{
- if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
- block_type_flag = TNG_TRAJECTORY_BLOCK;
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
- else
+ }
+ offset += sizeof(data->n_values_per_frame);
+
+ memcpy(block->block_contents+offset, &data->codec_id,
+ sizeof(data->codec_id));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
- block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
+ }
+ offset += sizeof(data->codec_id);
- if(tng_data_block_create(tng_data, block_type_flag) !=
- TNG_SUCCESS)
+ if(data->codec_id != TNG_UNCOMPRESSED)
+ {
+ memcpy(block->block_contents+offset, &data->compression_multiplier,
+ sizeof(data->compression_multiplier));
+ if(tng_data->output_endianness_swap_func_64)
{
- fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ offset += sizeof(data->compression_multiplier);
+ }
+
+ if(data->n_frames > 0 && stride_length > 1)
+ {
+ /* FIXME: first_frame_with_data is not reliably set */
+ if(data->first_frame_with_data == 0)
{
- data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
+ data->first_frame_with_data = frame_set->first_frame;
}
- else
+ memcpy(block->block_contents+offset, &data->first_frame_with_data,
+ sizeof(data->first_frame_with_data));
+ if(tng_data->output_endianness_swap_func_64)
{
- data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
- data->block_id = block->id;
+ offset += sizeof(data->first_frame_with_data);
- data->block_name = malloc(strlen(block->name) + 1);
- if(!data->block_name)
+ memcpy(block->block_contents+offset, &stride_length,
+ sizeof(stride_length));
+ if(tng_data->output_endianness_swap_func_64)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
- (int)strlen(block->name)+1, __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
- strcpy(data->block_name, block->name);
-
- data->datatype = datatype;
-
- data->values = 0;
- /* FIXME: Memory leak from strings. */
- data->strings = 0;
- data->n_frames = 0;
- data->codec_id = codec_id;
- data->compression_multiplier = multiplier;
- data->last_retrieved_frame = -1;
+ offset += sizeof(stride_length);
}
- n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
- if(codec_id != TNG_UNCOMPRESSED)
+ memcpy(block->block_contents+offset, &num_first_particle,
+ sizeof(num_first_particle));
+ if(tng_data->output_endianness_swap_func_64)
{
- switch(codec_id)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
-#ifdef USE_ZLIB
- case TNG_GZIP_COMPRESSION:
- data_size = n_frames_div * size * n_values;
- /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
- if(tng_gzip_uncompress(tng_data, block,
- block->block_contents + *offset,
- data_size) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
- __LINE__);
- return(TNG_CRITICAL);
- }
- /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
- break;
-#endif
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
}
+ offset += sizeof(num_first_particle);
- /* Allocate memory */
- if(!data->values || data->n_frames != n_frames ||
- data->n_values_per_frame != n_values)
+ memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles));
+ if(tng_data->output_endianness_swap_func_64)
{
- if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
- n_values) !=
- TNG_SUCCESS)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
- fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
}
+ offset += sizeof(n_particles);
- data->first_frame_with_data = first_frame_with_data;
-
- if(datatype == TNG_CHAR_DATA)
+ if(data->datatype == TNG_CHAR_DATA)
{
- for(i = 0; i < n_frames_div; i++)
+ if(data->strings)
{
- for(j = 0; j < n_values; j++)
+ for(i = 0; i < frame_step; i++)
{
- len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
- TNG_MAX_STR_LEN);
- if(data->strings[i][j])
- {
- free(data->strings[i][j]);
- }
- data->strings[i][j] = malloc(len);
- if(!data->strings[i][j])
+ first_dim_values = data->strings[i];
+ for(j = num_first_particle; j < num_first_particle + n_particles;
+ j++)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
- len, __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ second_dim_values = first_dim_values[j];
+ for(k = 0; k < data->n_values_per_frame; k++)
+ {
+ len = (unsigned int)strlen(second_dim_values[k]) + 1;
+ strncpy(block->block_contents+offset,
+ second_dim_values[k], len);
+ offset += len;
+ }
}
- strncpy(data->strings[i][j], block->block_contents+*offset,
- len);
- *offset += len;
}
}
}
- else
+ else if(data->values)
{
- memcpy(data->values, block->block_contents + *offset,
- block->block_contents_size - *offset);
- switch(datatype)
+ memcpy(block->block_contents + offset, data->values,
+ block->block_contents_size - offset);
+
+ switch(data->datatype)
{
case TNG_FLOAT_DATA:
- if(tng_data->input_endianness_swap_func_32)
+ if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+ data->codec_id == TNG_TNG_COMPRESSION)
{
- for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+ if(tng_data->input_endianness_swap_func_32)
{
- if(tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)((char *)data->values + i))
- != TNG_SUCCESS)
+ for(i = offset; i < block->block_contents_size; i+=size)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ if(tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ else
+ {
+ multiplier = data->compression_multiplier;
+ if(fabs(multiplier - 1.0) > 0.00001 ||
+ tng_data->input_endianness_swap_func_32)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ *(float *)(block->block_contents + i) *= (float)multiplier;
+ if(tng_data->input_endianness_swap_func_32 &&
+ tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
}
}
break;
case TNG_INT_DATA:
- case TNG_DOUBLE_DATA:
if(tng_data->input_endianness_swap_func_64)
{
- for(i = 0; i < (block->block_contents_size - *offset); i+=size)
+ for(i = offset; i < block->block_contents_size; i+=size)
{
if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)((char *)data->values + i))
- != TNG_SUCCESS)
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
break;
+ case TNG_DOUBLE_DATA:
+ if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+ data->codec_id == TNG_TNG_COMPRESSION)
+ {
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ else
+ {
+ multiplier = data->compression_multiplier;
+ if(fabs(multiplier - 1.0) > 0.00001 ||
+ tng_data->input_endianness_swap_func_64)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ *(double *)(block->block_contents + i) *= multiplier;
+ if(tng_data->input_endianness_swap_func_64 &&
+ tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ break;
case TNG_CHAR_DATA:
break;
}
}
+ else
+ {
+ memset(block->block_contents+offset, 0, block->block_contents_size - offset);
+ }
+
+ frame_set->n_written_frames += frame_set->n_unwritten_frames;
+ frame_set->n_unwritten_frames = 0;
+
+ if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
+ {
+ switch(data->codec_id)
+ {
+ case TNG_XTC_COMPRESSION:
+ fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
+ data->codec_id = TNG_UNCOMPRESSED;
+ break;
+ case TNG_TNG_COMPRESSION:
+ stat = tng_compress(tng_data, block, frame_step,
+ n_particles, data->datatype,
+ block->block_contents + data_start_pos);
+ if(stat != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
+ __FILE__, __LINE__);
+ if(stat == TNG_CRITICAL)
+ {
+ return(TNG_CRITICAL);
+ }
+ /* Set the data again, but with no compression (to write only
+ * the relevant data) */
+ data->codec_id = TNG_UNCOMPRESSED;
+ stat = tng_particle_data_block_write(tng_data, block,
+ block_index, mapping,
+ hash_mode);
+ return(stat);
+ }
+ break;
+#ifdef USE_ZLIB
+ case TNG_GZIP_COMPRESSION:
+ /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size);*/
+ stat = tng_gzip_compress(tng_data, block,
+ block->block_contents + data_start_pos,
+ block->block_contents_size - data_start_pos);
+ if(stat != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
+ __LINE__);
+ if(stat == TNG_CRITICAL)
+ {
+ return(TNG_CRITICAL);
+ }
+ /* Set the data again, but with no compression (to write only
+ * the relevant data) */
+ data->codec_id = TNG_UNCOMPRESSED;
+ stat = tng_particle_data_block_write(tng_data, block,
+ block_index, mapping,
+ hash_mode);
+ return(stat);
+ }
+ /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size);*/
+ break;
+#endif
+ }
+ }
+
+ if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+ tng_data->output_file_path, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+
+ if(fwrite(block->block_contents, block->block_contents_size, 1,
+ tng_data->output_file) != 1)
+ {
+ fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
+ __LINE__);
+ return(TNG_CRITICAL);
+ }
+
return(TNG_SUCCESS);
}
-/** Write a non-particle data block
+/* TEST: */
+/** Create a non-particle data block
* @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers and the block contents).
- * @param block_index is the index number of the data block in the frame set.
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @param block_type_flag specifies if this is a trajectory block or a
+ * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- const int64_t block_index,
- const char hash_mode)
+static tng_function_status tng_data_block_create
+ (tng_trajectory_t tng_data,
+ const char block_type_flag)
{
- int64_t n_frames, stride_length, frame_step;
- int64_t i, j;
- int offset = 0, size;
- unsigned int len;
-#ifdef USE_ZLIB
- int data_start_pos;
- tng_function_status stat;
-#endif
- char temp, dependency, *temp_name;
- double multiplier;
tng_trajectory_frame_set_t frame_set =
&tng_data->current_trajectory_frame_set;
tng_non_particle_data_t data;
- char block_type_flag;
-
- /* If we have already started writing frame sets it is too late to write
- * non-trajectory data blocks */
- if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
- {
- block_type_flag = TNG_TRAJECTORY_BLOCK;
- }
- else
- {
- block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
- }
-
- if(tng_output_file_init(tng_data) != TNG_SUCCESS)
- {
- return(TNG_CRITICAL);
- }
if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- data = &frame_set->tr_data[block_index];
-
- /* If this data block has not had any data added in this frame set
- * do not write it. */
- if(data->first_frame_with_data < frame_set->first_frame)
+ frame_set->n_data_blocks++;
+ data = realloc(frame_set->tr_data, sizeof(struct tng_non_particle_data) *
+ frame_set->n_data_blocks);
+ if(!data)
{
- return(TNG_SUCCESS);
+ fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+ sizeof(struct tng_non_particle_data) * frame_set->n_data_blocks,
+ __FILE__, __LINE__);
+ free(frame_set->tr_data);
+ frame_set->tr_data = 0;
+ return(TNG_CRITICAL);
}
-
- stride_length = tng_max_i64(1, data->stride_length);
+ frame_set->tr_data = data;
}
else
{
- data = &tng_data->non_tr_data[block_index];
- stride_length = 1;
- }
-
- switch(data->datatype)
- {
- case TNG_CHAR_DATA:
- size = 1;
- break;
- case TNG_INT_DATA:
- size = sizeof(int64_t);
- break;
- case TNG_FLOAT_DATA:
- size = sizeof(float);
- break;
- case TNG_DOUBLE_DATA:
- default:
- size = sizeof(double);
- }
-
- len = (unsigned int)strlen(data->block_name) + 1;
-
- if(!block->name || strlen(block->name) < len)
- {
- temp_name = realloc(block->name, len);
- if(!temp_name)
+ tng_data->n_data_blocks++;
+ data = realloc(tng_data->non_tr_data, sizeof(struct tng_non_particle_data) *
+ tng_data->n_data_blocks);
+ if(!data)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
- __FILE__, __LINE__);
- free(block->name);
- block->name = 0;
+ fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
+ sizeof(struct tng_non_particle_data) * tng_data->n_data_blocks,
+ __FILE__, __LINE__);
+ free(tng_data->non_tr_data);
+ tng_data->non_tr_data = 0;
return(TNG_CRITICAL);
}
- block->name = temp_name;
- }
- strncpy(block->name, data->block_name, len);
- block->id = data->block_id;
-
- /* If writing frame independent data data->n_frames is 0, but n_frames
- is used for the loop writing the data (and reserving memory) and needs
- to be at least 1 */
- n_frames = tng_max_i64(1, data->n_frames);
-
- if(block_type_flag == TNG_TRAJECTORY_BLOCK)
- {
- /* If the frame set is finished before writing the full number of frames
- make sure the data block is not longer than the frame set. */
- n_frames = tng_min_i64(n_frames, frame_set->n_frames);
-
- n_frames -= (data->first_frame_with_data - frame_set->first_frame);
+ tng_data->non_tr_data = data;
}
- frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
- n_frames / stride_length;
-
- /* TNG compression will use compression precision to get integers from
- * floating point data. The compression multiplier stores that information
- * to be able to return the precision of the compressed data. */
- if(data->codec_id == TNG_TNG_COMPRESSION)
- {
- data->compression_multiplier = tng_data->compression_precision;
- }
- /* Uncompressed data blocks do not use compression multipliers at all.
- * GZip compression does not need it either. */
- else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
- {
- data->compression_multiplier = 1.0;
- }
+ return(TNG_SUCCESS);
+}
- block->block_contents_size = sizeof(char) * 2 +
- sizeof(data->n_values_per_frame) +
- sizeof(data->codec_id);
+/* TEST: */
+/** Allocate memory for storing non-particle data.
+ * The allocated block will be refered to by data->values.
+ * @param tng_data is a trajectory data container.
+ * @param data is the data struct, which will contain the allocated memory in
+ * data->values.
+ * @param n_frames is the number of frames of data to store.
+ * @param n_values_per_frame is the number of data values per frame.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_allocate_data_mem
+ (tng_trajectory_t tng_data,
+ tng_non_particle_data_t data,
+ int64_t n_frames,
+ int64_t stride_length,
+ const int64_t n_values_per_frame)
+{
+ void **values;
+ int64_t i, j, size, frame_alloc;
+ (void)tng_data;
- if(stride_length > 1)
+ if(n_values_per_frame == 0)
{
- block->block_contents_size += sizeof(data->first_frame_with_data) +
- sizeof(data->stride_length);
+ return(TNG_FAILURE);
}
- if(data->codec_id != TNG_UNCOMPRESSED)
+ if(data->strings && data->datatype == TNG_CHAR_DATA)
{
- block->block_contents_size += sizeof(data->compression_multiplier);
+ for(i = 0; i < data->n_frames; i++)
+ {
+ for(j = 0; j < data->n_values_per_frame; j++)
+ {
+ if(data->strings[i][j])
+ {
+ free(data->strings[i][j]);
+ data->strings[i][j] = 0;
+ }
+ }
+ free(data->strings[i]);
+ data->strings[i] = 0;
+ }
+ free(data->strings);
}
+ data->n_frames = n_frames;
+ data->stride_length = tng_max_i64(1, stride_length);
+ n_frames = tng_max_i64(1, n_frames);
+ data->n_values_per_frame = n_values_per_frame;
+ frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
- if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+ if(data->datatype == TNG_CHAR_DATA)
{
- dependency = TNG_FRAME_DEPENDENT;
+ data->strings = malloc(sizeof(char **) * frame_alloc);
+ for(i = 0; i < frame_alloc; i++)
+ {
+ data->strings[i] = malloc(sizeof(char *) * n_values_per_frame);
+ if(!data->strings[i])
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ n_values_per_frame,
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
+ for(j = 0; j < n_values_per_frame; j++)
+ {
+ data->strings[i][j] = 0;
+ }
+ }
}
else
{
- dependency = 0;
- }
- if(dependency & TNG_FRAME_DEPENDENT)
- {
- block->block_contents_size += sizeof(char);
+ switch(data->datatype)
+ {
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
+ }
+
+ values = realloc(data->values,
+ size * frame_alloc *
+ n_values_per_frame);
+ if(!values)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ size * frame_alloc *
+ n_values_per_frame,
+ __FILE__, __LINE__);
+ free(data->values);
+ data->values = 0;
+ return(TNG_CRITICAL);
+ }
+ data->values = values;
}
+ return(TNG_SUCCESS);
+}
+
+/** Read the values of a non-particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers and the block contents).
+ * @param offset is the reading offset to point at the place where the actual
+ * values are stored, starting from the beginning of the block_contents. The
+ * offset is changed during the reading.
+ * @param datatype is the type of data of the data block (char, int, float or
+ * double).
+ * @param first_frame_with_data is the frame number of the first frame with data
+ * in this data block.
+ * @param stride_length is the number of frames between each data entry.
+ * @param n_frames is the number of frames in this data block.
+ * @param n_values is the number of values per frame stored in this data block.
+ * @param codec_id is the ID of the codec to compress the data.
+ * @param multiplier is the multiplication factor applied to each data value
+ * before compression. This factor is applied since some compression algorithms
+ * work only on integers.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_read(tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ int *offset,
+ const char datatype,
+ const int64_t first_frame_with_data,
+ const int64_t stride_length,
+ int64_t n_frames,
+ const int64_t n_values,
+ const int64_t codec_id,
+ const double multiplier)
+{
+ int64_t i, j, n_frames_div;
+ int size, len;
#ifdef USE_ZLIB
- data_start_pos = block->block_contents_size;
+ unsigned long data_size;
#endif
+ tng_non_particle_data_t data;
+ tng_trajectory_frame_set_t frame_set =
+ &tng_data->current_trajectory_frame_set;
+ char block_type_flag;
- if(data->datatype == TNG_CHAR_DATA)
- {
- for(i = n_frames; i--;)
- {
- for(j = data->n_values_per_frame; j--;)
- {
- block->block_contents_size += strlen(data->strings[i][j]) + 1;
- }
- }
- }
- else
- {
- block->block_contents_size += size * frame_step *
- data->n_values_per_frame;
- }
+ TNG_ASSERT(offset != 0, "TNG library: offset must not be a NULL pointer.");
- if(block->block_contents)
- {
- free(block->block_contents);
- }
- block->block_contents = malloc(block->block_contents_size);
- if(!block->block_contents)
+/* fprintf(stderr, "TNG library: %s\n", block->name);*/
+
+ switch(datatype)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ case TNG_CHAR_DATA:
+ size = 1;
+ break;
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
}
-
- memcpy(block->block_contents, &data->datatype, sizeof(char));
- offset += sizeof(char);
-
- memcpy(block->block_contents+offset, &dependency, sizeof(char));
- offset += sizeof(char);
-
- if(dependency & TNG_FRAME_DEPENDENT)
+ /* If the block does not exist, create it */
+ if(tng_data_find(tng_data, block->id, &data) != TNG_SUCCESS)
{
- if(stride_length > 1)
+ if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
{
- temp = 1;
+ block_type_flag = TNG_TRAJECTORY_BLOCK;
}
else
{
- temp = 0;
+ block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
}
- memcpy(block->block_contents+offset, &temp, sizeof(char));
- offset += sizeof(char);
- }
- memcpy(block->block_contents+offset, &data->n_values_per_frame,
- sizeof(data->n_values_per_frame));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
+ if(tng_data_block_create(tng_data, block_type_flag) !=
+ TNG_SUCCESS)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- }
- offset += sizeof(data->n_values_per_frame);
-
- memcpy(block->block_contents+offset, &data->codec_id,
- sizeof(data->codec_id));
- if(tng_data->output_endianness_swap_func_64)
- {
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
}
- }
- offset += sizeof(data->codec_id);
-
- if(data->codec_id != TNG_UNCOMPRESSED)
- {
- memcpy(block->block_contents+offset, &data->compression_multiplier,
- sizeof(data->compression_multiplier));
- if(tng_data->output_endianness_swap_func_64)
+ else
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
}
- offset += sizeof(data->compression_multiplier);
- }
+ data->block_id = block->id;
- if(data->n_frames > 0 && stride_length > 1)
- {
- /* FIXME: first_frame_with_data is not reliably set */
- if(data->first_frame_with_data == 0)
- {
- data->first_frame_with_data = frame_set->first_frame;
- }
- memcpy(block->block_contents+offset, &data->first_frame_with_data,
- sizeof(data->first_frame_with_data));
- if(tng_data->output_endianness_swap_func_64)
+ data->block_name = malloc(strlen(block->name) + 1);
+ if(!data->block_name)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+ (int)strlen(block->name)+1, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- offset += sizeof(data->first_frame_with_data);
+ strcpy(data->block_name, block->name);
- memcpy(block->block_contents+offset, &stride_length,
- sizeof(data->stride_length));
- if(tng_data->output_endianness_swap_func_64)
+ data->datatype = datatype;
+
+ data->values = 0;
+ /* FIXME: Memory leak from strings. */
+ data->strings = 0;
+ data->n_frames = 0;
+ data->codec_id = codec_id;
+ data->compression_multiplier = multiplier;
+ data->last_retrieved_frame = -1;
+ }
+
+ n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
+
+ if(codec_id != TNG_UNCOMPRESSED)
+ {
+ switch(codec_id)
{
- if(tng_data->output_endianness_swap_func_64(tng_data,
- (int64_t *)block->header_contents+offset)
- != TNG_SUCCESS)
+#ifdef USE_ZLIB
+ case TNG_GZIP_COMPRESSION:
+ data_size = n_frames_div * size * n_values;
+ /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+ if(tng_gzip_uncompress(tng_data, block,
+ block->block_contents + *offset,
+ data_size) != TNG_SUCCESS)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
+ __LINE__);
+ return(TNG_CRITICAL);
}
+ /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
+ break;
+#endif
}
- offset += sizeof(data->stride_length);
}
- if(data->datatype == TNG_CHAR_DATA)
+ /* Allocate memory */
+ if(!data->values || data->n_frames != n_frames ||
+ data->n_values_per_frame != n_values)
{
- if(data->strings)
+ if(tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
+ n_values) !=
+ TNG_SUCCESS)
{
- for(i = 0; i < frame_step; i++)
- {
- for(j = 0; j < data->n_values_per_frame; j++)
- {
- len = (unsigned int)strlen(data->strings[i][j]) + 1;
- strncpy(block->block_contents+offset, data->strings[i][j],
- len);
- offset += len;
- }
- }
+ fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
}
- else if(data->values)
+
+ data->first_frame_with_data = first_frame_with_data;
+
+ if(datatype == TNG_CHAR_DATA)
{
- memcpy(block->block_contents + offset, data->values,
- block->block_contents_size - offset);
- switch(data->datatype)
+ for(i = 0; i < n_frames_div; i++)
{
- case TNG_FLOAT_DATA:
- if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
- data->codec_id == TNG_TNG_COMPRESSION)
+ for(j = 0; j < n_values; j++)
{
- if(tng_data->input_endianness_swap_func_32)
+ len = tng_min_i((int)strlen(block->block_contents+*offset) + 1,
+ TNG_MAX_STR_LEN);
+ if(data->strings[i][j])
{
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- if(tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
+ free(data->strings[i][j]);
}
- }
- else
- {
- multiplier = data->compression_multiplier;
- if(fabs(multiplier - 1.0) > 0.00001 ||
- tng_data->input_endianness_swap_func_32)
+ data->strings[i][j] = malloc(len);
+ if(!data->strings[i][j])
{
- for(i = offset; block->block_contents_size; i+=size)
- {
- *(float *)(block->block_contents + i) *= (float)multiplier;
- if(tng_data->input_endianness_swap_func_32 &&
- tng_data->input_endianness_swap_func_32(tng_data,
- (int32_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+ len, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
+ strncpy(data->strings[i][j], block->block_contents+*offset,
+ len);
+ *offset += len;
}
- break;
- case TNG_INT_DATA:
- if(tng_data->input_endianness_swap_func_64)
+ }
+ }
+ else
+ {
+ memcpy(data->values, block->block_contents + *offset,
+ block->block_contents_size - *offset);
+ switch(datatype)
+ {
+ case TNG_FLOAT_DATA:
+ if(tng_data->input_endianness_swap_func_32)
{
- for(i = offset; i < block->block_contents_size; i+=size)
+ for(i = 0; i < (block->block_contents_size - *offset); i+=size)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
- != TNG_SUCCESS)
+ if(tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)((char *)data->values + i))
+ != TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
break;
+ case TNG_INT_DATA:
case TNG_DOUBLE_DATA:
- if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
- data->codec_id == TNG_TNG_COMPRESSION)
- {
- if(tng_data->input_endianness_swap_func_64)
- {
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
- }
- }
- else
+ if(tng_data->input_endianness_swap_func_64)
{
- multiplier = data->compression_multiplier;
- if(fabs(multiplier - 1.0) > 0.00001 ||
- tng_data->input_endianness_swap_func_64)
+ for(i = 0; i < (block->block_contents_size - *offset); i+=size)
{
- for(i = offset; i < block->block_contents_size; i+=size)
- {
- *(double *)(block->block_contents + i) *= multiplier;
- if(tng_data->input_endianness_swap_func_64 &&
- tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *)(block->block_contents + i))
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)((char *)data->values + i))
!= TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
}
}
break;
}
}
+ return(TNG_SUCCESS);
+}
+
+/** Write a non-particle data block
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers and the block contents).
+ * @param block_index is the index number of the data block in the frame set.
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_write(tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ const int64_t block_index,
+ const char hash_mode)
+{
+ int64_t n_frames, stride_length, frame_step, data_start_pos;
+ int64_t i, j;
+ int offset = 0, size;
+ unsigned int len;
+#ifdef USE_ZLIB
+ tng_function_status stat;
+#endif
+ char temp, dependency, *temp_name;
+ double multiplier;
+ tng_trajectory_frame_set_t frame_set =
+ &tng_data->current_trajectory_frame_set;
+
+ tng_non_particle_data_t data;
+ char block_type_flag;
+
+ /* If we have already started writing frame sets it is too late to write
+ * non-trajectory data blocks */
+ if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
+ {
+ block_type_flag = TNG_TRAJECTORY_BLOCK;
+ }
else
{
- memset(block->block_contents+offset, 0, block->block_contents_size - offset);
+ block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
}
- frame_set->n_written_frames += frame_set->n_unwritten_frames;
- frame_set->n_unwritten_frames = 0;
+ if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
- if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
{
- switch(data->codec_id)
+ data = &frame_set->tr_data[block_index];
+
+ /* If this data block has not had any data added in this frame set
+ * do not write it. */
+ if(data->first_frame_with_data < frame_set->first_frame)
{
-#ifdef USE_ZLIB
- case TNG_GZIP_COMPRESSION:
- /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
- stat = tng_gzip_compress(tng_data, block,
- block->block_contents + data_start_pos,
- block->block_contents_size - data_start_pos);
- if(stat != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
- __LINE__);
- if(stat == TNG_CRITICAL)
- {
- return(TNG_CRITICAL);
- }
- data->codec_id = TNG_UNCOMPRESSED;
- }
- /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
- break;
-#endif
+ return(TNG_SUCCESS);
}
+
+ stride_length = tng_max_i64(1, data->stride_length);
+ }
+ else
+ {
+ data = &tng_data->non_tr_data[block_index];
+ stride_length = 1;
}
- if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
+ switch(data->datatype)
{
- fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
- tng_data->output_file_path, __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ case TNG_CHAR_DATA:
+ size = 1;
+ break;
+ case TNG_INT_DATA:
+ size = sizeof(int64_t);
+ break;
+ case TNG_FLOAT_DATA:
+ size = sizeof(float);
+ break;
+ case TNG_DOUBLE_DATA:
+ default:
+ size = sizeof(double);
}
- if(fwrite(block->block_contents, block->block_contents_size, 1,
- tng_data->output_file) != 1)
+ len = (unsigned int)strlen(data->block_name) + 1;
+
+ if(!block->name || strlen(block->name) < len)
{
- fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ temp_name = realloc(block->name, len);
+ if(!temp_name)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len+1,
+ __FILE__, __LINE__);
+ free(block->name);
+ block->name = 0;
+ return(TNG_CRITICAL);
+ }
+ block->name = temp_name;
}
+ strncpy(block->name, data->block_name, len);
+ block->id = data->block_id;
- return(TNG_SUCCESS);
-}
+ /* If writing frame independent data data->n_frames is 0, but n_frames
+ is used for the loop writing the data (and reserving memory) and needs
+ to be at least 1 */
+ n_frames = tng_max_i64(1, data->n_frames);
-/** Read the meta information of a data block (particle or non-particle data).
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers).
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_data_block_meta_information_read
- (tng_trajectory_t tng_data,
- tng_gen_block_t block,
- int *offset,
- char *datatype,
- char *dependency,
- char *sparse_data,
- int64_t *n_values,
- int64_t *codec_id,
- int64_t *first_frame_with_data,
- int64_t *stride_length,
- int64_t *n_frames,
- int64_t *num_first_particle,
- int64_t *block_n_particles,
- double *multiplier)
-{
- int meta_size;
- char *contents;
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK)
+ {
+ /* If the frame set is finished before writing the full number of frames
+ make sure the data block is not longer than the frame set. */
+ n_frames = tng_min_i64(n_frames, frame_set->n_frames);
- if(block->block_contents)
+ n_frames -= (data->first_frame_with_data - frame_set->first_frame);
+ }
+
+ frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
+ n_frames / stride_length;
+
+ /* TNG compression will use compression precision to get integers from
+ * floating point data. The compression multiplier stores that information
+ * to be able to return the precision of the compressed data. */
+ if(data->codec_id == TNG_TNG_COMPRESSION)
{
- contents = block->block_contents;
+ data->compression_multiplier = tng_data->compression_precision;
+ }
+ /* Uncompressed data blocks do not use compression multipliers at all.
+ * GZip compression does not need it either. */
+ else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
+ {
+ data->compression_multiplier = 1.0;
+ }
+
+ if(block_type_flag == TNG_TRAJECTORY_BLOCK && data->n_frames > 0)
+ {
+ dependency = TNG_FRAME_DEPENDENT;
}
else
{
- meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
- contents = malloc(meta_size);
- if(!contents)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
- meta_size, __FILE__, __LINE__);
- }
+ dependency = 0;
+ }
+
+ if(tng_data_block_len_calculate(tng_data, (tng_particle_data_t)data, TNG_FALSE, n_frames,
+ frame_step, stride_length, 0,
+ 1, dependency, &data_start_pos,
+ &block->block_contents_size) != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
+ __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
- {
- fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
- free(contents);
- return(TNG_CRITICAL);
- }
+ if(block->block_contents)
+ {
+ free(block->block_contents);
+ }
+ block->block_contents = malloc(block->block_contents_size);
+ if(!block->block_contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
}
- memcpy(datatype, contents+*offset,
- sizeof(*datatype));
- *offset += sizeof(*datatype);
- memcpy(dependency, contents+*offset,
- sizeof(*dependency));
- *offset += sizeof(*dependency);
+ memcpy(block->block_contents, &data->datatype, sizeof(char));
+ offset += sizeof(char);
- if(*dependency & TNG_FRAME_DEPENDENT)
+ memcpy(block->block_contents+offset, &dependency, sizeof(char));
+ offset += sizeof(char);
+
+ if(dependency & TNG_FRAME_DEPENDENT)
{
- memcpy(sparse_data, contents+*offset,
- sizeof(*sparse_data));
- *offset += sizeof(*sparse_data);
+ if(stride_length > 1)
+ {
+ temp = 1;
+ }
+ else
+ {
+ temp = 0;
+ }
+ memcpy(block->block_contents+offset, &temp, sizeof(char));
+ offset += sizeof(char);
}
- memcpy(n_values, contents+*offset,
- sizeof(*n_values));
- if(tng_data->input_endianness_swap_func_64)
+ memcpy(block->block_contents+offset, &data->n_values_per_frame,
+ sizeof(data->n_values_per_frame));
+ if(tng_data->output_endianness_swap_func_64)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- n_values)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
- *offset += sizeof(*n_values);
+ offset += sizeof(data->n_values_per_frame);
- memcpy(codec_id, contents+*offset,
- sizeof(*codec_id));
- if(tng_data->input_endianness_swap_func_64)
+ memcpy(block->block_contents+offset, &data->codec_id,
+ sizeof(data->codec_id));
+ if(tng_data->output_endianness_swap_func_64)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- codec_id)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
- *offset += sizeof(*codec_id);
+ offset += sizeof(data->codec_id);
- if(*codec_id != TNG_UNCOMPRESSED)
+ if(data->codec_id != TNG_UNCOMPRESSED)
{
- memcpy(multiplier, contents+*offset,
- sizeof(*multiplier));
- if(tng_data->input_endianness_swap_func_64)
+ memcpy(block->block_contents+offset, &data->compression_multiplier,
+ sizeof(data->compression_multiplier));
+ if(tng_data->output_endianness_swap_func_64)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- (int64_t *) multiplier)
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
- *offset += sizeof(*multiplier);
- }
- else
- {
- *multiplier = 1;
+ offset += sizeof(data->compression_multiplier);
}
- if(*dependency & TNG_FRAME_DEPENDENT)
+ if(data->n_frames > 0 && stride_length > 1)
{
- if(*sparse_data)
+ /* FIXME: first_frame_with_data is not reliably set */
+ if(data->first_frame_with_data == 0)
{
- memcpy(first_frame_with_data, contents+*offset,
- sizeof(*first_frame_with_data));
- if(tng_data->input_endianness_swap_func_64)
+ data->first_frame_with_data = frame_set->first_frame;
+ }
+ memcpy(block->block_contents+offset, &data->first_frame_with_data,
+ sizeof(data->first_frame_with_data));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- first_frame_with_data)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
- *offset += sizeof(*first_frame_with_data);
+ }
+ offset += sizeof(data->first_frame_with_data);
- memcpy(stride_length, contents+*offset,
- sizeof(*stride_length));
- if(tng_data->input_endianness_swap_func_64)
+ memcpy(block->block_contents+offset, &stride_length,
+ sizeof(data->stride_length));
+ if(tng_data->output_endianness_swap_func_64)
+ {
+ if(tng_data->output_endianness_swap_func_64(tng_data,
+ (int64_t *)block->header_contents+offset)
+ != TNG_SUCCESS)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- stride_length)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
}
- *offset += sizeof(*stride_length);
- *n_frames = tng_data->current_trajectory_frame_set.n_frames -
- (*first_frame_with_data -
- tng_data->current_trajectory_frame_set.first_frame);
- }
- else
- {
- *first_frame_with_data = 0;
- *stride_length = 1;
- *n_frames = tng_data->current_trajectory_frame_set.n_frames;
}
- }
- else
- {
- *first_frame_with_data = 0;
- *stride_length = 1;
- *n_frames = 1;
+ offset += sizeof(data->stride_length);
}
- if (*dependency & TNG_PARTICLE_DEPENDENT)
+ if(data->datatype == TNG_CHAR_DATA)
{
- memcpy(num_first_particle, contents+*offset,
- sizeof(*num_first_particle));
- if(tng_data->input_endianness_swap_func_64)
+ if(data->strings)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- num_first_particle)
- != TNG_SUCCESS)
+ for(i = 0; i < frame_step; i++)
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ for(j = 0; j < data->n_values_per_frame; j++)
+ {
+ len = (unsigned int)strlen(data->strings[i][j]) + 1;
+ strncpy(block->block_contents+offset, data->strings[i][j],
+ len);
+ offset += len;
+ }
}
}
- *offset += sizeof(*num_first_particle);
-
- memcpy(block_n_particles, contents+*offset,
- sizeof(*block_n_particles));
- if(tng_data->input_endianness_swap_func_64)
+ }
+ else if(data->values)
+ {
+ memcpy(block->block_contents + offset, data->values,
+ block->block_contents_size - offset);
+ switch(data->datatype)
{
- if(tng_data->input_endianness_swap_func_64(tng_data,
- block_n_particles)
- != TNG_SUCCESS)
+ case TNG_FLOAT_DATA:
+ if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+ data->codec_id == TNG_TNG_COMPRESSION)
+ {
+ if(tng_data->input_endianness_swap_func_32)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ if(tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ else
+ {
+ multiplier = data->compression_multiplier;
+ if(fabs(multiplier - 1.0) > 0.00001 ||
+ tng_data->input_endianness_swap_func_32)
+ {
+ for(i = offset; block->block_contents_size; i+=size)
+ {
+ *(float *)(block->block_contents + i) *= (float)multiplier;
+ if(tng_data->input_endianness_swap_func_32 &&
+ tng_data->input_endianness_swap_func_32(tng_data,
+ (int32_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ break;
+ case TNG_INT_DATA:
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ break;
+ case TNG_DOUBLE_DATA:
+ if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
+ data->codec_id == TNG_TNG_COMPRESSION)
+ {
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+ else
{
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
+ multiplier = data->compression_multiplier;
+ if(fabs(multiplier - 1.0) > 0.00001 ||
+ tng_data->input_endianness_swap_func_64)
+ {
+ for(i = offset; i < block->block_contents_size; i+=size)
+ {
+ *(double *)(block->block_contents + i) *= multiplier;
+ if(tng_data->input_endianness_swap_func_64 &&
+ tng_data->input_endianness_swap_func_64(tng_data,
+ (int64_t *)(block->block_contents + i))
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ }
}
+ break;
+ case TNG_CHAR_DATA:
+ break;
}
- *offset += sizeof(*block_n_particles);
- }
-
- if(!block->block_contents)
- {
- free(contents);
- }
- return(TNG_SUCCESS);
-}
-
-/** Read the contents of a data block (particle or non-particle data).
- * @param tng_data is a trajectory data container.
- * @param block is the block to store the data (should already contain
- * the block headers).
- * @param hash_mode is an option to decide whether to use the md5 hash or not.
- * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
- * compared to the md5 hash of the read contents to ensure valid data.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_data_block_contents_read
- (tng_trajectory_t tng_data,
- tng_gen_block_t block,
- const char hash_mode)
-{
- int64_t n_values, codec_id, n_frames, first_frame_with_data;
- int64_t stride_length, block_n_particles, num_first_particle;
- double multiplier;
- char datatype, dependency, sparse_data;
- int offset = 0;
- tng_bool same_hash;
-
- if(tng_input_file_init(tng_data) != TNG_SUCCESS)
- {
- return(TNG_CRITICAL);
- }
-
- if(block->block_contents)
- {
- free(block->block_contents);
- }
-
- block->block_contents = malloc(block->block_contents_size);
- if(!block->block_contents)
- {
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
- return(TNG_CRITICAL);
}
-
- /* Read the whole block into block_contents to be able to write it to
- * disk even if it cannot be interpreted. */
- if(fread(block->block_contents, block->block_contents_size, 1,
- tng_data->input_file) == 0)
+ else
{
- fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ memset(block->block_contents+offset, 0, block->block_contents_size - offset);
}
- /* FIXME: Does not check if the size of the contents matches the expected
- * size or if the contents can be read. */
+ frame_set->n_written_frames += frame_set->n_unwritten_frames;
+ frame_set->n_unwritten_frames = 0;
- if(hash_mode == TNG_USE_HASH)
+ if(block_type_flag == TNG_NON_TRAJECTORY_BLOCK || frame_set->n_written_frames > 0)
{
- tng_md5_hash_match_verify(block, &same_hash);
- if(same_hash != TNG_TRUE)
+ switch(data->codec_id)
{
- fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
- block->name, __FILE__, __LINE__);
- /* return(TNG_FAILURE); */
+#ifdef USE_ZLIB
+ case TNG_GZIP_COMPRESSION:
+ /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
+ stat = tng_gzip_compress(tng_data, block,
+ block->block_contents + data_start_pos,
+ block->block_contents_size - data_start_pos);
+ if(stat != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
+ __LINE__);
+ if(stat == TNG_CRITICAL)
+ {
+ return(TNG_CRITICAL);
+ }
+ data->codec_id = TNG_UNCOMPRESSED;
+ }
+ /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
+ break;
+#endif
}
}
- if(tng_data_block_meta_information_read(tng_data, block,
- &offset, &datatype,
- &dependency, &sparse_data,
- &n_values, &codec_id,
- &first_frame_with_data,
- &stride_length, &n_frames,
- &num_first_particle,
- &block_n_particles,
- &multiplier) == TNG_CRITICAL)
- {
- fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
- block->name, __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- if (dependency & TNG_PARTICLE_DEPENDENT)
- {
- return(tng_particle_data_read(tng_data, block,
- &offset, datatype,
- num_first_particle,
- block_n_particles,
- first_frame_with_data,
- stride_length,
- n_frames, n_values,
- codec_id, multiplier));
- }
- else
- {
- return(tng_data_read(tng_data, block,
- &offset, datatype,
- first_frame_with_data,
- stride_length,
- n_frames, n_values,
- codec_id, multiplier));
- }
-}
-
-/** Update the md5 hash of a block already written to the file
- * @param tng_data is a trajectory data container.
- * @param block is the block, of which to update the md5 hash.
- * @param header_start_pos is the file position where the block header starts.
- * @param contents_start_pos is the file position where the block contents
- * start.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_md5_hash_update(tng_trajectory_t tng_data,
- tng_gen_block_t block,
- const int64_t header_start_pos,
- const int64_t contents_start_pos)
-{
- if(block->block_contents)
- {
- free(block->block_contents);
- }
-
- block->block_contents = malloc(block->block_contents_size);
- if(!block->block_contents)
+ if(tng_block_header_write(tng_data, block, hash_mode) != TNG_SUCCESS)
{
- fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
- block->block_contents_size, __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
+ tng_data->output_file_path, __FILE__, __LINE__);
return(TNG_CRITICAL);
}
- fseek(tng_data->output_file, (long)contents_start_pos, SEEK_SET);
- if(fread(block->block_contents, block->block_contents_size, 1,
- tng_data->output_file) == 0)
+ if(fwrite(block->block_contents, block->block_contents_size, 1,
+ tng_data->output_file) != 1)
{
- fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+ fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
+ __FILE__, __LINE__);
return(TNG_CRITICAL);
}
- tng_block_md5_hash_generate(block);
-
- fseek(tng_data->output_file, (long)header_start_pos + 3 * sizeof(int64_t),
- SEEK_SET);
- fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
-
return(TNG_SUCCESS);
}
-/** Update the frame set pointers in the file header (general info block),
- * already written to disk
+/** Read the meta information of a data block (particle or non-particle data).
* @param tng_data is a trajectory data container.
- * @param hash_mode specifies whether to update the block md5 hash when
- * updating the pointers.
+ * @param block is the block to store the data (should already contain
+ * the block headers).
* @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
* error has occured.
*/
-static tng_function_status tng_header_pointers_update
- (tng_trajectory_t tng_data, const char hash_mode)
+static tng_function_status tng_data_block_meta_information_read
+ (tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ int *offset,
+ char *datatype,
+ char *dependency,
+ char *sparse_data,
+ int64_t *n_values,
+ int64_t *codec_id,
+ int64_t *first_frame_with_data,
+ int64_t *stride_length,
+ int64_t *n_frames,
+ int64_t *num_first_particle,
+ int64_t *block_n_particles,
+ double *multiplier)
{
- tng_gen_block_t block;
- FILE *temp = tng_data->input_file;
- int64_t output_file_pos, pos, contents_start_pos;
+ int meta_size;
+ char *contents;
- if(tng_output_file_init(tng_data) != TNG_SUCCESS)
+ if(block->block_contents)
{
- fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
+ contents = block->block_contents;
}
-
- tng_data->input_file = tng_data->output_file;
-
- tng_block_init(&block);
-
- output_file_pos = ftell(tng_data->output_file);
- fseek(tng_data->output_file, 0, SEEK_SET);
-
- if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
+ else
{
- fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
- __FILE__, __LINE__);
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
+ meta_size = 3 * sizeof(char) + sizeof(double) + 6 * sizeof(int64_t);
+ contents = malloc(meta_size);
+ if(!contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
+ meta_size, __FILE__, __LINE__);
+ }
- contents_start_pos = ftell(tng_data->output_file);
+ if(fread(contents, meta_size, 1, tng_data->input_file) == 0)
+ {
+ fprintf(stderr, "TNG library: Cannot read data block meta information. %s: %d\n", __FILE__, __LINE__);
+ free(contents);
+ return(TNG_CRITICAL);
+ }
+ }
- fseek(tng_data->output_file, (long)block->block_contents_size - 5 *
- sizeof(int64_t), SEEK_CUR);
+ memcpy(datatype, contents+*offset,
+ sizeof(*datatype));
+ *offset += sizeof(*datatype);
- tng_data->input_file = temp;
+ memcpy(dependency, contents+*offset,
+ sizeof(*dependency));
+ *offset += sizeof(*dependency);
- pos = tng_data->first_trajectory_frame_set_output_file_pos;
+ if(*dependency & TNG_FRAME_DEPENDENT)
+ {
+ memcpy(sparse_data, contents+*offset,
+ sizeof(*sparse_data));
+ *offset += sizeof(*sparse_data);
+ }
+ memcpy(n_values, contents+*offset,
+ sizeof(*n_values));
if(tng_data->input_endianness_swap_func_64)
{
if(tng_data->input_endianness_swap_func_64(tng_data,
- &pos)
+ n_values)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
+ *offset += sizeof(*n_values);
- if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
- {
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
-
- pos = tng_data->last_trajectory_frame_set_output_file_pos;
-
+ memcpy(codec_id, contents+*offset,
+ sizeof(*codec_id));
if(tng_data->input_endianness_swap_func_64)
{
if(tng_data->input_endianness_swap_func_64(tng_data,
- &pos)
+ codec_id)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
+ *offset += sizeof(*codec_id);
- if(fwrite(&pos,
- sizeof(int64_t), 1, tng_data->output_file) != 1)
- {
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
-
- if(hash_mode == TNG_USE_HASH)
- {
- tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
- }
-
- tng_block_destroy(&block);
-
- fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
-
- return(TNG_SUCCESS);
-}
-
-/** Update the frame set pointers in the current frame set block, already
- * written to disk. It also updates the pointers of the blocks pointing to
- * the current frame set block.
- * @param tng_data is a trajectory data container.
- * @param hash_mode specifies whether to update the block md5 hash when
- * updating the pointers.
- * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
- * error has occured.
- */
-static tng_function_status tng_frame_set_pointers_update
- (tng_trajectory_t tng_data, const char hash_mode)
-{
- tng_gen_block_t block;
- tng_trajectory_frame_set_t frame_set;
- FILE *temp = tng_data->input_file;
- int64_t pos, output_file_pos, header_start_pos, contents_start_pos;
-
- if(tng_output_file_init(tng_data) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
- __FILE__, __LINE__);
- return(TNG_CRITICAL);
- }
-
- tng_block_init(&block);
- output_file_pos = ftell(tng_data->output_file);
-
- tng_data->input_file = tng_data->output_file;
-
- frame_set = &tng_data->current_trajectory_frame_set;
-
- /* Update previous frame set */
- if(frame_set->prev_frame_set_file_pos != -1 &&
- frame_set->prev_frame_set_file_pos != 0)
+ if(*codec_id != TNG_UNCOMPRESSED)
{
- fseek(tng_data->output_file, (long)frame_set->prev_frame_set_file_pos,
- SEEK_SET);
-
- header_start_pos = frame_set->prev_frame_set_file_pos;
-
- if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
- __FILE__, __LINE__);
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
-
- contents_start_pos = ftell(tng_data->output_file);
-
- fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
- sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
- pos = tng_data->current_trajectory_frame_set_output_file_pos;
-
+ memcpy(multiplier, contents+*offset,
+ sizeof(*multiplier));
if(tng_data->input_endianness_swap_func_64)
{
if(tng_data->input_endianness_swap_func_64(tng_data,
- &pos)
+ (int64_t *) multiplier)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
+ *offset += sizeof(*multiplier);
+ }
+ else
+ {
+ *multiplier = 1;
+ }
- if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
+ if(*dependency & TNG_FRAME_DEPENDENT)
+ {
+ if(*sparse_data)
{
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
+ memcpy(first_frame_with_data, contents+*offset,
+ sizeof(*first_frame_with_data));
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ first_frame_with_data)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ *offset += sizeof(*first_frame_with_data);
- if(hash_mode == TNG_USE_HASH)
+ memcpy(stride_length, contents+*offset,
+ sizeof(*stride_length));
+ if(tng_data->input_endianness_swap_func_64)
+ {
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ stride_length)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
+ }
+ *offset += sizeof(*stride_length);
+ *n_frames = tng_data->current_trajectory_frame_set.n_frames -
+ (*first_frame_with_data -
+ tng_data->current_trajectory_frame_set.first_frame);
+ }
+ else
{
- tng_md5_hash_update(tng_data, block, header_start_pos,
- contents_start_pos);
+ *first_frame_with_data = 0;
+ *stride_length = 1;
+ *n_frames = tng_data->current_trajectory_frame_set.n_frames;
}
- fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
}
-
- /* Update the frame set one medium stride step before */
- if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
- frame_set->medium_stride_prev_frame_set_file_pos != 0)
+ else
{
- fseek(tng_data->output_file,
- (long)frame_set->medium_stride_prev_frame_set_file_pos,
- SEEK_SET);
-
- if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
- __FILE__, __LINE__);
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
-
- contents_start_pos = ftell(tng_data->output_file);
-
- fseek(tng_data->output_file, (long)block->block_contents_size - (4 *
- sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
-
- pos = tng_data->current_trajectory_frame_set_output_file_pos;
+ *first_frame_with_data = 0;
+ *stride_length = 1;
+ *n_frames = 1;
+ }
+ if (*dependency & TNG_PARTICLE_DEPENDENT)
+ {
+ memcpy(num_first_particle, contents+*offset,
+ sizeof(*num_first_particle));
if(tng_data->input_endianness_swap_func_64)
{
if(tng_data->input_endianness_swap_func_64(tng_data,
- &pos)
+ num_first_particle)
!= TNG_SUCCESS)
{
fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
__FILE__, __LINE__);
}
}
+ *offset += sizeof(*num_first_particle);
- if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
- {
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
-
- if(hash_mode == TNG_USE_HASH)
+ memcpy(block_n_particles, contents+*offset,
+ sizeof(*block_n_particles));
+ if(tng_data->input_endianness_swap_func_64)
{
- tng_md5_hash_update(tng_data, block,
- frame_set->medium_stride_prev_frame_set_file_pos,
- contents_start_pos);
+ if(tng_data->input_endianness_swap_func_64(tng_data,
+ block_n_particles)
+ != TNG_SUCCESS)
+ {
+ fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
+ __FILE__, __LINE__);
+ }
}
+ *offset += sizeof(*block_n_particles);
}
- /* Update the frame set one long stride step before */
- if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
- frame_set->long_stride_prev_frame_set_file_pos != 0)
+ if(!block->block_contents)
{
- fseek(tng_data->output_file,
- (long)frame_set->long_stride_prev_frame_set_file_pos,
- SEEK_SET);
+ free(contents);
+ }
+ return(TNG_SUCCESS);
+}
- if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
- __FILE__, __LINE__);
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
+/** Read the contents of a data block (particle or non-particle data).
+ * @param tng_data is a trajectory data container.
+ * @param block is the block to store the data (should already contain
+ * the block headers).
+ * @param hash_mode is an option to decide whether to use the md5 hash or not.
+ * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
+ * compared to the md5 hash of the read contents to ensure valid data.
+ * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
+ * error has occured.
+ */
+static tng_function_status tng_data_block_contents_read
+ (tng_trajectory_t tng_data,
+ tng_gen_block_t block,
+ const char hash_mode)
+{
+ int64_t n_values, codec_id, n_frames, first_frame_with_data;
+ int64_t stride_length, block_n_particles, num_first_particle;
+ double multiplier;
+ char datatype, dependency, sparse_data;
+ int offset = 0;
+ tng_bool same_hash;
- contents_start_pos = ftell(tng_data->output_file);
+ if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
- fseek(tng_data->output_file, (long)block->block_contents_size - (2 *
- sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
+ if(block->block_contents)
+ {
+ free(block->block_contents);
+ }
- pos = tng_data->current_trajectory_frame_set_output_file_pos;
+ block->block_contents = malloc(block->block_contents_size);
+ if(!block->block_contents)
+ {
+ fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
+ block->block_contents_size, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- if(tng_data->input_endianness_swap_func_64)
- {
- if(tng_data->input_endianness_swap_func_64(tng_data,
- &pos)
- != TNG_SUCCESS)
- {
- fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
- __FILE__, __LINE__);
- }
- }
+ /* Read the whole block into block_contents to be able to write it to
+ * disk even if it cannot be interpreted. */
+ if(fread(block->block_contents, block->block_contents_size, 1,
+ tng_data->input_file) == 0)
+ {
+ fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
- {
- tng_data->input_file = temp;
- tng_block_destroy(&block);
- return(TNG_CRITICAL);
- }
+ /* FIXME: Does not check if the size of the contents matches the expected
+ * size or if the contents can be read. */
- if(hash_mode == TNG_USE_HASH)
+ if(hash_mode == TNG_USE_HASH)
+ {
+ tng_md5_hash_match_verify(block, &same_hash);
+ if(same_hash != TNG_TRUE)
{
- tng_md5_hash_update(tng_data, block,
- frame_set->long_stride_prev_frame_set_file_pos,
- contents_start_pos);
+ fprintf(stderr, "TNG library: '%s' data block contents corrupt. Hashes do not match. %s: %d\n",
+ block->name, __FILE__, __LINE__);
+ /* return(TNG_FAILURE); */
}
}
- fseek(tng_data->output_file, (long)output_file_pos, SEEK_SET);
-
- tng_data->input_file = temp;
-
- tng_block_destroy(&block);
+ if(tng_data_block_meta_information_read(tng_data, block,
+ &offset, &datatype,
+ &dependency, &sparse_data,
+ &n_values, &codec_id,
+ &first_frame_with_data,
+ &stride_length, &n_frames,
+ &num_first_particle,
+ &block_n_particles,
+ &multiplier) == TNG_CRITICAL)
+ {
+ fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
+ block->name, __FILE__, __LINE__);
+ return(TNG_CRITICAL);
+ }
- return(TNG_SUCCESS);
+ if (dependency & TNG_PARTICLE_DEPENDENT)
+ {
+ return(tng_particle_data_read(tng_data, block,
+ &offset, datatype,
+ num_first_particle,
+ block_n_particles,
+ first_frame_with_data,
+ stride_length,
+ n_frames, n_values,
+ codec_id, multiplier));
+ }
+ else
+ {
+ return(tng_data_read(tng_data, block,
+ &offset, datatype,
+ first_frame_with_data,
+ stride_length,
+ n_frames, n_values,
+ codec_id, multiplier));
+ }
}
+
/*
// ** Move the blocks in a frame set so that there is no unused space between
// * them. This can only be done on the last frame set in the file and should
const char *name,
tng_molecule_t *molecule)
{
- int64_t id, i;
- tng_bool found_id = TNG_TRUE;
+ int64_t id;
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
- /* Find an unused ID */
- id = 0;
- while(found_id)
+ /* Set ID to the ID of the last molecule + 1 */
+ if(tng_data->n_molecules)
{
- found_id = TNG_FALSE;
- for(i = tng_data->n_molecules; i--;)
- {
- if(tng_data->molecules[i].id == id)
- {
- found_id = TNG_TRUE;
- i = 0;
- }
- }
- if(found_id)
- {
- id++;
- }
+ id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
+ }
+ else
+ {
+ id = 1;
}
return(tng_molecule_w_id_add(tng_data, name, id, molecule));
tng_molecule_t *molecule)
{
tng_molecule_t new_molecules;
- int64_t *new_molecule_cnt_list, i;
+ int64_t *new_molecule_cnt_list;
tng_function_status stat = TNG_SUCCESS;
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
/* FIXME: Should this be a function argument instead? */
tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
- for(i = tng_data->n_molecules; i--;)
- {
- if(tng_data->molecules[i].id == id)
- {
- stat = TNG_FAILURE;
- fprintf(stderr, "TNG library: Molecule ID %"PRId64" already in use. %s: %d\n", id,
- __FILE__, __LINE__);
- break;
- }
- }
-
(*molecule)->id = id;
tng_data->n_molecules++;
(tng_trajectory_t tng_data,
tng_molecule_t *molecule_p)
{
- tng_bool found_id = TNG_TRUE;
+ int64_t *new_molecule_cnt_list, id;
tng_molecule_t new_molecules, molecule;
- int64_t *new_molecule_cnt_list, i, id;
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
- /* Find an unused ID */
- id = 0;
- while(found_id)
+ /* Set ID to the ID of the last molecule + 1 */
+ if(tng_data->n_molecules)
{
- found_id = TNG_FALSE;
- for(i = tng_data->n_molecules; i--;)
- {
- if(tng_data->molecules[i].id == id)
- {
- found_id = TNG_TRUE;
- i = 0;
- }
- }
- if(found_id)
- {
- id++;
- }
+ id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
+ }
+ else
+ {
+ id = 1;
}
new_molecules = realloc(tng_data->molecules,
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
- for(i = tng_data->n_molecules; i--;)
+ for(i = 0; i < tng_data->n_molecules; i++)
{
if(&tng_data->molecules[i] == molecule)
{
index = i;
- i = 0;
+ break;
}
}
if(index == -1)
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
- for(i = tng_data->n_molecules; i--;)
+ for(i = 0; i < tng_data->n_molecules; i++)
{
if(&tng_data->molecules[i] == molecule)
{
index = i;
- i = 0;
+ break;
}
}
if(index == -1)
n_molecules = tng_data->n_molecules;
- for(i = 0; i < n_molecules; i++)
+ for(i = n_molecules - 1; i >= 0; i--)
{
*molecule = &tng_data->molecules[i];
if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
n_chains = molecule->n_chains;
- for(i = 0; i < n_chains; i++)
+ for(i = n_chains - 1; i >= 0; i--)
{
*chain = &molecule->chains[i];
if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
const char *name,
tng_chain_t *chain)
{
+ int64_t id;
+
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+ /* Set ID to the ID of the last chain + 1 */
+ if(molecule->n_chains)
+ {
+ id = molecule->chains[molecule->n_chains-1].id + 1;
+ }
+ else
+ {
+ id = 1;
+ }
+
return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
- molecule->n_chains + 1, chain));
+ id, chain));
}
tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
const int64_t id,
tng_chain_t *chain)
{
- int64_t i;
tng_chain_t new_chains;
tng_function_status stat = TNG_SUCCESS;
(*chain)->molecule = molecule;
(*chain)->n_residues = 0;
- for(i = molecule->n_chains; i--;)
- {
- if(molecule->chains[i].id == id)
- {
- stat = TNG_FAILURE;
- fprintf(stderr, "TNG library: Chain ID already in use. %s: %d\n", __FILE__, __LINE__);
- break;
- }
- }
-
molecule->n_chains++;
(*chain)->id = id;
const int64_t to_atom_id,
tng_bond_t *bond)
{
- int64_t i;
tng_bond_t new_bonds;
(void)tng_data;
- for(i = 0; i < molecule->n_bonds; i++)
- {
- *bond = &molecule->bonds[i];
- /* Check if the bond already exists */
- if(((*bond)->from_atom_id == from_atom_id && (*bond)->to_atom_id == to_atom_id) ||
- ((*bond)->to_atom_id == from_atom_id && (*bond)->from_atom_id == to_atom_id))
- {
- return(TNG_SUCCESS);
- }
- }
-
new_bonds = realloc(molecule->bonds,
sizeof(struct tng_bond) *
(molecule->n_bonds + 1));
n_atoms = molecule->n_atoms;
- for(i = 0; i < n_atoms; i++)
+ for(i = n_atoms - 1; i >= 0; i--)
{
*atom = &molecule->atoms[i];
if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
n_residues = chain->n_residues;
- for(i = 0; i < n_residues; i++)
+ for(i = n_residues - 1; i >= 0; i--)
{
*residue = &chain->residues[i];
if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
const char *name,
tng_residue_t *residue)
{
+ int64_t id;
+
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
+ /* Set ID to the ID of the last residue + 1 */
+ if(chain->n_residues)
+ {
+ id = chain->residues[chain->n_residues-1].id + 1;
+ }
+ else
+ {
+ id = 0;
+ }
+
return(tng_chain_residue_w_id_add(tng_data, chain, name,
- chain->n_residues + 1, residue));
+ id, residue));
}
tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
const int64_t id,
tng_residue_t *residue)
{
- int64_t i, curr_index;
+ int64_t curr_index;
tng_residue_t new_residues, temp_residue, last_residue;
tng_molecule_t molecule = chain->molecule;
tng_function_status stat = TNG_SUCCESS;
{
chain->residues = *residue;
}
+ else
+ {
+ chain->residues = &molecule->residues[curr_index];
+ }
(*residue)->name = 0;
tng_residue_name_set(tng_data, *residue, name);
(*residue)->n_atoms = 0;
(*residue)->atoms_offset = 0;
- for(i = chain->n_residues; i--;)
- {
- if(chain->residues[i].id == id)
- {
- stat = TNG_FAILURE;
- fprintf(stderr, "TNG library: Residue ID already in use. %s: %d\n", __FILE__, __LINE__);
- break;
- }
- }
-
chain->n_residues++;
molecule->n_residues++;
const char *atom_type,
tng_atom_t *atom)
{
+ int64_t id;
+
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
+ /* Set ID to the ID of the last atom + 1 */
+ if(residue->chain->molecule->n_atoms)
+ {
+ id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
+ }
+ else
+ {
+ id = 0;
+ }
+
return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
- residue->chain->molecule->n_atoms + 1,
- atom));
+ id, atom));
}
tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
const int64_t id,
tng_atom_t *atom)
{
- int64_t i;
tng_atom_t new_atoms;
tng_molecule_t molecule = residue->chain->molecule;
tng_function_status stat = TNG_SUCCESS;
(*atom)->residue = residue;
- for(i = molecule->n_atoms; i--;)
- {
- if(molecule->atoms[i].id == id)
- {
- stat = TNG_FAILURE;
- fprintf(stderr, "TNG library: Atom ID %"PRId64" already in use. %s: %d\n", id, __FILE__, __LINE__);
- break;
- }
- }
-
residue->n_atoms++;
molecule->n_atoms++;
if(molecule->chains)
{
- for(i = molecule->n_chains; i--;)
+ for(i = 0; i < molecule->n_chains; i++)
{
if(molecule->chains[i].name)
{
if(molecule->residues)
{
- for(i = molecule->n_residues; i--;)
+ for(i = 0; i < molecule->n_residues; i++)
{
if(molecule->residues[i].name)
{
if(molecule->atoms)
{
- for(i = molecule->n_atoms; i--;)
+ for(i = 0; i < molecule->n_atoms; i++)
{
tng_atom_destroy(&molecule->atoms[i]);
}
if(frame_set->n_mapping_blocks && frame_set->mappings)
{
- for(i = frame_set->n_mapping_blocks; i--;)
+ for(i = 0; i < frame_set->n_mapping_blocks; i++)
{
mapping = &frame_set->mappings[i];
if(mapping->real_particle_numbers)
tng_data->current_trajectory_frame_set_output_file_pos = -1;
tng_data->frame_set_n_frames = 100;
tng_data->n_trajectory_frame_sets = 0;
- tng_data->n_trajectory_blocks = 0;
tng_data->medium_stride_length = 100;
tng_data->long_stride_length = 10000;
if(tng_data->input_file)
{
+ if(tng_data->output_file == tng_data->input_file)
+ {
+ tng_frame_set_finalize(tng_data, TNG_USE_HASH);
+ tng_data->output_file = 0;
+ }
fclose(tng_data->input_file);
tng_data->input_file = 0;
}
if(tng_data->non_tr_particle_data)
{
- for(i = tng_data->n_particle_data_blocks; i--; )
+ for(i = 0; i < tng_data->n_particle_data_blocks; i++)
{
if(tng_data->non_tr_particle_data[i].values)
{
n_values_per_frame;
if(tng_data->non_tr_particle_data[i].strings[0])
{
- for(j = n_particles; j--;)
+ for(j = 0; j < n_particles; j++)
{
if(tng_data->non_tr_particle_data[i].strings[0][j])
{
- for(k = n_values_per_frame; k--;)
+ for(k = 0; k < n_values_per_frame; k++)
{
if(tng_data->non_tr_particle_data[i].
strings[0][j][k])
if(tng_data->non_tr_data)
{
- for(i = tng_data->n_data_blocks; i--;)
+ for(i = 0; i < tng_data->n_data_blocks; i++)
{
if(tng_data->non_tr_data[i].values)
{
n_values_per_frame;
if(tng_data->non_tr_data[i].strings[0])
{
- for(j = n_values_per_frame; j--;)
+ for(j = 0; j < n_values_per_frame; j++)
{
if(tng_data->non_tr_data[i].strings[0][j])
{
if(frame_set->tr_particle_data)
{
- for(i = frame_set->n_particle_data_blocks; i--; )
+ for(i = 0; i < frame_set->n_particle_data_blocks; i++)
{
if(frame_set->tr_particle_data[i].values)
{
{
n_values_per_frame = frame_set->tr_particle_data[i].
n_values_per_frame;
- for(j = frame_set->tr_particle_data[i].n_frames; j--;)
+ for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
{
if(frame_set->tr_particle_data[i].strings[j])
{
- for(k = n_particles; k--;)
+ for(k = 0; k < n_particles; k++)
{
if(frame_set->tr_particle_data[i].
strings[j][k])
{
- for(l = n_values_per_frame; l--;)
+ for(l = 0; l < n_values_per_frame; l++)
{
if(frame_set->tr_particle_data[i].
strings[j][k][l])
if(frame_set->tr_data)
{
- for(i = frame_set->n_data_blocks; i--;)
+ for(i = 0; i < frame_set->n_data_blocks; i++)
{
if(frame_set->tr_data[i].values)
{
{
n_values_per_frame = frame_set->tr_data[i].
n_values_per_frame;
- for(j = frame_set->tr_data[i].n_frames; j--;)
+ for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
{
if(frame_set->tr_data[i].strings[j])
{
- for(k = n_values_per_frame; k--;)
+ for(k = 0; k < n_values_per_frame; k++)
{
if(frame_set->tr_data[i].strings[j][k])
{
if(tng_data->molecules)
{
- for(i=tng_data->n_molecules; i--;)
+ for(i = 0; i < tng_data->n_molecules; i++)
{
tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
}
src->current_trajectory_frame_set_output_file_pos;
dest->frame_set_n_frames = src->frame_set_n_frames;
dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
- dest->n_trajectory_blocks = src->n_trajectory_blocks;
dest->medium_stride_length = src->medium_stride_length;
dest->long_stride_length = src->long_stride_length;
tng_data->output_file_path, __FILE__, __LINE__);
return(TNG_CRITICAL);
}
+ tng_data->input_file = tng_data->output_file;
return(TNG_SUCCESS);
}
return(TNG_FAILURE);
}
- for(i = tng_data->n_molecules; i --;)
+ for(i = 0; i < tng_data->n_molecules; i++)
{
cnt += cnt_list[i];
}
}
if(tng_block_read_next(tng_data, block,
- TNG_SKIP_HASH) != TNG_SUCCESS)
+ TNG_SKIP_HASH) != TNG_SUCCESS)
{
tng_block_destroy(&block);
return(TNG_CRITICAL);
}
*/
+static tng_function_status tng_file_headers_len_get
+ (tng_trajectory_t tng_data,
+ int64_t *len)
+{
+ int64_t orig_pos;
+ tng_gen_block_t block;
+
+ TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
+
+ if(tng_input_file_init(tng_data) != TNG_SUCCESS)
+ {
+ return(TNG_CRITICAL);
+ }
+
+ *len = 0;
+
+ orig_pos = ftell(tng_data->input_file);
+
+ if(!tng_data->input_file_len)
+ {
+ fseek(tng_data->input_file, 0, SEEK_END);
+ tng_data->input_file_len = ftell(tng_data->input_file);
+ }
+ fseek(tng_data->input_file, 0, SEEK_SET);
+
+ tng_block_init(&block);
+ /* Read through the headers of non-trajectory blocks (they come before the
+ * trajectory blocks in the file) */
+ while (*len < tng_data->input_file_len &&
+ tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
+ block->id != -1 &&
+ block->id != TNG_TRAJECTORY_FRAME_SET)
+ {
+ *len += block->header_contents_size + block->block_contents_size;
+ fseek(tng_data->input_file, block->block_contents_size, SEEK_CUR);
+ }
+
+ fseek(tng_data->input_file, orig_pos, SEEK_SET);
+
+ tng_block_destroy(&block);
+
+ return(TNG_SUCCESS);
+}
+
tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
(tng_trajectory_t tng_data,
const char hash_mode)
{
- int cnt = 0, prev_pos = 0;
+ int64_t prev_pos = 0;
tng_gen_block_t block;
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
{
fseek(tng_data->input_file, 0, SEEK_END);
tng_data->input_file_len = ftell(tng_data->input_file);
- fseek(tng_data->input_file, 0, SEEK_SET);
}
+ fseek(tng_data->input_file, 0, SEEK_SET);
tng_block_init(&block);
/* Non trajectory blocks (they come before the trajectory
block->id != -1 &&
block->id != TNG_TRAJECTORY_FRAME_SET)
{
- if(tng_block_read_next(tng_data, block,
- hash_mode) == TNG_SUCCESS)
- {
- cnt++;
- }
+ tng_block_read_next(tng_data, block, hash_mode);
prev_pos = ftell(tng_data->input_file);
}
const char hash_mode)
{
int i;
- tng_gen_block_t data_block;
+ int64_t len, orig_len, tot_len = 0, data_start_pos;
+ tng_function_status stat;
+ tng_gen_block_t block;
TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
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. */
/* FIXME: Currently writing non-trajectory data blocks here.
* Should perhaps be moved. */
- tng_block_init(&data_block);
+ tng_block_init(&block);
for(i = 0; i < tng_data->n_data_blocks; i++)
{
- data_block->id = tng_data->non_tr_data[i].block_id;
- tng_data_block_write(tng_data, data_block,
+ block->id = tng_data->non_tr_data[i].block_id;
+ tng_data_block_write(tng_data, block,
i, hash_mode);
}
for(i = 0; i < tng_data->n_particle_data_blocks; i++)
{
- data_block->id = tng_data->non_tr_particle_data[i].block_id;
- tng_particle_data_block_write(tng_data, data_block,
+ block->id = tng_data->non_tr_particle_data[i].block_id;
+ tng_particle_data_block_write(tng_data, block,
i, 0, hash_mode);
}
- tng_block_destroy(&data_block);
+ tng_block_destroy(&block);
return(TNG_SUCCESS);
}
/* Read block headers first to see what block is found. */
stat = tng_block_header_read(tng_data, block);
- if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+ if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
+ block->id == -1)
{
fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
file_pos, __FILE__, __LINE__);
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
stat = tng_block_read_next(tng_data, block,
hash_mode);
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == block_id)
{
/* Read the next frame set from the previous frame set and one
* medium stride step back */
- fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
- sizeof(int64_t), SEEK_CUR);
+ fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
1, tng_data->output_file) == 0)
/* Read the next frame set from the previous frame set and one
* long stride step back */
- fseek(tng_data->output_file, (long)block->block_contents_size - 6 *
- sizeof(int64_t), SEEK_CUR);
+ fseek(tng_data->output_file, (long)block->block_contents_size - (6 *
+ sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
tng_block_destroy(&block);
stat = tng_block_header_read(tng_data, block);
while(file_pos < output_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == TNG_PARTICLE_MAPPING)
{
while(file_pos < output_file_len &&
stat != TNG_CRITICAL &&
block->id != block_id &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
file_pos = ftell(tng_data->output_file);
stat = tng_block_header_read(tng_data, block);
while(file_pos < output_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == TNG_PARTICLE_MAPPING)
{
stat = tng_block_header_read(tng_data, block);
while(file_pos < output_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == TNG_PARTICLE_MAPPING)
{
stat != TNG_CRITICAL &&
block->id != block_id &&
block->id != TNG_PARTICLE_MAPPING &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
fseek(tng_data->output_file, (long)block->block_contents_size, SEEK_CUR);
file_pos = ftell(tng_data->output_file);
}
- for(i = n_frames; i--;)
+ for(i = 0; i < n_frames; i++)
{
(*values)[i] = malloc(sizeof(union data_values) *
n_values_per_frame);
{
if(type == TNG_CHAR_DATA)
{
- for(j = n_values_per_frame; j--;)
+ for(j = 0; j < n_values_per_frame; j++)
{
if(values[i][j].c)
{
}
- for(i = n_frames; i--;)
+ for(i = 0; i < n_frames; i++)
{
(*values)[i] = malloc(sizeof(union data_values *) *
n_particles);
*values = 0;
return(TNG_CRITICAL);
}
- for(j = n_particles; j--;)
+ for(j = 0; j < n_particles; j++)
{
(*values)[i][j] = malloc(sizeof(union data_values) *
n_values_per_frame);
{
if(type == TNG_CHAR_DATA)
{
- for(k = n_values_per_frame; k--;)
+ for(k = 0; k < n_values_per_frame; k++)
{
if(values[i][j][k].c)
{
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
/* Use hash by default */
stat = tng_block_read_next(tng_data, block,
return(stat);
}
- for(i = frame_set->n_data_blocks; i-- ;)
+ for(i = 0; i < frame_set->n_data_blocks; i++)
{
data = &frame_set->tr_data[i];
if(data->block_id == block_id)
switch(*type)
{
case TNG_CHAR_DATA:
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
len = strlen(data->strings[i][j]) + 1;
(*values)[i][j].c = malloc(len);
break;
case TNG_INT_DATA:
size = sizeof(int);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].i = *(int *)((char *)data->values + size *
(i*(*n_values_per_frame) + j));
break;
case TNG_FLOAT_DATA:
size = sizeof(float);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].f = *(float *)((char *)data->values + size *
(i*(*n_values_per_frame) + j));
case TNG_DOUBLE_DATA:
default:
size = sizeof(double);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].d = *(double *)((char *)data->values + size *
(i*(*n_values_per_frame) + j));
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
/* Use hash by default */
stat = tng_block_read_next(tng_data, block,
return(stat);
}
- for(i = frame_set->n_data_blocks; i-- ;)
+ for(i = 0; i < frame_set->n_data_blocks; i++)
{
data = &frame_set->tr_data[i];
if(data->block_id == block_id)
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
stat = tng_block_read_next(tng_data, block,
hash_mode);
/* See if there is a data block of this ID.
* Start checking the last read frame set */
- for(i = frame_set->n_data_blocks; i-- ;)
+ for(i = 0; i < frame_set->n_data_blocks; i++)
{
data = &frame_set->tr_data[i];
if(data->block_id == block_id)
}
current_frame_pos = 0;
}
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
len = strlen(data->strings[current_frame_pos][j]) + 1;
(*values)[i][j].c = malloc(len);
}
current_frame_pos = 0;
}
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].i = *(int *)((char *)data->values + size *
(current_frame_pos *
}
current_frame_pos = 0;
}
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].f = *(float *)((char *)data->values + size *
(current_frame_pos *
}
current_frame_pos = 0;
}
- for(j=*n_values_per_frame; j--;)
+ for(j = 0; j < *n_values_per_frame; j++)
{
(*values)[i][j].d = *(double *)((char *)data->values + size *
(current_frame_pos *
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == block_id)
{
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
/* Use hash by default */
stat = tng_block_read_next(tng_data, block,
return(stat);
}
- for(i = frame_set->n_particle_data_blocks; i-- ;)
+ for(i = 0; i < frame_set->n_particle_data_blocks; i++)
{
data = &frame_set->tr_particle_data[i];
if(data->block_id == block_id)
switch(*type)
{
case TNG_CHAR_DATA:
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
len = strlen(data->strings[i][j][k]) + 1;
(*values)[i][mapping][k].c = malloc(len);
case TNG_INT_DATA:
size = sizeof(int);
i_step = (*n_particles) * (*n_values_per_frame);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
(*values)[i][mapping][k].i = *(int *)
((char *)data->values + size *
case TNG_FLOAT_DATA:
size = sizeof(float);
i_step = (*n_particles) * (*n_values_per_frame);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
(*values)[i][mapping][k].f = *(float *)
((char *)data->values + size *
default:
size = sizeof(double);
i_step = (*n_particles) * (*n_values_per_frame);
- for(i=*n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
(*values)[i][mapping][k].d = *(double *)
((char *)data->values + size *
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
/* Use hash by default */
stat = tng_block_read_next(tng_data, block,
return(stat);
}
- for(i = frame_set->n_particle_data_blocks; i-- ;)
+ for(i = 0; i < frame_set->n_particle_data_blocks; i++)
{
data = &frame_set->tr_particle_data[i];
if(data->block_id == block_id)
else
{
i_step = (*n_particles) * (*n_values_per_frame);
- for(i = *n_frames; i--;)
+ for(i = 0; i < *n_frames; i++)
{
- for(j = *n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
memcpy(((char *)*values) + size * (i * i_step + mapping *
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
stat = tng_block_read_next(tng_data, block,
hash_mode);
}
current_frame_pos = 0;
}
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
len = strlen(data->strings[current_frame_pos][j][k]) + 1;
(*values)[i][mapping][k].c = malloc(len);
}
current_frame_pos = 0;
}
- for(j=*n_particles; j--;)
+ for(j = 0; j < *n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k = 0; k < *n_values_per_frame; k++)
{
(*values)[i][mapping][k].i = *(int *)
((char *)data->values + size *
}
current_frame_pos = 0;
}
- for(j=*n_particles; j--;)
+ for(j=0; j<*n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k=0; k<*n_values_per_frame; k++)
{
(*values)[i][mapping][k].f = *(float *)
((char *)data->values + size *
}
current_frame_pos = 0;
}
- for(j=*n_particles; j--;)
+ for(j=0; j<*n_particles; j++)
{
tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
- for(k=*n_values_per_frame; k--;)
+ for(k=0; k<*n_values_per_frame; k++)
{
(*values)[i][mapping][k].d = *(double *)
((char *)data->values + size *
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
{
}
else if(mode == 'a')
{
+ if((*tng_data_p)->output_file)
+ {
+ fclose((*tng_data_p)->output_file);
+ }
+ (*tng_data_p)->output_file = (*tng_data_p)->input_file;
fseek((*tng_data_p)->input_file,
(long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos,
SEEK_SET);
fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
__FILE__, __LINE__);
}
+ (*tng_data_p)->output_file = 0;
(*tng_data_p)->first_trajectory_frame_set_output_file_pos =
(*tng_data_p)->first_trajectory_frame_set_input_file_pos;
(*tng_data_p)->last_trajectory_frame_set_input_file_pos;
(*tng_data_p)->current_trajectory_frame_set_output_file_pos =
(*tng_data_p)->current_trajectory_frame_set_input_file_pos;
- (*tng_data_p)->first_trajectory_frame_set_input_file_pos = -1;
- (*tng_data_p)->last_trajectory_frame_set_input_file_pos = -1;
- (*tng_data_p)->current_trajectory_frame_set_input_file_pos = -1;
if((*tng_data_p)->input_file)
{
fclose((*tng_data_p)->input_file);
}
}
- /* If no data blocks have been found in the frame set check what data blocks
- * are present. If they have already been found do not read them again. */
+ /* Check for data blocks only if they have not already been found. */
if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
{
file_pos = ftell(tng_data->input_file);
- /* Read all blocks until next frame set block */
if(file_pos < tng_data->input_file_len)
{
tng_block_init(&block);
stat = tng_block_header_read(tng_data, block);
while(file_pos < tng_data->input_file_len &&
stat != TNG_CRITICAL &&
- block->id != TNG_TRAJECTORY_FRAME_SET)
+ block->id != TNG_TRAJECTORY_FRAME_SET &&
+ block->id != -1)
{
stat = tng_block_read_next(tng_data, block,
TNG_USE_HASH);