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