177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/*
277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Copyright (c) 1999
377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Silicon Graphics Computer Systems, Inc.
477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Copyright (c) 1999
677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Boris Fomitchev
777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * This material is provided "as is", with absolutely no warranty expressed
977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * or implied. Any use is at your own risk.
1077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
1177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Permission to use or copy this software for any purpose is hereby granted
1277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * without fee, provided the above notices are retained on all copies.
1377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Permission to modify the code and to distribute modified code is granted,
1477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * provided the above notices are retained, and a notice that the code was
1577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * modified is included with the above copyright notice.
1677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
1777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner */
1877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
1977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#include <fstream>
2077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
2177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if !defined (_STLP_WCE)
2277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  ifdef __BORLANDC__
2377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#    include <cfcntl.h>           // For _O_RDONLY, etc
2477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  else
2577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#    include <io.h>               // For _get_osfhandle
2677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#    include <fcntl.h>            // For _O_RDONLY, etc
2777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  endif
2877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  include <sys/stat.h>         // For _fstat
2977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
3077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
3177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#define _TEXTBUF_SIZE 0x1000
3277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
3377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst _STLP_fd INVALID_STLP_FD = INVALID_HANDLE_VALUE;
3477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
3577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if !defined (INVALID_SET_FILE_POINTER)
3677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define INVALID_SET_FILE_POINTER 0xffffffff
3777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
3877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
3977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#ifndef O_ACCMODE
4077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
4177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
4277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
4377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_STLP_BEGIN_NAMESPACE
4477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
4577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if !defined(__MSL__) && !defined(_STLP_WCE)
4677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic ios_base::openmode flag_to_openmode(int mode) {
4777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  ios_base::openmode ret = ios_base::__default_mode;
4877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
4977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  switch (mode & O_ACCMODE) {
5077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case O_RDONLY:
5177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ret = ios_base::in; break;
5277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case O_WRONLY:
5377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ret = ios_base::out; break;
5477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case O_RDWR:
5577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ret = ios_base::in | ios_base::out; break;
5677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
5777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
5877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (mode & O_APPEND)
5977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ret |= ios_base::app;
6077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (mode & O_BINARY)
6277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ret |= ios_base::binary;
6377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return ret;
6577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
6677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
6777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_STLP_MOVE_TO_PRIV_NAMESPACE
6977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Helper functions for _Filebuf_base.
7177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic bool __is_regular_file(_STLP_fd fd) {
7377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  BY_HANDLE_FILE_INFORMATION info;
7477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // Return true if the file handle isn't a directory.
7677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return GetFileInformationByHandle(fd, &info) &&
7777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner         ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
7877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
7977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
8077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Number of characters in the file.
8177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic streamoff __file_size(_STLP_fd fd) {
8277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  streamoff ret = 0;
8377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
8477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner LARGE_INTEGER li;
8577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner li.LowPart = GetFileSize(fd, (unsigned long*) &li.HighPart);
8677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner if (li.LowPart != INVALID_FILE_SIZE || GetLastError() == NO_ERROR)
8777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner   ret = li.QuadPart;
8877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
8977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return ret;
9077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
9177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
9277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_STLP_MOVE_TO_STD_NAMESPACE
9377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
9477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Visual C++ and Intel use this, but not Metrowerks
9577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Also MinGW, msvcrt.dll (but not crtdll.dll) dependent version
9677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \
9777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    (defined (__MINGW32__) && defined (__MSVCRT__))
9877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
9977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// fcntl(fileno, F_GETFL) for Microsoft library
10077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// 'semi-documented' defines:
10177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define IOINFO_L2E          5
10277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
10377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + \
10477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              ((i) & (IOINFO_ARRAY_ELTS - 1)) )
10577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define FAPPEND         0x20    // O_APPEND flag
10677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define FTEXT           0x80    // O_TEXT flag
10777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// end of 'semi-documented' defines
10877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
10977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// 'semi-documented' internal structure
11077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerextern "C" {
11177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  struct ioinfo {
11277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    long osfhnd;    // the real os HANDLE
11377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    char osfile;    // file handle flags
11477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    char pipech;    // pipe buffer
11577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  if defined (_MT)
11677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // multi-threaded locking
11777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    int lockinitflag;
11877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    CRITICAL_SECTION lock;
11977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  endif
12077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  };
12177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  if defined (__MINGW32__)
12277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner __MINGW_IMPORT ioinfo * __pioinfo[];
12377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  else
12477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  extern _CRTIMP ioinfo * __pioinfo[];
12577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  endif
12677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner} // extern "C"
12777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// end of 'semi-documented' declarations
12877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
12977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) {
13077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  char dosflags = 0;
13177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (fd >= 0)
13277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dosflags = _pioinfo(fd)->osfile;
13377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  //else
13477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    //the file will be considered as open in binary mode with no append attribute
13577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // end of 'semi-documented' stuff
13677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
13777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int mode = 0;
13877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (dosflags & FAPPEND)
13977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_APPEND;
14077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
14177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (dosflags & FTEXT)
14277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_TEXT;
14377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else
14477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_BINARY;
14577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
14677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // For Read/Write access we have to guess
14777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  DWORD dummy, dummy2;
14877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  BOOL writeOk = WriteFile(oshandle, &dummy2, 0, &dummy, 0);
14977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  BOOL readOk = ReadFile(oshandle, &dummy2, 0, &dummy, NULL);
15077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (writeOk && readOk)
15177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_RDWR;
15277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else if (readOk)
15377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_RDONLY;
15477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else
15577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_WRONLY;
15677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
15777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return flag_to_openmode(mode);
15877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
15977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
16077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#elif defined (__DMC__)
16177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
16277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define FHND_APPEND 0x04
16377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define FHND_DEVICE 0x08
16477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define FHND_TEXT   0x10
16577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
16677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerextern "C" unsigned char __fhnd_info[_NFILE];
16777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
16877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) {
16977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int mode = 0;
17077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (__fhnd_info[fd] & FHND_APPEND)
17277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_APPEND;
17377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (__fhnd_info[fd] & FHND_TEXT == 0)
17577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    mode |= O_BINARY;
17677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  for (FILE *fp = &_iob[0]; fp < &_iob[_NFILE]; fp++) {
17877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if ((fileno(fp) == fd) && (fp->_flag & (_IOREAD | _IOWRT | _IORW))) {
17977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      const int osflags = fp->_flag;
18077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
18177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      if ((osflags & _IOREAD) && !(osflags & _IOWRT) && !(osflags & _IORW))
18277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        mode |= O_RDONLY;
18377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      else if ((osflags & _IOWRT) && !(osflags & _IOREAD) && !(osflags & _IORW))
18477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        mode |= O_WRONLY;
18577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      else
18677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        mode |= O_RDWR;
18777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      break;
18877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
18977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
19077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
19177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return flag_to_openmode(mode);
19277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
19377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
19477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
19577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnersize_t _Filebuf_base::_M_page_size = 4096;
19677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
19777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_Filebuf_base::_Filebuf_base()
19877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  : _M_file_id(INVALID_STLP_FD),
19977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_openmode(0),
20077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_is_open(false),
20177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_should_close(false),
20277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_view_id(0)
20377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{}
20477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
20577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnervoid _Filebuf_base::_S_initialize() {
20677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  SYSTEM_INFO SystemInfo;
20777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  GetSystemInfo(&SystemInfo);
20877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_page_size = SystemInfo.dwPageSize;
20977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // might be .dwAllocationGranularity
21077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
21177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
21277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Return the size of the file.  This is a wrapper for stat.
21377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Returns zero if the size cannot be determined or is ill-defined.
21477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstreamoff _Filebuf_base::_M_file_size() {
21577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return _STLP_PRIV __file_size(_M_file_id);
21677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
21777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
21877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode,
21977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                            long permission) {
22077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_fd file_no;
22177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
22277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_is_open)
22377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
22477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
22577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  DWORD dwDesiredAccess, dwCreationDisposition;
22677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  bool doTruncate = false;
22777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
22877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  switch (openmode & (~ios_base::ate & ~ios_base::binary)) {
22977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::out:
23077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::out | ios_base::trunc:
23177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwDesiredAccess = GENERIC_WRITE;
23277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwCreationDisposition = OPEN_ALWAYS;
23377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // boris : even though it is very non-intuitive, standard
23477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // requires them both to behave same.
23577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    doTruncate = true;
23677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
23777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::out | ios_base::app:
23877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwDesiredAccess = GENERIC_WRITE;
23977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwCreationDisposition = OPEN_ALWAYS;
24077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
24177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::in:
24277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwDesiredAccess = GENERIC_READ;
24377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwCreationDisposition = OPEN_EXISTING;
24477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    permission = 0;             // Irrelevant unless we're writing.
24577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
24677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::in | ios_base::out:
24777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
24877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwCreationDisposition = OPEN_EXISTING;
24977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
25077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::in | ios_base::out | ios_base::trunc:
25177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
25277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dwCreationDisposition = OPEN_ALWAYS;
25377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    doTruncate = true;
25477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
25577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  default:                      // The above are the only combinations of
25677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;               // flags allowed by the C++ standard.
25777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
25877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
25977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
26077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
26177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if defined(_STLP_USE_WIDE_INTERFACE)
26277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    file_no = CreateFile (_STLP_PRIV __ASCIIToWide(name).c_str(),
26377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#else
26477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    file_no = CreateFileA(name,
26577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
26677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                          dwDesiredAccess, dwShareMode, 0,
26777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                          dwCreationDisposition, permission, 0);
26877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
26977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (file_no == INVALID_STLP_FD)
27077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
27177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
27277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (
27377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if !defined (_STLP_WCE)
27477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      GetFileType(file_no) == FILE_TYPE_DISK &&
27577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
27677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      ((doTruncate && SetEndOfFile(file_no) == 0) ||
27777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner       (((openmode & ios_base::ate) != 0) &&
27877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        (SetFilePointer(file_no, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)))) {
27977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    CloseHandle(file_no);
28077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
28177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
28277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
28377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_is_open = true;
28477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_file_id = file_no;
28577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_should_close = _M_is_open;
28677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_openmode = openmode;
28777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
28877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_is_open)
28977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
29077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
29177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return (_M_is_open != 0);
29277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
29377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
29477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) {
29577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // This doesn't really grant everyone in the world read/write
29677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // access.  On Unix, file-creation system calls always clear
29777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // bits that are set in the umask from the permissions flag.
29877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return this->_M_open(name, openmode, FILE_ATTRIBUTE_NORMAL);
29977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
30077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_open(_STLP_fd __id, ios_base::openmode init_mode) {
30277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \
30377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__)
30477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_is_open || __id == INVALID_STLP_FD)
30677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
30777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (init_mode != ios_base::__default_mode)
30977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_openmode = init_mode;
31077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else
31177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_openmode = _get_osfflags(-1, __id);
31277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
31377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_is_open = true;
31477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_file_id = __id;
31577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_should_close = false;
31677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
31777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
31877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return true;
31977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#else
32077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  (void)__id;
32177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  (void)init_mode;    // dwa 4/27/00 - suppress unused parameter warning
32277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
32377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // not available for the API
32477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return false;
32577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
32677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
32777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
32877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
32977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Associated the filebuf with a file descriptor pointing to an already-
33077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// open file.  Mode is set to be consistent with the way that the file
33177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// was opened.
33277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_open(int file_no, ios_base::openmode init_mode) {
33377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_is_open || file_no < 0)
33477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
33577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
33677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \
33777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__)
33877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
33977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  HANDLE oshandle = (HANDLE)_get_osfhandle(file_no);
34077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (oshandle == INVALID_STLP_FD)
34177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
34277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
34377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (init_mode != ios_base::__default_mode)
34477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_openmode = init_mode;
34577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else
34677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    _M_openmode = _get_osfflags(file_no, oshandle);
34777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
34877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_file_id = oshandle;
34977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_is_open = true;
35077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_should_close = false;
35177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
35277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return true;
35377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#else
35477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(&init_mode)
35577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // not available for the API
35677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return false;
35777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
35877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
35977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
36077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_close() {
36177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!_M_is_open)
36277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return false;
36377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
36477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  bool ok;
36577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
36677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!_M_should_close)
36777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ok = true;
36877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else {
36977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (_M_file_id != INVALID_STLP_FD) {
37077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      ok = (CloseHandle(_M_file_id) != 0);
37177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
37277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    else {
37377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      ok = false;
37477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
37577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
37677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
37777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_is_open = _M_should_close = false;
37877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_openmode = 0;
37977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return ok;
38077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
38177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
38277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
38377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#define _STLP_LF 10
38477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#define _STLP_CR 13
38577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#define _STLP_CTRLZ 26
38677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
38777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Read up to n characters into a buffer.  Return value is number of
38877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// characters read.
38977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) {
39077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  ptrdiff_t readen = 0;
39177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  //Here cast to size_t is safe as n cannot be negative.
39277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  size_t chunkSize = (min)(size_t(0xffffffff), __STATIC_CAST(size_t, n));
39377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // The following, while validating that we are still able to extract chunkSize
39477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // charaters to the buffer, avoids extraction of too small chunk of datas
39577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // which would be counter performant.
39677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  while (__STATIC_CAST(size_t, (n - readen)) >= chunkSize) {
39777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    DWORD numberOfBytesRead;
39877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ReadFile(_M_file_id, buf + readen, __STATIC_CAST(DWORD, chunkSize), &numberOfBytesRead, 0);
39977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
40077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (numberOfBytesRead == 0)
40177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      break;
40277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
40377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (!(_M_openmode & ios_base::binary)) {
40477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // translate CR-LFs to LFs in the buffer
40577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char *to = buf + readen;
40677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char *from = to;
40777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char *last = from + numberOfBytesRead - 1;
40877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      for (; from <= last && *from != _STLP_CTRLZ; ++from) {
40977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        if (*from != _STLP_CR)
41077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          *to++ = *from;
41177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        else { // found CR
41277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          if (from < last) { // not at buffer end
41377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            if (*(from + 1) != _STLP_LF)
41477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              *to++ = _STLP_CR;
41577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          }
41677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          else { // last char is CR, peek for LF
41777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            char peek = ' ';
41877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            DWORD NumberOfBytesPeeked;
41977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            ReadFile(_M_file_id, (LPVOID)&peek, 1, &NumberOfBytesPeeked, 0);
42077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            if (NumberOfBytesPeeked != 0) {
42177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              if (peek != _STLP_LF) { //not a <CR><LF> combination
42277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                *to++ = _STLP_CR;
42377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                if ((to < buf + n) && (peek != _STLP_CR))
42477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  //We have enough place to store peek and it is no a special
42577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  //_STLP_CR character, we can store it.
42677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  *to++ = peek;
42777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                else
42877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  SetFilePointer(_M_file_id, (LONG)-1, 0, FILE_CURRENT);
42977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              }
43077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              else {
43177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                // A <CR><LF> combination, we keep the <LF>:
43277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                *to++ = _STLP_LF;
43377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              }
43477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            }
43577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            else {
43677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              /* This case is tedious, we could
43777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *  - put peek back in the file but this would then generate an infinite loop
43877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *  - report an error as we don't know if in a future call to ReadFile we won't then
43977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *    get a <LF>. Doing so would make all files with a <CR> last an invalid file
44077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *    for STLport, a hard solution for STLport clients.
44177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *  - store the <CR> in the returned buffer, the chosen solution, even if in this
44277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               *    case we could miss a <CR><LF> combination.
44377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner               */
44477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              *to++ = _STLP_CR;
44577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner            }
44677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          }
44777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        } // found CR
44877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      } // for
44977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      readen = to - buf;
45077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // seek back to TEXT end of file if hit CTRL-Z
45177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      if (from <= last) { // terminated due to CTRLZ
45277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        SetFilePointer(_M_file_id, -(LONG)((last + 1) - from), 0, FILE_CURRENT);
45377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        break;
45477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
45577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
45677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    else
45777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      readen += numberOfBytesRead;
45877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
45977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return readen;
46077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
46177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
46277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Write n characters from a buffer.  Return value: true if we managed
46377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// to write the entire buffer, false if we didn't.
46477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerbool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) {
46577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  for (;;) {
46677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    ptrdiff_t written;
46777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
46877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    //In the following implementation we are going to cast most of the ptrdiff_t
46977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    //values in size_t to work with coherent unsigned values. Doing so make code
47077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    //more simple especially in the min function call.
47177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
47277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // In append mode, every write does an implicit seek to the end
47377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // of the file.
47477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (_M_openmode & ios_base::app)
47577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      _M_seek(0, ios_base::end);
47677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
47777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (_M_openmode & ios_base::binary) {
47877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // binary mode
47977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      size_t bytes_to_write = (size_t)n;
48077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      DWORD NumberOfBytesWritten;
48177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      written = 0;
48277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      for (; bytes_to_write != 0;) {
48377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        WriteFile(_M_file_id, buf + written,
48477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), bytes_to_write)),
48577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  &NumberOfBytesWritten, 0);
48677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        if (NumberOfBytesWritten == 0)
48777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          return false;
48877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        bytes_to_write -= NumberOfBytesWritten;
48977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        written += NumberOfBytesWritten;
49077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
49177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
49277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    else {
49377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char textbuf[_TEXTBUF_SIZE + 1]; // extra 1 in case LF at end
49477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char * nextblock = buf, * ptrtextbuf = textbuf;
49577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char * endtextbuf = textbuf + _TEXTBUF_SIZE;
49677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char * endblock = buf + n;
49777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      ptrdiff_t nextblocksize = (min) (n, (ptrdiff_t)_TEXTBUF_SIZE);
49877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char * nextlf;
49977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
50077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      while ( (nextblocksize > 0) &&
50177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner              (nextlf = (char *)memchr(nextblock, _STLP_LF, nextblocksize)) != 0) {
50277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        ptrdiff_t linelength = nextlf - nextblock;
50377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        memcpy(ptrtextbuf, nextblock, linelength);
50477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        ptrtextbuf += linelength;
50577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        nextblock += (linelength + 1);
50677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        * ptrtextbuf ++ = _STLP_CR;
50777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        * ptrtextbuf ++ = _STLP_LF;
50877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        nextblocksize = (min) (ptrdiff_t(endblock - nextblock),
50977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                               (max) (ptrdiff_t(0), ptrdiff_t(endtextbuf - ptrtextbuf)));
51077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
51177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // write out what's left, > condition is here since for LF at the end ,
51277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // endtextbuf may get < ptrtextbuf ...
51377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      if (nextblocksize > 0) {
51477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        memcpy(ptrtextbuf, nextblock, nextblocksize);
51577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        ptrtextbuf += nextblocksize;
51677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        nextblock += nextblocksize;
51777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
51877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // now write out the translated buffer
51977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      char * writetextbuf = textbuf;
52077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      for (size_t NumberOfBytesToWrite = (size_t)(ptrtextbuf - textbuf);
52177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner           NumberOfBytesToWrite;) {
52277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        DWORD NumberOfBytesWritten;
52377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        WriteFile((HANDLE)_M_file_id, writetextbuf,
52477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), NumberOfBytesToWrite)),
52577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                  &NumberOfBytesWritten, 0);
52677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        if (!NumberOfBytesWritten) // write shortfall
52777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          return false;
52877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        writetextbuf += NumberOfBytesWritten;
52977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        NumberOfBytesToWrite -= NumberOfBytesWritten;
53077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
53177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      // count non-translated characters
53277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      written = (nextblock - buf);
53377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
53477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
53577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (n == written)
53677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      return true;
53777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    else if (written > 0 && written < n) {
53877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      n -= written;
53977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      buf += written;
54077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
54177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    else
54277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      return false;
54377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
54477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
54577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
54677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Wrapper for lseek or the like.
54777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstreamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) {
54877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  streamoff result = -1;
54977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int whence;
55077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
55177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  switch(dir) {
55277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::beg:
55377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (offset < 0 /* || offset > _M_file_size() */ )
55477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      return streamoff(-1);
55577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    whence = FILE_BEGIN;
55677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
55777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::cur:
55877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    whence = FILE_CURRENT;
55977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
56077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  case ios_base::end:
56177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (/* offset > 0 || */  -offset > _M_file_size() )
56277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      return streamoff(-1);
56377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    whence = FILE_END;
56477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    break;
56577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  default:
56677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return streamoff(-1);
56777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
56877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
56977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  LARGE_INTEGER li;
57077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  li.QuadPart = offset;
57177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  li.LowPart = SetFilePointer(_M_file_id, li.LowPart, &li.HighPart, whence);
57277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (li.LowPart != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR)
57377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    result = li.QuadPart;
57477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
57577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return result;
57677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
57777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
57877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
57977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// Attempts to memory-map len bytes of the current file, starting
58077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// at position offset.  Precondition: offset is a multiple of the
58177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// page size.  Postcondition: return value is a null pointer if the
58277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// memory mapping failed.  Otherwise the return value is a pointer to
58377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner// the memory-mapped file and the file position is set to offset.
58477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnervoid* _Filebuf_base::_M_mmap(streamoff offset, streamoff len) {
58577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  void* base;
58677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_view_id = CreateFileMapping(_M_file_id, (PSECURITY_ATTRIBUTES)0 ,
58777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                 PAGE_READONLY, 0 /* len >> 32 */ ,
58877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                 0 /* len & 0xFFFFFFFF */ , // low-order DWORD of size
58977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                 0);
59077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
59177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_view_id) {
59277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if 0
59377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/*
59477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    printf("view %x created from file %x, error = %d, size = %d, map_offset = %d map_len = %d\n",
59577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner     _M_view_id, _M_file_id, GetLastError(),
59677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner     (int)cur_filesize, ULL(offset) & 0xffffffff, len);
59777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner*/
59877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
59977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    LARGE_INTEGER li;
60077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    li.QuadPart = offset;
60177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    base = MapViewOfFile(_M_view_id, FILE_MAP_READ, li.HighPart, li.LowPart,
60277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if !defined (__DMC__)
60377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                         __STATIC_CAST(SIZE_T, len));
60477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#else
60577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                         __STATIC_CAST(DWORD, len));
60677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
60777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    // check if mapping succeded and is usable
60877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (base == 0  || _M_seek(offset + len, ios_base::beg) < 0) {
60977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      this->_M_unmap(base, len);
61077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      base = 0;
61177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
61277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  } else
61377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    base = 0;
61477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
61577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return base;
61677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
61777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
61877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnervoid _Filebuf_base::_M_unmap(void* base, streamoff len) {
61977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // precondition : there is a valid mapping at the moment
62077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (base != NULL)
62177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    UnmapViewOfFile(base);
62277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  // destroy view handle as well
62377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (_M_view_id != NULL)
62477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    CloseHandle(_M_view_id);
62577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _M_view_id = NULL;
62677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  (void)len; //unused variable
62777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
62877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
62977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_STLP_END_NAMESPACE
630