1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- 2 * 3 * $Id: xdrfile.h,v 1.1 2010/10/08 11:53:37 spoel Exp spoel $ 4 * 5 /* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- 6 * 7 * $Id$ 8 * 9 * Copyright (c) 2009-2014, Erik Lindahl & David van der Spoel 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright notice, this 16 * list of conditions and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright notice, 19 * this list of conditions and the following disclaimer in the documentation 20 * and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /*! \file xdrfile.h 35 * \brief Interface to read/write portabile binary files using XDR. 36 * 37 * This file provides an interface to read & write portably binary files, 38 * using XDR - the external data representation standard defined in RFC 1014. 39 * 40 * There are several advantages to the XDR approach: 41 * 42 * -# It is portable. And not just portable between big/small integer endian, 43 * but truly portable if you have system XDR routines. For example: 44 * - It doesn't matter if the character representation is ASCII or EBCDIC. 45 * - Some systems are small endian but use big endian order of the two 46 * dword in a double precision floating-point variable. The system XDR 47 * libraries will read/write this correctly. 48 * - Some systems (VAX...) don't use IEEE floating point. Their system 49 * XDR libraries will convert to/from this automatically. 50 * -# XDR libraries are required for NFS and lots of other network functions. 51 * This means there isn't a single Unix-like system that doesn't have them. 52 * -# There is NO extra metadata whatsoever, and we write plain XDR files. 53 * If you write a float, it will take exactly 4 bytes in the file. 54 * (All basic datatypes are 4 bytes, double fp 8 bytes). 55 * -# You can read/write the files by calling the system XDR routines directly 56 * too - you don't have to use the routines defined in this file. 57 * -# It is no problem if your system doesn't have XDR libraries (MS Windows). 58 * We have written our own versions of the necessary routines that work if 59 * your system uses ASCII for strings and IEEE floating-point. All types 60 * of byte and dword endian for integer and floating-point are supported. 61 * -# You can use these routines for any type of data, but since we designed 62 * them for Gromacs we also provide a special routine to write coordinates 63 * with (adjustable) lossy compression. The default precision will give you 64 * three decimals guaranteed accuracy, and reduces the filesize to 1/10th 65 * of normal binary data. 66 * 67 * We do not support getting or setting positions in XDR files, since it can 68 * break in horrible ways for large (64-bit) files, resulting in silent data 69 * corruption. Note that it works great to open/read/write 64-bit files if 70 * your system supports it; it is just the random access we cannot trust! 71 * 72 * We also provide wrapper routines so this module can be used from FORTRAN - 73 * see the file xdrfile_fortran.txt in the Gromacs distribution for 74 * documentation on the FORTRAN interface! 75 */ 76 77 78 #ifndef _XDRFILE_H_ 79 #define _XDRFILE_H_ 80 81 #include <stdint.h> 82 83 #ifdef __cplusplus 84 extern "C" 85 { 86 #endif 87 88 /*! \brief Abstract datatype for an portable binary file handle 89 * 90 * This datatype essentially works just like the standard FILE type in C. 91 * The actual contents is hidden in the implementation, so you can only 92 * define pointers to it, for use with the xdrfile routines. 93 * 94 * If you \a really need to see the definition it is in xdrfile.c, but you 95 * cannot access elements of the structure outside that file. 96 * 97 * \warning The implementation is completely different from the C standard 98 * library FILE, so don't even think about using an XDRFILE pointer as an 99 * argument to a routine that needs a standard FILE pointer. 100 */ 101 typedef struct XDRFILE XDRFILE; 102 103 enum { exdrOK, exdrHEADER, exdrSTRING, exdrDOUBLE, 104 exdrINT, exdrFLOAT, exdrUINT, exdr3DX, exdrCLOSE, exdrMAGIC, 105 exdrNOMEM, exdrENDOFFILE, exdrFILENOTFOUND, exdrNR }; 106 107 extern char *exdr_message[exdrNR]; 108 109 #define DIM 3 110 typedef float matrix[DIM][DIM]; 111 typedef float rvec[DIM]; 112 typedef int mybool; 113 114 115 /*! \brief Open a portable binary file, just like fopen() 116 * 117 * Use this routine much like calls to the standard library function 118 * fopen(). The only difference is that the returned pointer should only 119 * be used with routines defined in this header. 120 * 121 * \param path Full or relative path (including name) of the file 122 * \param mode "r" for reading, "w" for writing, "a" for append. 123 * 124 * \return Pointer to abstract xdr file datatype, or NULL if an error occurs. 125 * 126 */ 127 XDRFILE * 128 xdrfile_open (const char * path, 129 const char * mode); 130 131 132 /*! \brief Close a previously opened portable binary file, just like fclose() 133 * 134 * Use this routine much like calls to the standard library function 135 * fopen(). The only difference is that it is used for an XDRFILE handle 136 * instead of a FILE handle. 137 * 138 * \param xfp Pointer to an abstract XDRFILE datatype 139 * 140 * \return 0 on success, non-zero on error. 141 */ 142 int 143 xdrfile_close (XDRFILE * xfp); 144 145 146 147 148 /*! \brief Read one or more \a char type variable(s) 149 * 150 * \param ptr Pointer to memory where data should be written 151 * \param ndata Number of characters to read 152 * \param xfp Handle to portable binary file, created with xdrfile_open() 153 * 154 * \return Number of characters read 155 */ 156 int 157 xdrfile_read_char(char * ptr, 158 int ndata, 159 XDRFILE * xfp); 160 161 162 163 /*! \brief Write one or more \a characters type variable(s) 164 * 165 * \param ptr Pointer to memory where data should be read 166 * \param ndata Number of characters to write. 167 * \param xfp Handle to portable binary file, created with xdrfile_open() 168 * 169 * \return Number of characters written 170 */ 171 int 172 xdrfile_write_char(char * ptr, 173 int ndata, 174 XDRFILE * xfp); 175 176 177 178 /*! \brief Read one or more \a unsigned \a char type variable(s) 179 * 180 * \param ptr Pointer to memory where data should be written 181 * \param ndata Number of unsigned characters to read 182 * \param xfp Handle to portable binary file, created with xdrfile_open() 183 * 184 * \return Number of unsigned characters read 185 */ 186 int 187 xdrfile_read_uchar(unsigned char * ptr, 188 int ndata, 189 XDRFILE * xfp); 190 191 192 193 /*! \brief Write one or more \a unsigned \a characters type variable(s) 194 * 195 * \param ptr Pointer to memory where data should be read 196 * \param ndata Number of unsigned characters to write. 197 * \param xfp Handle to portable binary file, created with xdrfile_open() 198 * 199 * \return Number of unsigned characters written 200 */ 201 int 202 xdrfile_write_uchar(unsigned char * ptr, 203 int ndata, 204 XDRFILE * xfp); 205 206 207 208 /*! \brief Read one or more \a short type variable(s) 209 * 210 * \param ptr Pointer to memory where data should be written 211 * \param ndata Number of shorts to read 212 * \param xfp Handle to portable binary file, created with xdrfile_open() 213 * 214 * \return Number of shorts read 215 */ 216 int 217 xdrfile_read_short(short * ptr, 218 int ndata, 219 XDRFILE * xfp); 220 221 222 223 /*! \brief Write one or more \a short type variable(s) 224 * 225 * \param ptr Pointer to memory where data should be read 226 * \param ndata Number of shorts to write. 227 * \param xfp Handle to portable binary file, created with xdrfile_open() 228 * 229 * \return Number of shorts written 230 */ 231 int 232 xdrfile_write_short(short * ptr, 233 int ndata, 234 XDRFILE * xfp); 235 236 237 238 /*! \brief Read one or more \a unsigned \a short type variable(s) 239 * 240 * \param ptr Pointer to memory where data should be written 241 * \param ndata Number of unsigned shorts to read 242 * \param xfp Handle to portable binary file, created with xdrfile_open() 243 * 244 * \return Number of unsigned shorts read 245 */ 246 int 247 xdrfile_read_ushort(unsigned short * ptr, 248 int ndata, 249 XDRFILE * xfp); 250 251 252 253 /*! \brief Write one or more \a unsigned \a short type variable(s) 254 * 255 * \param ptr Pointer to memory where data should be read 256 * \param ndata Number of unsigned shorts to write. 257 * \param xfp Handle to portable binary file, created with xdrfile_open() 258 * 259 * \return Number of unsigned shorts written 260 */ 261 int 262 xdrfile_write_ushort(unsigned short * ptr, 263 int ndata, 264 XDRFILE * xfp); 265 266 267 /*! \brief Read one or more \a integer type variable(s) 268 * 269 * \param ptr Pointer to memory where data should be written 270 * \param ndata Number of integers to read 271 * \param xfp Handle to portable binary file, created with xdrfile_open() 272 * 273 * \return Number of integers read 274 * 275 * The integer data type is assumed to be less than or equal to 32 bits. 276 * 277 * We do not provide any routines for reading/writing 64-bit integers, since 278 * - Not all XDR implementations support it 279 * - Not all machines have 64-bit integers 280 * 281 * Split your 64-bit data into two 32-bit integers for portability! 282 */ 283 int 284 xdrfile_read_int(int * ptr, 285 int ndata, 286 XDRFILE * xfp); 287 288 289 290 /*! \brief Write one or more \a integer type variable(s) 291 * 292 * \param ptr Pointer to memory where data should be read 293 * \param ndata Number of integers to write. 294 * \param xfp Handle to portable binary file, created with xdrfile_open() 295 * 296 * \return Number of integers written 297 * 298 * The integer data type is assumed to be less than or equal to 32 bits. 299 * 300 * We do not provide any routines for reading/writing 64-bit integers, since 301 * - Not all XDR implementations support it 302 * - Not all machines have 64-bit integers 303 * 304 * Split your 64-bit data into two 32-bit integers for portability! 305 */ 306 int 307 xdrfile_write_int(int * ptr, 308 int ndata, 309 XDRFILE * xfp); 310 311 /*! \brief Read one or more \a unsigned \a integers type variable(s) 312 * 313 * \param ptr Pointer to memory where data should be written 314 * \param ndata Number of unsigned integers to read 315 * \param xfp Handle to portable binary file, created with xdrfile_open() 316 * 317 * \return Number of unsigned integers read 318 * 319 * The integer data type is assumed to be less than or equal to 32 bits. 320 * 321 * We do not provide any routines for reading/writing 64-bit integers, since 322 * - Not all XDR implementations support it 323 * - Not all machines have 64-bit integers 324 * 325 * Split your 64-bit data into two 32-bit integers for portability! 326 */ 327 int 328 xdrfile_read_uint(unsigned int * ptr, 329 int ndata, 330 XDRFILE * xfp); 331 332 333 334 /*! \brief Write one or more \a unsigned \a integer type variable(s) 335 * 336 * \param ptr Pointer to memory where data should be read 337 * \param ndata Number of unsigned integers to write. 338 * \param xfp Handle to portable binary file, created with xdrfile_open() 339 * 340 * \return Number of unsigned integers written 341 * 342 * The integer data type is assumed to be less than or equal to 32 bits. 343 * 344 * We do not provide any routines for reading/writing 64-bit integers, since 345 * - Not all XDR implementations support it 346 * - Not all machines have 64-bit integers 347 * 348 * Split your 64-bit data into two 32-bit integers for portability! 349 */ 350 int 351 xdrfile_write_uint(unsigned int * ptr, 352 int ndata, 353 XDRFILE * xfp); 354 355 356 357 /*! \brief Read one or more \a float type variable(s) 358 * 359 * \param ptr Pointer to memory where data should be written 360 * \param ndata Number of floats to read 361 * \param xfp Handle to portable binary file, created with xdrfile_open() 362 * 363 * \return Number of floats read 364 */ 365 int 366 xdrfile_read_float(float * ptr, 367 int ndata, 368 XDRFILE * xfp); 369 370 371 372 /*! \brief Write one or more \a float type variable(s) 373 * 374 * \param ptr Pointer to memory where data should be read 375 * \param ndata Number of floats to write. 376 * \param xfp Handle to portable binary file, created with xdrfile_open() 377 * 378 * \return Number of floats written 379 */ 380 int 381 xdrfile_write_float(float * ptr, 382 int ndata, 383 XDRFILE * xfp); 384 385 386 387 /*! \brief Read one or more \a double type variable(s) 388 * 389 * \param ptr Pointer to memory where data should be written 390 * \param ndata Number of doubles to read 391 * \param xfp Handle to portable binary file, created with xdrfile_open() 392 * 393 * \return Number of doubles read 394 */ 395 int 396 xdrfile_read_double(double * ptr, 397 int ndata, 398 XDRFILE * xfp); 399 400 401 402 /*! \brief Write one or more \a double type variable(s) 403 * 404 * \param ptr Pointer to memory where data should be read 405 * \param ndata Number of double to write. 406 * \param xfp Handle to portable binary file, created with xdrfile_open() 407 * 408 * \return Number of doubles written 409 */ 410 int 411 xdrfile_write_double(double * ptr, 412 int ndata, 413 XDRFILE * xfp); 414 415 416 417 /*! \brief Read a string (array of characters) 418 * 419 * \param ptr Pointer to memory where data should be written 420 * \param maxlen Maximum length of string. If no end-of-string is encountered, 421 * one byte less than this is read and end-of-string appended. 422 * \param xfp Handle to portable binary file, created with xdrfile_open() 423 * 424 * \return Number of characters read, including end-of-string 425 */ 426 int 427 xdrfile_read_string(char * ptr, 428 int maxlen, 429 XDRFILE * xfp); 430 431 432 433 /*! \brief Write a string (array of characters) 434 * 435 * \param ptr Pointer to memory where data should be read 436 * \param xfp Handle to portable binary file, created with xdrfile_open() 437 * 438 * \return Number of characters written, including end-of-string 439 */ 440 int 441 xdrfile_write_string(char * ptr, 442 XDRFILE * xfp); 443 444 445 446 /*! \brief Read raw bytes from file (unknown datatype) 447 * 448 * \param ptr Pointer to memory where data should be written 449 * \param nbytes Number of bytes to read. No conversion whatsoever is done. 450 * \param xfp Handle to portable binary file, created with xdrfile_open() 451 * 452 * \return Number of bytes read from file 453 */ 454 int 455 xdrfile_read_opaque(char * ptr, 456 int nbytes, 457 XDRFILE * xfp); 458 459 460 461 462 /*! \brief Write raw bytes to file (unknown datatype) 463 * 464 * \param ptr Pointer to memory where data should be read 465 * \param nbytes Number of bytes to write. No conversion whatsoever is done. 466 * \param xfp Handle to portable binary file, created with xdrfile_open() 467 * 468 * \return Number of bytes written to file 469 */ 470 int 471 xdrfile_write_opaque(char * ptr, 472 int nbytes, 473 XDRFILE * xfp); 474 475 476 477 478 479 480 /*! \brief Compress coordiates in a float array to XDR file 481 * 482 * This routine will perform \a lossy compression on the three-dimensional 483 * coordinate data data specified and store it in the XDR file. 484 * 485 * The lossy part of the compression consists of multiplying each 486 * coordinate with the precision argument and then rounding to integers. 487 * We suggest a default value of 1000.0, which means you are guaranteed 488 * three decimals of accuracy. The only limitation is that scaled coordinates 489 * must still fit in an integer variable, so if the precision is 1000.0 the 490 * coordinate magnitudes must be less than +-2e6. 491 * 492 * \param ptr Pointer to coordinates to compress (length 3*ncoord) 493 * \param ncoord Number of coordinate triplets in data 494 * \param precision Scaling factor for lossy compression. If it is <=0, 495 * the default value of 1000.0 is used. 496 * \param xfp Handle to portably binary file 497 * 498 * \return Number of coordinate triplets written. 499 * IMPORTANT: Check that this is equal to ncoord - if it is 500 * negative, an error occured. This should not happen with 501 * normal data, but if your coordinates are NaN or very 502 * large (>1e6) it is not possible to use the compression. 503 * 504 * \warning The compression algorithm is not part of the XDR standard, 505 * and very complicated, so you will need this xdrfile module 506 * to read it later. 507 */ 508 int 509 xdrfile_compress_coord_float(float * ptr, 510 int ncoord, 511 float precision, 512 XDRFILE * xfp); 513 514 515 516 517 /*! \brief Decompress coordiates from XDR file to array of floats 518 * 519 * This routine will decompress three-dimensional coordinate data previously 520 * stored in an XDR file and store it in the specified array of floats. 521 * 522 * The precision used during the earlier compression is read from the file 523 * and returned - you cannot adjust the accuracy at this stage. 524 * 525 * \param ptr Pointer to coordinates to compress (length>= 3*ncoord) 526 * \param ncoord Max number of coordinate triplets to read on input, actual 527 * number of coordinate triplets read on return. If this 528 * is smaller than the number of coordinates in the frame an 529 * error will occur. 530 * \param precision The precision used in the previous compression will be 531 * written to this variable on return. 532 * \param xfp Handle to portably binary file 533 * 534 * \return Number of coordinate triplets read. If this is negative, 535 * an error occured. 536 * 537 * \warning Since we cannot count on being able to set/get the 538 * position of large files (>2Gb), it is not possible to 539 * recover from errors by re-reading the frame if the 540 * storage area you provided was too small. To avoid this 541 * from happening, we recommend that you store the number of 542 * coordinates triplet as an integer either in a header or 543 * just before the compressed coordinate data, so you can 544 * read it first and allocated enough memory. 545 */ 546 int 547 xdrfile_decompress_coord_float(float * ptr, 548 int * ncoord, 549 float * precision, 550 XDRFILE * xfp); 551 552 553 554 555 /*! \brief Compress coordiates in a double array to XDR file 556 * 557 * This routine will perform \a lossy compression on the three-dimensional 558 * coordinate data data specified and store it in the XDR file. Double will 559 * NOT give you any extra precision since the coordinates are compressed. This 560 * routine just avoids allocating a temporary array of floats. 561 * 562 * The lossy part of the compression consists of multiplying each 563 * coordinate with the precision argument and then rounding to integers. 564 * We suggest a default value of 1000.0, which means you are guaranteed 565 * three decimals of accuracy. The only limitation is that scaled coordinates 566 * must still fit in an integer variable, so if the precision is 1000.0 the 567 * coordinate magnitudes must be less than +-2e6. 568 * 569 * \param ptr Pointer to coordinates to compress (length 3*ncoord) 570 * \param ncoord Number of coordinate triplets in data 571 * \param precision Scaling factor for lossy compression. If it is <=0, the 572 * default value of 1000.0 is used. 573 * \param xfp Handle to portably binary file 574 * 575 * \return Number of coordinate triplets written. 576 * IMPORTANT: Check that this is equal to ncoord - if it is 577 * negative, an error occured. This should not happen with 578 * normal data, but if your coordinates are NaN or very 579 * large (>1e6) it is not possible to use the compression. 580 * 581 * \warning The compression algorithm is not part of the XDR standard, 582 * and very complicated, so you will need this xdrfile module 583 * to read it later. 584 */ 585 int 586 xdrfile_compress_coord_double(double * ptr, 587 int ncoord, 588 double precision, 589 XDRFILE * xfp); 590 591 592 593 594 /*! \brief Decompress coordiates from XDR file to array of doubles 595 * 596 * This routine will decompress three-dimensional coordinate data previously 597 * stored in an XDR file and store it in the specified array of doubles. 598 * Double will NOT give you any extra precision since the coordinates are 599 * compressed. This routine just avoids allocating a temporary array of floats. 600 * 601 * The precision used during the earlier compression is read from the file 602 * and returned - you cannot adjust the accuracy at this stage. 603 * 604 * \param ptr Pointer to coordinates to compress (length>= 3*ncoord) 605 * \param ncoord Max number of coordinate triplets to read on input, actual 606 * number of coordinate triplets read on return. If this 607 * is smaller than the number of coordinates in the frame an 608 * error will occur. 609 * \param precision The precision used in the previous compression will be 610 * written to this variable on return. 611 * \param xfp Handle to portably binary file 612 * 613 * \return Number of coordinate triplets read. If this is negative, 614 * an error occured. 615 * 616 * \warning Since we cannot count on being able to set/get the 617 * position of large files (>2Gb), it is not possible to 618 * recover from errors by re-reading the frame if the 619 * storage area you provided was too small. To avoid this 620 * from happening, we recommend that you store the number of 621 * coordinates triplet as an integer either in a header or 622 * just before the compressed coordinate data, so you can 623 * read it first and allocated enough memory. 624 */ 625 int 626 xdrfile_decompress_coord_double(double * ptr, 627 int * ncoord, 628 double * precision, 629 XDRFILE * xfp); 630 631 int64_t xdr_tell(XDRFILE *xd); 632 int xdr_seek(XDRFILE *xd, int64_t pos, int whence); 633 634 #ifdef __cplusplus 635 } 636 #endif 637 638 #endif /* _XDRFILE_H_ */ 639