OFFIS DCMTK  Version 3.6.0
offile.h
1 /*
2  *
3  * Copyright (C) 2006-2010, OFFIS e.V.
4  * All rights reserved. See COPYRIGHT file for details.
5  *
6  * This software and supporting documentation were developed by
7  *
8  * OFFIS e.V.
9  * R&D Division Health
10  * Escherweg 2
11  * D-26121 Oldenburg, Germany
12  *
13  *
14  * Module: ofstd
15  *
16  * Author: Marco Eichelberg
17  *
18  * Purpose: C++ wrapper class for stdio FILE functions
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2010-12-17 10:50:30 $
22  * CVS/RCS Revision: $Revision: 1.17 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 #ifndef OFFILE_H
30 #define OFFILE_H
31 
32 #include "dcmtk/config/osconfig.h"
33 #include "dcmtk/ofstd/oftypes.h" /* for class OFBool */
34 #include "dcmtk/ofstd/ofstring.h" /* for class OFString */
35 #include "dcmtk/ofstd/ofstd.h" /* for class OFStandard */
36 
37 #define INCLUDE_UNISTD
38 #define INCLUDE_CSTDIO
39 #define INCLUDE_CSTRING
40 #define INCLUDE_CSTDARG
41 #define INCLUDE_CERRNO
42 //#define INCLUDE_CWCHAR /* not yet implemented in "ofstdinc.h" */
43 #include "dcmtk/ofstd/ofstdinc.h"
44 
45 BEGIN_EXTERN_C
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h> /* needed for struct _stati64 on Win32 */
48 #endif
49 END_EXTERN_C
50 
51 /* HP-UX has clearerr both as macro and as a function definition. We have to
52  * undef the macro so that we can define a function called "clearerr".
53  */
54 #if defined(__hpux) && defined(clearerr)
55 #undef clearerr
56 #endif
57 
58 /* When using the ISO C++ include files such as <cstdio>, <cstdarg> etc.,
59  * all ANSI C functions like fopen() are declared in namespace std,
60  * (e.g. we have to use std::fopen()), but non-ANSI Posix functions remain
61  * in global namespace, e.g. we have to use ::fopen64().
62  * To make things even more difficult, not all compilers really declare
63  * ANSI C functions in namespace std in accordance with the C++ standard.
64  * Yes, this is ugly.
65  */
66 
67 /* Find out whether current operating system needs explicit function calls
68  * to handle large file support
69  */
70 #ifdef _LARGEFILE64_SOURCE
71  // Mac OS X defines _LARGEFILE64_SOURCE but anyhow expects implicit 64 bit calls.
72  // The same is true for current Cygwin versions (tested with version 1.7.7-1).
73  #if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__CYGWIN__)
74  #define EXPLICIT_LFS_64
75  #endif
76 #endif
77 
78 #if defined(_WIN32) && !defined(__MINGW32__)
79  // On Win32 systems except MinGW (where Posix definitions are available)
80  // we use Win32 specific definitions
81  typedef __int64 offile_off_t;
82  typedef fpos_t offile_fpos_t;
83 #else
84  #ifdef EXPLICIT_LFS_64
85  // Explicit LFS (LFS64)
86  typedef fpos64_t offile_fpos_t;
87  typedef off64_t offile_off_t;
88  #else
89  // Implicit LFS or no LFS
90  #ifdef HAVE_FSEEKO
91  typedef off_t offile_off_t;
92  #else
93  typedef long offile_off_t;
94  #endif
95  typedef fpos_t offile_fpos_t;
96  #endif
97 #endif
98 
99 // the type we use to store the last error.
100 typedef int offile_errno_t;
101 
115 class OFFile
116 {
117 public:
119  OFFile(): file_(NULL), popened_(OFFalse), lasterror_(0) {}
120 
124  OFFile(FILE *f): file_(f), popened_(OFFalse), lasterror_(0) {}
125 
128  {
129  if (file_) fclose();
130  }
131 
139  OFBool fopen(const char *filename, const char *modes)
140  {
141  if (file_) fclose();
142 #ifdef EXPLICIT_LFS_64
143  file_ = :: fopen64(filename, modes);
144 #else
145  file_ = STDIO_NAMESPACE fopen(filename, modes);
146 #endif
147  if (file_) popened_ = OFFalse; else storeLastError();
148  return (file_ != NULL);
149  }
150 
151 #if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
152 
158  OFBool wfopen(const wchar_t *filename, const wchar_t *modes)
159  {
160  if (file_) fclose();
161  file_ = _wfopen(filename, modes);
162  if (file_) popened_ = OFFalse; else storeLastError();
163  return (file_ != NULL);
164  }
165 #endif
166 
179  OFBool fdopen(int fd, const char *modes)
180  {
181  if (file_) fclose();
182  file_ = :: fdopen(fd, modes);
183  if (file_) popened_ = OFFalse; else storeLastError();
184  return (file_ != NULL);
185  }
186 
196  OFBool popen(const char *command, const char *modes)
197  {
198  if (file_) fclose();
199 #ifdef _WIN32
200  file_ = _popen(command, modes);
201 #else
202  file_ = :: popen(command, modes);
203 #endif
204  if (file_) popened_ = OFTrue; else storeLastError();
205  return (file_ != NULL);
206  }
207 
217  OFBool freopen(const char *filename, const char *modes)
218  {
219 #if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
220  // MinGW has EXPLICIT_LFS_64 but no freopen64()
221  file_ = :: freopen64(filename, modes, file_);
222 #else
223  file_ = STDIO_NAMESPACE freopen(filename, modes, file_);
224 #endif
225  if (file_) popened_ = OFFalse; else storeLastError();
226  return (file_ != NULL);
227  }
228 
234  OFBool tmpfile()
235  {
236  if (file_) fclose();
237 #if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
238  // MinGW has EXPLICIT_LFS_64 but no tmpfile64()
239  file_ = :: tmpfile64();
240 #else
241  file_ = STDIO_NAMESPACE tmpfile();
242 #endif
243  if (file_) popened_ = OFFalse; else storeLastError();
244  return (file_ != NULL);
245  }
246 
254  int fclose()
255  {
256  int result = 0;
257  if (file_)
258  {
259  if (popened_)
260  {
261 #ifdef _WIN32
262  result = _pclose(file_);
263 #else
264  result = :: pclose(file_);
265 #endif
266  }
267  else
268  {
269  result = STDIO_NAMESPACE fclose(file_);
270  }
271  // After calling fclose() once, the FILE* is gone even if fclose() failed.
272  file_ = NULL;
273  }
274  if (result) storeLastError();
275  return result;
276  }
277 
283  int pclose() { return fclose(); }
284 
294  size_t fwrite(const void *ptr, size_t size, size_t n)
295  {
296  return STDIO_NAMESPACE fwrite(ptr, size, n, file_);
297  }
298 
310  size_t fread(void *ptr, size_t size, size_t n)
311  {
312  return STDIO_NAMESPACE fread(ptr, size, n, file_);
313  }
314 
320  int fflush()
321  {
322  int result = STDIO_NAMESPACE fflush(file_);
323  if (result) storeLastError();
324  return result;
325  }
326 
331  int fgetc() { return STDIO_NAMESPACE fgetc(file_); }
332 
346  void setlinebuf()
347  {
348 #if defined(_WIN32) || defined(__hpux)
349  this->setvbuf(NULL, _IOLBF, 0);
350 #else
352 #endif
353  }
354 
359  void rewind() { STDIO_NAMESPACE rewind(file_); }
360 
363  void clearerr() { STDIO_NAMESPACE clearerr(file_); }
364 
371  int eof() const
372  {
373 #ifdef feof
374  // feof is a macro on some systems. Macros never have namespaces.
375  return feof(file_);
376 #else
377  return STDIO_NAMESPACE feof(file_);
378 #endif
379  }
380 
387  int error()
388  {
389 #ifdef ferror
390  // ferror is a macro on some systems. Macros never have namespaces.
391  return ferror(file_);
392 #else
393  return STDIO_NAMESPACE ferror(file_);
394 #endif
395  }
396 
403 #ifdef fileno
404  int fileNo() { return fileno(file_); }
405 #else
406  int fileNo() { return :: fileno(file_); }
407 #endif
408 
422  void setbuf(char *buf) { STDIO_NAMESPACE setbuf(file_, buf); }
423 
439  int setvbuf(char * buf, int modes, size_t n)
440  {
441  int result = STDIO_NAMESPACE setvbuf(file_, buf, modes, n);
442  if (result) storeLastError();
443  return result;
444  }
445 
460  void setbuffer(char *buf, size_t size)
461  {
462 #if defined(_WIN32) || defined(__hpux)
463  this->setvbuf(NULL, buf ? _IOFBF : _IONBF, size);
464 #else
465  :: setbuffer(file_, buf, size);
466 #endif
467  }
468 
473  int fputc(int c) { return STDIO_NAMESPACE fputc(c, file_); }
474 
483  char *fgets(char *s, int n) { return STDIO_NAMESPACE fgets(s, n, file_); }
484 
489  int fputs(const char *s) { return STDIO_NAMESPACE fputs(s, file_); }
490 
497  int ungetc(int c) { return STDIO_NAMESPACE ungetc(c, file_); }
498 
510  int fseek(offile_off_t off, int whence)
511  {
512  int result;
513 #ifdef _WIN32
514  // Windows does not have a 64-bit fseek.
515  // We emulate fseek through fsetpos, which does exist on Windows.
516  // fpos_t is (hopefully always) defined as __int64 on this platform
517  offile_fpos_t off2 = off;
518  fpos_t pos;
519  struct _stati64 buf;
520  switch (whence)
521  {
522  case SEEK_END:
523  // flush write buffer, if any, so that the file size is correct
524  STDIO_NAMESPACE fflush(file_);
525 #if 0
526  // Python implementation based on _lseeki64(). May be unsafe because
527  // there is no guarantee that fflush also empties read buffers.
528  STDIO_NAMESPACE fflush(file_);
529 #ifdef fileno
530  if (_lseeki64( fileno(file_), 0, 2) == -1)
531 #else
532  if (_lseeki64(:: fileno(file_), 0, 2) == -1)
533 #endif
534  {
535  storeLastError();
536  return -1;
537  }
538  // fall through
539 #else
540  // determine file size (using underlying file descriptor). This should be safe.
541 #ifdef fileno
542  if (_fstati64( fileno(file_), &buf) == -1)
543 #else
544  if (_fstati64(:: fileno(file_), &buf) == -1)
545 #endif
546  {
547  storeLastError();
548  return -1;
549  }
550 
551  // fsetpos position is offset + file size.
552  off2 += buf.st_size;
553  break;
554 #endif
555  case SEEK_CUR:
556  if (STDIO_NAMESPACE fgetpos(file_, &pos) != 0)
557  {
558  storeLastError();
559  return -1;
560  }
561 
562  off2 += pos;
563  break;
564  case SEEK_SET:
565  /* do nothing */
566  break;
567  }
568  result = this->fsetpos(&off2);
569 #elif defined(__BEOS__)
570  result = :: _fseek(fp, offset, whence);
571 #else
572 #ifdef HAVE_FSEEKO
573 #ifdef EXPLICIT_LFS_64
574  result = :: fseeko64(file_, off, whence);
575 #else
576  result = :: fseeko(file_, off, whence);
577 #endif
578 #else
579  result = STDIO_NAMESPACE fseek(file_, off, whence);
580 #endif
581 #endif
582  if (result) storeLastError();
583  return result;
584  }
585 
589  offile_off_t ftell()
590  {
591  offile_off_t result;
592 #ifdef _WIN32
593  // Windows does not have a 64-bit ftell, and _telli64 cannot be used
594  // because it operates on file descriptors and ignores FILE buffers.
595  // We emulate ftell through fgetpos, which does exist on Windows.
596  // fpos_t is (hopefully always) defined as __int64 on this platform.
597  offile_fpos_t pos;
598  if (this->fgetpos(&pos) != 0)
599  {
600  storeLastError();
601  return -1;
602  }
603  return pos;
604 #else
605 #ifdef HAVE_FSEEKO
606 #ifdef EXPLICIT_LFS_64
607  result = :: ftello64(file_);
608 #else
609  result = :: ftello(file_);
610 #endif
611 #else
612  result = STDIO_NAMESPACE ftell(file_);
613 #endif
614 #endif
615  if (result < 0) storeLastError();
616  return result;
617  }
618 
626  int fgetpos(offile_fpos_t *pos)
627  {
628  int result;
629 #if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
630  // MinGW has EXPLICIT_LFS_64 but no fgetpos64()
631  result = :: fgetpos64(file_, pos);
632 #else
633  result = STDIO_NAMESPACE fgetpos(file_, pos);
634 #endif
635  if (result) storeLastError();
636  return result;
637  }
638 
646  int fsetpos(offile_fpos_t *pos)
647  {
648  int result;
649 #if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
650  // MinGW has EXPLICIT_LFS_64 but no fsetpos64()
651  result = :: fsetpos64(file_, pos);
652 #else
653  result = STDIO_NAMESPACE fsetpos(file_, pos);
654 #endif
655  if (result) storeLastError();
656  return result;
657  }
658 
664  int fprintf(const char *format, ...)
665  {
666  int result = 0;
667  va_list ap;
668  va_start(ap, format);
669  result = STDIO_NAMESPACE vfprintf(file_, format, ap);
670  va_end(ap);
671  return result;
672  }
673 
679  int vfprintf(const char *format, va_list arg)
680  {
681  return STDIO_NAMESPACE vfprintf(file_, format, arg);
682  }
683 
684  // we cannot emulate fscanf because we would need vfscanf for this
685  // purpose, which does not exist, e.g. on Win32.
686 
692  FILE *file() { return file_; }
693 
697  OFBool open() const { return file_ != NULL; }
698 
702  offile_errno_t getLastError() const { return lasterror_; }
703 
708  {
709  char buf[1000];
710  s = OFStandard::strerror(lasterror_, buf, 1000);
711  }
712 
713 // wide character functions (disabled by default, since currently not used within DCMTK)
714 #ifdef WIDE_CHAR_FILE_IO_FUNCTIONS
715 
733  int fwide(int mode)
734  {
735  return STDIO_NAMESPACE fwide(file_, mode);
736  }
737 
744  wint_t fgetwc()
745  {
746  wint_t result = STDIO_NAMESPACE fgetwc(file_);
747  if (result == WEOF) storeLastError();
748  return result;
749  }
750 
757  wint_t fputwc(wchar_t wc)
758  {
759  wint_t result = STDIO_NAMESPACE fputwc(wc, file_);
760  if (result == WEOF) storeLastError();
761  return result;
762  }
763 
778  wint_t ungetwc(wint_t wc)
779  {
780  wint_t result = STDIO_NAMESPACE ungetwc(wc, file_);
781  if (result == WEOF) storeLastError();
782  return result;
783  }
784 
790  int fwprintf(const wchar_t *format, ...)
791  {
792  int result = 0;
793  va_list ap;
794  va_start(ap, format);
795  result = STDIO_NAMESPACE vfwprintf(file_, format, ap);
796  va_end(ap);
797  return result;
798  }
799 
805  int vfwprintf(const wchar_t *format, va_list arg)
806  {
807  return STDIO_NAMESPACE vfwprintf(file_, format, arg);
808  }
809 
810  // we cannot emulate fwscanf because we would need vfwscanf for this
811  // purpose, which does not exist, e.g. on Win32.
812 
813 #endif /* WIDE_CHAR_FILE_IO_FUNCTIONS */
814 
815 private:
816 
817  // private undefined copy constructor
818  OFFile(const OFFile &arg);
819 
820  // private undefined assignment operator
821  OFFile &operator=(const OFFile &arg);
822 
824  FILE *file_;
825 
827  OFBool popened_;
828 
830  offile_errno_t lasterror_;
831 
833  inline void storeLastError()
834  {
835  lasterror_ = errno;
836  }
837 
838 };
839 
840 
841 #endif
842 
843 /*
844  * CVS/RCS Log:
845  * $Log: offile.h,v $
846  * Revision 1.17 2010-12-17 10:50:30 joergr
847  * Check whether "feof" and "ferror" are defined as macros (e.g. on IRIX 6.3).
848  *
849  * Revision 1.16 2010-12-15 11:29:07 uli
850  * Made OFFile compile successfully on HP-UX.
851  *
852  * Revision 1.15 2010-12-08 16:04:35 joergr
853  * Disable currently unused wide character file I/O functions in order to avoid
854  * problems with old compilers (e.g. gcc 2.95.3).
855  *
856  * Revision 1.14 2010-12-06 13:02:49 joergr
857  * Fixed issue with large file support for current Cygwin systems (1.7.7-1).
858  *
859  * Revision 1.13 2010-10-14 13:15:50 joergr
860  * Updated copyright header. Added reference to COPYRIGHT file.
861  *
862  * Revision 1.12 2010-06-02 12:55:30 joergr
863  * Introduced new helper function strerror() which is used as a wrapper to the
864  * various approaches found on different systems.
865  *
866  * Revision 1.11 2010-04-26 12:22:30 uli
867  * Fixed a some minor doxygen warnings.
868  *
869  * Revision 1.10 2009-09-24 07:10:52 meichel
870  * Fixed bug in class OFFile that caused undefined behaviour
871  * once fclose() failed
872  *
873  * Revision 1.9 2009-08-10 07:52:09 meichel
874  * Some modifications needed to make class OFFile compile on MinGW.
875  *
876  * Revision 1.8 2009-03-12 11:37:54 joergr
877  * Fixed various Doxygen API documentation issues.
878  *
879  * Revision 1.7 2009-02-13 12:56:18 joergr
880  * Added private undefined copy constructor and assignment operator in order to
881  * avoid compiler warnings (reported by gcc with additional flags).
882  *
883  * Revision 1.6 2009-01-30 13:49:01 joergr
884  * Replaced checking of macro WIN32 by _WIN32.
885  *
886  * Revision 1.5 2008-05-29 10:37:11 meichel
887  * Fixed compile error on Cygwin where no wide-char FILE functions are available
888  *
889  * Revision 1.4 2008-02-07 16:57:46 meichel
890  * Class OFFile now makes use of HAVE_CHARP_STRERROR_R to use the
891  * correct version of strerror_r.
892  *
893  * Revision 1.3 2007/06/06 13:55:58 onken
894  * Fixed compilation for Mac OS X with making large file support function calls
895  * implicit for this OS (Mac OS X misleadingly defines _LARGEFILE64_SOURCE).
896  *
897  * Revision 1.2 2007/02/19 16:03:47 meichel
898  * Added constructor to class OFFile that takes FILE * as argument.
899  *
900  * Revision 1.1 2006/08/21 12:40:44 meichel
901  * Added new class OFFile that provides a simple encapsulation layer for
902  * FILE based stream I/O and, in particular, provides long file support
903  * (LFS) if available on the underlying operating system platform through
904  * a single API.
905  *
906  *
907  */


Generated on Thu Dec 20 2012 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.8.2