You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

503 lines
15 KiB

/***************************************************************************
*
* _file.h - Wrapper definitions for platform independent file I/O
*
* This is an internal header file used to implement the C++ Standard
* Library. It should never be #included directly by a program.
*
* $Id: _file.h 186353 2014-07-29 16:30:44Z ransin01 $
*
***************************************************************************
*
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
*
* This computer software is owned by Rogue Wave Software, Inc. and is
* protected by U.S. copyright laws and other laws and by international
* treaties. This computer software is furnished by Rogue Wave Software,
* Inc. pursuant to a written license agreement and may be used, copied,
* transmitted, and stored only in accordance with the terms of such
* license and with the inclusion of the above copyright notice. This
* computer software or any other copies thereof may not be provided or
* otherwise made available to any other person.
*
* U.S. Government Restricted Rights. This computer software is provided
* with Restricted Rights. Use, duplication, or disclosure by the
* Government is subject to restrictions as set forth in subparagraph (c)
* (1) (ii) of The Rights in Technical Data and Computer Software clause
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
* Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
* Flatiron Parkway, Boulder, Colorado 80301 USA.
*
**************************************************************************/
#ifndef _RWSTD_FILE_H_INCLUDED
#define _RWSTD_FILE_H_INCLUDED
#include <rw/_defs.h>
#include _RWSTD_CSTDIO
#if (defined (_WIN32) || defined (_WIN64)) && !defined (__CYGWIN__)
# include <io.h>
# ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
# endif // STDIN_FILENO
#else
#ifndef _RWSTD_NO_FILENO
# include <unistd.h>
#endif //_RWSTD_NO_FILENO
#endif // _WIN32 || _WIN64
#ifndef _RWSTD_NO_FILENO
#include <fcntl.h>
#endif //_RWSTD_NO_FILENO
#if defined (_WIN32) || defined (_WIN64)
# define _BINARY _O_BINARY
#else
# define _BINARY 0
#endif
#if defined (__sun__) || defined (__sun) || defined (sun)
// fileno isn't available (e.g., for strict ANSI C conformance)
// this may result in a (hopefully) benign redeclaration
extern "C" int fileno (FILE*);
#endif // __sun__
_RWSTD_NAMESPACE_BEGIN (__rw)
_USING (namespace std);
// __rw_file_t implements a file abstraction used by std::basic_filebuf<>
// the size of the object is guaranteed to be the same regardless
// of whether FILE* or int (for file descriptor) is used - switching
// between one and the other (for efficiency) is controlled via the
// macro _RWSTD_NO_NATIVE_IO
union _RWSTD_EXPORT __rw_file_t
{
private:
static bool _C_is_open (FILE *__fp) {
return !(__fp == (FILE*)_RWSTD_INVALID_FILE_PTR);
}
#ifndef _RWSTD_NO_NATIVE_IO
static int _C_fileno (FILE *__fp) {
return _C_is_open (__fp)
? fileno(__fp)
: _RWSTD_INVALID_FILE_DESC;
}
#endif
public:
static int _C_get_mode (int);
static int _C_get_mode (FILE *__fp);
#ifndef _RWSTD_NO_NATIVE_IO
__rw_file_t ( ) : _C_fdsc (_RWSTD_INVALID_FILE_DESC)
{ }
__rw_file_t (FILE *__fp) : _C_fdsc (_C_fileno (__fp))
{ }
__rw_file_t (int __fd) : _C_fdsc (__fd)
{ }
__rw_file_t (const __rw_file_t &__f) : _C_fdsc (__f._C_fdsc)
{ }
__rw_file_t & operator= (const __rw_file_t &__f) {
_C_fdsc = __f._C_fdsc;
return *this;
}
int _C_get_mode () const;
int _C_get_mode_arg (int) const;
int _C_get_fd () const {
return _C_fdsc;
}
bool _C_is_open () const {
return _C_fdsc != _RWSTD_INVALID_FILE_DESC;
}
bool _C_is_stdin () const {
return STDIN_FILENO == _C_fdsc;
}
bool _C_is_stdout () const {
return STDOUT_FILENO == _C_fdsc;
}
bool _C_is_stderr () const {
return STDERR_FILENO == _C_fdsc;
}
bool _C_is_std () const {
return _C_is_stdin () || _C_is_stdout () || _C_is_stderr ();
}
__rw_file_t& _C_open (const char *__name, int __mode, long __prot);
bool _C_close () {
return 0 == close (_C_fdsc);
}
size_t _C_read (void *__buf, size_t __size, size_t __count) {
_RWSTD_SSIZE_T __nbytes = read (_C_fdsc, __buf, __size * __count);
return __nbytes < 0 ? 0 : _RWSTD_STATIC_CAST (size_t, __nbytes);
}
bool _C_write (const void* __buf, size_t __size, size_t __count) {
return ( (size_t)write (_C_fdsc, __buf, __size * __count)
== __size * __count);
}
long _C_seek (long __offset, int __origin) {
return lseek (_C_fdsc, __offset, __origin);
}
// For non-native i/o facilitation only.
int _C_flush ( ) {
return 0;
}
#else // if defined (_RWSTD_NO_NATIVE_IO)
const char* _C_get_mode_arg (int) const;
__rw_file_t ( ) : _C_fptr (0)
{ }
__rw_file_t (FILE *__fp) : _C_fptr (__fp)
{ }
__rw_file_t (int);
__rw_file_t (const __rw_file_t &__f) : _C_fptr (__f._C_fptr)
{ }
__rw_file_t& operator= (const __rw_file_t &__f) {
_C_fptr = __f._C_fptr;
return *this;
}
int _C_get_mode () const;
#ifndef _RWSTD_NO_NATIVE_IO
int _C_get_fd () const {
return _C_fileno (_C_fptr);
}
#endif
bool _C_is_open () const {
return !!_C_fptr;
}
bool _C_is_stdin () const {
#ifndef _RWSTD_NO_NATIVE_IO
return STDOUT_FILENO ==_C_fileno (_C_fptr);
#else
return _C_fptr == stdin;
#endif
}
bool _C_is_stdout () const {
#ifndef _RWSTD_NO_NATIVE_IO
return STDOUT_FILENO ==_C_fileno (_C_fptr);
#else
return _C_fptr == stdout;
#endif
}
bool _C_is_stderr () const {
#ifndef _RWSTD_NO_NATIVE_IO
return STDERR_FILENO ==_C_fileno (_C_fptr);
#else
return _C_fptr == stderr;
#endif
}
bool _C_is_std () const {
return _C_is_stdin () || _C_is_stdout () || _C_is_stderr ();
}
__rw_file_t &
_C_open (const char *__name, int __mode, long);
bool _C_close () {
return !_C_is_open () ? true : 0 == fclose (_C_fptr);
}
size_t _C_read (void *__buf, size_t __size, size_t __count) {
#define __ARM_USE_FREAD_BYTES_AVAIL
#ifdef __ARM_USE_FREAD_BYTES_AVAIL
size_t __bytes_read = __fread_bytes_avail(__buf, __size * __count, _C_fptr);
/* fread can set a sticky EOF, clear it if there has been no error */
if (!ferror(_C_fptr)) clearerr(_C_fptr);
return __bytes_read;
#else
return __size * fread (__buf, __size, __count, _C_fptr);
#endif
}
bool _C_write (const void* __buf, size_t __size, size_t __count) {
return fwrite (__buf, __size, __count, _C_fptr) == __count;
}
long _C_seek (long __offset, int __origin) {
int __rc = fseek (_C_fptr, __offset, __origin);
if (__rc != 0)
return -1;
return ftell (_C_fptr);
}
int _C_flush () {
return _C_is_open () ? fflush(_C_fptr) : EOF;
}
#endif //_RWSTD_NO_NATIVE_IO
private:
FILE *_C_fptr; // file pointer - used if _RWSTD_NO_NATIVE_IO is undef'd
int _C_fdsc; // file descriptor - used otherwise (default)
};
#ifndef _RWSTD_NO_NATIVE_IO
inline int __rw_file_t::_C_get_mode (int __fd)
{
// FIXME -- need to have equivalent of fcntl() on win32.
#if defined (_RWSTD_NO_NATIVE_IO)
return __fd == STDIN_FILENO
? _RWSTD_IOS_IN
: __fd == STDOUT_FILENO || __fd == STDERR_FILENO
? _RWSTD_IOS_OUT : _RWSTD_IOS_OUT | _RWSTD_IOS_IN;
#else
int __m = fcntl (__fd, F_GETFL);
if (__m == -1)
return _RWSTD_INVALID_OPENMODE;
int __mode = __m & O_APPEND ? _RWSTD_IOS_APP : 0;
switch (__m & O_ACCMODE) {
case O_RDONLY: __mode |= _RWSTD_IOS_IN; break;
case O_WRONLY: __mode |= _RWSTD_IOS_OUT; break;
case O_RDWR: __mode |= _RWSTD_IOS_IN | _RWSTD_IOS_OUT; break;
}
return __mode;
#endif
}
#endif
inline int __rw_file_t::_C_get_mode (FILE *__fp)
{
#ifndef _RWSTD_NO_NATIVE_IO
return _C_get_mode (_C_fileno (__fp));
#else
return __fp == stdin
? _RWSTD_IOS_IN
: __fp == stdout || __fp == stderr
? _RWSTD_IOS_OUT : _RWSTD_IOS_OUT | _RWSTD_IOS_IN;
#endif
}
#ifndef _RWSTD_NO_NATIVE_IO
#ifdef _INLINE_WITH_STATICS
_INLINE_WITH_STATICS int
__rw_file_t::_C_get_mode_arg (int __index) const
{
#if !(defined (__osf__) && defined (__GNUG__) \
&& __GNUG__ == 2 && __GNUG_MINOR__ < 96)
// static not used to prevent a g++ 2.95.2 warning on Tru64
// sorry: semantics of inline function static data are wrong
// (you'll wind up with multiple copies)
static
#endif
const int __modetbl [] = {
-1, // no flags error
O_WRONLY | O_APPEND | O_CREAT, // app
-1 | _BINARY, // binary
O_WRONLY | _BINARY | O_APPEND | O_CREAT, // binary|app
O_RDONLY, // in
O_RDONLY | O_APPEND, // in|app
O_RDONLY | _BINARY, // in|binary
O_RDONLY | _BINARY | O_APPEND | O_CREAT, // in|binary|app
O_TRUNC | O_WRONLY | O_CREAT, // out
O_WRONLY | O_APPEND | O_CREAT, // out|app
O_TRUNC | O_WRONLY | O_CREAT | _BINARY, // out|binary
O_WRONLY | _BINARY | O_APPEND | O_CREAT, // out|binary|app
O_RDWR, // out|in
O_RDWR | O_APPEND | O_CREAT, // out|in|app
O_RDWR | _BINARY, // out|in|binary
O_RDWR | _BINARY | O_APPEND | O_CREAT, // out|in|binary|app
O_TRUNC, // trunc
O_TRUNC | O_APPEND, // trunc|app
O_TRUNC | _BINARY, // trunc|binary
O_TRUNC | O_APPEND | _BINARY, // trunc|binary|app
O_TRUNC | O_RDONLY, // trunc|in
O_TRUNC | O_RDONLY | O_APPEND, // trunc|in|app
O_TRUNC | O_RDONLY | _BINARY, // trunc|in|binary
O_TRUNC | O_RDONLY | _BINARY | O_APPEND, // trunc|in|binary|app
O_TRUNC | O_WRONLY | O_CREAT, // trunc|out
O_TRUNC | O_WRONLY | O_APPEND | O_CREAT, // trunc|out|app
O_TRUNC | O_WRONLY | _BINARY | O_CREAT, // trunc|out|binary
O_TRUNC | O_WRONLY | _BINARY | O_APPEND| O_CREAT,// trunc|out|binary|app
O_TRUNC | O_RDWR | O_CREAT, // trunc|out|in
O_TRUNC | O_RDWR | O_APPEND | O_CREAT, // trunc|out|in|app
O_TRUNC | O_RDWR | O_CREAT | _BINARY, // trunc|out|in|binary
O_TRUNC | O_RDWR | _BINARY | O_APPEND | O_CREAT // trunc|out|in|binary|app
};
if ( 0 > __index
|| int (sizeof __modetbl / sizeof *__modetbl) <= __index)
return _RWSTD_INVALID_OPENMODE;
return __modetbl[__index];
}
#endif // _INLINE_WITH_STATICS
inline __rw_file_t&
__rw_file_t::_C_open (const char *__name, int __mode, long __prot)
{
int __m = _C_get_mode_arg ( __mode
& ~(_RWSTD_IOS_NOCREATE | _RWSTD_IOS_NOREPLACE));
if (__m == _RWSTD_INVALID_OPENMODE){
_C_fdsc = _RWSTD_INVALID_FILE_DESC;
return *this;
}
if (__mode & _RWSTD_IOS_OUT) {
if (__mode & _RWSTD_IOS_NOCREATE)
__m &= ~O_CREAT;
if (__mode & _RWSTD_IOS_NOREPLACE)
__m |= O_EXCL;
}
_C_fdsc = open (__name, __m, __prot);
return *this;
}
inline int __rw_file_t::_C_get_mode () const
{
return _C_get_mode (_C_fdsc);
}
#else // if defined (_RWSTD_NO_NATIVE_IO)
inline const char* __rw_file_t::_C_get_mode_arg (int __index) const
{
#if !(defined (__osf__) && defined (__GNUG__) \
&& __GNUG__ == 2 && __GNUG_MINOR__ < 96)
// static not used to prevent a g++ 2.95.2 warning on Tru64
// sorry: semantics of inline function static data are wrong
// (you'll wind up with multiple copies)
static
#endif
const char __modetbl [][4] = {
"", // no flags error 0
"a", // app 1
"", // binary 2
"ab", // binary|app 3
"r", // in 4
"a", // in|app 5
"rb", // in|binary 6
"ab", // in|binary|app 7
"w", // out 8
"a", // out|app 9
"wb", // out|binary 10
"ab", // out|binary|app 11
"r+", // out|in 12
"a+", // out|in|app 13
"r+b", // out|in|binary 14
"a+b", // out|in|binary|app 15
"w", // trunc 16
"w", // trunc|app 17
"wb", // trunc|binary 18
"wb", // trunc|binary|app 19
"", // trunc|in 20
"", // trunc|in|app 21
"", // trunc|in|binary 22
"", // trunc|in|binary|app 23
"w", // trunc|out 24
"w", // trunc|out|app 25
"wb", // trunc|out|binary 26
"wb", // trunc|out|binary|app 27
"w+", // trunc|out|in 28
"w+", // trunc|out|in|app 29
"w+b", // trunc|out|in|binary 30
"w+b" // trunc|out|in|binary|app 31
};
if ( 0 > __index
|| int (sizeof __modetbl / sizeof *__modetbl) <= __index)
return 0;
return __modetbl[__index];
}
#ifndef _RWSTD_NO_FILENO
inline __rw_file_t::__rw_file_t (int __fd)
{
const char *__mode = _C_get_mode_arg (_C_get_mode (__fd));
_C_fptr = __mode && __fd > -1 ? fdopen (__fd, __mode) : 0;
}
#endif //_RWSTD_NO_FILENO
inline __rw_file_t& __rw_file_t::_C_open (const char *__name, int __mode, long)
{
const char *__m = _C_get_mode_arg (__mode);
if (!__m) {
_C_fptr = 0;
return *this;
}
_C_fptr = fopen (__name, __m);
#ifndef __ARM_DONT_WANT_IONBF
if (_C_is_open ( ))
setvbuf (_C_fptr, 0, _IONBF, 0);
#endif
return *this;
}
inline int __rw_file_t::_C_get_mode () const
{
return _C_get_mode (_C_fptr);
}
#endif // _RWSTD_NO_NATIVE_IO
_RWSTD_NAMESPACE_END // __rw
#endif // _RWSTD_FILE_H_INCLUDED