/usr/include/dcmtk/ofstd/offile.h is in libdcmtk-dev 3.6.2-3build3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 | /*
*
* Copyright (C) 2006-2017, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: ofstd
*
* Author: Marco Eichelberg, Joerg Riesmeier
*
* Purpose: C++ wrapper class for stdio FILE functions and
* wide character filenames
*
*/
#ifndef OFFILE_H
#define OFFILE_H
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/oftypes.h" /* for class OFBool */
#include "dcmtk/ofstd/ofstring.h" /* for class OFString */
#include "dcmtk/ofstd/ofstd.h" /* for class OFStandard */
#define INCLUDE_UNISTD
#define INCLUDE_CSTDIO
#define INCLUDE_CSTRING
#define INCLUDE_CSTDARG
#define INCLUDE_CERRNO
//#define INCLUDE_CWCHAR /* not yet implemented in "ofstdinc.h" */
#include "dcmtk/ofstd/ofstdinc.h"
BEGIN_EXTERN_C
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* needed for struct _stati64 on Win32 */
#endif
END_EXTERN_C
#ifdef HAVE_UNIX_H
#include <unix.h> /* needed for setlinebuf() on QNX */
#endif
/* HP-UX has clearerr both as macro and as a function definition. We have to
* undef the macro so that we can define a function called "clearerr".
*/
#if defined(__hpux) && defined(clearerr)
#undef clearerr
#endif
/* When using the ISO C++ include files such as <cstdio>, <cstdarg> etc.,
* all ANSI C functions like fopen() are declared in namespace std,
* (e.g. we have to use std::fopen()), but non-ANSI Posix functions remain
* in global namespace, e.g. we have to use ::fopen64().
* To make things even more difficult, not all compilers really declare
* ANSI C functions in namespace std in accordance with the C++ standard.
* Yes, this is ugly.
*/
/* Find out whether to use explicit LFS function calls to handle
* large file support
*/
#if defined(DCMTK_ENABLE_LFS) && DCMTK_ENABLE_LFS == DCMTK_LFS64
#define EXPLICIT_LFS_64
// Use POSIX 64 bit file position type when available
#ifdef HAVE_FPOS64_T
typedef fpos64_t offile_fpos_t;
#else // Otherwise this should be sufficient
typedef fpos_t offile_fpos_t;
#endif
// Use POSIX 64 bit file offset type when available
#ifdef HAVE_OFF64_T
typedef off64_t offile_off_t;
#elif !defined(OF_NO_SINT64) // Otherwise use a 64 bit integer
typedef Sint64 offile_off_t;
#else // Cry when 64 LFS is required but no 64 bit integer exists
#error \
Could not find a suitable offset-type for LFS64 support.
#endif
#else // Implicit LFS or no LFS
#if defined(DCMTK_ENABLE_LFS) && DCMTK_ENABLE_LFS == DCMTK_LFS
#if defined(SIZEOF_FPOS_T) && (!defined(SIZEOF_OFF_T) || SIZEOF_FPOS_T > SIZEOF_OFF_T)
// strange Windows LFS where sizeof(fpos_t) == 8 but sizeof(off_t) == 4
#ifndef OF_NO_SINT64 // Use a 64 bit integer
typedef Sint64 offile_off_t;
#else // Cry when LFS is required but no 64 bit integer exists
#error \
Could not find a suitable offset-type for LFS support.
#endif
#else
typedef off_t offile_off_t;
#endif
#elif defined(HAVE_FSEEKO)
typedef off_t offile_off_t;
#else
typedef long offile_off_t;
#endif
typedef fpos_t offile_fpos_t;
#endif // basic type definitions
// the type we use to store the last error.
typedef int offile_errno_t;
/** class for managing filenames consisting either of conventional (8-bit) or
* wide (e.g.\ 16-bit) characters. The wide character support is currently
* Windows-specific because most other operating systems use UTF-8, which is
* compatible with conventional 8-bit character strings.
*/
class DCMTK_OFSTD_EXPORT OFFilename
{
public:
/** default constructor
*/
OFFilename();
/** constructor expecting a conventional character string
* @param filename filename to be stored (8-bit characters, e.g. UTF-8)
* @param convert convert given filename to wide character encoding as an
* alternative representation
*/
OFFilename(const char *filename,
const OFBool convert = OFFalse);
/** constructor expecting a character string as an OFString instance
* @param filename filename to be stored (8-bit characters, e.g. UTF-8)
* @param convert convert given filename to wide character encoding as an
* alternative representation. Only works on Windows systems.
*/
OFFilename(const OFString &filename,
const OFBool convert = OFFalse);
#if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32)
/** constructor expecting a wide character string
* @param filename filename to be stored (e.g. 16-bit characters)
* @param convert convert given filename to UTF-8 encoding as an
* alternative representation. Only works on Windows systems.
*/
OFFilename(const wchar_t *filename,
const OFBool convert = OFTrue);
#endif
/** copy constructor
* @param arg filename object to be copied
*/
OFFilename(const OFFilename &arg);
/** destructor. Frees memory.
*/
~OFFilename();
/** assignment operator
* @param arg filename object to be copied
* @return reference to this filename object
*/
OFFilename &operator=(const OFFilename &arg);
/** clear currently stored filename
*/
void clear();
/** fast, non-throwing swap function. The time complexity of this function
* is constant.
* @param arg filename object to swap with
*/
void swap(OFFilename &arg);
/** checks whether this object stores an empty filename
* @return OFTrue if the filename is empty, OFFalse otherwise
*/
OFBool isEmpty() const;
/** checks whether this object stores a wide character filename
* @return OFTrue if the filename uses wide characters, OFFalse otherwise
*/
inline OFBool usesWideChars() const
{
#if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32)
return (wfilename_ != NULL);
#else
return OFFalse;
#endif
}
/** get stored filename consisting of conventional characters
* @return filename (might be NULL if none is stored)
*/
inline const char *getCharPointer() const
{
return filename_;
}
#if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32)
/** get stored filename consisting of wide characters
* @return wide char filename (might be NULL if none is stored)
*/
inline const wchar_t *getWideCharPointer() const
{
return wfilename_;
}
#endif
/** replace currently stored filename by given value
* @param filename filename to be stored (8-bit characters, e.g. UTF-8)
* @param convert convert given filename to wide character encoding as an
* alternative representation. Only works on Windows systems.
*/
void set(const char *filename,
const OFBool convert = OFFalse);
/** replace currently stored filename by given value
* @param filename filename to be stored (8-bit characters, e.g. UTF-8)
* @param convert convert given filename to wide character encoding as an
* alternative representation). Only works on Windows systems.
*/
void set(const OFString &filename,
const OFBool convert = OFFalse);
#if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32)
/** replace currently stored filename by given value
* @param filename filename to be stored (e.g. 16-bit characters)
* @param convert convert given filename to UTF-8 encoding as an alternative
* representation. Only works on Windows systems.
*/
void set(const wchar_t *filename,
const OFBool convert = OFTrue);
#endif
private:
/// filename consisting of conventional characters (8-bit, e.g. UTF-8)
char *filename_;
#if (defined(WIDE_CHAR_FILE_IO_FUNCTIONS) || defined(WIDE_CHAR_MAIN_FUNCTION)) && defined(_WIN32)
/// filename consisting of wide characters (e.g. 16-bit on Windows)
wchar_t *wfilename_;
#endif
};
/** swap function for OFFilename class. The time complexity of this function
* is constant.
* @param lhs left-hand side filename
* @param rhs right-hand side filename
*/
inline void swap(OFFilename &lhs, OFFilename &rhs)
{
lhs.swap(rhs);
}
/** output filename to the given stream.
* Only the string of conventional characters (e.g. ASCII or UTF-8) is printed since
* we do not expect the output stream (console or logger) to support wide characters.
* @param stream output stream
* @param filename OFFilename object to print
* @return reference to the output stream
*/
DCMTK_OFSTD_EXPORT STD_NAMESPACE ostream &operator<<(STD_NAMESPACE ostream &stream, const OFFilename &filename);
/** this class provides a simple C++ encapsulation layer for stdio FILE pointers.
* All stdio functions on files are directly mapped into member functions.
* The handling of large files (64 bit file systems) is transparent. Instead
* of type off_t, fseek() and ftell() use offile_off_t which is a 64 bit type
* if available on the underlying platform. Similarly, getpos() and setpos() use
* type offile_fpos_t, which is defined appropriately.
* This class provides both fclose() and pclose(), but these are equivalent -
* the code always closes pipes with pclose() and files with fclose().
* Finally, an abstraction for errno is provided. Error codes should always
* be retrieves using methods getLastError() and getLastErrorString() which
* on Unix platforms are based on errno and strerror/strerror_r, but may be based
* on other mechanisms on platforms where errno does not exist.
*/
class OFFile
{
public:
/// default constructor, creates an object that is not associated with any file.
OFFile(): file_(NULL), popened_(OFFalse), lasterror_(0) {}
/** create object for given stdio FILE
* @param f stdio FILE
*/
OFFile(FILE *f): file_(f), popened_(OFFalse), lasterror_(0) {}
/// destructor. Closes file if still open.
~OFFile()
{
if (file_) fclose();
}
/** opens the file whose name is the string pointed to by path and associates
* a stream with it.
* @param filename path to file
* @param modes "r", "w" or "a" with possible modifiers "+", "b"
* @return true if stream was successfully created, false otherwise, in which
* case the error code is set.
*/
OFBool fopen(const char *filename, const char *modes)
{
if (file_) fclose();
#ifdef EXPLICIT_LFS_64
file_ = :: fopen64(filename, modes);
#else
file_ = STDIO_NAMESPACE fopen(filename, modes);
#endif
if (file_) popened_ = OFFalse; else storeLastError();
return (file_ != NULL);
}
#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
/** opens the file whose name is the wide character string pointed to by path and
* associates a stream with it. This function is Win32 specific and only exists on
* WinNT and newer.
* @param filename Unicode filename path to file
* @param modes "r", "w" or "a" with possible modifiers "+", "b", as a wide
* character string
* @return true if stream was successfully created, false otherwise, in which case
* the error code is set.
*/
OFBool wfopen(const wchar_t *filename, const wchar_t *modes)
{
if (file_) fclose();
file_ = _wfopen(filename, modes);
if (file_) popened_ = OFFalse; else storeLastError();
return (file_ != NULL);
}
#endif
/** opens the file whose name is a conventional or wide character string pointed to
* by path and associates. The wide character support is currently Windows-specific.
* @param filename object containing the filename path to file
* @param modes "r", "w" or "a" with possible modifiers "+", "b"
* @return true if stream was successfully created, false otherwise, in which case
* the error code is set.
*/
OFBool fopen(const OFFilename &filename, const char *modes)
{
OFBool result = OFFalse;
#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
if (filename.usesWideChars())
{
// convert file mode to wide char string
const size_t length = strlen(modes) + 1;
wchar_t *wmodes = new wchar_t[length];
if (wmodes != NULL)
{
for (size_t i = 0; i < length; ++i)
{
// conversion of ASCII codes (7-bit) is easy
wmodes[i] = OFstatic_cast(wchar_t, modes[i]);
}
result = wfopen(filename.getWideCharPointer(), wmodes);
}
delete[] wmodes;
} else
#endif
result = fopen(filename.getCharPointer(), modes);
return result;
}
/** associates a stream with the existing file descriptor 'fd'. The mode of
* the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be
* compatible with the mode of the file descriptor. The file position
* indicator of the new stream is set to that belonging to 'fd', and the
* error and end-of-file indicators are cleared. Modes "w" or "w+" do not
* cause truncation of the file. The file descriptor is not dup'ed, and
* will be closed when the stream created by fdopen is closed. The result
* of applying fdopen to a shared memory object is undefined.
* @param fd file descriptor
* @param modes "r", "w" or "a" with possible modifiers "+", "b"
* @return true if stream was successfully created, false otherwise, in
* which case the error code is set.
*/
OFBool fdopen(int fd, const char *modes)
{
if (file_) fclose();
file_ = :: fdopen(fd, modes);
if (file_) popened_ = OFFalse; else storeLastError();
return (file_ != NULL);
}
/** opens a process by creating a pipe, forking, and invoking the shell.
* Since a pipe is by definition unidirectional, the type argument may
* specify only reading or writing, not both; the resulting stream is
* correspondingly read-only or write-only. If the object was already
* associated with another file or pipe, that one is closed.
* @param command shell command line
* @param modes "r" or "w"
* @return true if pipe was successfully created, false otherwise
*/
OFBool popen(const char *command, const char *modes)
{
if (file_) fclose();
#ifdef HAVE_POPEN
file_ = :: popen(command, modes);
#else
file_ = _popen(command, modes);
#endif
if (file_) popened_ = OFTrue; else storeLastError();
return (file_ != NULL);
}
/** opens the file whose name is the string pointed to by path and associates
* the stream pointed maintained by this object with it. The original stream
* (if it exists) is closed. The mode argument is used just as in the fopen
* function. The primary use of the freopen function is to change the file
* associated with a standard text stream (stderr, stdin, or stdout).
* @param filename path to file
* @param modes "r", "w" or "a" with possible modifiers "+", "b"
* @return true if stream was successfully created, false otherwise, in
* which case the error code is set.
*/
OFBool freopen(const char *filename, const char *modes)
{
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
// MinGW has EXPLICIT_LFS_64 but no freopen64()
file_ = :: freopen64(filename, modes, file_);
#else
file_ = STDIO_NAMESPACE freopen(filename, modes, file_);
#endif
if (file_) popened_ = OFFalse; else storeLastError();
return (file_ != NULL);
}
/** generates a unique temporary filename. The temporary file is then opened
* in binary read/write (w+b) mode. The file will be automatically deleted
* when it is closed or the program terminates normally.
* @return true if stream was successfully created, false otherwise, in
* which case the error code is set.
*/
OFBool tmpfile()
{
if (file_) fclose();
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
// MinGW has EXPLICIT_LFS_64 but no tmpfile64()
file_ = :: tmpfile64();
#else
file_ = STDIO_NAMESPACE tmpfile();
#endif
if (file_) popened_ = OFFalse; else storeLastError();
return (file_ != NULL);
}
/** dissociates the named stream from its underlying file or set of functions.
* If the stream was being used for output, any buffered data is written
* first, using fflush. Independent of the return value of this method,
* any further access (including another call to fclose()) to the stream
* maintained by this object results in undefined behaviour.
* @return 0 upon success, EOF otherwise, in which case the error code is set.
*/
int fclose()
{
int result = 0;
if (file_)
{
if (popened_)
{
#ifdef HAVE_PCLOSE
result = :: pclose(file_);
#else
result = _pclose(file_);
#endif
}
else
{
result = STDIO_NAMESPACE fclose(file_);
}
// After calling fclose() once, the FILE* is gone even if fclose() failed.
file_ = NULL;
}
if (result) storeLastError();
return result;
}
/** waits for the associated process (created with popen) to terminate and
* returns the exit status of the command as returned by wait4.
* In this implementation, fclose and pclose can be used synonymously.
* @return process ID of the child which exited, or -1 on error, in which
* case the error code is set
*/
int pclose() { return fclose(); }
/** writes n elements of data, each size bytes long, to the stream, obtaining
* them from the location given by ptr. Returns the number of items successfully written
* (i.e., not the number of characters). If an error occurs the return value is a short
* item count (or zero).
* @param ptr pointer to buffer
* @param size size of item
* @param n number of items
* @return number of items written
*/
size_t fwrite(const void *ptr, size_t size, size_t n)
{
return STDIO_NAMESPACE fwrite(ptr, size, n, file_);
}
/** reads n elements of data, each size bytes long, from the stream, storing
* them at the location given by ptr. Returns the number of items successfully
* read (i.e., not the number of characters). If an error occurs, or the
* end-of-file is reached, the return value is a short item count (or zero).
* fread does not distinguish between end-of-file and error, and callers must
* use feof and ferror to determine which occurred.
* @param ptr pointer to buffer
* @param size size of item
* @param n number of items
* @return number of items read
*/
size_t fread(void *ptr, size_t size, size_t n)
{
return STDIO_NAMESPACE fread(ptr, size, n, file_);
}
/** forces a write of all user-space buffered data for the given output or
* update stream via the stream's underlying write function. The open status
* of the stream is unaffected.
* @return 0 upon success, EOF otherwise, in which case the error code is set.
*/
int fflush()
{
int result = STDIO_NAMESPACE fflush(file_);
if (result) storeLastError();
return result;
}
/** reads the next character from stream and returns it as an unsigned char
* cast to an int, or EOF on end of file or error.
* @return next character from stream or EOF
*/
int fgetc() { return STDIO_NAMESPACE fgetc(file_); }
/** The three types of buffering available are unbuffered, block buffered, and
* line buffered. When an output stream is unbuffered, information appears on
* the destination file or terminal as soon as written; when it is block
* buffered many characters are saved up and written as a block; when it is
* line buffered characters are saved up until a newline is output or input
* is read from any stream attached to a terminal device (typically stdin).
* Normally all files are block buffered. if a stream refers to a terminal
* (as stdout normally does) it is line buffered. The standard error stream
* stderr is always unbuffered by default. this function allows to set the
* mode of the stream to line buffered.
* @return 0 upon success, nonzero otherwise, in which case the error code may be set
*
*/
void setlinebuf()
{
#if defined(_WIN32) || defined(__hpux)
this->setvbuf(NULL, _IOLBF, 0);
#else
:: setlinebuf(file_);
#endif
}
/** sets the file position indicator for the stream pointed to by stream to
* the beginning of the file. This is equivalent to fseek(0, SEEK_SET)
* except that the error indicator for the stream is also cleared.
*/
void rewind()
{
#if defined(_WIN32) || defined(__CYGWIN__)
/* On these platforms rewind() fails after reading to the end of file
* if the file is read-only. Using fseek() instead.
*/
(void) this->fseek(0L, SEEK_SET);
#else
STDIO_NAMESPACE rewind(file_);
#endif
}
/** clears the end-of-file and error indicators for the stream
*/
void clearerr() { STDIO_NAMESPACE clearerr(file_); }
/** tests the end-of-file indicator for the stream, returning non-zero if it
* is set. The end-of-file indicator can only be cleared by the function
* clearerr. This method is called eof, not feof, because feof() is a macro
* on some systems and, therefore, cannot be used as a method name.
* @return non-zero if EOF, zero otherwise
*/
int eof() const
{
#ifdef feof
// feof is a macro on some systems. Macros never have namespaces.
return feof(file_);
#else
return STDIO_NAMESPACE feof(file_);
#endif
}
/** tests the error indicator for the stream, returning non-zero if it is set.
* This method is named error, not ferror, because ferror() is a macro
* on some systems and, therefore, cannot be used as a method name.
* The error indicator can only be reset by the clearerr function.
* @return non-zero if error flag is set, zero otherwise
*/
int error()
{
#ifdef ferror
// ferror is a macro on some systems. Macros never have namespaces.
return ferror(file_);
#else
return STDIO_NAMESPACE ferror(file_);
#endif
}
/** returns the low-level file descriptor associated with the stream.
* The spelling of this member function is different from stdio fileno()
* because on some systems (such as MinGW) fileno() is a macro
* and, therefore, cannot be used as a method name.
* @return low-level file descriptor associated with stream
*/
#ifdef fileno
int fileNo() { return fileno(file_); }
#else
int fileNo() { return :: fileno(file_); }
#endif
/** The three types of buffering available are unbuffered, block buffered, and
* line buffered. When an output stream is unbuffered, information appears on
* the destination file or terminal as soon as written; when it is block
* buffered many characters are saved up and written as a block; when it is
* line buffered characters are saved up until a newline is output or input
* is read from any stream attached to a terminal device (typically stdin).
* Normally all files are block buffered. if a stream refers to a terminal
* (as stdout normally does) it is line buffered. The standard error stream
* stderr is always unbuffered by default. This function allows to set the
* mode of the stream to unbuffered (if buf is NULL) or block buffered.
* @param buf pointer to buffer of size BUFSIZ as declared in cstdio, or NULL
* @return 0 upon success, nonzero otherwise, in which case the error code may be set
*/
void setbuf(char *buf) { STDIO_NAMESPACE setbuf(file_, buf); }
/** The three types of buffering available are unbuffered, block buffered, and
* line buffered. When an output stream is unbuffered, information appears on
* the destination file or terminal as soon as written; when it is block
* buffered many characters are saved up and written as a block; when it is
* line buffered characters are saved up until a newline is output or input
* is read from any stream attached to a terminal device (typically stdin).
* Normally all files are block buffered. if a stream refers to a terminal
* (as stdout normally does) it is line buffered. The standard error stream
* stderr is always unbuffered by default. This function allows to set the
* stream mode.
* @param buf pointer to buffer, may be NULL
* @param modes _IONBF (unbuffered) _IOLBF (line buffered) or _IOFBF (fully buffered)
* @param n size of buffer, in bytes
* @return 0 upon success, nonzero otherwise, in which case the error code may be set
*/
int setvbuf(char * buf, int modes, size_t n)
{
int result = STDIO_NAMESPACE setvbuf(file_, buf, modes, n);
if (result) storeLastError();
return result;
}
/** The three types of buffering available are unbuffered, block buffered, and
* line buffered. When an output stream is unbuffered, information appears on
* the destination file or terminal as soon as written; when it is block
* buffered many characters are saved up and written as a block; when it is
* line buffered characters are saved up until a newline is output or input
* is read from any stream attached to a terminal device (typically stdin).
* Normally all files are block buffered. if a stream refers to a terminal
* (as stdout normally does) it is line buffered. The standard error stream
* stderr is always unbuffered by default. This function allows to set the
* mode of the stream to unbuffered (if buf is NULL) or block buffered.
* @param buf pointer to buffer
* @param size size of buffer, in bytes
* @return 0 upon success, nonzero otherwise, in which case the error code may be set
*/
void setbuffer(char *buf, size_t size)
{
#if defined(_WIN32) || defined(__hpux)
this->setvbuf(NULL, buf ? _IOFBF : _IONBF, size);
#else
:: setbuffer(file_, buf, size);
#endif
}
/** writes the character c, cast to an unsigned char, to stream.
* @param c character
* @return the character written as an unsigned char cast to an int or EOF on error
*/
int fputc(int c) { return STDIO_NAMESPACE fputc(c, file_); }
/** reads in at most one less than n characters from stream and stores them
* into the buffer pointed to by s. Reading stops after an EOF or a newline.
* If a newline is read, it is stored into the buffer. A '@\0' is stored after
* the last character in the buffer.
* @param s pointer to buffer of size n
* @param n buffer size
* @return pointer to string
*/
char *fgets(char *s, int n) { return STDIO_NAMESPACE fgets(s, n, file_); }
/** writes the string s to stream, without its trailing '@\0'.
* @param s string to be written
* @return a non-negative number on success, or EOF on error.
*/
int fputs(const char *s) { return STDIO_NAMESPACE fputs(s, file_); }
/** pushes c back to stream, cast to unsigned char, where it is available for
* subsequent read operations. Pushed - back characters will be returned in
* reverse order; only one pushback is guaranteed.
* @param c character to push back
* @return c on success, or EOF on error.
*/
int ungetc(int c) { return STDIO_NAMESPACE ungetc(c, file_); }
/** sets the file position indicator for the stream pointed to by stream. The
* new position, measured in bytes, is obtained by adding offset bytes to the
* position specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or
* SEEK_END, the offset is relative to the start of the file, the current
* position indicator, or end-of-file, respectively. A successful call to the
* fseek function clears the end-of- file indicator for the stream and undoes
* any effects of the ungetc function on the same stream.
* @param off offset to seek to
* @param whence SEEK_SET, SEEK_CUR, or SEEK_END
* @return 0 upon success, -1 otherwise in which case the error code is set.
*/
int fseek(offile_off_t off, int whence)
{
int result;
#ifdef _WIN32
// Windows does not have a 64-bit fseek.
// We emulate fseek through fsetpos, which does exist on Windows.
// fpos_t is (hopefully always) defined as __int64 on this platform
offile_fpos_t off2 = off;
fpos_t pos;
struct _stati64 buf;
switch (whence)
{
case SEEK_END:
// flush write buffer, if any, so that the file size is correct
STDIO_NAMESPACE fflush(file_);
#if 0
// Python implementation based on _lseeki64(). May be unsafe because
// there is no guarantee that fflush also empties read buffers.
STDIO_NAMESPACE fflush(file_);
#ifdef fileno
if (_lseeki64( fileno(file_), 0, 2) == -1)
#else
if (_lseeki64(:: fileno(file_), 0, 2) == -1)
#endif
{
storeLastError();
return -1;
}
// fall through
#else
// determine file size (using underlying file descriptor). This should be safe.
#ifdef fileno
if (_fstati64( fileno(file_), &buf) == -1)
#else
if (_fstati64(:: fileno(file_), &buf) == -1)
#endif
{
storeLastError();
return -1;
}
// fsetpos position is offset + file size.
off2 += buf.st_size;
break;
#endif
case SEEK_CUR:
if (STDIO_NAMESPACE fgetpos(file_, &pos) != 0)
{
storeLastError();
return -1;
}
off2 += pos;
break;
case SEEK_SET:
/* do nothing */
break;
}
result = this->fsetpos(&off2);
#elif defined(__BEOS__)
result = :: _fseek(fp, offset, whence);
#else
#ifdef HAVE_FSEEKO
#ifdef EXPLICIT_LFS_64
result = :: fseeko64(file_, off, whence);
#else
result = :: fseeko(file_, off, whence);
#endif
#else
result = STDIO_NAMESPACE fseek(file_, off, whence);
#endif
#endif
if (result) storeLastError();
return result;
}
/** obtains the current value of the file position indicator for the stream pointed to by the stream.
* @return current file position
*/
offile_off_t ftell()
{
offile_off_t result;
#ifdef _WIN32
// Windows does not have a 64-bit ftell, and _telli64 cannot be used
// because it operates on file descriptors and ignores FILE buffers.
// We emulate ftell through fgetpos, which does exist on Windows.
// fpos_t is (hopefully always) defined as __int64 on this platform.
offile_fpos_t pos;
if (this->fgetpos(&pos) != 0)
{
storeLastError();
return -1;
}
return pos;
#else
#ifdef HAVE_FSEEKO
#ifdef EXPLICIT_LFS_64
result = :: ftello64(file_);
#else
result = :: ftello(file_);
#endif
#else
result = STDIO_NAMESPACE ftell(file_);
#endif
#endif
if (result < 0) storeLastError();
return result;
}
/** alternate interface equivalent to ftell, storing the current value of the
* file offset into the object referenced by pos. On some non-UNIX systems an
* fpos_t object may be a complex object and these routines may be the only
* way to portably reposition a text stream.
* @param pos pointer to offile_fpos_t structure
* @return 0 upon success, -1 otherwise in which case the error code is set.
*/
int fgetpos(offile_fpos_t *pos)
{
int result;
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__) && ! defined(__QNX__)
// MinGW and QNX have EXPLICIT_LFS_64 but no fgetpos64()
result = :: fgetpos64(file_, pos);
#else
result = STDIO_NAMESPACE fgetpos(file_, pos);
#endif
if (result) storeLastError();
return result;
}
/** alternate interface equivalent to fseek (with whence set to SEEK_SET),
* setting the current value of the file offset from the object referenced by
* pos. On some non-UNIX systems an fpos_t object may be a complex object and
* these routines may be the only way to portably reposition a text stream.
* @param pos pointer to offile_fpos_t structure
* @return 0 upon success, -1 otherwise in which case the error code is set.
*/
int fsetpos(offile_fpos_t *pos)
{
int result;
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__) && ! defined(__QNX__)
// MinGW and QNX have EXPLICIT_LFS_64 but no fsetpos64()
result = :: fsetpos64(file_, pos);
#else
result = STDIO_NAMESPACE fsetpos(file_, pos);
#endif
if (result) storeLastError();
return result;
}
/** print formatted string into stream, see printf(3)
* @param format format string
* @param ... further parameters according to format string
* @return number of characters printed
*/
int fprintf(const char *format, ...)
{
int result = 0;
va_list ap;
va_start(ap, format);
result = STDIO_NAMESPACE vfprintf(file_, format, ap);
va_end(ap);
return result;
}
/** print formatted string into stream, see printf(3)
* @param format format string
* @param arg list of further parameters according to format string
* @return number of characters printed
*/
int vfprintf(const char *format, va_list arg)
{
return STDIO_NAMESPACE vfprintf(file_, format, arg);
}
// we cannot emulate fscanf because we would need vfscanf for this
// purpose, which does not exist, e.g. on Win32.
/** return FILE pointer managed by this object. This allows the user
* to call some stdio functions that are not encapsulated in this class
* (but possibly should be).
* @return pointer to FILE structure managed by this object
*/
FILE *file() { return file_; }
/** return true if this object is currently associated with a stream, false otherwise
* @return true if this object is currently associated with a stream, false otherwise
*/
OFBool open() const { return file_ != NULL; }
/** return last error code for this stream
* @return last error code for this stream
*/
offile_errno_t getLastError() const { return lasterror_; }
/** return string describing last error code for this stream
* @param s string describing last error code for this stream returned in this parameter
*/
void getLastErrorString(OFString& s) const
{
char buf[1000];
s = OFStandard::strerror(lasterror_, buf, 1000);
}
// wide character functions (disabled by default, since currently not used within DCMTK)
#ifdef WIDE_CHAR_FILE_IO_FUNCTIONS
/** When mode is zero, the fwide function determines the current orientation
* of stream. It returns a value > 0 if stream is wide-character oriented,
* i.e. if wide character I/O is permitted but char I/O is disallowed. It
* returns a value < 0 if stream is byte oriented, i.e. if char I/O is
* permitted but wide character I/O is disallowed. It returns zero if stream
* has no orientation yet; in this case the next I/O operation might change
* the orientation (to byte oriented if it is a char I/O operation, or to
* wide-character oriented if it is a wide character I/O operation).
* Once a stream has an orientation, it cannot be changed and persists until
* the stream is closed.
* When mode is non-zero, the fwide function first attempts to set stream's
* orientation (to wide-character oriented if mode > 0, or to byte oriented
* if mode < 0). It then returns a value denoting the current orientation, as
* above.
* @param mode mode of operation for fwide
* @return orientation of stream
*/
int fwide(int mode)
{
return STDIO_NAMESPACE fwide(file_, mode);
}
/** reads a wide character from stream and returns it. If the end of stream is
* reached, or if ferror(stream) becomes true, it returns WEOF. If a wide
* character conversion error occurs, it sets the error code to EILSEQ and returns
* WEOF.
* @return next character from stream or WEOF
*/
wint_t fgetwc()
{
wint_t result = STDIO_NAMESPACE fgetwc(file_);
if (result == WEOF) storeLastError();
return result;
}
/** writes the wide character wc to stream. If ferror(stream) becomes true, it returns WEOF.
* If a wide character conversion error occurs, it sets the error code to EILSEQ and returns WEOF.
* Otherwise it returns wc.
* @param wc wide character to write to stream
* @return character written or WEOF
*/
wint_t fputwc(wchar_t wc)
{
wint_t result = STDIO_NAMESPACE fputwc(wc, file_);
if (result == WEOF) storeLastError();
return result;
}
/** pushes back a wide character onto stream and returns it. If wc is WEOF, it
* returns WEOF. If wc is an invalid wide character, it sets errno to EILSEQ
* and returns WEOF. If wc is a valid wide character, it is pushed back onto
* the stream and thus becomes available for future wide character read
* operations. The file-position indicator is decremented by one or more.
* The end-of-file indicator is cleared. The backing storage of the file is
* not affected. Note: wc need not be the last wide character read from the
* stream; it can be any other valid wide character. If the implementation
* supports multiple push-back operations in a row, the pushed-back wide
* characters will be read in reverse order; however, only one level of
* push-back is guaranteed.
* @param wc wide character to put back to stream
* @return character put back or WEOF
*/
wint_t ungetwc(wint_t wc)
{
wint_t result = STDIO_NAMESPACE ungetwc(wc, file_);
if (result == WEOF) storeLastError();
return result;
}
/** print formatted wide string into stream, see wprintf(3)
* @param format format string
* @param ... further parameters according to format string
* @return number of characters printed
*/
int fwprintf(const wchar_t *format, ...)
{
int result = 0;
va_list ap;
va_start(ap, format);
result = STDIO_NAMESPACE vfwprintf(file_, format, ap);
va_end(ap);
return result;
}
/** print formatted wide string into stream, see printf(3)
* @param format format string
* @param arg list of further parameters according to format string
* @return number of characters printed
*/
int vfwprintf(const wchar_t *format, va_list arg)
{
return STDIO_NAMESPACE vfwprintf(file_, format, arg);
}
// we cannot emulate fwscanf because we would need vfwscanf for this
// purpose, which does not exist, e.g. on Win32.
#endif /* WIDE_CHAR_FILE_IO_FUNCTIONS */
private:
// private undefined copy constructor
OFFile(const OFFile &arg);
// private undefined assignment operator
OFFile &operator=(const OFFile &arg);
/// the file maintained by this object
FILE *file_;
/// a flag indicating whether or not this object was created with popen().
OFBool popened_;
/// the last error code for operations of this stream
offile_errno_t lasterror_;
/// store last error code. For now we simply store the content of errno.
inline void storeLastError()
{
lasterror_ = errno;
}
};
#endif
|