From c67f1fbd4afb9b064dbb3d86dbc5080f5ce87f68 Mon Sep 17 00:00:00 2001 From: Magnus Lundborg Date: Mon, 3 Dec 2012 14:50:57 +0100 Subject: Initial repository setup. Adding files. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3f09cfe --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.6) + +set(CMAKE_CXX_FLAGS "-g -Wall") + +project(TRAJECTORY) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +add_subdirectory(src) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/example_files/trg_example.trg b/example_files/trg_example.trg new file mode 100644 index 0000000..eac8c8c Binary files /dev/null and b/example_files/trg_example.trg differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..165c089 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(lib) +add_subdirectory(tests) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt new file mode 100644 index 0000000..c4c40bf --- /dev/null +++ b/src/lib/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(trg_io SHARED trg_io.c md5.c) + diff --git a/src/lib/md5.c b/src/lib/md5.c new file mode 100644 index 0000000..8bbde52 --- /dev/null +++ b/src/lib/md5.c @@ -0,0 +1,424 @@ +/* + * + * This source code is distributed with + * + * G R O M A C S + * + * GROningen MAchine for Chemical Simulations + * + * VERSION 4.5 + * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others. + * Copyright (c) 1991-2010, The GROMACS development team, + * check out http://www.gromacs.org for more information. + * + * Gromacs is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * If you want to redistribute modifications, please consider that + * scientific software is very special. Version control is crucial - + * bugs must be traceable. We will be happy to consider code for + * inclusion in the official distribution, but derived work must not + * be called official GROMACS. Details are found in the README & COPYING + * files - if they are missing, get the official version at www.gromacs.org. + * + * To help us fund GROMACS development, we humbly ask that you cite + * the papers on the package - you can find them in the top README file. + * + * For more info, check our website at http://www.gromacs.org + * + * And Hey: + * GROningen Mixture of Alchemy and Childrens' Stories + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef GMX_INTEGER_BIG_ENDIAN +#define ARCH_IS_BIG_ENDIAN 1 +#else +#define ARCH_IS_BIG_ENDIAN 0 +#endif + +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static inline void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + /* cppcheck-suppress unassignedVariable */ + const md5_word_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/lib/md5.h b/src/lib/md5.h new file mode 100644 index 0000000..15719fd --- /dev/null +++ b/src/lib/md5.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +void md5_init(md5_state_t *pms); + +/* Append a string to the message. */ +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + +/* Finish the message and return the digest. */ +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/lib/trg_io.c b/src/lib/trg_io.c new file mode 100644 index 0000000..c05d078 --- /dev/null +++ b/src/lib/trg_io.c @@ -0,0 +1,6934 @@ +/* This code is part of the trg binary trajectory format. + * + * VERSION 1.0 + * + * Written by Magnus Lundborg + * Copyright (c) 2012, The GROMACS development team. + * check out http://www.gromacs.org for more information. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + + +/* TODO: Make sure UTF-8 works properly */ + +#include +#include +#include +#include +#include +#include + +#include "trg_io.h" +#include "md5.h" + +#ifndef LOGIN_NAME_MAX +#define LOGIN_NAME_MAX 33 +#endif +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 257 +#endif + + +/* This function swaps the byte order of a 32 bit numerical variable. + It does not only work with integer, but e.g. floats need casting */ +static inline trg_function_status trg_swap_byte_order_32 + (const struct trg_trajectory *trg_data, uint32_t *v) +{ + switch(trg_data->endianness_32) + { + case TRG_LITTLE_ENDIAN_32: // Byte order is reversed. + *v = (*v << 24) | // Move first byte to end + ((*v & 0x00FF0000) >> 8) | // Move 2nd byte to pos 3 + ((*v & 0x0000FF00) << 8) | // Move 3rd byte to pos 2 + (*v >> 24); // Move last byte to first + + return(TRG_SUCCESS); + + case TRG_BYTE_PAIR_SWAP_32: // byte pair swap + *v = ((*v & 0xFFFF0000) >> 16) | + ((*v & 0x0000FFFF) << 16); + + return(TRG_SUCCESS); + + case TRG_BIG_ENDIAN_32: // Already correct + return(TRG_SUCCESS); + + default: + return(TRG_FAILURE); + } +} + +/* This function swaps the byte order of a 64 bit numerical variable. + It does not only work with integer, but e.g. floats need casting + The byte order swapping routine can convert five different byte + orders to big endian. */ +static inline trg_function_status trg_swap_byte_order_64 + (const struct trg_trajectory *trg_data, uint64_t *v) +{ + switch(trg_data->endianness_64) + { + case TRG_LITTLE_ENDIAN_64: // Byte order is reversed. + *v = (*v >> 56) | // Move first byte to end + ((*v & 0x00FF000000000000) >> 40) | // Move 2nd byte to pos 7 + ((*v & 0x0000FF0000000000) >> 24) | // Move 3rd byte to pos 6 + ((*v & 0x000000FF00000000) >> 8 ) | // Move 4th byte to pos 5 + ((*v & 0x00000000FF000000) << 8 ) | // Move 5th byte to pos 4 + ((*v & 0x0000000000FF0000) << 24) | // Move 6th byte to pos 3 + ((*v & 0x000000000000FF00) << 40) | // Move 7th byte to pos 2 + (*v << 56); // Move last byte to first + + return(TRG_SUCCESS); + + case TRG_QUAD_SWAP_64: // Byte quad swap + *v = ((*v & 0xFFFFFFFF00000000) >> 32) | + ((*v & 0x00000000FFFFFFFF) << 32); + + return(TRG_SUCCESS); + + case TRG_BYTE_PAIR_SWAP_64: // Byte pair swap + *v = ((*v & 0xFFFF0000FFFF0000) >> 16) | + ((*v & 0x0000FFFF0000FFFF) << 16); + + return(TRG_SUCCESS); + + case TRG_BYTE_SWAP_64: // Byte swap + *v = ((*v & 0xFF00FF00FF00FF00) >> 8) | + ((*v & 0x00FF00FF00FF00FF) << 8); + + return(TRG_SUCCESS); + + case TRG_BIG_ENDIAN_64: // Already correct + return(TRG_SUCCESS); + + default: + return(TRG_FAILURE); + } +} + +/* Generate the md5 hash of a block. + The hash is created based on the actual block contents. */ +static trg_function_status trg_generate_block_hash(struct trg_gen_block *block) +{ + md5_state_t md5_state; + + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *)block->block_contents, + block->block_contents_size); + md5_finish(&md5_state, (md5_byte_t *)block->hash); + + return(TRG_SUCCESS); +} + +/* Compare the current block hash (e.g. read from file) with the hash + calculated from the current contents. + If the current hash is all zeros skip the comparison. + If the hashes match results is set to TRUE, otherwise it is set to + FALSE. */ +static trg_function_status trg_verify_hash_match(struct trg_gen_block *block, + trg_bool *results) +{ + md5_state_t md5_state; + char hash[TRG_HASH_LEN]; + + if(strcmp(block->hash,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") == 0) + { + *results = TRUE; + return(TRG_SUCCESS); + } + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *)block->block_contents, + block->block_contents_size); + md5_finish(&md5_state, (md5_byte_t *)hash); + + if(strncmp(block->hash, hash, 16) != 0) + { + *results = FALSE; + } + else + { + *results = TRUE; + } + + return(TRG_SUCCESS); +} + + +static trg_function_status trg_init_input_file(struct trg_trajectory *trg_data, + const trg_bool update_read_pos) +{ + if(!trg_data->input_file) + { + if(!trg_data->input_file_path) + { + printf("No file specified for reading. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + trg_data->input_file = fopen(trg_data->input_file_path, "r"); + if(!trg_data->input_file) + { + printf("Cannot open file %s. %s: %d\n", + trg_data->input_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(fseek(trg_data->input_file, trg_data->input_file_pos, + SEEK_SET) != 0) + { + printf("Cannot specify position in file %s. %s: %d\n", + trg_data->input_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + else if(update_read_pos && fseek(trg_data->input_file, + trg_data->input_file_pos, SEEK_SET) != 0) + { + printf("Cannot specify position in file %s. %s: %d\n", + trg_data->input_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); +} + +static trg_function_status trg_init_output_file + (struct trg_trajectory *trg_data, + const trg_bool update_write_pos) +{ + if(!trg_data->output_file) + { + if(!trg_data->output_file_path) + { + printf("No file specified for writing. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + if(trg_data->output_file_pos <= 0) + { + trg_data->output_file = fopen(trg_data->output_file_path, "w+"); + } + else + { + trg_data->output_file = fopen(trg_data->output_file_path, "a+"); + } + + if(!trg_data->output_file) + { + printf("Cannot open file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(fseek(trg_data->output_file, 0, SEEK_SET) != 0) + { + printf("Cannot specify position in file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + else if(update_write_pos && fseek(trg_data->output_file, 0, + SEEK_SET) != 0) + { + printf("Cannot specify position in file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_block_header + (struct trg_trajectory *trg_data, struct trg_gen_block *block) +{ + int len, offset = 0; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + /* First read the header size to be able to read the whole header. */ + if(fread(&block->header_contents_size, sizeof(block->header_contents_size), + 1, trg_data->input_file) == 0) + { + printf("Cannot read header size. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &block->header_contents_size) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + /* Move the reading position to the beginning of the header. */ + fseek(trg_data->input_file, -sizeof(block->header_contents_size), + SEEK_CUR); + + /* If there is already memory allocated for the contents free it (we do not + * know if the size is correct). */ + if(block->header_contents) + { + free(block->header_contents); + } + + block->header_contents = (char *) malloc(block->header_contents_size); + if(!block->header_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->header_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* Read the whole header into header_contents. This way it can be saved + * even if it cannot be interpreted + * for one reason or another. */ + if(fread(block->header_contents, block->header_contents_size, 1, + trg_data->input_file) == 0) + { + printf("Cannot read header. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* The header contents size has already been read. Skip ahead. */ + offset = sizeof(block->header_contents_size); + + + /* Copy the respective parameters from the header contents block */ + memcpy(&block->block_contents_size, block->header_contents+offset, + sizeof(block->block_contents_size)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &block->block_contents_size) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->block_contents_size); + + memcpy(&block->id, block->header_contents+offset, sizeof(block->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &block->id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->id); + + memcpy(block->hash, block->header_contents+offset, TRG_HASH_LEN); + offset += TRG_HASH_LEN; + + if(block->name && strcmp(block->name, block->header_contents+offset) != 0) + { + free(block->name); + block->name = 0; + } + len = min(strlen(block->header_contents+offset) + 1, TRG_MAX_STR_LEN); + if(!block->name) + { + block->name = (char *) malloc(len); + if(!block->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strncpy(block->name, block->header_contents+offset, len); + } + offset += len; + + memcpy(&block->block_version, block->header_contents+offset, + sizeof(block->block_version)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &block->block_version) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->block_version); + + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_block_header + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, write_mode mode) +{ + int name_len, offset = 0; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + printf("Cannot initialise destination file. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + + /* Just dump the full header contents to file */ + if(mode == TRG_COPY_EXISTING) + { + if(!block->header_contents) + { + printf("No contents to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->header_contents, block->header_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all header data. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + if(!block->name) + { + block->name = (char *) malloc(1); + if(!block->name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + block->name[0] = 0; + } + + name_len = min(strlen(block->name) + 1, TRG_MAX_STR_LEN); + + trg_generate_block_hash(block); + + /* 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) + + TRG_HASH_LEN + + name_len; + + if(block->header_contents) + { + free(block->header_contents); + } + + block->header_contents = (char *) malloc(block->header_contents_size); + if(!block->header_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->header_contents_size, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + /* 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(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->header_contents)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %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(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->header_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->block_contents_size); + + memcpy(block->header_contents+offset, &block->id, sizeof(block->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->header_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->id); + + memcpy(block->header_contents+offset, block->hash, TRG_HASH_LEN); + offset += TRG_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(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->header_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block->block_version); + + if(fwrite(block->header_contents, block->header_contents_size, + 1, trg_data->output_file) != 1) + { + printf("Could not write all header data. %s: %d\n", __FILE__, __LINE__); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); +} + + +static trg_function_status trg_read_general_info_block + (struct trg_trajectory *trg_data, struct trg_gen_block *block) +{ + int len, offset = 0; + trg_bool same_hash; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("General info block contents corrupt. Hashes do not match. " + "%s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + len = min(strlen(block->block_contents) + 1, TRG_MAX_STR_LEN); + trg_data->program_name = (char *) malloc(len); + if(!trg_data->program_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strncpy(trg_data->program_name, block->block_contents, len); + offset += len; + + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + trg_data->forcefield_name = (char *) malloc(len); + if(!trg_data->forcefield_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strncpy(trg_data->forcefield_name, block->block_contents+offset, len); + offset += len; + + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + trg_data->user_name = (char *) malloc(len); + if(!trg_data->user_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strncpy(trg_data->user_name, block->block_contents+offset, len); + offset += len; + + memcpy(&trg_data->time, block->block_contents+offset, + sizeof(trg_data->time)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &trg_data->time) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->time); + + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + trg_data->computer_name = (char *) malloc(len); + if(!trg_data->computer_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(trg_data->computer_name, block->block_contents+offset, len); + offset += len; + + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + trg_data->pgp_signature = (char *) malloc(len); + if(!trg_data->pgp_signature) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(trg_data->pgp_signature, block->block_contents+offset, len); + offset += len; + + memcpy(&trg_data->var_num_atoms_flag, block->block_contents+offset, + sizeof(trg_data->var_num_atoms_flag)); + offset += sizeof(trg_data->var_num_atoms_flag); + + memcpy(&trg_data->frame_set_n_frames, block->block_contents+offset, + sizeof(trg_data->frame_set_n_frames)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &trg_data->frame_set_n_frames) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->frame_set_n_frames); + + memcpy(&trg_data->first_trajectory_frame_set_input_file_pos, + block->block_contents+offset, + sizeof(trg_data->first_trajectory_frame_set_input_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &trg_data->first_trajectory_frame_set_input_file_pos) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->first_trajectory_frame_set_input_file_pos); + trg_data->current_trajectory_frame_set.next_frame_set_file_pos = + trg_data->first_trajectory_frame_set_input_file_pos; + + + memcpy(&trg_data->last_trajectory_frame_set_input_file_pos, + block->block_contents+offset, + sizeof(trg_data->last_trajectory_frame_set_input_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &trg_data->last_trajectory_frame_set_input_file_pos) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->last_trajectory_frame_set_input_file_pos); + + memcpy(&trg_data->stride_length, block->block_contents+offset, + sizeof(trg_data->stride_length)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &trg_data->stride_length) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_general_info_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + write_mode mode) +{ + int program_name_len, forcefield_name_len, user_name_len; + int computer_name_len, pgp_signature_len; + int offset = 0; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + if(!trg_data->program_name) + { + trg_data->program_name = (char *) malloc(1); + if(!trg_data->program_name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + trg_data->program_name[0] = 0; + } + if(!trg_data->forcefield_name) + { + trg_data->forcefield_name = (char *) malloc(1); + if(!trg_data->forcefield_name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + trg_data->forcefield_name[0] = 0; + } + if(!trg_data->user_name) + { + trg_data->user_name = (char *) malloc(1); + if(!trg_data->user_name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + trg_data->user_name[0] = 0; + } + if(!trg_data->computer_name) + { + trg_data->computer_name = (char *) malloc(1); + if(!trg_data->computer_name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + trg_data->computer_name[0] = 0; + } + if(!trg_data->pgp_signature) + { + trg_data->pgp_signature = (char *) malloc(1); + if(!trg_data->pgp_signature) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + trg_data->pgp_signature[0] = 0; + } + + program_name_len = min(strlen(trg_data->program_name) + 1, + TRG_MAX_STR_LEN); + forcefield_name_len = min(strlen(trg_data->forcefield_name) + 1, + TRG_MAX_STR_LEN); + user_name_len = min(strlen(trg_data->user_name) + 1, + TRG_MAX_STR_LEN); + computer_name_len = min(strlen(trg_data->computer_name) + 1, + TRG_MAX_STR_LEN); + pgp_signature_len = min(strlen(trg_data->pgp_signature) + 1, + TRG_MAX_STR_LEN); + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", + __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + block->block_contents_size = sizeof(trg_data->time) + + sizeof(trg_data->var_num_atoms_flag) + + sizeof(trg_data->frame_set_n_frames) + + sizeof(trg_data->first_trajectory_frame_set_input_file_pos) + + sizeof(trg_data->last_trajectory_frame_set_input_file_pos) + + sizeof(trg_data->stride_length) + + program_name_len + + forcefield_name_len + + user_name_len + + computer_name_len + + pgp_signature_len; + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + strncpy(block->block_contents, trg_data->program_name, program_name_len); + offset += program_name_len; + + strncpy(block->block_contents+offset, trg_data->forcefield_name, + forcefield_name_len); + offset += forcefield_name_len; + + strncpy(block->block_contents+offset, trg_data->user_name, user_name_len); + offset += user_name_len; + + memcpy(block->block_contents+offset, &trg_data->time, + sizeof(trg_data->time)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->time); + + strncpy(block->block_contents+offset, trg_data->computer_name, + computer_name_len); + offset += computer_name_len; + + strncpy(block->block_contents+offset, trg_data->pgp_signature, + pgp_signature_len); + offset += pgp_signature_len; + + memcpy(block->block_contents+offset, &trg_data->var_num_atoms_flag, + sizeof(trg_data->var_num_atoms_flag)); + offset += sizeof(trg_data->var_num_atoms_flag); + + memcpy(block->block_contents+offset, &trg_data->frame_set_n_frames, + sizeof(trg_data->frame_set_n_frames)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->frame_set_n_frames); + + memcpy(block->block_contents+offset, + &trg_data->first_trajectory_frame_set_input_file_pos, + sizeof(trg_data->first_trajectory_frame_set_input_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->first_trajectory_frame_set_input_file_pos); + + memcpy(block->block_contents+offset, + &trg_data->last_trajectory_frame_set_input_file_pos, + sizeof(trg_data->last_trajectory_frame_set_input_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->last_trajectory_frame_set_input_file_pos); + + + memcpy(block->block_contents+offset, &trg_data->stride_length, + sizeof(trg_data->stride_length)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +/* FIXME: Update this according to the new specs */ +static trg_function_status trg_read_molecules_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block) +{ + int i, j, k, l, len, offset = 0; + struct trg_molecule *molecule; + struct trg_chain *chain; + struct trg_residue *residue; + struct trg_atom *atom; + struct trg_bond *bond; + trg_bool same_hash; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("Molecules block contents corrupt. Hashes do not match. " + "%s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + memcpy(&trg_data->n_molecules, block->block_contents, + sizeof(trg_data->n_molecules)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &trg_data->n_molecules) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->n_molecules); + + if(trg_data->molecules) + { + free(trg_data->molecules); + } + + trg_data->n_particles = 0; + + trg_data->molecules = (struct trg_molecule *) + malloc(trg_data->n_molecules * + sizeof(struct trg_molecule)); + if(!trg_data->molecules) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + trg_data->n_molecules * sizeof(struct trg_molecule), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!trg_data->var_num_atoms_flag) + { + if(trg_data->molecule_cnt_list) + { + free(trg_data->molecule_cnt_list); + } + trg_data->molecule_cnt_list = (uint64_t *) malloc(sizeof(uint64_t) * + trg_data->n_molecules); + if(!trg_data->molecule_cnt_list) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + trg_data->n_molecules * sizeof(struct trg_molecule), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + } + + + for(i=0; i < trg_data->n_molecules; i++) + { + molecule = &trg_data->molecules[i]; + + memcpy(&molecule->id, block->block_contents+offset, + sizeof(molecule->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->id); + +// printf("Read id: %"PRId64" offset: %d\n", molecule->id, offset); + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + molecule->name = (char *) malloc(len); + strncpy(molecule->name, block->block_contents+offset, len); + offset += len; + + memcpy(&molecule->quaternary_str, block->block_contents+offset, + sizeof(molecule->quaternary_str)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->quaternary_str) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->quaternary_str); + + if(!trg_data->var_num_atoms_flag) + { + memcpy(&trg_data->molecule_cnt_list[i], + block->block_contents+offset, + sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &trg_data->molecule_cnt_list[i]) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + } + + + memcpy(&molecule->n_chains, block->block_contents+offset, + sizeof(molecule->n_chains)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->n_chains) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_chains); + + memcpy(&molecule->n_residues, block->block_contents+offset, + sizeof(molecule->n_residues)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->n_residues) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_residues); + + memcpy(&molecule->n_atoms, block->block_contents+offset, + sizeof(molecule->n_atoms)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->n_atoms) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_atoms); + + trg_data->n_particles += molecule->n_atoms * + trg_data->molecule_cnt_list[i]; + + molecule->chains = (struct trg_chain *) malloc(molecule->n_chains * + sizeof(struct trg_chain)); + if(!molecule->chains) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + molecule->n_chains * sizeof(struct trg_chain), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + chain = molecule->chains; + + molecule->residues = (struct trg_residue *) + malloc(molecule->n_residues * + sizeof(struct trg_residue)); + if(!molecule->residues) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + molecule->n_residues * sizeof(struct trg_residue), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + residue = molecule->residues; + + molecule->atoms = (struct trg_atom *) malloc(molecule->n_atoms * + sizeof(struct trg_atom)); + if(!molecule->atoms) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + molecule->n_atoms * sizeof(struct trg_atom), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + atom = molecule->atoms; + + for(j=molecule->n_chains; j--;) + { + chain->molecule = molecule; + + memcpy(&chain->id, block->block_contents+offset, + sizeof(chain->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &chain->id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(chain->id); + + len = min(strlen(block->block_contents+offset) + 1, + TRG_MAX_STR_LEN); + chain->name = (char *) malloc(len); + strncpy(chain->name, + block->block_contents+offset, len); + offset += len; + + memcpy(&chain->n_residues, block->block_contents+offset, + sizeof(chain->n_residues)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &chain->n_residues) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(chain->n_residues); + + chain->residues = residue; + for(k=chain->n_residues; k--;) + { + residue->chain = chain; + memcpy(&residue->id, block->block_contents+offset, + sizeof(residue->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &residue->id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(residue->id); + + len = min(strlen(block->block_contents+offset) + 1, + TRG_MAX_STR_LEN); + residue->name = (char *) malloc(len); + strncpy(residue->name, + block->block_contents+offset, len); + offset += len; + + memcpy(&residue->n_atoms, block->block_contents+offset, + sizeof(residue->n_atoms)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &residue->n_atoms) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(residue->n_atoms); + + residue->atoms = atom; + for(l=residue->n_atoms; l--;) + { + atom->residue = residue; + + memcpy(&atom->id, block->block_contents+offset, + sizeof(atom->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &atom->id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(atom->id); + + len = min(strlen(block->block_contents+offset) + 1, + TRG_MAX_STR_LEN); + atom->name = (char *) malloc(len); + strncpy(atom->name, + block->block_contents+offset, len); + offset += len; + + len = min(strlen(block->block_contents+offset) + 1, + TRG_MAX_STR_LEN); + atom->atom_type = (char *) malloc(len); + strncpy(atom->atom_type, + block->block_contents+offset, len); + offset += len; + + atom++; + } + residue++; + } + chain++; + } + + memcpy(&molecule->n_bonds, block->block_contents+offset, + sizeof(molecule->n_bonds)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &molecule->n_bonds) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_bonds); + + molecule->bonds = (struct trg_bond *) malloc(molecule->n_bonds * + sizeof(struct trg_bond)); + if(!molecule->bonds) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + molecule->n_bonds * sizeof(struct trg_bond), + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + bond = molecule->bonds; + + for(j=molecule->n_bonds; j--;) + { + memcpy(&bond->from_atom_id, block->block_contents+offset, + sizeof(bond->from_atom_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &bond->from_atom_id) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(bond->from_atom_id); + + memcpy(&bond->to_atom_id, block->block_contents+offset, + sizeof(bond->to_atom_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &bond->to_atom_id) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(bond->to_atom_id); + + bond++; + } + } + + return(TRG_SUCCESS); +} + +/* FIXME: Update this according to the new specs */ +static trg_function_status trg_write_molecules_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + write_mode mode) +{ + int len = 0; + int i, j, k, l, offset = 0; + struct trg_molecule *molecule; + struct trg_chain *chain; + struct trg_residue *residue; + struct trg_atom *atom; + struct trg_bond *bond; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(mode != TRG_COPY_EXISTING && !trg_data->molecules) + { + return(TRG_SUCCESS); + } + +// printf("Predicting block size\n"); + /* First predict the size of the block */ + for(i = 0; i < trg_data->n_molecules; i++) + { + molecule = &trg_data->molecules[i]; +// printf("mol %s\n", molecule->name); + if(!molecule->name) + { + molecule->name = (char *) malloc(1); + if(!molecule->name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + molecule->name[0] = 0; + } + len += min(strlen(molecule->name) + 1, TRG_MAX_STR_LEN); + + chain = molecule->chains; + for(j = molecule->n_chains; j--;) + { + len += sizeof(chain->id); + + if(!chain->name) + { + chain->name = (char *) malloc(1); + if(!chain->name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + chain->name[0] = 0; + } + len += min(strlen(chain->name) + 1, TRG_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 = (char *) malloc(1); + if(!residue->name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + residue->name[0] = 0; + } + len += min(strlen(residue->name) + 1, TRG_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 = (char *) malloc(1); + if(!atom->name) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + atom->name[0] = 0; + } + len += min(strlen(atom->name) + 1, TRG_MAX_STR_LEN); + + if(!atom->atom_type) + { + atom->atom_type = (char *) malloc(1); + if(!atom->atom_type) + { + printf("Cannot allocate memory (1 byte). %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + atom->atom_type[0] = 0; + } + len += min(strlen(atom->atom_type) + 1, TRG_MAX_STR_LEN); + + atom++; + } + + bond = molecule->bonds; + for(j = molecule->n_bonds; j--;) + { + len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id); + } + } + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + block->block_contents_size = sizeof(trg_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)) * + trg_data->n_molecules + + len; + + if(!trg_data->var_num_atoms_flag) + { + block->block_contents_size += trg_data->n_molecules * sizeof(uint64_t); + } + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + memcpy(block->block_contents+offset, &trg_data->n_molecules, + sizeof(trg_data->n_molecules)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(trg_data->n_molecules); + + for(i = 0; i < trg_data->n_molecules; i++) + { + molecule = &trg_data->molecules[i]; +// printf("i=%d\n", i); + memcpy(block->block_contents+offset, &molecule->id, + sizeof(molecule->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->id); + +// printf("Wrote id: %"PRId64" offset: %d\n", molecule->id, offset); + len = min(strlen(molecule->name) + 1, TRG_MAX_STR_LEN); + strncpy(block->block_contents + offset, molecule->name, len); + offset += len; + + memcpy(block->block_contents+offset, &molecule->quaternary_str, + sizeof(molecule->quaternary_str)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->quaternary_str); + + if(!trg_data->var_num_atoms_flag) + { + memcpy(block->block_contents+offset, + &trg_data->molecule_cnt_list[i], sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + } + + memcpy(block->block_contents+offset, &molecule->n_chains, + sizeof(molecule->n_chains)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_chains); + + memcpy(block->block_contents+offset, &molecule->n_residues, + sizeof(molecule->n_residues)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_residues); + + memcpy(block->block_contents+offset, &molecule->n_atoms, + sizeof(molecule->n_atoms)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_atoms); + + chain = molecule->chains; + for(j = molecule->n_chains; j--;) + { + memcpy(block->block_contents+offset, &chain->id, sizeof(chain->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(chain->id); + + len = min(strlen(chain->name) + 1, TRG_MAX_STR_LEN); + strncpy(block->block_contents + offset, chain->name, len); + offset += len; + + memcpy(block->block_contents+offset, &chain->n_residues, + sizeof(chain->n_residues)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(chain->n_residues); + + residue = chain->residues; + for(k = chain->n_residues; k--;) + { + memcpy(block->block_contents+offset, &residue->id, sizeof(residue->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(residue->id); + + len = min(strlen(residue->name) + 1, TRG_MAX_STR_LEN); + strncpy(block->block_contents + offset, residue->name, len); + offset += len; + + memcpy(block->block_contents+offset, &residue->n_atoms, + sizeof(residue->n_atoms)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(residue->n_atoms); + + atom = residue->atoms; + for(l = residue->n_atoms; l--;) + { + // printf("j=%d\n", j); + memcpy(block->block_contents+offset, &atom->id, sizeof(atom->id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(atom->id); + + len = min(strlen(atom->name) + 1, TRG_MAX_STR_LEN); + strncpy(block->block_contents + offset, atom->name, len); + offset += len; + + len = min(strlen(atom->atom_type) + 1, TRG_MAX_STR_LEN); + strncpy(block->block_contents + offset, atom->atom_type, len); + offset += len; + + atom++; + } + residue++; + } + chain++; + } + + memcpy(block->block_contents+offset, &molecule->n_bonds, + sizeof(molecule->n_bonds)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(molecule->n_bonds); + + bond = molecule->bonds; + for(j = molecule->n_bonds; j--;) + { + memcpy(block->block_contents+offset, &bond->from_atom_id, + sizeof(bond->from_atom_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(bond->from_atom_id); + + memcpy(block->block_contents+offset, &bond->to_atom_id, + sizeof(bond->to_atom_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(bond->to_atom_id); + + bond++; + } + } + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + + +static trg_function_status trg_read_frame_set_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block) +{ + int i, file_pos, offset = 0; + uint64_t prev_n_particles; + trg_bool same_hash; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + struct trg_particle_mapping *mapping; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("Frame set block contents corrupt. Hashes do not match. " + "%s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + file_pos = ftell(trg_data->input_file); + + if(frame_set->n_mapping_blocks && frame_set->mappings) + { + for(i = frame_set->n_mapping_blocks; i--;) + { + mapping = &frame_set->mappings[i]; + if(mapping->real_particle_numbers) + { + free(mapping->real_particle_numbers); + mapping->real_particle_numbers = 0; + } + } + free(frame_set->mappings); + frame_set->n_mapping_blocks = 0; + } + + if(trg_data->first_trajectory_frame_set_input_file_pos <= 0) + { + trg_data->first_trajectory_frame_set_input_file_pos = file_pos; + } + /* FIXME: Should check the frame number instead of the file_pos, in case + * frame sets are not in order */ + if(trg_data->last_trajectory_frame_set_input_file_pos < file_pos) + { + trg_data->last_trajectory_frame_set_input_file_pos = file_pos; + } + + memcpy(&frame_set->first_frame, block->block_contents, + sizeof(frame_set->first_frame)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &frame_set->first_frame) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->first_frame); + + memcpy(&frame_set->n_frames, block->block_contents + offset, + sizeof(frame_set->n_frames)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &frame_set->n_frames) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->n_frames); + + if(trg_data->var_num_atoms_flag) + { + prev_n_particles = frame_set->n_particles; + frame_set->n_particles = 0; + /* If the list of molecule counts has already been created assume that + * it is of correct size. */ + if(!frame_set->molecule_cnt_list) + { + frame_set->molecule_cnt_list = + (uint64_t *) malloc(sizeof(uint64_t) * trg_data->n_molecules); + + if(!frame_set->molecule_cnt_list) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(uint64_t) * trg_data->n_molecules, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + } + for(i = 0; i < trg_data->n_molecules; i++) + { + memcpy(&frame_set->molecule_cnt_list[i], + block->block_contents + offset, + sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set->molecule_cnt_list[i]) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + frame_set->n_particles += trg_data->molecules[i].n_atoms * + frame_set->molecule_cnt_list[i]; + } + if(prev_n_particles && frame_set->n_particles != prev_n_particles) + { + /* FIXME: Particle dependent data memory management */ + } + } + + memcpy(&frame_set->next_frame_set_file_pos, + block->block_contents + offset, + sizeof(frame_set->next_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set->next_frame_set_file_pos) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->next_frame_set_file_pos); + + memcpy(&frame_set->prev_frame_set_file_pos, + block->block_contents + offset, + sizeof(frame_set->prev_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set->prev_frame_set_file_pos) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->prev_frame_set_file_pos); + + memcpy(&frame_set->long_stride_next_frame_set_file_pos, + block->block_contents + offset, + sizeof(frame_set->long_stride_next_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set-> + long_stride_next_frame_set_file_pos) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->long_stride_next_frame_set_file_pos); + + memcpy(&frame_set->long_stride_prev_frame_set_file_pos, + block->block_contents + offset, + sizeof(frame_set->long_stride_prev_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set-> + long_stride_prev_frame_set_file_pos) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos); + +// frame_set->n_double_particle_data_blocks = 0; +// frame_set->n_float_particle_data_blocks = 0; +// frame_set->n_int_particle_data_blocks = 0; +// frame_set->n_gen_particle_data_blocks = 0; +// frame_set->n_double_data_blocks = 0; +// frame_set->n_float_data_blocks = 0; +// frame_set->n_int_data_blocks = 0; +// frame_set->n_gen_data_blocks = 0; + + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_frame_set_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + write_mode mode) +{ + char *temp_name; + uint64_t i; + int offset = 0, name_len; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + name_len = strlen("TRAJECTORY FRAME SET"); + + if(!block->name || strlen(block->name) < name_len) + { + temp_name = realloc(block->name, name_len + 1); + if(!temp_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + name_len+1, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + block->name = temp_name; + } + strcpy(block->name, "TRAJECTORY FRAME SET"); + + block->block_contents_size = sizeof(uint64_t) * 6; + if(trg_data->var_num_atoms_flag) + { + block->block_contents_size += sizeof(uint64_t) * trg_data->n_molecules; + } + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + memcpy(block->block_contents, &frame_set->first_frame, + sizeof(frame_set->first_frame)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->first_frame); + + memcpy(block->block_contents+offset, &frame_set->n_frames, + sizeof(frame_set->n_frames)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->n_frames); + + if(trg_data->var_num_atoms_flag) + { + for(i = 0; i < trg_data->n_molecules; i++) + { + memcpy(block->block_contents+offset, + &frame_set->molecule_cnt_list[i], + sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + } + } + + + memcpy(block->block_contents+offset, &frame_set->next_frame_set_file_pos, + sizeof(frame_set->next_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->next_frame_set_file_pos); + + memcpy(block->block_contents+offset, &frame_set->prev_frame_set_file_pos, + sizeof(frame_set->prev_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->prev_frame_set_file_pos); + + memcpy(block->block_contents+offset, + &frame_set->long_stride_next_frame_set_file_pos, + sizeof(frame_set->long_stride_next_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->long_stride_next_frame_set_file_pos); + + memcpy(block->block_contents+offset, + &frame_set->long_stride_prev_frame_set_file_pos, + sizeof(frame_set->long_stride_prev_frame_set_file_pos)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(frame_set->long_stride_prev_frame_set_file_pos); + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_trajectory_toc_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block) +{ + uint64_t i, old_n_blocks; + int offset = 0, len; + trg_bool same_hash; + struct trg_frame_set_toc *toc = + &trg_data->current_trajectory_frame_set.contents; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("Table of contents block contents corrupt. Hashes do not match. " + "%s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + old_n_blocks = toc->n_blocks; + + memcpy(&toc->n_blocks, block->block_contents, + sizeof(toc->n_blocks)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &toc->n_blocks) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(toc->n_blocks); + + if(old_n_blocks != toc->n_blocks) + { + if(toc->block_names) + { + for(i = old_n_blocks; i--;) + { + if(toc->block_names[i]) + { + free(toc->block_names[i]); + } + } + free(toc->block_names); + } + toc->block_names = (char **) malloc(toc->n_blocks * sizeof(char *)); + if(!toc->block_names) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + toc->n_blocks * sizeof(uint64_t), __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + } + + for(i = 0; i < toc->n_blocks; i++) + { + len = min(strlen(block->block_contents+offset) + 1, TRG_MAX_STR_LEN); + + toc->block_names[i] = (char *) malloc(len); + if(!toc->block_names[i]) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + len, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + strncpy(toc->block_names[i], block->block_contents+offset, len); + + offset += len; + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_trajectory_toc_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + write_mode mode) +{ + char *temp_name; + uint64_t i; + int offset = 0, name_len; + struct trg_frame_set_toc *toc = + &trg_data->current_trajectory_frame_set.contents; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + name_len = strlen("BLOCK TABLE OF CONTENTS"); + + if(!block->name || strlen(block->name) < name_len) + { + temp_name = realloc(block->name, name_len + 1); + if(!temp_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + name_len+1, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + block->name = temp_name; + } + strcpy(block->name, "BLOCK TABLE OF CONTENTS"); + + block->block_contents_size = sizeof(uint64_t); + + for(i = toc->n_blocks; i--;) + { + block->block_contents_size += strlen(toc->block_names[i]) + 1; + } + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + memcpy(block->block_contents, &toc->n_blocks, sizeof(toc->n_blocks)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(toc->n_blocks); + + for(i = 0; i < toc->n_blocks; i++) + { + name_len = strlen(toc->block_names[i]) + 1; + strncpy(block->block_contents+offset, toc->block_names[i], name_len); + offset += name_len; + } + + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_trajectory_mapping_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block) +{ + uint64_t i, old_n_particles; + int offset = 0; + trg_bool same_hash; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_particle_mapping *mapping, *mappings; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("Particle mapping block contents corrupt. Hashes do not match. " + "%s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + frame_set->n_mapping_blocks++; + mappings = realloc(frame_set->mappings, + sizeof(struct trg_particle_mapping) * + frame_set->n_mapping_blocks); + if(!mappings) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + frame_set->mappings = mappings; + mapping = &mappings[frame_set->n_mapping_blocks - 1]; + + + memcpy(&mapping->num_first_particle, block->block_contents+offset, + sizeof(mapping->num_first_particle)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &mapping->num_first_particle) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(mapping->num_first_particle); + + old_n_particles = mapping->n_particles; + + memcpy(&mapping->n_particles, block->block_contents+offset, + sizeof(mapping->n_particles)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &mapping->n_particles) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(mapping->n_particles); + + if(old_n_particles != mapping->n_particles) + { + if(mapping->real_particle_numbers) + { + free(mapping->real_particle_numbers); + } + mapping->real_particle_numbers = malloc(mapping->n_particles * + sizeof(uint64_t)); + if(!mapping->real_particle_numbers) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + mapping->n_particles * sizeof(uint64_t), __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + } + + for(i = 0; i < mapping->n_particles; i++) + { + memcpy(&mapping->real_particle_numbers[i], + block->block_contents + offset, + sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &mapping->real_particle_numbers[i]) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_trajectory_mapping_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + int mapping_block_nr, + write_mode mode) +{ + char *temp_name; + int i, offset = 0, name_len; + struct trg_particle_mapping *mapping = + &trg_data->current_trajectory_frame_set.mappings[mapping_block_nr]; + + if(mapping_block_nr >= + trg_data->current_trajectory_frame_set.n_mapping_blocks) + { + printf("Mapping block index out of bounds. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + name_len = strlen("PARTICLE MAPPING"); + + if(!block->name || strlen(block->name) < name_len) + { + temp_name = realloc(block->name, name_len + 1); + if(!temp_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + name_len+1, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + block->name = temp_name; + } + strcpy(block->name, "PARTICLE MAPPING"); + + block->block_contents_size = sizeof(uint64_t) * (2 + mapping->n_particles); + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + memcpy(block->block_contents, &mapping->num_first_particle, + sizeof(mapping->num_first_particle)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(mapping->num_first_particle); + + memcpy(block->block_contents+offset, &mapping->n_particles, + sizeof(mapping->n_particles)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(mapping->n_particles); + + for(i = 0; i < mapping->n_particles; i++) + { + memcpy(block->block_contents+offset, &mapping->real_particle_numbers[i], + sizeof(uint64_t)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(uint64_t); + } + + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_create_particle_data_block + (struct trg_trajectory *trg_data, + const trg_block_type block_type_flag) +{ + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_particle_data *data; + + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + frame_set->n_particle_data_blocks++; + data = realloc(frame_set->tr_particle_data, + sizeof(struct trg_particle_data) * + frame_set->n_particle_data_blocks); + if(!data) + { + printf("Cannot allocate memory (%lu bytes). %s: %d\n", + sizeof(struct trg_particle_data) * + frame_set->n_particle_data_blocks, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + frame_set->tr_particle_data = data; + data = &frame_set->tr_particle_data[frame_set-> + n_particle_data_blocks - 1]; + } + else + { + trg_data->n_particle_data_blocks++; + data = realloc(trg_data->non_tr_particle_data, + sizeof(struct trg_particle_data) * + trg_data->n_particle_data_blocks); + if(!data) + { + printf("Cannot allocate memory (%lu bytes). %s: %d\n", + sizeof(struct trg_particle_data) * + trg_data->n_particle_data_blocks, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + trg_data->non_tr_particle_data = data; + data = &trg_data->non_tr_particle_data[trg_data-> + n_particle_data_blocks - 1]; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_allocate_particle_data_mem + (struct trg_trajectory *trg_data, + struct trg_particle_data *data, + uint64_t n_frames, + const uint64_t n_particles, + const uint64_t n_values_per_frame) +{ + union data_values ***values; + uint64_t i, j, k; + + for(i = data->n_frames; i--;) + { + for(j = n_particles; j--;) + { + free(data->values[i][j]); + } + free(data->values[i]); + } + data->n_frames = n_frames; + n_frames = max(1, n_frames); + data->n_values_per_frame = n_values_per_frame; + values = (union data_values ***) realloc(data->values, + sizeof(union data_values **) * + n_frames); + if(!values) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(union data_values **) * n_frames, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + data->values = values; + + for(i = n_frames; i-- ;) + { + data->values[i] = (union data_values **) + malloc(sizeof(union data_values *) * + n_particles); + if(!data->values[i]) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(union data_values *) * n_particles, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + for(j = n_particles; j--;) + { + data->values[i][j] = (union data_values *) + malloc(sizeof(union data_values) * + n_values_per_frame); + if(!data->values[i][j]) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(union data_values) * n_values_per_frame, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(data->datatype == TRG_CHAR_DATA) + { + for(k = n_values_per_frame; k--;) + { + data->values[i][j][k].c = 0; + } + } + } + } + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_particle_data + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + int *offset, + const char datatype, + const uint64_t first_particle_number, + const uint64_t n_particles, + const uint64_t first_frame_with_data, + const uint64_t stride_length, + uint64_t n_frames, + const uint64_t n_values, + const uint64_t codec_id, + const uint64_t multiplier) +{ + uint64_t block_index, i, j, k, tot_n_particles; + int size, len; + struct trg_particle_data *data; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + trg_block_type block_type_flag; + + switch(datatype) + { + case TRG_CHAR_DATA: + size = 1; + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + } + + if(trg_data->current_trajectory_frame_set_input_file_pos > 0) + { + block_type_flag = TRG_TRAJECTORY_BLOCK; + } + else + { + block_type_flag = TRG_NON_TRAJECTORY_BLOCK; + } + + block_index = -1; + /* See if there is already a data block of this ID */ + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + for(i = frame_set->n_particle_data_blocks; i-- ;) + { + data = &frame_set->tr_particle_data[i]; + if(data->block_id == block->id) + { + block_index = i; + break; + } + } + } + else + { + for(i = trg_data->n_particle_data_blocks; i-- ;) + { + data = &trg_data->non_tr_particle_data[i]; + if(data->block_id == block->id) + { + block_index = i; + break; + } + } + } + + /* Otherwise create a data block */ + if(block_index == -1) + { + if(trg_create_particle_data_block(trg_data, block_type_flag) != + TRG_SUCCESS) + { + printf("Cannot create particle data block. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + data = &frame_set->tr_particle_data[frame_set-> + n_particle_data_blocks - 1]; + } + else + { + data = &trg_data->non_tr_particle_data[trg_data-> + n_particle_data_blocks - 1]; + } + data->block_id = block->id; + + data->block_name = malloc(strlen(block->name) + 1); + if(!data->block_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + (int)strlen(block->name)+1, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strcpy(data->block_name, block->name); + + data->datatype = datatype; + + data->values = 0; + data->n_frames = 0; + data->codec_id = codec_id; + data->compression_multiplier = multiplier; + } + + if(block_type_flag == TRG_TRAJECTORY_BLOCK && + trg_data->var_num_atoms_flag) + { + tot_n_particles = frame_set->n_particles; + } + else + { + tot_n_particles = trg_data->n_particles; + } + + /* Allocate memory */ + if(!data->values || data->n_frames != n_frames || + data->n_values_per_frame != n_values) + { + if(trg_allocate_particle_data_mem(trg_data, data, n_frames, + tot_n_particles, n_values) != + TRG_SUCCESS) + { + printf("Cannot allocate memory for particle data. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + data->first_frame_with_data = first_frame_with_data; + data->stride_length = stride_length; + + for(i = 0; i < n_frames; i++) + { + for(j = first_particle_number; j < n_particles; j++) + { + for(k = 0; k < n_values; k++) + { + /* FIXME: Not optimal to have this switch statement inside + * the for loops. Check if it should be moved outside. */ + switch(datatype) + { + case TRG_FLOAT_DATA: + memcpy(&data->values[i][j][k].f, + block->block_contents+*offset, + size); + if(trg_data->endianness_32 != TRG_BIG_ENDIAN_32) + { + if(trg_swap_byte_order_32(trg_data, + (uint32_t *) &data->values[i][j][k]) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + break; + case TRG_INT_DATA: + memcpy(&data->values[i][j][k].i, + block->block_contents+*offset, + size); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *) &data->values[i][j][k].i) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + break; + case TRG_CHAR_DATA: + len = min(strlen(block->block_contents+*offset) + 1, + TRG_MAX_STR_LEN); + if(data->values[i][j][k].c) + { + free(data->values[i][j][k].c); + } + data->values[i][j][k].c = malloc(len); + if(!data->values[i][j][k].c) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + len, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->values[i][j][k].c, + block->block_contents+*offset, len); + *offset += len; + break; + case TRG_DOUBLE_DATA: + default: + memcpy(&data->values[i][j][k].d, + block->block_contents+*offset, + size); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *) &data->values[i][j][k].d) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + } + } + } + } + return(TRG_SUCCESS); +} + + +static trg_function_status trg_write_particle_data_block + (struct trg_trajectory *trg_data, + struct trg_gen_block *block, + const int block_index, + const struct trg_particle_mapping *mapping, + const write_mode mode) +{ + uint64_t n_particles, num_first_particle, n_frames; + int i, j, k, offset = 0, size, len; + char temp, *temp_name; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_particle_data *data; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(trg_data->current_trajectory_frame_set_output_file_pos > 0) + { + data = &frame_set->tr_particle_data[block_index]; + } + else + { + data = &trg_data->non_tr_particle_data[block_index]; + } + + switch(data->datatype) + { + case TRG_CHAR_DATA: + size = 1; + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + } + + len = strlen(data->block_name) + 1; + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + if(!block->name || strlen(block->name) < len) + { + temp_name = realloc(block->name, len); + if(!temp_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + block->name = temp_name; + } + strncpy(block->name, data->block_name, len); + + /* If writing frame independent data data->n_frames is be 0, but n_frames + is used for the loop writing the data (and reserving memory) and needs + to be at least 1 */ + n_frames = max(1, data->n_frames); + + + if(mapping && mapping->n_particles != 0) + { + n_particles = mapping->n_particles; + num_first_particle = mapping->num_first_particle; + } + else + { + num_first_particle = 0; + if(trg_data->var_num_atoms_flag) + { + n_particles = frame_set->n_particles; + } + else + { + n_particles = trg_data->n_particles; + } + } + + block->block_contents_size = sizeof(char) * 3 + + sizeof(data->n_values_per_frame) + + sizeof(data->codec_id) + + sizeof(num_first_particle) + + sizeof(n_particles); + + if(data->codec_id != TRG_UNCOMPRESSED) + { + block->block_contents_size += sizeof(data->compression_multiplier); + } + + if(data->datatype == TRG_CHAR_DATA) + { + for(i = n_frames; i--;) + { + for(j = num_first_particle; j < n_particles; j++) + { + for(k = data->n_values_per_frame; k--;) + { + block->block_contents_size += + strlen(data->values[i][j][k].c) + 1; + } + } + } + } + else + { + block->block_contents_size += size * n_frames * n_particles * + data->n_values_per_frame; + } + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + + memcpy(block->block_contents, &data->datatype, sizeof(char)); + offset += sizeof(char); + + if(data->n_frames > 0) + { + temp = TRG_FRAME_DEPENDENT + TRG_PARTICLE_DEPENDENT; + } + else + { + temp = TRG_PARTICLE_DEPENDENT; + } + memcpy(block->block_contents+offset, &temp, sizeof(char)); + offset += sizeof(char); + + if(data->n_frames > 0 && data->stride_length > 1) + { + temp = 1; + } + else + { + temp = 0; + } + 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(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->n_values_per_frame); + + memcpy(block->block_contents+offset, &data->codec_id, + sizeof(data->codec_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->codec_id); + + if(data->codec_id != TRG_UNCOMPRESSED) + { + memcpy(block->block_contents+offset, &data->compression_multiplier, + sizeof(data->compression_multiplier)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->compression_multiplier); + } + + if(data->n_frames > 0 && data->stride_length > 1) + { + memcpy(block->block_contents+offset, &data->first_frame_with_data, + sizeof(data->first_frame_with_data)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->first_frame_with_data); + + memcpy(block->block_contents+offset, &data->stride_length, + sizeof(data->stride_length)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->stride_length); + } + + + memcpy(block->block_contents+offset, &num_first_particle, + sizeof(num_first_particle)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(num_first_particle); + + memcpy(block->block_contents+offset, &n_particles, sizeof(n_particles)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents+offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(n_particles); + + + for(i = 0; i < data->n_frames; i++) + { + for(j = num_first_particle; j < n_particles; j++) + { + for(k = 0; k < data->n_values_per_frame; k++) + { + switch(data->datatype) + { + case TRG_FLOAT_DATA: + memcpy(block->block_contents+offset, + &data->values[i][j][k].f, + size); + break; + case TRG_INT_DATA: + memcpy(block->block_contents+offset, + &data->values[i][j][k].i, + size); + break; + case TRG_CHAR_DATA: + len = strlen(data->values[i][j][k].c) + 1; + strncpy(block->block_contents+offset, + data->values[i][j][k].c, len); + offset += len; + break; + case TRG_DOUBLE_DATA: + default: + memcpy(block->block_contents+offset, + &data->values[i][j][k].d, + size); + } + if(data->datatype == TRG_FLOAT_DATA) + { + if(trg_data->endianness_32 != TRG_BIG_ENDIAN_32) + { + if(trg_swap_byte_order_32(trg_data, + (uint32_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(size); + } + else if(data->datatype == TRG_INT_DATA || + data->datatype == TRG_DOUBLE_DATA) + { + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(size); + } + } + } + } + + + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +/* UNTESTED */ +static trg_function_status trg_create_data_block + (struct trg_trajectory *trg_data, + const trg_block_type block_type_flag) +{ + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_data *data; + + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + frame_set->n_data_blocks++; + data = realloc(frame_set->tr_data, sizeof(struct trg_data) * + frame_set->n_data_blocks); + if(!data) + { + printf("Cannot allocate memory (%lu bytes). %s: %d\n", + sizeof(struct trg_data) * frame_set->n_data_blocks, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + frame_set->tr_data = data; + data = &frame_set->tr_data[frame_set->n_data_blocks - 1]; + } + else + { + trg_data->n_data_blocks++; + data = realloc(trg_data->non_tr_data, sizeof(struct trg_data) * + trg_data->n_data_blocks); + if(!data) + { + printf("Cannot allocate memory (%lu bytes). %s: %d\n", + sizeof(struct trg_data) * trg_data->n_data_blocks, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + trg_data->non_tr_data = data; + data = &trg_data->non_tr_data[trg_data->n_data_blocks - 1]; + } + + return(TRG_SUCCESS); +} + +/* UNTESTED */ +trg_function_status trg_allocate_data_mem + (struct trg_trajectory *trg_data, + struct trg_data *data, + uint64_t n_frames, + const uint64_t n_values_per_frame) +{ + union data_values **values; + uint64_t i, j; + + for(i = data->n_frames; i--;) + { + if(data->datatype == TRG_CHAR_DATA) + { + for(j = data->n_values_per_frame; j--;) + { + if(data->values[i][j].c) + { + free(data->values[i][j].c); + data->values[i][j].c = 0; + } + } + } + free(data->values[i]); + } + data->n_frames = n_frames; + n_frames = max(1, n_frames); + data->n_values_per_frame = n_values_per_frame; + values = (union data_values **) realloc(data->values, + sizeof(union data_values *) * + n_frames); + if(!values) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(union data_values **) * n_frames, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + data->values = values; + + for(i = n_frames; i-- ;) + { + data->values[i] = (union data_values *) + malloc(sizeof(union data_values) * + n_values_per_frame); + if(!data->values[i]) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(union data_values) * n_values_per_frame, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(data->datatype == TRG_CHAR_DATA) + { + for(j = n_values_per_frame; j--;) + { + data->values[i][j].c = 0; + } + } + } + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_data(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + int *offset, + const char datatype, + const uint64_t first_frame_with_data, + const uint64_t stride_length, + uint64_t n_frames, + const uint64_t n_values, + const uint64_t codec_id, + const uint64_t multiplier) +{ + uint64_t block_index, i, j; + int size, len; + struct trg_data *data; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + trg_block_type block_type_flag; + +// printf("%s\n", block->name); + + if(trg_data->current_trajectory_frame_set_input_file_pos > 0) + { + block_type_flag = TRG_TRAJECTORY_BLOCK; + } + else + { + block_type_flag = TRG_NON_TRAJECTORY_BLOCK; + } + + switch(datatype) + { + case TRG_CHAR_DATA: + size = 1; + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + } + + block_index = -1; + /* See if there is already a data block of this ID */ + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + for(i = frame_set->n_data_blocks; i-- ;) + { + data = &frame_set->tr_data[i]; + if(data->block_id == block->id) + { + block_index = i; + break; + } + } + } + else + { + for(i = trg_data->n_data_blocks; i-- ;) + { + data = &trg_data->non_tr_data[i]; + if(data->block_id == block->id) + { + block_index = i; + break; + } + } + } + + /* Otherwise create a data block */ + if(block_index == -1) + { + if(trg_create_data_block(trg_data, block_type_flag) != + TRG_SUCCESS) + { + printf("Cannot create particle data block. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + data = &frame_set->tr_data[frame_set->n_data_blocks - 1]; + } + else + { + data = &trg_data->non_tr_data[trg_data->n_data_blocks - 1]; + } + data->block_id = block->id; + + data->block_name = malloc(strlen(block->name) + 1); + if(!data->block_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + (int)strlen(block->name)+1, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + strcpy(data->block_name, block->name); + + data->datatype = datatype; + + data->values = 0; + data->n_frames = 0; + data->codec_id = codec_id; + data->compression_multiplier = multiplier; + } + + /* Allocate memory */ + if(!data->values || data->n_frames != n_frames || + data->n_values_per_frame != n_values) + { + if(trg_allocate_data_mem(trg_data, data, n_frames, n_values) != + TRG_SUCCESS) + { + printf("Cannot allocate memory for data. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + data->first_frame_with_data = first_frame_with_data; + data->stride_length = stride_length; + + n_frames = max(1, n_frames); + + for(i = 0; i < n_frames; i++) + { + for(j = 0; j < n_values; j++) + { + switch(datatype) + { + case TRG_CHAR_DATA: + len = min(strlen(block->block_contents+*offset) + 1, + TRG_MAX_STR_LEN); + if(data->values[i][j].c) + { + free(data->values[i][j].c); + } + data->values[i][j].c = malloc(len); + if(!data->values[i][j].c) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + len, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->values[i][j].c, block->block_contents+*offset, + len); + *offset += len; + break; + case TRG_INT_DATA: + memcpy(&data->values[i][j].i, block->block_contents+*offset, + size); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *) &data->values[i][j].i) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + break; + case TRG_FLOAT_DATA: + memcpy(&data->values[i][j].f, block->block_contents+*offset, + size); + if(trg_data->endianness_32 != TRG_BIG_ENDIAN_32) + { + if(trg_swap_byte_order_32(trg_data, + (uint32_t *) &data->values[i][j]) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + break; + case TRG_DOUBLE_DATA: + default: + memcpy(&data->values[i][j].d, block->block_contents+*offset, + size); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *) &data->values[i][j].d) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + *offset += size; + } + } + } + return(TRG_SUCCESS); +} + +static trg_function_status trg_write_data_block(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + const int block_index, + const write_mode mode) +{ + uint64_t n_frames; + int i, j, offset = 0, size, len; + char temp, *temp_name; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_data *data; + trg_block_type block_type_flag; + + if(trg_data->current_trajectory_frame_set_output_file_pos > 0) + { + block_type_flag = TRG_TRAJECTORY_BLOCK; + } + else + { + block_type_flag = TRG_NON_TRAJECTORY_BLOCK; + } + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + data = &frame_set->tr_data[block_index]; + } + else + { + data = &trg_data->non_tr_data[block_index]; + } + + switch(data->datatype) + { + case TRG_CHAR_DATA: + size = 1; + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + } + + /* If just dumping the whole block_contents it is not certain that the + * contents are known beforehand (e.g. due to different file versions) */ + if(mode == TRG_COPY_EXISTING) + { + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(!block->block_contents) + { + printf("No block data to write. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + return(TRG_SUCCESS); + } + + len = strlen(data->block_name) + 1; + + if(!block->name || strlen(block->name) < len) + { + temp_name = realloc(block->name, len); + if(!temp_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len+1, + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + block->name = temp_name; + } + strncpy(block->name, data->block_name, len); + + /* If writing frame independent data data->n_frames is be 0, but n_frames + is used for the loop writing the data (and reserving memory) and needs + to be at least 1 */ + n_frames = max(1, data->n_frames); + + + block->block_contents_size = sizeof(char) * 2 + + sizeof(data->n_values_per_frame) + + sizeof(data->codec_id); + + if(data->codec_id != TRG_UNCOMPRESSED) + { + block->block_contents_size += sizeof(data->compression_multiplier); + } + + if(data->datatype == TRG_CHAR_DATA) + { + for(i = n_frames; i--;) + { + for(j = data->n_values_per_frame; j--;) + { + block->block_contents_size += strlen(data->values[i][j].c) + 1; + } + } + } + else + { + block->block_contents_size += size * n_frames * + data->n_values_per_frame; + } + + if(data->n_frames > 0 || data->stride_length != 0) + { + block->block_contents_size += sizeof(char); + } + + if(block->block_contents) + { + free(block->block_contents); + } + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + + memcpy(block->block_contents, &data->datatype, sizeof(char)); + offset += sizeof(char); + + if(data->n_frames > 0 || data->stride_length != 0) + { + temp = TRG_FRAME_DEPENDENT; + } + else + { + temp = 0; + } + memcpy(block->block_contents+offset, &temp, sizeof(char)); + offset += sizeof(char); + + if(data->n_frames > 0) + { + if(data->stride_length > 1) + { + temp = 1; + } + else + { + temp = 0; + } + 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(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->n_values_per_frame); + + memcpy(block->block_contents+offset, &data->codec_id, + sizeof(data->codec_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->codec_id); + + if(data->codec_id != TRG_UNCOMPRESSED) + { + memcpy(block->block_contents+offset, &data->compression_multiplier, + sizeof(data->compression_multiplier)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->compression_multiplier); + } + + if(data->n_frames > 0 && data->stride_length > 1) + { + memcpy(block->block_contents+offset, &data->first_frame_with_data, + sizeof(data->first_frame_with_data)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->first_frame_with_data); + + memcpy(block->block_contents+offset, &data->stride_length, + sizeof(data->stride_length)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *) + (block->block_contents + offset)) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(data->stride_length); + } + + for(i = 0; i < n_frames; i++) + { + for(j = 0; j < data->n_values_per_frame; j++) + { + switch(data->datatype) + { + case TRG_CHAR_DATA: + len = strlen(data->values[i][j].c) + 1; + strncpy(block->block_contents+offset, data->values[i][j].c, + len); + offset += len; + break; + case TRG_INT_DATA: + memcpy(block->block_contents+offset, &data->values[i][j].i, + size); + break; + case TRG_FLOAT_DATA: + memcpy(block->block_contents+offset, &data->values[i][j].f, + size); + break; + case TRG_DOUBLE_DATA: + default: + memcpy(block->block_contents+offset, &data->values[i][j].d, + size); + } + if(data->datatype != TRG_CHAR_DATA) + { + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + (uint64_t *)(block->block_contents+offset)) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. " + "%s: %d\n", + __FILE__, __LINE__); + } + } + offset += size; + } + } + } + + if(trg_write_block_header(trg_data, block, mode) != TRG_SUCCESS) + { + printf("Cannot write header of file %s. %s: %d\n", + trg_data->output_file_path, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(fwrite(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) != 1) + { + printf("Could not write all block data. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_read_data_block_contents + (struct trg_trajectory *trg_data, + struct trg_gen_block *block) +{ + uint64_t n_values, codec_id, n_frames, first_frame_with_data; + uint64_t steps_between_data, block_n_particles, first_particle_number; + double multiplier; + char datatype, dependency, sparse_data; + int offset = 0; + trg_bool same_hash; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = (char *) malloc(block->block_contents_size); + if(!block->block_contents) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + block->block_contents_size, __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_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, + trg_data->input_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(block); + return(TRG_CRITICAL); + } + + /* FIXME: Does not check if the size of the contents matches the expected + * size or if the contents can be read. */ + + + if(trg_verify_hash_match(block, &same_hash) != TRG_SUCCESS) + { + printf("Error comparing hashes. %s: %d\n", __FILE__, __LINE__); + return(TRG_FAILURE); + } + if(same_hash != TRUE) + { + printf("%s\n", block->hash); + printf("Data block contents corrupt. Hashes do not match. %s: %d\n", + __FILE__, __LINE__); +// return(TRG_FAILURE); + } + + memcpy(&datatype, block->block_contents+offset, + sizeof(datatype)); + offset += sizeof(datatype); + + memcpy(&dependency, block->block_contents+offset, + sizeof(dependency)); + offset += sizeof(dependency); + +// memcpy(&var_n_particles, block->block_contents+offset, +// sizeof(var_n_particles)); +// offset += sizeof(var_n_particles); + + if(dependency & TRG_FRAME_DEPENDENT) + { + memcpy(&sparse_data, block->block_contents+offset, + sizeof(sparse_data)); + offset += sizeof(sparse_data); + } + +// memcpy(&var_n_values, block->block_contents+offset, +// sizeof(var_n_values)); +// offset += sizeof(var_n_values); +// +// if(!var_n_values) +// { + memcpy(&n_values, block->block_contents+offset, + sizeof(n_values)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &n_values) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(n_values); +// } + + memcpy(&codec_id, block->block_contents+offset, + sizeof(codec_id)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &codec_id) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(codec_id); + + if(codec_id != TRG_UNCOMPRESSED) + { + memcpy(&multiplier, block->block_contents+offset, + sizeof(multiplier)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, (uint64_t *)&multiplier) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(multiplier); + } + else + { + multiplier = 1; + } + + if(dependency & TRG_FRAME_DEPENDENT) + { + if(sparse_data) + { + memcpy(&first_frame_with_data, block->block_contents+offset, + sizeof(first_frame_with_data)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &first_frame_with_data) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(first_frame_with_data); + + memcpy(&steps_between_data, block->block_contents+offset, + sizeof(steps_between_data)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &steps_between_data) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(steps_between_data); + } + else + { + first_frame_with_data = 0; + steps_between_data = 0; + } + n_frames = trg_data->current_trajectory_frame_set.n_frames; + } + else + { + first_frame_with_data = 0; + steps_between_data = 0; + n_frames = 0; + } + + if (dependency & TRG_PARTICLE_DEPENDENT) + { + memcpy(&first_particle_number, block->block_contents+offset, + sizeof(first_particle_number)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &first_particle_number) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(first_particle_number); + + memcpy(&block_n_particles, block->block_contents+offset, + sizeof(block_n_particles)); + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &block_n_particles) != + TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + offset += sizeof(block_n_particles); + } + + if (dependency & TRG_PARTICLE_DEPENDENT) + { + return(trg_read_particle_data(trg_data, block, + &offset, datatype, + first_particle_number, + block_n_particles, + first_frame_with_data, + steps_between_data, + n_frames, n_values, + codec_id, multiplier)); + } + else + { + return(trg_read_data(trg_data, block, + &offset, datatype, + first_frame_with_data, + steps_between_data, + n_frames, n_values, + codec_id, multiplier)); + } +} + +static trg_function_status trg_update_md5_hash(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + uint64_t header_start_pos, + uint64_t contents_start_pos) +{ + if(block->block_contents) + { + free(block->block_contents); + } + + block->block_contents = malloc(block->block_contents_size); + fseek(trg_data->output_file, contents_start_pos, SEEK_SET); + if(fread(block->block_contents, block->block_contents_size, 1, + trg_data->output_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + trg_generate_block_hash(block); + + fseek(trg_data->output_file, header_start_pos + 3 * sizeof(uint64_t), + SEEK_SET); + fwrite(block->hash, TRG_HASH_LEN, 1, trg_data->output_file); + + return(TRG_SUCCESS); +} + + +static trg_function_status trg_update_header_pointers + (struct trg_trajectory *trg_data) +{ + struct trg_gen_block block; + FILE *temp = trg_data->input_file; + uint64_t pos, contents_start_pos; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + printf("Cannot initialise destination file. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + trg_data->input_file = trg_data->output_file; + + trg_init_block(&block); + + trg_data->output_file_pos = ftell(trg_data->output_file); + fseek(trg_data->output_file, 0, SEEK_SET); + + if(trg_read_block_header(trg_data, &block) != TRG_SUCCESS) + { + printf("Cannot read general info header. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + contents_start_pos = ftell(trg_data->output_file); + + fseek(trg_data->output_file, block.block_contents_size - 3 * + sizeof(uint64_t), SEEK_CUR); + + trg_data->input_file = temp; + +// printf("Updating header\n"); +// printf("%ld: First frame set %ld\n", ftell(trg_data->output_file), +// trg_data->first_trajectory_frame_set_output_file_pos); + + pos = trg_data->first_trajectory_frame_set_output_file_pos; + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &pos) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + if(fwrite(&pos, sizeof(uint64_t), 1, trg_data->output_file) != 1) + { + trg_destroy_block(&block); + return(TRG_CRITICAL); + } + +// printf("%ld: Last frame set %ld\n", ftell(trg_data->output_file), +// trg_data->last_trajectory_frame_set_output_file_pos); + + pos = trg_data->last_trajectory_frame_set_output_file_pos; + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &pos) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + if(fwrite(&pos, + sizeof(uint64_t), 1, trg_data->output_file) != 1) + { + trg_destroy_block(&block); + return(TRG_CRITICAL); + } + + trg_update_md5_hash(trg_data, &block, 0, contents_start_pos); + + fseek(trg_data->output_file, trg_data->output_file_pos, SEEK_SET); + + trg_destroy_block(&block); + + return(TRG_SUCCESS); +} + +static trg_function_status trg_update_frame_set_pointers + (struct trg_trajectory *trg_data) +{ + struct trg_gen_block block; + struct trg_trajectory_frame_set *frame_set; + FILE *temp = trg_data->input_file; + uint64_t pos, header_start_pos, contents_start_pos; + + if(trg_init_output_file(trg_data, FALSE) != TRG_SUCCESS) + { + printf("Cannot initialise destination file. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + trg_init_block(&block); + trg_data->output_file_pos = ftell(trg_data->output_file); + + trg_data->input_file = trg_data->output_file; + + frame_set = &trg_data->current_trajectory_frame_set; + if(frame_set->prev_frame_set_file_pos != -1ULL && + frame_set->prev_frame_set_file_pos != 0) + { + fseek(trg_data->output_file, frame_set->prev_frame_set_file_pos, + SEEK_SET); + + header_start_pos = frame_set->prev_frame_set_file_pos; + + if(trg_read_block_header(trg_data, &block) != TRG_SUCCESS) + { + printf("Cannot read frame header. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + contents_start_pos = ftell(trg_data->output_file); + + fseek(trg_data->output_file, block.block_contents_size - 4 * + sizeof(uint64_t), SEEK_CUR); + +// printf("Updating frame set\n"); +// printf("%ld: Next frame set %ld\n", ftell(trg_data->output_file), +// trg_data->current_trajectory_frame_set_output_file_pos); + + pos = trg_data->current_trajectory_frame_set_output_file_pos; + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &pos) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + if(fwrite(&pos, sizeof(uint64_t), 1, trg_data->output_file) != 1) + { + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + trg_update_md5_hash(trg_data, &block, header_start_pos, + contents_start_pos); + + fseek(trg_data->output_file, trg_data->output_file_pos, SEEK_SET); + } + + if(frame_set->long_stride_prev_frame_set_file_pos != -1ULL && + frame_set->long_stride_prev_frame_set_file_pos != 0) + { + fseek(trg_data->output_file, + frame_set->long_stride_prev_frame_set_file_pos, + SEEK_SET); + + if(trg_read_block_header(trg_data, &block) != TRG_SUCCESS) + { + printf("Cannot read frame header. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + contents_start_pos = ftell(trg_data->output_file); + + fseek(trg_data->output_file, block.block_contents_size - 2 * + sizeof(uint64_t), SEEK_CUR); + + pos = trg_data->current_trajectory_frame_set_output_file_pos; + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, &pos) != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + if(fwrite(&pos, sizeof(uint64_t), 1, trg_data->output_file) != 1) + { + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + trg_update_md5_hash(trg_data, &block, + frame_set->long_stride_prev_frame_set_file_pos, + contents_start_pos); + } + + fseek(trg_data->output_file, trg_data->output_file_pos, SEEK_SET); + + trg_data->input_file = temp; + trg_destroy_block(&block); + + return(TRG_SUCCESS); +} + + +trg_function_status trg_set_block_name(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(block->name && strlen(block->name) < len) + { + free(block->name); + block->name = 0; + } + if(!block->name) + { + block->name = (char *) malloc(len); + if(!block->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(block->name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_init_block(struct trg_gen_block *block) +{ +// printf("In trg_init_block\n"); + + block->id = -1; +/* block->hash_type = TRG_NO_HASH; + block->hash_name = 0;*/ + memcpy(block->hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TRG_HASH_LEN); + block->name = 0; + block->block_version = TRG_VERSION; + block->header_contents = 0; + block->header_contents_size = 0; + block->block_contents = 0; + block->block_contents_size = 0; + + return(TRG_SUCCESS); +} + + +trg_function_status trg_destroy_block(struct trg_gen_block *block) +{ +// printf("Destroying block\n"); +/* if(block->hash_name) + { + free(block->hash_name); + block->hash_name = 0; + }*/ +/* if(block->hash) + { + free(block->hash); + block->hash = 0; + }*/ + if(block->name) + { + free(block->name); + block->name = 0; + } + if(block->header_contents) + { + free(block->header_contents); + block->header_contents = 0; + } + if(block->block_contents) + { + free(block->block_contents); + block->block_contents = 0; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_atom_name(struct trg_trajectory *trg_data, + struct trg_atom *atom, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(atom->name && strlen(atom->name) < len) + { + free(atom->name); + atom->name = 0; + } + if(!atom->name) + { + atom->name = (char *) malloc(len); + if(!atom->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(atom->name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_atom_type(struct trg_trajectory *trg_data, + struct trg_atom *atom, + const char *new_type) +{ + int len; + + len = min(strlen(new_type) + 1, TRG_MAX_STR_LEN); + + if(atom->atom_type && strlen(atom->atom_type) < len) + { + free(atom->atom_type); + atom->atom_type = 0; + } + if(!atom->atom_type) + { + atom->atom_type = (char *) malloc(len); + if(!atom->atom_type) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(atom->atom_type, new_type, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_init_atom(struct trg_atom *atom) +{ + atom->name = 0; + atom->atom_type = 0; + + return(TRG_SUCCESS); +} + +trg_function_status trg_destroy_atom(struct trg_atom *atom) +{ + if(atom->name) + { + free(atom->name); + atom->name = 0; + } + if(atom->atom_type) + { + free(atom->atom_type); + atom->atom_type = 0; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_add_molecule(struct trg_trajectory *trg_data, + const char *name, + struct trg_molecule **molecule) +{ + struct trg_molecule *new_molecules; + uint64_t *new_molecule_cnt_list; + int id, i; + trg_bool found_id = TRUE; + + new_molecules = (struct trg_molecule *)realloc(trg_data->molecules, + sizeof(struct trg_molecule) * + (trg_data->n_molecules + 1)); + + if(!new_molecules) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(struct trg_molecule) * (trg_data->n_molecules + 1), + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + new_molecule_cnt_list = (uint64_t *) realloc(trg_data->molecule_cnt_list, + sizeof(uint64_t) * + (trg_data->n_molecules + 1)); + + if(!new_molecules) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(uint64_t) * (trg_data->n_molecules + 1), + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + trg_data->molecules = new_molecules; + trg_data->molecule_cnt_list = new_molecule_cnt_list; + + *molecule = &new_molecules[trg_data->n_molecules]; + + trg_init_molecule(*molecule); + trg_set_molecule_name(trg_data, *molecule, name); + + /* FIXME: Should this be a function argument instead? */ + trg_data->molecule_cnt_list[trg_data->n_molecules] = 0; + + /* Find an unused ID */ + id = 0; + while(found_id) + { + found_id = FALSE; + for(i = trg_data->n_molecules; i--;) + { + if(trg_data->molecules[i].id == id) + { + found_id = TRUE; + i = 0; + } + } + if(found_id) + { + id++; + } + } + + (*molecule)->id = id; + + trg_data->n_molecules++; + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_molecule_name(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(molecule->name && strlen(molecule->name) < len) + { + free(molecule->name); + molecule->name = 0; + } + if(!molecule->name) + { + molecule->name = (char *) malloc(len); + if(!molecule->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(molecule->name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_get_molecule_cnt(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + uint64_t *cnt) +{ + int i, index = -1; + + for(i = trg_data->n_molecules; i--;) + { + if(&trg_data->molecules[i] == molecule) + { + index = i; + i = 0; + } + } + if(index == -1) + { + return(TRG_FAILURE); + } + *cnt = trg_data->molecule_cnt_list[index]; + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_molecule_cnt(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + const uint64_t cnt) +{ + int i, index = -1, old_cnt; + + for(i = trg_data->n_molecules; i--;) + { + if(&trg_data->molecules[i] == molecule) + { + index = i; + i = 0; + } + } + if(index == -1) + { + return(TRG_FAILURE); + } + old_cnt = trg_data->molecule_cnt_list[index]; + trg_data->molecule_cnt_list[index] = cnt; + + trg_data->n_particles += (cnt-old_cnt) * + trg_data->molecules[index].n_atoms; + + return(TRG_SUCCESS); +} + +trg_function_status trg_add_chain_to_molecule(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + const char *name, + struct trg_chain **chain) +{ + struct trg_chain *new_chains; + + new_chains = (struct trg_chain *) realloc(molecule->chains, + sizeof(struct trg_chain) * + (molecule->n_chains + 1)); + + if(!new_chains) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(struct trg_chain) * (molecule->n_chains + 1), + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + molecule->chains = new_chains; + + *chain = &new_chains[molecule->n_chains]; + (*chain)->name = 0; + + trg_set_chain_name(trg_data, *chain, name); + + (*chain)->molecule = molecule; + (*chain)->id = molecule->n_chains; + (*chain)->n_residues = 0; + + molecule->n_chains++; + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_chain_name(struct trg_trajectory *trg_data, + struct trg_chain *chain, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(chain->name && strlen(chain->name) < len) + { + free(chain->name); + chain->name = 0; + } + if(!chain->name) + { + chain->name = (char *) malloc(len); + if(!chain->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(chain->name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_add_residue_to_chain(struct trg_trajectory *trg_data, + struct trg_chain *chain, + const char *name, + struct trg_residue **residue) +{ + int curr_index; + struct trg_residue *new_residues, *temp_residue, *last_residue; + struct trg_molecule *molecule = chain->molecule; + + if(chain->n_residues) + { + curr_index = (chain->residues - molecule->residues) / + sizeof(struct trg_residue); + } + else + { + curr_index = -1; + } + + new_residues = (struct trg_residue *) realloc(molecule->residues, + sizeof(struct trg_residue) * + (molecule->n_residues + 1)); + + if(!new_residues) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(struct trg_residue) * (molecule->n_residues + 1), + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + molecule->residues = new_residues; + + if(curr_index != -1) + { + chain->residues = new_residues + curr_index * sizeof(struct trg_residue); + if(molecule->n_residues) + { + last_residue = &new_residues[molecule->n_atoms-1]; + + temp_residue = chain->residues + (chain->n_residues - 1); + /* Make space in list of residues to add the new residues together with the other + * residues of this chain */ + if(temp_residue != last_residue) + { + temp_residue++; + memmove(temp_residue + 1, temp_residue, + last_residue - temp_residue); + } + } + } + else + { + curr_index = molecule->n_residues; + } + + *residue = &new_residues[curr_index + chain->n_residues]; + + if(!chain->n_residues) + { + chain->residues = *residue; + } + + (*residue)->name = 0; + trg_set_residue_name(trg_data, *residue, name); + + (*residue)->chain = chain; + (*residue)->id = chain->n_residues; + (*residue)->n_atoms = 0; + (*residue)->atoms = 0; + + chain->n_residues++; + molecule->n_residues++; + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_residue_name(struct trg_trajectory *trg_data, + struct trg_residue *residue, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(residue->name && strlen(residue->name) < len) + { + free(residue->name); + residue->name = 0; + } + if(!residue->name) + { + residue->name = (char *) malloc(len); + if(!residue->name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(residue->name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_add_atom_to_residue(struct trg_trajectory *trg_data, + struct trg_residue *residue, + const char *atom_name, + const char *atom_type, + struct trg_atom **atom) +{ + int curr_index; + struct trg_atom *new_atoms, *temp_atom, *last_atom; + struct trg_molecule *molecule = residue->chain->molecule; + + if(residue->n_atoms) + { + curr_index = (residue->atoms - molecule->atoms) / + sizeof(struct trg_atom); + } + else + { + curr_index = -1; + } + + new_atoms = (struct trg_atom *) realloc(molecule->atoms, + sizeof(struct trg_atom) * + (molecule->n_atoms + 1)); + + if(!new_atoms) + { + printf("Cannot allocate memory (%"PRId64" bytes). %s: %d\n", + sizeof(struct trg_atom) * (molecule->n_atoms + 1), + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + molecule->atoms = new_atoms; + + if(curr_index != -1) + { + residue->atoms = new_atoms + curr_index * sizeof(struct trg_atom); + if(molecule->n_atoms) + { + last_atom = &new_atoms[molecule->n_atoms-1]; + + temp_atom = residue->atoms + (residue->n_atoms - 1); + /* Make space in list of atoms to add the new atoms together with the other + * atoms of this residue */ + if(temp_atom != last_atom) + { + temp_atom++; + memmove(temp_atom + 1, temp_atom, + last_atom - temp_atom); + } + } + } + else + { + curr_index = molecule->n_atoms; + } + + *atom = &new_atoms[curr_index + residue->n_atoms]; + + if(!residue->n_atoms) + { + residue->atoms = *atom; + } + + trg_init_atom(*atom); + trg_set_atom_name(trg_data, *atom, atom_name); + trg_set_atom_type(trg_data, *atom, atom_type); + + (*atom)->residue = residue; + (*atom)->id = molecule->n_atoms; + + residue->n_atoms++; + molecule->n_atoms++; + + return(TRG_SUCCESS); +} + + +trg_function_status trg_init_molecule(struct trg_molecule *molecule) +{ + molecule->name = 0; + molecule->n_chains = 0; + molecule->chains = 0; + molecule->n_residues = 0; + molecule->residues = 0; + molecule->n_atoms = 0; + molecule->atoms = 0; + molecule->n_bonds = 0; + molecule->bonds = 0; + + return(TRG_SUCCESS); +} + +trg_function_status trg_destroy_molecule(struct trg_molecule *molecule) +{ + int i; + + if(molecule->name) + { + free(molecule->name); + molecule->name = 0; + } + + if(molecule->chains) + { + for(i = molecule->n_chains; i--;) + { + if(molecule->chains[i].name) + { + free(molecule->chains[i].name); + molecule->chains[i].name = 0; + } + } + free(molecule->chains); + molecule->chains = 0; + } + molecule->n_chains = 0; + + if(molecule->residues) + { + for(i = molecule->n_residues; i--;) + { + if(molecule->residues[i].name) + { + free(molecule->residues[i].name); + molecule->residues[i].name = 0; + } + } + free(molecule->residues); + molecule->residues = 0; + } + molecule->n_residues = 0; + + if(molecule->atoms) + { + for(i = molecule->n_atoms; i--;) + { + trg_destroy_atom(&molecule->atoms[i]); + } + free(molecule->atoms); + molecule->atoms = 0; + } + molecule->n_atoms = 0; + + if(molecule->bonds) + { + free(molecule->bonds); + molecule->bonds = 0; + } + molecule->n_bonds = 0; + + return(TRG_SUCCESS); +} + +trg_function_status trg_init_trajectory(struct trg_trajectory *trg_data) +{ + time_t seconds; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + trg_data->input_file_path = 0; + trg_data->input_file = 0; + trg_data->input_file_pos = 0; + trg_data->input_file_len = 0; + trg_data->output_file_path = 0; + trg_data->output_file = 0; + trg_data->output_file_pos = 0; + + trg_data->program_name = 0; + trg_data->forcefield_name = 0; + + /* FIXME: No unistd.h on Windows!! */ +// trg_data->user_name = (char *) malloc(LOGIN_NAME_MAX); +// if(getlogin_r(trg_data->user_name, LOGIN_NAME_MAX) != 0) +// { +// printf("Cannot get user name. %s: %d\n", __FILE__, __LINE__); +// free(trg_data->user_name); +// trg_data->user_name = 0; +// } + trg_data->user_name = 0; + + seconds = time(0); + if ( seconds == -1) + { + printf("Cannot get time. %s: %d\n", __FILE__, __LINE__); + } + else + { + trg_data->time = seconds; + } + + /* FIXME: No unistd.h on Windows!! */ + /* FIXME: Append operating system to computer_name */ +// trg_data->computer_name = (char *) malloc(HOST_NAME_MAX); +// if(gethostname(trg_data->computer_name, HOST_NAME_MAX) != 0) +// { +// printf("Cannot get computer name. %s: %d\n", __FILE__, __LINE__); +// free(trg_data->computer_name); +// trg_data->computer_name = 0; +// } + trg_data->computer_name = 0; + + trg_data->pgp_signature = 0; + trg_data->var_num_atoms_flag = TRG_CONSTANT_N_ATOMS; + trg_data->first_trajectory_frame_set_input_file_pos = -1; + trg_data->last_trajectory_frame_set_input_file_pos = -1; + trg_data->current_trajectory_frame_set_input_file_pos = -1; + trg_data->first_trajectory_frame_set_output_file_pos = -1; + trg_data->last_trajectory_frame_set_output_file_pos = -1; + trg_data->current_trajectory_frame_set_output_file_pos = -1; + trg_data->frame_set_n_frames = 100; + trg_data->n_trajectory_frame_sets = 0; + trg_data->n_trajectory_blocks = 0; + trg_data->stride_length = 100; + + trg_data->n_particle_data_blocks = 0; + trg_data->n_data_blocks = 0; + + trg_data->non_tr_particle_data = 0; + trg_data->non_tr_data = 0; + + frame_set->contents.n_blocks = 0; + frame_set->contents.block_names = 0; + frame_set->n_mapping_blocks = 0; + frame_set->mappings = 0; + frame_set->molecule_cnt_list = 0; + + frame_set->n_particle_data_blocks = 0; + frame_set->n_data_blocks = 0; + + frame_set->tr_particle_data = 0; + frame_set->tr_data = 0; + + trg_data->n_molecules = 0; + trg_data->molecules = 0; + trg_data->molecule_cnt_list = 0; + trg_data->n_particles = 0; + + trg_data->n_id_name_pairs = 0; + trg_data->id_name_pairs = 0; + + /* Check the endianness of the computer */ + static uint32_t endianness_32 = 0x01234567; + /* 0x01234567 */ + if ( *(const uint8_t*)&endianness_32 == 0x01 ) + { + trg_data->endianness_32 = TRG_BIG_ENDIAN_32; + } + + /* 0x67452301 */ + else if( *(const uint8_t*)&endianness_32 == 0x67 ) + { + trg_data->endianness_32 = TRG_LITTLE_ENDIAN_32; + + } + + /* 0x45670123 */ + else if ( *(const uint8_t*)&endianness_32 == 0x45 ) + { + trg_data->endianness_32 = TRG_BYTE_PAIR_SWAP_32; + } + + static uint64_t endianness_64 = 0x0123456789ABCDEF; + /* 0x0123456789ABCDEF */ + if ( *(const uint8_t*)&endianness_64 == 0x01 ) + { + trg_data->endianness_64 = TRG_BIG_ENDIAN_64; + } + + /* 0xEFCDAB8967452301 */ + else if ( *(const uint8_t*)&endianness_64 == 0xEF ) + { + trg_data->endianness_64 = TRG_LITTLE_ENDIAN_64; + } + + /* 0x89ABCDEF01234567 */ + else if ( *(const uint8_t*)&endianness_64 == 0x89 ) + { + trg_data->endianness_64 = TRG_QUAD_SWAP_64; + } + + /* 0x45670123CDEF89AB */ + else if ( *(const uint8_t*)&endianness_64 == 0x45 ) + { + trg_data->endianness_64 = TRG_BYTE_PAIR_SWAP_64; + } + + /* 0x23016745AB89EFCD */ + else if ( *(const uint8_t*)&endianness_64 == 0x23 ) + { + trg_data->endianness_64 = TRG_BYTE_SWAP_64; + } + + + + trg_init_block(&trg_data->non_trajectory_blocks[0]); + trg_data->non_trajectory_blocks[0].id = TRG_GENERAL_INFO; + trg_set_block_name(trg_data, &trg_data->non_trajectory_blocks[0], + "GENERAL INFO"); + + trg_data->current_trajectory_frame_set.next_frame_set_file_pos = -1; + trg_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1; + + /* The Endianness and String Length block and the Trajectory Info block + * are present. */ + trg_data->n_non_trajectory_blocks = 1; + + return(TRG_SUCCESS); +} + +trg_function_status trg_destroy_trajectory(struct trg_trajectory *trg_data) +{ + uint64_t n_frames, n_particles; + int i, j, k, l; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + struct trg_particle_mapping *mapping; + + if(trg_data->input_file_path) + { + free(trg_data->input_file_path); + trg_data->input_file_path = 0; + } + + if(trg_data->input_file) + { + fclose(trg_data->input_file); + trg_data->input_file = 0; + } + + if(trg_data->output_file_path) + { + free(trg_data->output_file_path); + trg_data->output_file_path = 0; + } + + if(trg_data->output_file) + { + fclose(trg_data->output_file); + trg_data->output_file = 0; + } + + if(trg_data->program_name) + { + free(trg_data->program_name); + trg_data->program_name = 0; + } + + if(trg_data->forcefield_name) + { + free(trg_data->forcefield_name); + trg_data->forcefield_name = 0; + } + + if(trg_data->user_name) + { + free(trg_data->user_name); + trg_data->user_name = 0; + } + + if(trg_data->computer_name) + { + free(trg_data->computer_name); + trg_data->computer_name = 0; + } + + if(trg_data->pgp_signature) + { + free(trg_data->pgp_signature); + trg_data->pgp_signature = 0; + } + + if(frame_set->contents.block_names) + { + for(i = frame_set->contents.n_blocks; i--;) + { + if(frame_set->contents.block_names[i]) + { + free(frame_set->contents.block_names[i]); + frame_set->contents.block_names[i] = 0; + } + } + free(frame_set->contents.block_names); + frame_set->contents.block_names = 0; + } + + for(i = frame_set->n_mapping_blocks; i--;) + { + mapping = &frame_set->mappings[i]; + if(mapping->real_particle_numbers) + { + free(mapping->real_particle_numbers); + mapping->real_particle_numbers = 0; + } + } + free(frame_set->mappings); + frame_set->n_mapping_blocks = 0; + + if(frame_set->molecule_cnt_list) + { + free(frame_set->molecule_cnt_list); + frame_set->molecule_cnt_list = 0; + } + + for(i=trg_data->n_non_trajectory_blocks; i--;) + { + trg_destroy_block(&trg_data->non_trajectory_blocks[i]); + } + trg_data->n_trajectory_blocks = 0; + + if(trg_data->var_num_atoms_flag) + { + n_particles = trg_data->current_trajectory_frame_set.n_particles; + } + else + { + n_particles = trg_data->n_particles; + } + + if(trg_data->non_tr_particle_data) + { + for(i = trg_data->n_particle_data_blocks; i--; ) + { + if(trg_data->non_tr_particle_data[i].values) + { + /* Only one frame for non-trajectory data */ + j = 0; + if(trg_data->non_tr_particle_data[i].values[j]) + { + for(k = n_particles; k--;) + { + if(trg_data->non_tr_particle_data[i].values[j][k]) + { + if(trg_data->non_tr_particle_data[i].datatype == + TRG_CHAR_DATA) + { + for(l = trg_data->non_tr_particle_data[i]. + n_values_per_frame; + l--;) + { + if(trg_data->non_tr_particle_data[i]. + values[j][k][l].c) + { + free(trg_data->non_tr_particle_data[i]. + values[j][k][l].c); + trg_data->non_tr_particle_data[i]. + values[j][k][l].c = 0; + } + } + } + free(trg_data->non_tr_particle_data[i]. + values[j][k]); + trg_data->non_tr_particle_data[i]. + values[j][k] = 0; + } + } + free(trg_data->non_tr_particle_data[i].values[j]); + trg_data->non_tr_particle_data[i].values[j] = 0; + } + free(trg_data->non_tr_particle_data[i].values); + trg_data->non_tr_particle_data[i].values = 0; + } + if(trg_data->non_tr_particle_data[i].block_name) + { + free(trg_data->non_tr_particle_data[i].block_name); + trg_data->non_tr_particle_data[i].block_name = 0; + } + } + free(trg_data->non_tr_particle_data); + trg_data->non_tr_particle_data = 0; + } + + if(trg_data->non_tr_data) + { + for(i = trg_data->n_data_blocks; i--;) + { + if(trg_data->non_tr_data[i].values) + { + /* Only one frame for non-trajectory data */ + if(trg_data->non_tr_data[i].values[0]) + { + if(trg_data->non_tr_data[i].datatype == + TRG_CHAR_DATA) + { + for(k = trg_data->non_tr_data[i].n_values_per_frame; + k--;) + { + if(trg_data->non_tr_data[i].values[0][k].c) + { + free(trg_data->non_tr_data[i].values[0][k].c); + trg_data->non_tr_data[i].values[0][k].c = 0; + } + } + } + free(trg_data->non_tr_data[i].values[0]); + trg_data->non_tr_data[i].values[0] = 0; + } + free(trg_data->non_tr_data[i].values); + trg_data->non_tr_data[i].values = 0; + } + if(trg_data->non_tr_data[i].block_name) + { + free(trg_data->non_tr_data[i].block_name); + trg_data->non_tr_data[i].block_name = 0; + } + } + free(trg_data->non_tr_data); + trg_data->non_tr_data = 0; + } + + trg_data->n_particle_data_blocks = 0; + trg_data->n_data_blocks = 0; + + if(frame_set->tr_particle_data) + { + for(i = frame_set->n_particle_data_blocks; i--; ) + { + if(frame_set->tr_particle_data[i].values) + { + n_frames = max(1, frame_set->tr_particle_data[i].n_frames); + for(j = n_frames; j--;) + { + if(frame_set->tr_particle_data[i].values[j]) + { + for(k = n_particles; k--;) + { + if(frame_set->tr_particle_data[i].values[j][k]) + { + if(frame_set->tr_particle_data[i].datatype == + TRG_CHAR_DATA) + { + for(l = frame_set->tr_particle_data[i]. + n_values_per_frame; + l--;) + { + if(frame_set->tr_particle_data[i]. + values[j][k][l].c) + { + free(frame_set->tr_particle_data[i]. + values[j][k][l].c); + + frame_set->tr_particle_data[i]. + values[j][k][l].c = 0; + } + } + } + free(frame_set->tr_particle_data[i]. + values[j][k]); + frame_set->tr_particle_data[i].values[j][k] = 0; + } + } + free(frame_set->tr_particle_data[i].values[j]); + frame_set->tr_particle_data[i].values[j] = 0; + } + } + free(frame_set->tr_particle_data[i].values); + frame_set->tr_particle_data[i].values = 0; + } + if(frame_set->tr_particle_data[i].block_name) + { + free(frame_set->tr_particle_data[i].block_name); + frame_set->tr_particle_data[i].block_name = 0; + } + } + free(frame_set->tr_particle_data); + frame_set->tr_particle_data = 0; + } + + if(frame_set->tr_data) + { + for(i = frame_set->n_data_blocks; i--;) + { + if(frame_set->tr_data[i].values) + { + n_frames = max(1, frame_set->tr_data[i].n_frames); + for(j = n_frames; j--;) + { + if(frame_set->tr_data[i].values[j]) + { + if(frame_set->tr_data[i].datatype == + TRG_CHAR_DATA) + { + for(k = frame_set->tr_data[i].n_values_per_frame; + k--;) + { + if(frame_set->tr_data[i].values[j][k].c) + { + free(frame_set->tr_data[i]. + values[j][k].c); + + frame_set->tr_data[i]. + values[j][k].c = 0; + } + } + } + free(frame_set->tr_data[i].values[j]); + frame_set->tr_data[i].values[j] = 0; + } + } + free(frame_set->tr_data[i].values); + frame_set->tr_data[i].values = 0; + } + if(frame_set->tr_data[i].block_name) + { + free(frame_set->tr_data[i].block_name); + frame_set->tr_data[i].block_name = 0; + } + } + free(frame_set->tr_data); + frame_set->tr_data = 0; + } + + frame_set->n_particle_data_blocks = 0; + frame_set->n_data_blocks = 0; + + if(trg_data->molecules) + { + for(i=trg_data->n_molecules; i--;) + { + trg_destroy_molecule(&trg_data->molecules[i]); + } + free(trg_data->molecules); + trg_data->molecules = 0; + trg_data->n_molecules = 0; + } + if(trg_data->molecule_cnt_list) + { + free(trg_data->molecule_cnt_list); + trg_data->molecule_cnt_list = 0; + } + return(TRG_SUCCESS); +} + +trg_function_status trg_set_input_file(struct trg_trajectory *trg_data, + const char *file_name) +{ + int len; + char *temp; + + if(trg_data->input_file_path && strcmp(trg_data->input_file_path, + file_name) == 0) + { + return(TRG_SUCCESS); + } + + if(trg_data->input_file) + { + fclose(trg_data->input_file); + } + + len = min(strlen(file_name) + 1, TRG_MAX_STR_LEN); + temp = realloc(trg_data->input_file_path, len); + if(!temp) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + trg_data->input_file_path = temp; + + strncpy(trg_data->input_file_path, file_name, len); + + return(trg_init_input_file(trg_data, FALSE)); +} + +trg_function_status trg_set_output_file(struct trg_trajectory *trg_data, + const char *file_name) +{ + int len; + char *temp; + + if(trg_data->output_file_path && + strcmp(trg_data->output_file_path, file_name) == 0) + { + return(TRG_SUCCESS); + } + + if(trg_data->output_file) + { + fclose(trg_data->output_file); + } + + len = min(strlen(file_name) + 1, TRG_MAX_STR_LEN); + temp = realloc(trg_data->output_file_path, len); + if(!temp) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + trg_data->output_file_path = temp; + + strncpy(trg_data->output_file_path, file_name, len); + + return(trg_init_output_file(trg_data, FALSE)); +} + + +trg_function_status trg_set_program_name(struct trg_trajectory *trg_data, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(trg_data->program_name && strlen(trg_data->program_name) < len) + { + free(trg_data->program_name); + trg_data->program_name = 0; + } + if(!trg_data->program_name) + { + trg_data->program_name = (char *) malloc(len); + if(!trg_data->program_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(trg_data->program_name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_forcefield_name(struct trg_trajectory *trg_data, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(trg_data->forcefield_name && strlen(trg_data->forcefield_name) < len) + { + free(trg_data->forcefield_name); + trg_data->forcefield_name = 0; + } + if(!trg_data->forcefield_name) + { + trg_data->forcefield_name = (char *) malloc(len); + if(!trg_data->forcefield_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(trg_data->forcefield_name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_user_name(struct trg_trajectory *trg_data, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(trg_data->user_name && strlen(trg_data->user_name) < len) + { + free(trg_data->user_name); + trg_data->user_name = 0; + } + if(!trg_data->user_name) + { + trg_data->user_name = (char *) malloc(len); + if(!trg_data->user_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(trg_data->user_name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_computer_name(struct trg_trajectory *trg_data, + const char *new_name) +{ + int len; + + len = min(strlen(new_name) + 1, TRG_MAX_STR_LEN); + + if(trg_data->computer_name && strlen(trg_data->computer_name) < len) + { + free(trg_data->computer_name); + trg_data->computer_name = 0; + } + if(!trg_data->computer_name) + { + trg_data->computer_name = (char *) malloc(len); + if(!trg_data->computer_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(trg_data->computer_name, new_name, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_set_signature(struct trg_trajectory *trg_data, + const char *signature) +{ + int len; + + len = min(strlen(signature) + 1, TRG_MAX_STR_LEN); + + if(trg_data->pgp_signature && strlen(trg_data->pgp_signature) < len) + { + free(trg_data->pgp_signature); + trg_data->pgp_signature = 0; + } + if(!trg_data->pgp_signature) + { + trg_data->pgp_signature = (char *) malloc(len); + if(!trg_data->pgp_signature) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + strncpy(trg_data->pgp_signature, signature, len); + + return(TRG_SUCCESS); +} + +trg_function_status trg_read_file_headers(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + int i, cnt = 0, prev_pos = 0; + struct trg_gen_block *block = trg_data->non_trajectory_blocks; + + trg_data->input_file_pos = 0; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + if(!trg_data->input_file_len) + { + fseek(trg_data->input_file, 0, SEEK_END); + trg_data->input_file_len = ftell(trg_data->input_file); + fseek(trg_data->input_file, 0, SEEK_SET); + } + + for(i = trg_data->n_non_trajectory_blocks; i--;) + { + trg_destroy_block(block++); + } + trg_data->n_non_trajectory_blocks = 0; + + block = trg_data->non_trajectory_blocks; + + trg_init_block(block); + /* Non trajectory blocks (they come before the trajectory + * blocks in the file) */ + while (prev_pos < trg_data->input_file_len && + trg_read_block_header(trg_data, block) != TRG_CRITICAL && + block->id != -1 && + block->id != TRG_TRAJECTORY_FRAME_SET && + trg_data->n_non_trajectory_blocks < 32) + { +// printf("Reading block header %d: %s\n", (int)block->id, block->name); + if(trg_read_next_block(trg_data, block, + TRG_KEEP_FILE_OPEN) == TRG_SUCCESS) + { +// printf("Read block %s\n", block->name); + block++; + cnt++; + trg_data->n_non_trajectory_blocks++; + if(trg_init_block(block) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + } + else + { + trg_destroy_block(block); + } + prev_pos = ftell(trg_data->input_file); + } + + /* Go back if a trajectory block was encountered */ + if(block->id == TRG_TRAJECTORY_FRAME_SET) + { + trg_destroy_block(block); + fseek(trg_data->input_file, prev_pos, SEEK_SET); + } + + if(close_file) + { + trg_data->input_file_pos=ftell(trg_data->input_file); + fclose(trg_data->input_file); + trg_data->input_file = 0; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_write_file_headers(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + int i; + struct trg_gen_block *block, data_block; + + trg_data->output_file_pos = 0; + + if(trg_init_output_file(trg_data, TRUE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + + for(i=0; in_non_trajectory_blocks; ++i) + { + block = &trg_data->non_trajectory_blocks[i]; + if(block->id == TRG_GENERAL_INFO) + { + if(trg_write_general_info_block(trg_data, block, TRG_NORMAL_WRITE) + != TRG_SUCCESS) + { + printf("Error writing general info block of file %s. %s: %d\n", + trg_data->input_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + break; + } + } + + for(i=0; in_non_trajectory_blocks; ++i) + { + block = &trg_data->non_trajectory_blocks[i]; + if(block->id == TRG_MOLECULES) + { + if(trg_write_molecules_block(trg_data, block, TRG_NORMAL_WRITE) + != TRG_SUCCESS) + { + printf("Error writing atom names block of file %s. %s: %d\n", + trg_data->input_file_path, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + break; + } + } + + /* FIXME: Currently writing non-trajectory data blocks here. + * Should perhaps be moved. */ + trg_init_block(&data_block); + for(i = 0; i < trg_data->n_data_blocks; i++) + { + data_block.id = trg_data->non_tr_data[i].block_id; + trg_write_data_block(trg_data, &data_block, + i, TRG_NORMAL_WRITE); + } + + for(i = 0; i < trg_data->n_particle_data_blocks; i++) + { + data_block.id = trg_data->non_tr_particle_data[i].block_id; + trg_write_particle_data_block(trg_data, &data_block, + i, 0, TRG_NORMAL_WRITE); + } + + trg_destroy_block(&data_block); + + if(close_file) + { + trg_data->output_file_pos=ftell(trg_data->output_file); + fclose(trg_data->output_file); + trg_data->output_file = 0; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_read_next_block(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + trg_close_file_flag close_file) +{ + switch(block->id) + { + case TRG_TRAJECTORY_FRAME_SET: + return(trg_read_frame_set_block(trg_data, block)); + case TRG_BLOCK_TABLE_OF_CONTENTS: + return(trg_read_trajectory_toc_block(trg_data, block)); + case TRG_PARTICLE_MAPPING: + return(trg_read_trajectory_mapping_block(trg_data, block)); + case TRG_GENERAL_INFO: + return(trg_read_general_info_block(trg_data, block)); + case TRG_MOLECULES: + return(trg_read_molecules_block(trg_data, block)); + default: + if(block->id >= TRG_TRAJ_BOX_SHAPE) + { + return(trg_read_data_block_contents(trg_data, block)); + } + else + { + /* Skip to the next block */ + fseek(trg_data->input_file, block->block_contents_size, SEEK_CUR); + return(TRG_FAILURE); + } + } + + /* FIXME: Never reached. */ + if(close_file) + { + trg_data->input_file_pos=ftell(trg_data->input_file); + fclose(trg_data->input_file); + trg_data->input_file = 0; + } +} + +// trg_function_status trg_write_block(struct trg_trajectory *trg_data, +// struct trg_gen_block *block, +// trg_close_file_flag close_file) +// { +// if(trg_data->output_file) +// { +// trg_data->output_file_pos = ftell(trg_data->output_file); +// } +// +// switch(block->id) +// { +// case TRG_TRAJECTORY_FRAME_SET: +// return(trg_write_frame_set_block(trg_data, block, TRG_NORMAL_WRITE)); +// break; +// case TRG_BLOCK_TABLE_OF_CONTENTS: +// return(trg_write_trajectory_toc_block(trg_data, block, +// TRG_NORMAL_WRITE)); +// break; +// case TRG_PARTICLE_MAPPING: +// return(trg_write_trajectory_mapping_block(trg_data, block, +// TRG_NORMAL_WRITE)); +// break; +// case TRG_TRAJ_POSITIONS: +// break; +// case TRG_TRAJ_VELOCITIES: +// break; +// case TRG_TRAJ_FORCES: +// break; +// case TRG_TRAJ_BOX_SHAPE: +// break; +// case TRG_GENERAL_INFO: +// return(trg_write_general_info_block(trg_data, block, +// TRG_NORMAL_WRITE)); +// case TRG_MOLECULES: +// return(trg_write_molecules_block(trg_data, block, +// TRG_NORMAL_WRITE)); +// default: +// if(block->id > TRG_TRAJ_FORCES) +// { +// /* Implement writing data blocks. */ +// return(TRG_FAILURE); +// } +// else +// { +// return(TRG_FAILURE); +// } +// } +// +// /* FIXME: Never reached. */ +// if(close_file) +// { +// fclose(trg_data->output_file); +// trg_data->output_file = 0; +// } +// +// return(TRG_SUCCESS); +// } + +trg_function_status trg_read_next_frame_set(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + long int file_pos; + struct trg_gen_block block; + trg_function_status stat = TRG_SUCCESS; + + if(trg_init_input_file(trg_data, FALSE) != TRG_SUCCESS) + { + return(TRG_CRITICAL); + } + + trg_init_block(&block); + + file_pos = trg_data->current_trajectory_frame_set.next_frame_set_file_pos; + + if(file_pos > 0) + { + fseek(trg_data->input_file, + file_pos, + SEEK_SET); + } + else + { + return(TRG_CRITICAL); + } + + if(!trg_data->input_file_len) + { + fseek(trg_data->input_file, 0, SEEK_END); + trg_data->input_file_len = ftell(trg_data->input_file); + fseek(trg_data->input_file, file_pos, SEEK_SET); + } + + stat = trg_read_block_header(trg_data, &block); + if(stat == TRG_CRITICAL || block.id != TRG_TRAJECTORY_FRAME_SET) + { + return(TRG_CRITICAL); + } + + trg_data->current_trajectory_frame_set_input_file_pos = file_pos; + + if(trg_read_next_block(trg_data, &block, + TRG_KEEP_FILE_OPEN) == TRG_SUCCESS) + { + file_pos = ftell(trg_data->input_file); + /* Read all blocks until next frame set block */ + stat = trg_read_block_header(trg_data, &block); + while(file_pos < trg_data->input_file_len && + stat != TRG_CRITICAL && + block.id != TRG_TRAJECTORY_FRAME_SET) + { + stat = trg_read_next_block(trg_data, &block, + TRG_KEEP_FILE_OPEN) == TRG_SUCCESS; + + if(stat != TRG_CRITICAL) + { + file_pos = ftell(trg_data->input_file); + if(file_pos < trg_data->input_file_len) + { + stat = trg_read_block_header(trg_data, &block); + } + } + } + if(stat == TRG_CRITICAL) + { + return(stat); + } + + if(block.id == TRG_TRAJECTORY_FRAME_SET) + { + fseek(trg_data->input_file, file_pos, SEEK_SET); + } + } + + trg_data->input_file_pos=ftell(trg_data->input_file); + + trg_destroy_block(&block); + + if(close_file) + { + fclose(trg_data->input_file); + trg_data->input_file = 0; + } + + return(TRG_SUCCESS); +} + +trg_function_status trg_write_frame_set(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + int i, j; + struct trg_gen_block block; + struct trg_trajectory_frame_set *frame_set = + &trg_data->current_trajectory_frame_set; + + trg_function_status stat; + + + if(trg_data->output_file) + { + trg_data->current_trajectory_frame_set_output_file_pos = + ftell(trg_data->output_file); + } + else + { + trg_data->current_trajectory_frame_set_output_file_pos = + trg_data->output_file_pos; + } + + trg_init_block(&block); + block.id = TRG_TRAJECTORY_FRAME_SET; + + trg_write_frame_set_block(trg_data, &block, TRG_NORMAL_WRITE); + + if(frame_set->contents.n_blocks > 0) + { + block.id = TRG_BLOCK_TABLE_OF_CONTENTS; + trg_write_trajectory_toc_block(trg_data, &block, TRG_NORMAL_WRITE); + } + for(i = 0; in_data_blocks; i++) + { + block.id = frame_set->tr_data[i].block_id; + trg_write_data_block(trg_data, &block, i, TRG_NORMAL_WRITE); + } + if(frame_set->n_mapping_blocks) + { + for(i = 0; i < frame_set->n_mapping_blocks; i++) + { + block.id = TRG_PARTICLE_MAPPING; + if(frame_set->mappings[i].n_particles > 0) + { + trg_write_trajectory_mapping_block(trg_data, &block, i, + TRG_NORMAL_WRITE); + for(j = 0; jn_particle_data_blocks; j++) + { + block.id = frame_set->tr_particle_data[i].block_id; + trg_write_particle_data_block(trg_data, &block, + j, &frame_set->mappings[i], + TRG_NORMAL_WRITE); + } + } + } + } + else + { + for(i = 0; in_particle_data_blocks; i++) + { + block.id = frame_set->tr_particle_data[i].block_id; + trg_write_particle_data_block(trg_data, &block, + i, 0, TRG_NORMAL_WRITE); + } + } + + trg_data->output_file_pos = ftell(trg_data->output_file); + + stat = trg_update_header_pointers(trg_data); + + if(stat == TRG_SUCCESS) + { + stat = trg_update_frame_set_pointers(trg_data); + } + + trg_destroy_block(&block); + + if(close_file) + { + fclose(trg_data->input_file); + trg_data->input_file = 0; + } + + return(stat); +} + +trg_function_status trg_new_frame_set(struct trg_trajectory *trg_data, + const uint64_t first_frame, + const uint64_t n_frames) +{ + int i; + struct trg_gen_block block; + struct trg_trajectory_frame_set *frame_set; + struct trg_particle_mapping *mapping; + FILE *temp = trg_data->input_file; + uint64_t curr_pos; + + frame_set = &trg_data->current_trajectory_frame_set; + + if(trg_data->n_trajectory_frame_sets) + { + frame_set->prev_frame_set_file_pos = + trg_data->current_trajectory_frame_set_output_file_pos; + } + + if(trg_data->output_file) + { + trg_data->current_trajectory_frame_set_output_file_pos = + ftell(trg_data->output_file); + } + else + { + trg_data->current_trajectory_frame_set_output_file_pos = + trg_data->output_file_pos; + } + + if(frame_set->n_mapping_blocks && frame_set->mappings) + { + for(i = frame_set->n_mapping_blocks; i--;) + { + mapping = &frame_set->mappings[i]; + if(mapping->real_particle_numbers) + { + free(mapping->real_particle_numbers); + mapping->real_particle_numbers = 0; + } + } + free(frame_set->mappings); + frame_set->n_mapping_blocks = 0; + } + + trg_data->n_trajectory_frame_sets++; + + /* Set the long range pointers */ + if(trg_data->n_trajectory_frame_sets == trg_data->stride_length + 1) + { + frame_set->long_stride_prev_frame_set_file_pos = + trg_data->first_trajectory_frame_set_output_file_pos; + } + else if(trg_data->n_trajectory_frame_sets > trg_data->stride_length + 1) + { + /* FIXME: Currently only working if the previous frame set has its + * long stride pointer already set. This might need some fixing. */ + if(frame_set->long_stride_prev_frame_set_file_pos != -1ULL && + frame_set->long_stride_prev_frame_set_file_pos != 0) + { + trg_init_block(&block); + trg_data->input_file = trg_data->output_file; + + curr_pos = ftell(trg_data->output_file); + fseek(trg_data->output_file, + frame_set->long_stride_prev_frame_set_file_pos, + SEEK_SET); + + if(trg_read_block_header(trg_data, &block) != TRG_SUCCESS) + { + printf("Cannot read frame header. %s: %d\n", + __FILE__, __LINE__); + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + /* Read the next frame set from the previous frame set and one + * long stride step back */ + fseek(trg_data->output_file, block.block_contents_size - 4 * + sizeof(uint64_t), SEEK_CUR); + if(fread(&frame_set->long_stride_prev_frame_set_file_pos, + sizeof(frame_set->long_stride_prev_frame_set_file_pos), + 1, trg_data->output_file) == 0) + { + printf("Cannot read block. %s: %d\n", __FILE__, __LINE__); + trg_destroy_block(&block); + trg_data->input_file = temp; + return(TRG_CRITICAL); + } + + if(trg_data->endianness_64 != TRG_BIG_ENDIAN_64) + { + if(trg_swap_byte_order_64(trg_data, + &frame_set-> + long_stride_prev_frame_set_file_pos) + != TRG_SUCCESS) + { + printf("Cannot swap byte order to get big endian. %s: %d\n", + __FILE__, __LINE__); + } + } + + trg_destroy_block(&block); + trg_data->input_file = temp; + fseek(trg_data->output_file, curr_pos, SEEK_SET); + } + } + + frame_set->first_frame = first_frame; + frame_set->n_frames = n_frames; +// frame_set->n_particle_data_blocks = 0; +// frame_set->n_data_blocks = 0; + + if(trg_data->first_trajectory_frame_set_output_file_pos == -1ULL || + trg_data->first_trajectory_frame_set_output_file_pos == 0) + { + trg_data->first_trajectory_frame_set_output_file_pos = + trg_data->current_trajectory_frame_set_output_file_pos; + } + /* FIXME: Should check the frame number instead of the file_pos, + * in case frame sets are not in order */ + if(trg_data->last_trajectory_frame_set_output_file_pos == -1ULL || + trg_data->last_trajectory_frame_set_output_file_pos == 0 || + trg_data->last_trajectory_frame_set_output_file_pos < + trg_data->current_trajectory_frame_set_output_file_pos) + { + trg_data->last_trajectory_frame_set_output_file_pos = + trg_data->current_trajectory_frame_set_output_file_pos; + } + + return(TRG_SUCCESS); +} + +/* UNTESTED */ +trg_function_status trg_add_data_block(struct trg_trajectory *trg_data, + const uint64_t id, + const char *block_name, + const char datatype, + const uint64_t n_frames, + const uint64_t n_values_per_frame, + const uint64_t stride_length, + uint64_t codec_id, + void *new_data) +{ + int i, j, block_index, size, len; + struct trg_trajectory_frame_set *frame_set; + struct trg_data *data; + void *orig; + trg_block_type block_type_flag; + + frame_set = &trg_data->current_trajectory_frame_set; + + if(trg_data->current_trajectory_frame_set_output_file_pos > 0) + { + block_type_flag = TRG_TRAJECTORY_BLOCK; + } + else + { + block_type_flag = TRG_NON_TRAJECTORY_BLOCK; + } + + block_index = -1; + /* See if there is already a data block of this ID */ + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + for(i = frame_set->n_data_blocks; i-- ;) + { + data = &frame_set->tr_data[i]; + if(data->block_id == id) + { + block_index = i; + break; + } + } + } + else + { + for(i = trg_data->n_data_blocks; i-- ;) + { + data = &trg_data->non_tr_data[i]; + if(data->block_id == id) + { + block_index = i; + break; + } + } + } + + /* Otherwise create a data block */ + if(block_index == -1) + { + if(trg_create_data_block(trg_data, block_type_flag) != + TRG_SUCCESS) + { + printf("Cannot create data block. %s: %d\n", __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + data = &frame_set->tr_data[frame_set->n_data_blocks - 1]; + } + else + { + data = &trg_data->non_tr_data[trg_data->n_data_blocks - 1]; + } + data->block_id = id; + + data->block_name = malloc(strlen(block_name) + 1); + if(!data->block_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + (int)strlen(block_name)+1, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->block_name, block_name, strlen(block_name) + 1); + + data->datatype = datatype; + + data->stride_length = 1; + data->values = 0; + data->n_values_per_frame = 0; + data->n_frames = 0; + data->codec_id = codec_id; + } + + /* Allocate memory */ + if(!data->values || data->n_frames != n_frames || + data->n_values_per_frame != n_values_per_frame) + { + if(trg_allocate_data_mem(trg_data, data, n_frames, + n_values_per_frame) != + TRG_SUCCESS) + { + printf("Cannot allocate data memory. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + switch(datatype) + { + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_CHAR_DATA: + size = sizeof(char); + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + break; + } + + orig = new_data; + + for(i = 0; i < n_frames; i++) + { + for(j = 0; j < n_values_per_frame; j++) + { + /* FIXME: Not optimal to have this switch statement inside + * the for loops. Check if it should be moved outside. */ + switch(datatype) + { + case TRG_CHAR_DATA: + len = min(strlen(new_data) + 1, + TRG_MAX_STR_LEN); + if(data->values[i][j].c) + { + free(data->values[i][j].c); + } + data->values[i][j].c = malloc(len); + if(!data->values[i][j].c) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + len, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->values[i][j].c, + new_data, len); + new_data += len; + break; + case TRG_INT_DATA: + memcpy(&data->values[i][j].i, + new_data, size); + new_data += size; + break; + case TRG_FLOAT_DATA: + memcpy(&data->values[i][j].f, + new_data, size); + new_data += size; + break; + case TRG_DOUBLE_DATA: + default: + memcpy(&data->values[i][j].d, + new_data, size); + new_data += size; + } + } + } + + new_data = orig; + + return(TRG_SUCCESS); +} + + +trg_function_status trg_add_particle_data_block(struct trg_trajectory *trg_data, + const uint64_t id, + const char *block_name, + const char datatype, + const uint64_t n_frames, + const uint64_t n_values_per_frame, + const uint64_t stride_length, + const uint64_t first_particle_number, + const uint64_t n_particles, + uint64_t codec_id, + void *new_data) +{ + int i, j, k, block_index, size, len; + uint64_t tot_n_particles; + struct trg_trajectory_frame_set *frame_set; + struct trg_particle_data *data; + void *orig; + trg_block_type block_type_flag; + + frame_set = &trg_data->current_trajectory_frame_set; + + if(trg_data->current_trajectory_frame_set_output_file_pos > 0) + { + block_type_flag = TRG_TRAJECTORY_BLOCK; + } + else + { + block_type_flag = TRG_NON_TRAJECTORY_BLOCK; + } + + block_index = -1; + /* See if there is already a data block of this ID */ + if(block_type_flag == TRG_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 = trg_data->n_particle_data_blocks; i-- ;) + { + data = &trg_data->non_tr_particle_data[i]; + if(data->block_id == id) + { + block_index = i; + break; + } + } + } + + /* Otherwise create a data block */ + if(block_index == -1) + { + if(trg_create_particle_data_block(trg_data, block_type_flag) != + TRG_SUCCESS) + { + printf("Cannot create particle data block. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + if(block_type_flag == TRG_TRAJECTORY_BLOCK) + { + data = &frame_set->tr_particle_data[frame_set-> + n_particle_data_blocks - 1]; + } + else + { + data = &trg_data->non_tr_particle_data[trg_data-> + n_particle_data_blocks - 1]; + } + data->block_id = id; + + data->block_name = malloc(strlen(block_name) + 1); + if(!data->block_name) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + (int)strlen(block_name)+1, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->block_name, block_name, strlen(block_name) + 1); + + data->datatype = datatype; + + data->stride_length = 1; + data->values = 0; + data->n_values_per_frame = 0; + data->n_frames = 0; + data->codec_id = codec_id; + } + + if(block_type_flag == TRG_TRAJECTORY_BLOCK && trg_data->var_num_atoms_flag) + { + tot_n_particles = frame_set->n_particles; + } + else + { + tot_n_particles = trg_data->n_particles; + } + + /* Allocate memory */ + if(!data->values || data->n_frames != n_frames || + data->n_values_per_frame != n_values_per_frame) + { + if(trg_allocate_particle_data_mem(trg_data, data, n_frames, + tot_n_particles, + n_values_per_frame) != + TRG_SUCCESS) + { + printf("Cannot allocate particle data memory. %s: %d\n", + __FILE__, __LINE__); + return(TRG_CRITICAL); + } + } + + switch(datatype) + { + case TRG_FLOAT_DATA: + size = sizeof(float); + break; + case TRG_INT_DATA: + size = sizeof(uint64_t); + break; + case TRG_CHAR_DATA: + size = sizeof(char); + case TRG_DOUBLE_DATA: + default: + size = sizeof(double); + break; + } + + orig = new_data; + + for(i = 0; i < n_frames; i++) + { + for(j = first_particle_number; j < n_particles; j++) + { + for(k = 0; k < n_values_per_frame; k++) + { + /* FIXME: Not optimal to have this switch statement inside + * the for loops. Check if it should be moved outside. */ + switch(datatype) + { + case TRG_CHAR_DATA: + len = min(strlen(new_data) + 1, + TRG_MAX_STR_LEN); + if(data->values[i][j][k].c) + { + free(data->values[i][j][k].c); + } + data->values[i][j][k].c = malloc(len); + if(!data->values[i][j][k].c) + { + printf("Cannot allocate memory (%d bytes). %s: %d\n", + len, __FILE__, __LINE__); + return(TRG_CRITICAL); + } + strncpy(data->values[i][j][k].c, + new_data, len); + new_data += len; + break; + case TRG_INT_DATA: + memcpy(&data->values[i][j][k].i, + new_data, size); + new_data += size; + break; + case TRG_FLOAT_DATA: + memcpy(&data->values[i][j][k].f, + new_data, size); + new_data += size; + break; + case TRG_DOUBLE_DATA: + default: + memcpy(&data->values[i][j][k].d, + new_data, size); + new_data += size; + } + } + } + } + + new_data = orig; + + return(TRG_SUCCESS); +} + + +trg_function_status trg_read_next_traj_block(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_write_next_traj_block(struct trg_trajectory *trg_data, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_read_traj_block(struct trg_trajectory *trg_data, + uint64_t block_id, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_write_traj_block(struct trg_trajectory *trg_data, + uint64_t block_id, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_read_frame_nr(struct trg_trajectory *trg_data, + uint64_t frame_nr, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_write_frame_nr(struct trg_trajectory *trg_data, + uint64_t frame_nr, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_read_frame_nrs(struct trg_trajectory *trg_data, + uint64_t start_frame_nr, + uint64_t end_frame_nr, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_write_frame_nrs(struct trg_trajectory *trg_data, + uint64_t start_frame_nr, + uint64_t end_frame_nr, + trg_close_file_flag close_file) +{ + /* STUB */ + return(TRG_SUCCESS); +} + +trg_function_status trg_read_frame_set_nr(struct trg_trajectory *trg_data, + uint64_t frame_set_nr) +{ + return(TRG_SUCCESS); +} + + +trg_function_status trg_get_time_str(struct trg_trajectory *trg_data, + char *time) +{ + struct tm *time_data; + time_t secs; + + secs = trg_data->time; + + time_data = localtime(&secs); // Returns a statically allocated variable. + snprintf(time, TRG_MAX_DATE_STR_LEN, + "%4d-%02d-%02d %02d:%02d:%02d", + time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday, + time_data->tm_hour, time_data->tm_min, time_data->tm_sec); + + return(TRG_SUCCESS); +} + diff --git a/src/lib/trg_io.h b/src/lib/trg_io.h new file mode 100644 index 0000000..7bdca5e --- /dev/null +++ b/src/lib/trg_io.h @@ -0,0 +1,760 @@ +#ifndef _TRGIO_H +#define _TRGIO_H 1 + +#include +#include + +#define TRG_VERSION 1 + +#define TRG_UNCOMPRESSED 0ULL +#define TRG_XTC 1ULL +#define TRG_TNG_POSITIONS 2ULL +#define TRG_TNG_VELOCITIES 3ULL +#define TRG_TNG_FORCES 4ULL + +#define TRG_PARTICLE_DEPENDENT 1 +#define TRG_FRAME_DEPENDENT 2 + +// #define TRG_MAX_BLOCK_PARTICLES 1000 +#define TRG_MAX_DATE_STR_LEN 24 +#define TRG_HASH_LEN 16 +#define TRG_MAX_STR_LEN 1024 + +typedef enum {TRG_BIG_ENDIAN_32, + TRG_LITTLE_ENDIAN_32, + TRG_BYTE_PAIR_SWAP_32} trg_endianness_32; + +typedef enum {TRG_BIG_ENDIAN_64, + TRG_LITTLE_ENDIAN_64, + TRG_QUAD_SWAP_64, + TRG_BYTE_PAIR_SWAP_64, + TRG_BYTE_SWAP_64} trg_endianness_64; + + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +typedef enum {TRG_NON_TRAJECTORY_BLOCK, TRG_TRAJECTORY_BLOCK} trg_block_type; + +typedef enum {TRG_ENDIANNESS_AND_STRING_LENGTH, + TRG_GENERAL_INFO, + TRG_MOLECULES, + TRG_TRAJECTORY_IDS_AND_NAMES, + TRG_TRAJECTORY_FRAME_SET, + TRG_BLOCK_TABLE_OF_CONTENTS, + TRG_PARTICLE_MAPPING} trg_non_trajectory_block_ids; + +typedef enum {TRG_TRAJ_BOX_SHAPE = 10000, + TRG_TRAJ_POSITIONS, + TRG_TRAJ_VELOCITIES, + TRG_TRAJ_FORCES} trg_trajectory_block_ids; + + +typedef enum {TRG_NON_PARTICLE_BLOCK_DATA, + TRG_PARTICLE_BLOCK_DATA} trg_particle_block_data; + +/*typedef enum {TRG_NO_HASH, TRG_OTHER_HASH, + TRG_MD5_HASH, TRG_MD6_HASH, + TRG_SHA0_HASH, TRG_SHA1_HASH, + TRG_SHA256_HASH, TRG_SHA512_HASH} trg_hash_type;*/ + +typedef enum {FALSE, TRUE} trg_bool; + +typedef enum {TRG_KEEP_FILE_OPEN, TRG_CLOSE_FILE} trg_close_file_flag; + +typedef enum {TRG_CONSTANT_N_ATOMS, TRG_VARIABLE_N_ATOMS} trg_variable_n_atoms_flag; + +typedef enum {TRG_SUCCESS, TRG_FAILURE, TRG_CRITICAL} trg_function_status; + +typedef enum {TRG_NORMAL_WRITE, TRG_COPY_EXISTING} write_mode; + +typedef enum {TRG_CHAR_DATA, + TRG_INT_DATA, + TRG_FLOAT_DATA, + TRG_DOUBLE_DATA} trg_data_type; + + + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct trg_bond { + uint64_t from_atom_id; /* One of the atoms of the bond */ + uint64_t to_atom_id; /* The other atom of the bond */ +}; + +struct trg_atom { + struct trg_residue *residue; /* The molecule containing this atom */ + uint64_t id; /* A unique (per molecule) ID number of the atom */ + char *atom_type; /* The atom_type (depending on the forcefield) */ + char *name; /* The name of the atom */ +}; + +struct trg_residue { + struct trg_chain *chain; /* The chain containing this residue */ + uint64_t id; /* A unique (per chain) ID number of the residue */ + char *name; /* The name of the residue */ + uint64_t n_atoms; /* The number of atoms in the residue */ + struct trg_atom *atoms; /* A list of atoms in the residue */ +}; + +struct trg_chain { + struct trg_molecule *molecule; /* The molecule containing this chain */ + uint64_t id; /* A unique (per molecule) ID number of the chain */ + char *name; /* The name of the chain */ + uint64_t n_residues; /* The number of residues in the chain */ + struct trg_residue *residues; /* A list of residues in the chain */ +}; + +struct trg_molecule { + uint64_t id; /* A unique ID number of the molecule */ + uint64_t quaternary_str; /* Quaternary structure of the molecule. + 1 => monomeric + 2 => dimeric + 3 => trimeric + etc */ + uint64_t n_chains; /* The number of chains in the molecule */ + uint64_t n_residues; /* The number of residues in the molecule */ + uint64_t n_atoms; /* The number of atoms in the molecule */ + uint64_t n_bonds; /* The number of bonds in the molecule. + If the bonds are not specified this + value can be 0. */ + char *name; /* The name of the molecule */ + struct trg_chain *chains; /* A list of chains in the molecule */ + struct trg_residue *residues; /* A list of residues in the molecule */ + struct trg_atom *atoms; /* A list of the atoms in the molecule */ + struct trg_bond *bonds; /* A list of the bonds in the molecule */ +}; + +struct trg_gen_block { + uint64_t header_contents_size; /* The size of the block header in bytes */ + uint64_t block_contents_size; /* The size of the block contents in bytes */ + uint64_t id; /* The ID of the block to determine its type */ + char hash[TRG_HASH_LEN]; /* The MD5 hash of the block to verify integrity */ + char *name; /* The name of the block */ + uint64_t block_version; /* The library version used to write the block */ + char *header_contents; /* The full block header contents */ + char *block_contents; /* The full block contents */ +}; + +struct trg_frame_set_toc { + uint64_t n_blocks; /* The number of blocks listed in this + table of contents */ + char **block_names; /* A list of block names */ +}; + +struct trg_particle_mapping { + uint64_t num_first_particle; /* The index number of the first particle + in this mapping block */ + uint64_t n_particles; /* The number of particles list in this + mapping block */ + uint64_t *real_particle_numbers; /* the mapping of index numbers to the + real particle numbers in the + trajectory */ +}; + +struct trg_trajectory_frame_set { + struct trg_frame_set_toc contents; /* The table of contents of this frame set */ + uint64_t n_mapping_blocks; /* The number of different particle + mapping blocks present. */ + struct trg_particle_mapping *mappings; /* The atom mappings of this frame set */ + uint64_t first_frame; /* The first frame of this frame set */ + uint64_t n_frames; /* The number of frames in this frame set */ + uint64_t *molecule_cnt_list; /* A list of the number of each molecule + type - only used when using variable + number of atoms */ + uint64_t n_particles; /* The number of particles/atoms - only + used when using variable number of + atoms */ + uint64_t next_frame_set_file_pos; /* The file position of the next frame set */ + uint64_t prev_frame_set_file_pos; /* The file position of the previous + frame set */ + uint64_t long_stride_next_frame_set_file_pos; /* The file position of the frame + set one stride step ahead */ + uint64_t long_stride_prev_frame_set_file_pos; /* The file position of the frame + set one stride step behind */ + + /* The data blocks in a frame set are trajectory data blocks */ + int n_particle_data_blocks; /* The number of data blocks + of particle dependent data */ + struct trg_particle_data *tr_particle_data; /* A list of data blocks + containing particle + dependent data */ + int n_data_blocks; + struct trg_data *tr_data; +}; + +/* Data can be either double, float, int or a string */ +union data_values { + double d; + float f; + int i; + char *c; +}; + +/* FIXME: Should there be a pointer to a trg_gen_block from each data block? */ +struct trg_particle_data { + uint64_t block_id; /* The block ID of the data block + containing this particle data. + This is used to determine the + kind of data that is stored */ + char *block_name; /* The name of the data block. + This is used to determine the + kind of data that is stored */ + trg_data_type datatype; /* The type of data stored. */ + uint64_t first_frame_with_data; /* The first frame number of the + first data point */ + uint64_t n_frames; /* The number of frames in this + frame set */ + uint64_t n_values_per_frame; /* The number of values stored per + frame */ + uint64_t stride_length; /* The number of frames between + each data point - e.g. when + storing sparse data. */ + uint64_t codec_id; /* ID of the CODEC used for compression + 0 == no compression. */ + double compression_multiplier; /* The multiplier used for getting + integer values for compression */ + union data_values ***values; /* A 3-dimensional array of values, + sized n_frames x n_particles x + n_values_per_frame */ +}; + +struct trg_data { + uint64_t block_id; + char *block_name; /* The name of the data block. + This is used to determine the + kind of data that is stored */ + trg_data_type datatype; /* The type of data stored. */ + uint64_t first_frame_with_data; + uint64_t n_frames; + uint64_t n_values_per_frame; + uint64_t stride_length; + uint64_t codec_id; /* ID of the CODEC used for compression + 0 == no compression. */ + double compression_multiplier; + union data_values **values; /* A 2-dimensional array of values, + sized n_frames x n_values_per_frame */ +}; + + + +struct trg_trajectory { + char *input_file_path; /* The path of the input trajectory file */ + FILE *input_file; /* A handle to the input file */ + long int input_file_pos; /* The reading position of the file */ + long int input_file_len; /* The length of the input file */ + char *output_file_path; /* The path of the output trajectory file */ + FILE *output_file; /* A handle to the output file */ + long int output_file_pos; /* The writing position of the file */ + + trg_endianness_32 endianness_32; /* The endianness of 32 bit values of + the current computer */ + trg_endianness_64 endianness_64; /* The endianness of 64 bit values of + the current computer */ + + char *program_name; /* The name of the program producing + this trajectory */ + char *forcefield_name; /* The forcefield used in the simulations */ + char *user_name; /* The name of the user running the + simulations */ + uint64_t time; /* The time (n seconds since 1970) when + the file was created */ + char *computer_name; /* The name of the computer on which the + simulations were performed */ + char *pgp_signature; /* The PGP signature of the user creating + the file. */ + char var_num_atoms_flag; /* A flag indicating if the number of atoms + can vary throughout the simulation, e.g. + using a grand canonical ensemble */ + uint64_t frame_set_n_frames; /* The number of frames in a frame set. + It is allowed to have frame sets with + fewer frames, but this will help searching + for specific frames */ + uint64_t stride_length; /* The number of frame sets in a long stride + step */ + + uint64_t n_molecules; /* The number of different kinds of + molecules in the trajectory */ + struct trg_molecule *molecules; /* A list of molecules in the trajectory */ + uint64_t *molecule_cnt_list; /* A list of the count of each molecule - + if using variable number of particles + this will be specified in each frame set */ + uint64_t n_particles; /* The total number of particles/atoms. If + using variable number of particles this + will be specified in each frame set */ + + uint64_t n_id_name_pairs; /* The number of ID-name + pairs */ + struct trg_block_id_name_pair *id_name_pairs; /* A list of ID-name + pairs */ + + uint64_t first_trajectory_frame_set_input_file_pos; /* The pos in the src + file of the first + frame set */ + uint64_t first_trajectory_frame_set_output_file_pos; /* The pos in the dest + file of the first + frame set */ + uint64_t last_trajectory_frame_set_input_file_pos; /* The pos in the src + file of the last + frame set */ + uint64_t last_trajectory_frame_set_output_file_pos; /* The pos in the dest + file of the last + frame set */ + struct trg_trajectory_frame_set current_trajectory_frame_set; /* The currently + active frame + set */ + long int current_trajectory_frame_set_input_file_pos; /* The pos in the src + file of the current + frame set */ + long int current_trajectory_frame_set_output_file_pos;/* The pos in the dest + file of the current + frame set */ + uint64_t n_trajectory_frame_sets; /* The number of frame sets + in the trajectory */ + + uint64_t n_trajectory_blocks; /* The number of trajectory blocks + in the file */ + uint64_t n_non_trajectory_blocks; /* The number of non-trajectory blocks + in the file */ + struct trg_gen_block non_trajectory_blocks[32]; /* A list of non-trajectory + blocks */ + + /* These data blocks are non-trajectory data blocks */ + int n_particle_data_blocks; /* The number of non-frame dependent + particle dependent data blocks */ + struct trg_particle_data *non_tr_particle_data; /* A list of data blocks containing particle + dependent data */ + + int n_data_blocks; /* The number of frame and particle independent + data blocks */ + struct trg_data *non_tr_data; /* A list of frame and particle indepdendent data blocks */ +}; + + + +/* Setup a trajectory data container. + *trg_data is a pointer to pre-allocated memory. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_init_trajectory(struct trg_trajectory *trg_data); + +/* Clean up a trajectory data container. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + All allocated memory in the data structure is freed. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_destroy_trajectory(struct trg_trajectory *trg_data); + +/* Set the name of the input file. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_input_file(struct trg_trajectory *trg_data, + const char *file_name); + +/* Set the name of the output file. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_output_file(struct trg_trajectory *trg_data, + const char *file_name); + +/* Set the program name used when creating the trajectory. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + *new_name is a pointer to the string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_program_name(struct trg_trajectory *trg_data, + const char *new_name); + +/* Set the name of the forcefield used in the trajectory. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + *new_name is a pointer to the string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_forcefield_name(struct trg_trajectory *trg_data, + const char *new_name); + +/* Set the name of the user creating the trajectory. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + *new_name is a pointer to the string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_user_name(struct trg_trajectory *trg_data, + const char *new_name); + +/* Set the name of the computer used when creating the trajectory. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + *new_name is a pointer to the string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_computer_name(struct trg_trajectory *trg_data, + const char *new_name); + +/* Set the pgp_signature of the trajectory. + *trg_data is a pointer to pre-allocated memory containing trajectory data. + *signature is a pointer to the string containing the pgp_signature. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_signature(struct trg_trajectory *trg_data, + const char *signature); + +/* Setup a molecule container. + *molecule is a pointer to pre-allocated memory. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_init_molecule(struct trg_molecule *molecule); + +/* Clean up a molecule container. + *molecule is a pointer to pre-allocated memory containing a molecule. + All allocated memory in the data structure is freed. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_destroy_molecule(struct trg_molecule *molecule); + +/* Setup a data block. + *block is a pointer to pre-allocated memory. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_init_block(struct trg_gen_block *block); + +/* Clean up a data block. + *block is a pointer to pre-allocated memory. + All allocated memory in the data structure is freed. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_destroy_block(struct trg_gen_block *block); + +/* Set the name of a data block. + *trg_data is a pointer to the trajectory containing the block. + *block is a pointer to the block to rename. + *new_name is a string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_block_name(struct trg_trajectory *trg_data, + struct trg_gen_block *block, + const char *new_name); + +/* Add a molecule to the trajectory. + *trg_data is a pointer to the trajectory containing the block. + *name is a pointer to the string containing the name of the new molecule. + **molecule is a pointer to a pointer to the newly created molecule. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_add_molecule(struct trg_trajectory *trg_data, + const char *name, + struct trg_molecule **molecule); + +/* Set the name of a molecule. + *trg_data is a pointer to the trajectory containing the molecule. + *molecule is a pointer to the molecule to rename. + *new_name is a string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_molecule_name(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + const char *new_name); + +/* Set the count of a molecule. + *trg_data is a pointer to the trajectory containing the molecule. + *molecule is a pointer to the molecule to rename. + *cnt is a pointer to the variable to be populated with the count. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_get_molecule_cnt(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + uint64_t *cnt); + +/* Set the count of a molecule. + *trg_data is a pointer to the trajectory containing the molecule. + *molecule is a pointer to the molecule to rename. + cnt is the number of instances of this molecule. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_molecule_cnt(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + uint64_t cnt); + +/* Add a chain to a molecule. + *trg_data is a pointer to the trajectory containing the molecule. + *molecule is a pointer to the molecule to add a chain to. + *name is a pointer to a string containing the name of the chain. + **chain is a pointer to a pointer to the newly created chain. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_add_chain_to_molecule(struct trg_trajectory *trg_data, + struct trg_molecule *molecule, + const char *name, + struct trg_chain **chain); + +/* Set the name of a chain. + *trg_data is a pointer to the trajectory containing the atom. + *chain is a pointer to the chain to rename. + *new_name is a string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_chain_name(struct trg_trajectory *trg_data, + struct trg_chain *chain, + const char *new_name); + +/* Add a residue to a chain. + *trg_data is a pointer to the trajectory containing the chain. + *chain is a pointer to the chain to add a residue to. + *name is a pointer to a string containing the name of the residue. + **residue is a pointer to a pointer to the newly created residue. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_add_residue_to_chain(struct trg_trajectory *trg_data, + struct trg_chain *chain, + const char *name, + struct trg_residue **residue); + +/* Set the name of a residue. + *trg_data is a pointer to the trajectory containing the atom. + *residue is a pointer to the residue to rename. + *new_name is a string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_residue_name(struct trg_trajectory *trg_data, + struct trg_residue *residue, + const char *new_name); + +/* Add an atom to a residue. + *trg_data is a pointer to the trajectory containing the residue. + *residue is a pointer to the residue to add an atom to. + *atom_name is a pointer to a string containing the name of the atom. + *atom_type is a pointer to a string containing the atom type of the atom. + **atom is a pointer to a pointer to the newly created atom. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_add_atom_to_residue(struct trg_trajectory *trg_data, + struct trg_residue *residue, + const char *atom_name, + const char *atom_type, + struct trg_atom **atom); + +/* Set the name of an atom. + *trg_data is a pointer to the trajectory containing the atom. + *atom is a pointer to the atom to rename. + *new_name is a string containing the wanted name. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_atom_name(struct trg_trajectory *trg_data, + struct trg_atom *atom, + const char *new_name); + +/* Set the atom type of an atom. + *trg_data is a pointer to the trajectory containing the atom. + *atom is a pointer to the atom to change. + *new_name is a string containing the atom type. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_set_atom_type(struct trg_trajectory *trg_data, + struct trg_atom *atom, + const char *new_type); + +/* Read the header blocks from the input_file of trg_data. + The trajectory blocks must be read separately and iteratively in chunks + to fit in memory. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_file_headers(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + +/* Write the header blocks to the output_file of trg_data. + The trajectory blocks must be written separately and iteratively in chunks + to fit in memory. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (output_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_file_headers(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + + +/* Read one (the next) block (of any kind) from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + *block_data is a pointer to the struct which will be populated with the + data. If block_data->input_file_pos > 0 it is the position from where the reading + starts otherwise it starts from the current position. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor + error has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_next_block(struct trg_trajectory *trg_data, + struct trg_gen_block *block_data, + trg_close_file_flag close_file); + +/* Write one block (of any kind) to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to read from. If the file (output_file) is not open it will be opened. + *block_data is a pointer to the struct containing the + data. If block_data->output_file_pos > 0 it is the position from where the writing + starts otherwise it starts from the current position. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +// trg_function_status trg_write_block(struct trg_trajectory *trg_data, +// struct trg_gen_block *block_data, +// trg_close_file_flag close_file); + + +/* Read one (the next) frame set, including toc, mapping and related data blocks + from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_next_frame_set(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + +/* Write one (the next) frame set, including toc, mapping and related data blocks + to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (output_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_frame_set(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + +trg_function_status trg_new_frame_set(struct trg_trajectory *trg_data, + const uint64_t first_frame, + const uint64_t n_frames); + +trg_function_status trg_add_particle_data_block(struct trg_trajectory *trg_data, + const uint64_t id, + const char *block_name, + const char datatype, + const uint64_t n_frames, + const uint64_t n_values_per_frame, + const uint64_t stride_length, + const uint64_t first_particle_number, + const uint64_t n_particles, + uint64_t codec_id, + void *new_data); + + +/* Read one (the next) trajectory block from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_next_traj_block(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + +/* Write one (the next) trajectory block to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (output_file) is not open it will be opened. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_next_traj_block(struct trg_trajectory *trg_data, + trg_close_file_flag close_file); + +/* Read one trajectory block from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + block_id is the ID of the block to read. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_traj_block(struct trg_trajectory *trg_data, + uint64_t block_id, + trg_close_file_flag close_file); + +/* Write one trajectory block to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (output_file) is not open it will be opened. + block_id is the ID of the block to write. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_traj_block(struct trg_trajectory *trg_data, + uint64_t block_id, + trg_close_file_flag close_file); + +/* Read a requested frame set. + *trg_data is a pointer to trajectory data. trg_data->current_trajectory_frame_set + will be the read frame set. + frame_set_nr is the number of the frame set to return (starting from 0). + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_frame_set_nr(struct trg_trajectory *trg_data, + uint64_t frame_set_nr); + +/* Read one trajectory frame from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + frame_nr is the index number of the frame to read. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_frame_nr(struct trg_trajectory *trg_data, + uint64_t frame_nr, + trg_close_file_flag close_file); + +/* Write one trajectory frame to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (output_file) is not open it will be opened. + frame_nr is the index number of the frame to write. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_frame_nr(struct trg_trajectory *trg_data, + uint64_t frame_nr, + trg_close_file_flag close_file); + +/* Read a number of consecutive trajectory frames from the input_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->input_file_path specifies which + file to read from. If the file (input_file) is not open it will be opened. + start_frame_nr is the index number of the first frame to read. + end_frame_nr is the index number of the last frame to read. + If close_file == TRG_CLOSE_FILE (1) the input_file will be closed after reading the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_read_frame_nrs(struct trg_trajectory *trg_data, + uint64_t start_frame_nr, + uint64_t end_frame_nr, + trg_close_file_flag close_file); + +/* Write a number of consecutive trajectory frames to the output_file of trg_data. + *trg_data is a pointer to trajectory data. trg_data->output_file_path specifies which + file to write to. If the file (input_file) is not open it will be opened. + start_frame_nr is the index number of the first frame to write. + end_frame_nr is the index number of the last frame to write. + If close_file == TRG_CLOSE_FILE (1) the output_file will be closed after writing the data. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_write_frame_nrs(struct trg_trajectory *trg_data, + uint64_t start_frame_nr, + uint64_t end_frame_nr, + trg_close_file_flag close_file); + +/* Get the date and time of initial file creation in ISO format (string). + *trg_data is a pointer to trajectory data. + *time is a pointer to the string in which the date will be stored. Memory + must be reserved beforehand. + Returns TRG_SUCCESS (0) if successful, TRG_FAILURE (1) if a minor error + has occurred or TRG_CRITICAL (2) if a major error has occured. */ +trg_function_status trg_get_time_str(struct trg_trajectory *trg_data, char *time); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* _TRGIO_H */ \ No newline at end of file diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt new file mode 100644 index 0000000..ea5a644 --- /dev/null +++ b/src/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +include_directories(${TRAJECTORY_SOURCE_DIR}/src/lib) +link_directories(${TRAJECTORY_BINARY_DIR}/src/lib) + +add_executable(trg_testing trg_io_testing.c) +target_link_libraries(trg_testing trg_io) \ No newline at end of file diff --git a/src/tests/trg_io_testing.c b/src/tests/trg_io_testing.c new file mode 100644 index 0000000..caa74dd --- /dev/null +++ b/src/tests/trg_io_testing.c @@ -0,0 +1,341 @@ +#include +#include +#include +#include "trg_io.h" + + + + +static trg_function_status trg_setup_test_molecules(struct trg_trajectory *traj) +{ + struct trg_molecule *molecule; + struct trg_chain *chain; + struct trg_residue *residue; + struct trg_atom *atom; + uint64_t cnt; +// int i; + + trg_add_molecule(traj, "water", &molecule); + trg_add_chain_to_molecule(traj, molecule, "W", &chain); + trg_add_residue_to_chain(traj, chain, "WAT", &residue); + if(trg_add_atom_to_residue(traj, residue, "O", "O", &atom) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + if(trg_add_atom_to_residue(traj, residue, "HO1", "H", &atom) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + if(trg_add_atom_to_residue(traj, residue, "HO2", "H", &atom) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + trg_set_molecule_cnt(traj, molecule, 200); + trg_get_molecule_cnt(traj, molecule, &cnt); + printf("Created %"PRId64" %s molecules.\n", cnt, molecule->name); +// traj->molecule_cnt_list[traj->n_molecules-1] = 5; +// trg_set_molecule_name(traj, &traj->molecules[1], "ligand"); +// trg_set_molecule_name(traj, &traj->molecules[2], "water"); +// trg_set_molecule_name(traj, &traj->molecules[3], "dummy"); +// traj->molecules[0].id = 0; +// traj->molecules[1].id = 1; +// traj->molecules[2].id = 2; +// traj->molecules[3].id = 3; + +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom1", "type1") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom2", "type1") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom3", "type1") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom4", "type2") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom5", "type2") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom6", "type2") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[0], "atom7", "type3") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[1], "C1", "C") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[1], "O1", "O") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[1], "H11", "H") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[1], "H12", "H") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } +// if(trg_add_atom_to_molecule(traj, &traj->molecules[1], "H13", "H") == TRG_CRITICAL) +// { +// return(TRG_CRITICAL); +// } + + return(TRG_SUCCESS); +} + +static trg_function_status trg_test_read_and_write_file + (struct trg_trajectory *traj) +{ + trg_function_status stat; + + stat = trg_read_file_headers(traj, TRG_KEEP_FILE_OPEN); + if(stat == TRG_CRITICAL) + { + return(stat); + } + stat = trg_write_file_headers(traj, TRG_KEEP_FILE_OPEN); + if(stat == TRG_CRITICAL) + { + return(stat); + } + + while(stat != TRG_CRITICAL && traj->input_file_pos < traj->input_file_len && + traj->current_trajectory_frame_set.next_frame_set_file_pos != -1UL) + { + stat = trg_read_next_frame_set(traj, TRG_KEEP_FILE_OPEN); + if(stat == TRG_CRITICAL) + { + return(stat); + } + stat = trg_write_frame_set(traj, TRG_KEEP_FILE_OPEN); + } + + return(stat); +} + +static trg_function_status trg_test_write_and_read_traj(struct trg_trajectory *traj) +{ + int i, j, k, nr, tot_n_mols, cnt; + float *data, *molpos; + trg_function_status stat; + + /* Create molecules */ + if(trg_setup_test_molecules(traj) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + + if(trg_init_block(&traj->non_trajectory_blocks[traj->n_non_trajectory_blocks]) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + traj->non_trajectory_blocks[traj->n_non_trajectory_blocks].id = TRG_MOLECULES; + if(trg_set_block_name(traj, + &traj->non_trajectory_blocks[traj->n_non_trajectory_blocks++], + "MOLECULES") == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + + if(trg_write_file_headers(traj, TRG_KEEP_FILE_OPEN) == TRG_CRITICAL) + { + return(TRG_CRITICAL); + } + + data = malloc(sizeof(float) * traj->n_particles * + traj->frame_set_n_frames * 3); + if(!data) + { + printf("Cannot allocate memory. %s: %d\n", __FILE__, __LINE__); + return(TRG_CRITICAL); + } + + tot_n_mols = 0; + for(i = 0; i < traj->n_molecules; i++) + { + tot_n_mols += traj->molecule_cnt_list[i]; + } + molpos = malloc(sizeof(float) * tot_n_mols * 3); + + /* Set initial coordinates */ + for(i = 0; i < tot_n_mols; i++) + { + nr = i * 3; + /* Somewhat random coordinates (between 0 and 100), + * but not specifying a random seed */ + molpos[nr] = 100.0 * rand() / (RAND_MAX + 1.0); + molpos[nr+1] = 100.0 * rand() / (RAND_MAX + 1.0); + molpos[nr+2] = 100.0 * rand() / (RAND_MAX + 1.0); + } + + /* Generate 200 frame sets - each with 100 frames (by default) */ + for(i = 0; i < 200; i++) + { + cnt = 0; + for(j = 0; j < traj->frame_set_n_frames; j++) + { + for(k = 0; k < tot_n_mols; k++) + { + nr = k * 3; + /* Move -1 to 1 */ + molpos[nr] += 2 * (rand() / (RAND_MAX + 1.0)) - 1; + molpos[nr+1] += 2 * (rand() / (RAND_MAX + 1.0)) - 1; + molpos[nr+2] += 2 * (rand() / (RAND_MAX + 1.0)) - 1; + + data[cnt++] = molpos[nr]; + data[cnt++] = molpos[nr + 1]; + data[cnt++] = molpos[nr + 2]; + data[cnt++] = molpos[nr] + 1; + data[cnt++] = molpos[nr + 1] + 1; + data[cnt++] = molpos[nr + 2] + 1; + data[cnt++] = molpos[nr] - 1; + data[cnt++] = molpos[nr + 1] - 1; + data[cnt++] = molpos[nr + 2] - 1; + } + } + if(trg_new_frame_set(traj, i * traj->frame_set_n_frames, + traj->frame_set_n_frames) != TRG_SUCCESS) + { + printf("Error creating frame set %d. %s: %d\n", + i, __FILE__, __LINE__); + free(molpos); + free(data); + return(TRG_CRITICAL); + } + + if(trg_add_particle_data_block(traj, TRG_TRAJ_POSITIONS, + "POSITIONS", + TRG_FLOAT_DATA, + traj->frame_set_n_frames, 3, + 1, 0, traj->n_particles, + TRG_UNCOMPRESSED, + data) != TRG_SUCCESS) + { + printf("Error adding data. %s: %d\n", __FILE__, __LINE__); + free(molpos); + free(data); + return(TRG_CRITICAL); + } + if(trg_write_frame_set(traj, TRG_KEEP_FILE_OPEN) != TRG_SUCCESS) + { + printf("Error writing frame set. %s: %d\n", __FILE__, __LINE__); + free(molpos); + free(data); + return(TRG_CRITICAL); + } + } + +// trg_add_ids_names_pair(traj, TRG_TRAJ_VELOCITIES, "BOX SHAPE"); +// trg_add_ids_names_pair(traj, TRG_TRAJ_POSITIONS, "TRAJECTORY POSITIONS"); +// trg_add_ids_names_pair(traj, TRG_TRAJ_VELOCITIES, "TRAJECTORY VELOCITIES"); +// trg_add_ids_names_pair(traj, TRG_TRAJ_FORCES, "TRAJECTORY FORCES"); +// trg_add_ids_names_pair(traj, 11000, "TEST DATA"); + + free(molpos); + free(data); + + trg_destroy_trajectory(traj); + trg_set_input_file(traj, "/tmp/trg_test.trg"); + + stat = trg_read_file_headers(traj, TRG_KEEP_FILE_OPEN); + + while(stat != TRG_CRITICAL && traj->input_file_pos < traj->input_file_len && + traj->current_trajectory_frame_set.next_frame_set_file_pos != -1ULL) + { + stat = trg_read_next_frame_set(traj, TRG_KEEP_FILE_OPEN); + if(stat == TRG_CRITICAL) + { + return(stat); + } + } + + return(stat); +} + +int main() +{ + struct trg_trajectory traj; + char time_str[TRG_MAX_DATE_STR_LEN]; + + if(trg_init_trajectory(&traj) != TRG_SUCCESS) + { + trg_destroy_trajectory(&traj); + printf("Test Init trajectory:\t\t\t\tFailed. %s: %d.\n", + __FILE__, __LINE__); + exit(1); + } + printf("Test Init trajectory:\t\t\t\tSucceeded.\n"); + + trg_get_time_str(&traj, time_str); + + printf("Creation time: %s\n", time_str); + + trg_set_input_file(&traj, "trg_example.trg"); + trg_set_output_file(&traj, "/tmp/trg_example_test.trg"); + +// if(trg_test_endianness(&traj) != TRG_SUCCESS) +// { +// printf("Test failed: Endianness. %s: %d\n", __FILE__, __LINE__); +// } + + if(trg_test_read_and_write_file(&traj) == TRG_CRITICAL) + { + printf("Test Read and write file:\t\t\tFailed. %s: %d\n", + __FILE__, __LINE__); + } + else + { + printf("Test Read and write file:\t\t\tSucceeded.\n"); + } + + if(trg_destroy_trajectory(&traj) == TRG_CRITICAL || + trg_init_trajectory(&traj) == TRG_CRITICAL) + { + printf("Test Destroy and init trajectory:\t\tFailed. %s: %d\n", + __FILE__, __LINE__); + } + else + { + printf("Test Destroy and init trajectory:\t\tSucceeded.\n"); + } + + + trg_set_output_file(&traj, "/tmp/trg_test.trg"); + + if(trg_test_write_and_read_traj(&traj) == TRG_CRITICAL) + { + printf("Test Write and read file:\t\t\tFailed. %s: %d\n", + __FILE__, __LINE__); + } + else + { + printf("Test Write and read file:\t\t\tSucceeded.\n"); + } + + if(trg_destroy_trajectory(&traj) == TRG_CRITICAL) + { + printf("Test Destroy trajectory:\t\t\tFailed. %s: %d.\n", + __FILE__, __LINE__); + exit(1); + } + else + { + printf("Test Destroy trajectory:\t\t\tSucceeded.\n"); + } + + + printf("Tests finished\n"); + + exit(0); +} \ No newline at end of file -- cgit v0.10.1