1/*
2 * Copyright (c) 1999
3 * Silicon Graphics Computer Systems, Inc.
4 *
5 * Copyright (c) 1999
6 * Boris Fomitchev
7 *
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
10 *
11 * Permission to use or copy this software for any purpose is hereby granted
12 * without fee, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
16 *
17 */
18
19#include "stlport_prefix.h"
20#include "stdio_streambuf.h"
21
22#ifdef _STLP_UNIX
23#  include <sys/types.h>
24#  include <sys/stat.h>
25#endif
26
27#include <fstream>
28#include <limits>
29
30_STLP_BEGIN_NAMESPACE
31_STLP_MOVE_TO_PRIV_NAMESPACE
32
33// Compare with streamoff definition in stl/char_traits.h!
34
35#if defined (_STLP_USE_DEFAULT_FILE_OFFSET) || \
36    (!defined(_LARGEFILE_SOURCE) && !defined(_LARGEFILE64_SOURCE))
37#  if !defined (_STLP_MSVC) || (_STLP_MSVC < 1400) || defined(_STLP_WCE)
38#    define FSEEK fseek
39#  else
40#    define FSEEK _fseeki64
41#  endif
42#  define FSETPOS  fsetpos
43#  define FGETPOS  fgetpos
44#  define FPOS_T   fpos_t
45#else
46#  define FSEEK fseeko64
47#  define FSETPOS  fsetpos64
48#  define FGETPOS  fgetpos64
49#  define FPOS_T   fpos64_t
50#endif
51
52//----------------------------------------------------------------------
53// Class stdio_streambuf_base
54
55stdio_streambuf_base::stdio_streambuf_base(FILE* file)
56    : /* _STLP_STD::FILE_basic_streambuf(file, 0), */
57    _M_file(file)
58{}
59
60stdio_streambuf_base::~stdio_streambuf_base() {
61  _STLP_VENDOR_CSTD::fflush(_M_file);
62}
63
64_STLP_STD::streambuf* stdio_streambuf_base::setbuf(char* s, streamsize n) {
65#ifdef _STLP_WCE
66  // no buffering in windows ce .NET
67#else
68  size_t __n_size_t = (sizeof(streamsize) > sizeof(size_t)) ? __STATIC_CAST(size_t, (min)(__STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()), n))
69                                                            : __STATIC_CAST(size_t, n);
70  _STLP_VENDOR_CSTD::setvbuf(_M_file, s, (s == 0 && n == 0) ? _IONBF : _IOFBF, __n_size_t);
71#endif
72  return this;
73}
74
75stdio_streambuf_base::pos_type
76stdio_streambuf_base::seekoff(off_type off, ios_base::seekdir dir,
77                              ios_base::openmode /* mode */) {
78  int whence;
79  switch (dir) {
80  case ios_base::beg:
81    whence = SEEK_SET;
82    break;
83  case ios_base::cur:
84    whence = SEEK_CUR;
85    break;
86  case ios_base::end:
87    whence = SEEK_END;
88    break;
89  default:
90    return pos_type(-1);
91  }
92
93  if (off <= numeric_limits<off_type>::max() && FSEEK(_M_file, off, whence) == 0) {
94    FPOS_T pos;
95    FGETPOS(_M_file, &pos);
96    // added 21 june 00 mdb,rjf,wjs: glibc 2.2 changed fpos_t to be a struct instead
97    // of a primitive type
98#if (defined (__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2))))
99    return pos_type((streamoff)pos.__pos);
100#elif defined (__ISCPP__) || defined (__MVS__) || defined (__OS400__)
101    return pos_type(pos.__fpos_elem[ 0 ]);
102#elif defined (__EMX__)
103    return pos_type((streamoff)pos._pos);
104#else
105    return pos_type(pos);
106#endif
107  }
108  else
109    return pos_type(-1);
110}
111
112
113stdio_streambuf_base::pos_type
114stdio_streambuf_base::seekpos(pos_type pos, ios_base::openmode /* mode */) {
115  // added 21 june 00 mdb,rjf,wjs: glibc 2.2 changed fpos_t to be a struct instead
116  // of a primitive type
117#if (defined(__GLIBC__) && ( (__GLIBC__ > 2) || ( (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2) ) ) )
118  FPOS_T p;
119  p.__pos = pos;
120#  ifdef _STLP_USE_UCLIBC
121#    ifdef __STDIO_MBSTATE
122  memset( &(p.__mbstate), 0, sizeof(p.__mbstate) );
123#    endif
124#    ifdef __STDIO_WIDE
125  p.mblen_pending = 0;
126#    endif
127#  else
128  memset( &(p.__state), 0, sizeof(p.__state) );
129#  endif
130#elif defined (__MVS__) || defined (__OS400__)
131  FPOS_T p;
132  p.__fpos_elem[0] = pos;
133#elif defined (__EMX__)
134  FPOS_T p;
135  p._pos = pos;
136  memset( &(p._mbstate), 0, sizeof(p._mbstate) );
137#else
138  FPOS_T p(pos);
139#endif
140
141  return FSETPOS(_M_file, &p) == 0 ? pos : pos_type(-1);
142}
143
144int stdio_streambuf_base::sync() {
145  return _STLP_VENDOR_CSTD::fflush(_M_file) == 0 ? 0 : -1;
146}
147
148//----------------------------------------------------------------------
149// Class stdio_istreambuf
150
151stdio_istreambuf::~stdio_istreambuf() {}
152
153streamsize stdio_istreambuf::showmanyc()
154{ return 0; }
155
156stdio_istreambuf::int_type stdio_istreambuf::underflow()
157{
158#ifdef _STLP_WCE
159  int c = fgetc(_M_file);
160#else
161  int c = getc(_M_file);
162#endif
163  if (c != EOF) {
164    _STLP_VENDOR_CSTD::ungetc(c, _M_file);
165    return c;
166  }
167  else
168    return traits_type::eof();
169}
170
171stdio_istreambuf::int_type stdio_istreambuf::uflow() {
172#ifdef _STLP_WCE
173  int c = fgetc(_M_file);
174#else
175  int c = getc(_M_file);
176#endif
177  return c != EOF ? c : traits_type::eof();
178}
179
180stdio_istreambuf::int_type stdio_istreambuf::pbackfail(int_type c) {
181  if (c != traits_type::eof()) {
182    int result = _STLP_VENDOR_CSTD::ungetc(c, _M_file);
183    return result != EOF ? result : traits_type::eof();
184  }
185  else{
186    if (this->eback() < this->gptr()) {
187      this->gbump(-1);
188      return traits_type::not_eof(c);
189    }
190    else
191      return traits_type::eof();
192  }
193}
194
195//----------------------------------------------------------------------
196// Class stdio_ostreambuf
197
198stdio_ostreambuf::~stdio_ostreambuf() {}
199
200streamsize stdio_ostreambuf::showmanyc()
201{ return -1; }
202
203stdio_ostreambuf::int_type stdio_ostreambuf::overflow(int_type c) {
204  // Write the existing buffer, without writing any additional character.
205  if (c == traits_type::eof()) {
206    // Do we have a buffer to write?
207    ptrdiff_t unwritten = this->pptr() - this->pbase();
208    if (unwritten != 0) {
209      _STLP_VENDOR_CSTD::fflush(_M_file);
210      // Test if the write succeeded.
211      if (this->pptr() - this->pbase() < unwritten)
212        return traits_type::not_eof(c);
213      else
214        return traits_type::eof();
215    }
216
217    // We always succeed if we don't have to do anything.
218    else
219      return traits_type::not_eof(c);
220  }
221
222  // Write the character c, and whatever else might be in the buffer.
223  else {
224#ifdef _STLP_WCE
225    int result = fputc(c, _M_file);
226#else
227    int result = putc(c, _M_file);
228#endif
229    return result != EOF ? result : traits_type::eof();
230  }
231}
232
233_STLP_MOVE_TO_STD_NAMESPACE
234_STLP_END_NAMESPACE
235
236// Local Variables:
237// mode:C++
238// End:
239
240