OSDN Git Service

* config/os/irix/irix6.5/os_defines.h (_GLIBCXX_FIONREAD_TAKES_OFF_T):
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / config / io / basic_file_stdio.cc
index b3223f5..8cba0db 100644 (file)
@@ -1,6 +1,6 @@
 // Wrapper of C-language FILE struct -*- C++ -*-
 
-// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 # endif
 #endif
 
+#include <limits> // For <off_t>::max() and min()
+
+namespace __gnu_internal
+{
+  // Map ios_base::openmode flags to a string for use in fopen().
+  // Table of valid combinations as given in [lib.filebuf.members]/2.
+  static const char*
+  fopen_mode(std::ios_base::openmode mode)
+  {
+    enum 
+      {
+       in     = std::ios_base::in,
+       out    = std::ios_base::out,
+       trunc  = std::ios_base::trunc,
+       app    = std::ios_base::app,
+       binary = std::ios_base::binary
+      };
+    
+    switch (mode & (in|out|trunc|app|binary))
+      {
+      case (   out                 ): return "w";  
+      case (   out      |app       ): return "a";  
+      case (   out|trunc           ): return "w";  
+      case (in                     ): return "r";  
+      case (in|out                 ): return "r+"; 
+      case (in|out|trunc           ): return "w+"; 
+       
+      case (   out          |binary): return "wb"; 
+      case (   out      |app|binary): return "ab"; 
+      case (   out|trunc    |binary): return "wb"; 
+      case (in              |binary): return "rb"; 
+      case (in|out          |binary): return "r+b";
+      case (in|out|trunc    |binary): return "w+b";
+       
+      default: return 0; // invalid
+      }
+  }
+} // namespace __gnu_internal
+
 namespace std 
 {
   // Definitions for __basic_file<char>.
@@ -77,53 +116,6 @@ namespace std
   __basic_file<char>::~__basic_file()
   { this->close(); }
       
-  void 
-  __basic_file<char>::_M_open_mode(ios_base::openmode __mode, int& __p_mode, 
-                                  int&, char* __c_mode)
-  {  
-    bool __testb = __mode & ios_base::binary;
-    bool __testi = __mode & ios_base::in;
-    bool __testo = __mode & ios_base::out;
-    bool __testt = __mode & ios_base::trunc;
-    bool __testa = __mode & ios_base::app;
-      
-    // Set __c_mode for use in fopen.
-    // Set __p_mode for use in open.
-    if (!__testi && __testo && !__testt && !__testa)
-      {
-       strcpy(__c_mode, "w");
-       __p_mode = O_WRONLY | O_CREAT;
-      }
-    if (!__testi && __testo && !__testt && __testa)
-      {
-       strcpy(__c_mode, "a");
-       __p_mode = O_WRONLY | O_CREAT | O_APPEND;
-      }
-    if (!__testi && __testo && __testt && !__testa)
-      {
-       strcpy(__c_mode, "w");
-       __p_mode = O_WRONLY | O_CREAT | O_TRUNC;
-      }
-
-    if (__testi && !__testo && !__testt && !__testa)
-      {
-       strcpy(__c_mode, "r");
-       __p_mode = O_RDONLY;
-      }
-    if (__testi && __testo && !__testt && !__testa)
-      {
-       strcpy(__c_mode, "r+");
-       __p_mode = O_RDWR | O_CREAT;
-      }
-    if (__testi && __testo && __testt && !__testa)
-      {
-       strcpy(__c_mode, "w+");
-       __p_mode = O_RDWR | O_CREAT | O_TRUNC;
-      }
-    if (__testb)
-      strcat(__c_mode, "b");
-  }
-  
   __basic_file<char>*
   __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode) 
   {
@@ -132,29 +124,23 @@ namespace std
       {
        _M_cfile = __file;
        _M_cfile_created = false;
+       this->sync();
        __ret = this;
       }
     return __ret;
   }
   
   __basic_file<char>*
-  __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode, 
-                              bool __del) 
+  __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode)
   {
     __basic_file* __ret = NULL;
-    int __p_mode = 0;
-    int __rw_mode = 0;
-    char __c_mode[4];
-    
-    _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode);
-    if (!this->is_open() && (_M_cfile = fdopen(__fd, __c_mode)))
+    const char* __c_mode = __gnu_internal::fopen_mode(__mode);
+    if (__c_mode && !this->is_open() 
+       && (_M_cfile = fdopen(__fd, __c_mode)))
       {
-       // Iff __del is true, then close will fclose the fd.
-       _M_cfile_created = __del;
-
+       _M_cfile_created = true;
        if (__fd == 0)
          setvbuf(_M_cfile, reinterpret_cast<char*>(NULL), _IONBF, 0);
-
        __ret = this;
       }
     return __ret;
@@ -165,15 +151,14 @@ namespace std
                           int /*__prot*/)
   {
     __basic_file* __ret = NULL;
-    int __p_mode = 0;
-    int __rw_mode = 0;
-    char __c_mode[4];
-      
-    _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode);
-
-    if (!this->is_open())
+    const char* __c_mode = __gnu_internal::fopen_mode(__mode);
+    if (__c_mode && !this->is_open())
       {
+#ifdef _GLIBCXX_USE_LFS
+       if ((_M_cfile = fopen64(__name, __c_mode)))
+#else
        if ((_M_cfile = fopen(__name, __c_mode)))
+#endif
          {
            _M_cfile_created = true;
            __ret = this;
@@ -193,17 +178,17 @@ namespace std
   __basic_file<char>* 
   __basic_file<char>::close()
   { 
-    __basic_file* __retval = static_cast<__basic_file*>(NULL);
+    __basic_file* __ret = static_cast<__basic_file*>(NULL);
     if (this->is_open())
       {
        if (_M_cfile_created)
          fclose(_M_cfile);
        else
-         fflush(_M_cfile);
+         this->sync();
        _M_cfile = 0;
-       __retval = this;
+       __ret = this;
       }
-    return __retval;
+    return __ret;
   }
  
   streamsize 
@@ -260,13 +245,18 @@ namespace std
     return __ret;
   }
 
-  streampos
+  streamoff
   __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way)
-  { return lseek(this->fd(), __off, __way); }
-
-  streampos
-  __basic_file<char>::seekpos(streampos __pos)
-  { return lseek(this->fd(), __pos, ios_base::beg); }
+  {
+#ifdef _GLIBCXX_USE_LFS
+    return lseek64(this->fd(), __off, __way);
+#else
+    if (__off > std::numeric_limits<off_t>::max()
+       || __off < std::numeric_limits<off_t>::min())
+      return -1L;
+    return lseek(this->fd(), __off, __way);
+#endif
+  }
 
   int 
   __basic_file<char>::sync() 
@@ -277,7 +267,11 @@ namespace std
   {
 #ifdef FIONREAD
     // Pipes and sockets.    
+#ifdef _GLIBCXX_FIONREAD_TAKES_OFF_T
+    off_t __num = 0;
+#else
     int __num = 0;
+#endif
     int __r = ioctl(this->fd(), FIONREAD, &__num);
     if (!__r && __num >= 0)
       return __num; 
@@ -301,5 +295,4 @@ namespace std
 #endif
     return 0;
   }
-
 }  // namespace std