vil_stream_fstream.cxx
Go to the documentation of this file.
1 // This is core/vil/vil_stream_fstream.cxx
2 
3 #include <limits>
4 #include <iostream>
5 #include <ios>
6 #include "vil_stream_fstream.h"
7 #include <cassert>
8 #ifdef _MSC_VER
9 # include <vcl_msvc_warnings.h>
10 #endif
11 
12 static std::ios::openmode modeflags(char const* mode)
13 {
14  if (*mode == 0)
15  return std::ios::openmode(0);
16 
17  if (*mode == 'r') {
18  if (mode[1] == '+' || mode[1] == 'w')
19  return std::ios::in | std::ios::out | modeflags(mode+2);
20  else
21  return std::ios::in | modeflags(mode+1);
22  }
23 
24  if (*mode == 'w') {
25  if (mode[1] == '+')
26  return std::ios::in | std::ios::out | std::ios::trunc | modeflags(mode+2);
27  else
28  return std::ios::out | std::ios::trunc | modeflags(mode+1);
29  }
30 
31  std::cerr << std::endl << __FILE__ ": DODGY MODE " << mode << std::endl;
32  return std::ios::openmode(0);
33 }
34 
35 #define xerr if (true) ; else (std::cerr << "std::fstream#" << id_ << ": ")
36 
37 static int id = 0;
38 
39 vil_stream_fstream::vil_stream_fstream(char const* fn, char const* mode):
40  flags_(modeflags(mode)),
41  f_(fn, flags_ | std::ios::binary), // need ios::binary on windows.
42  end_( -1 )
43 {
44  id_ = ++id;
45  xerr << "vil_stream_fstream(\"" << fn << "\", \""<<mode<<"\") = " << id_ << '\n';
46 #if 0
47  if (!f_) {
48  std::cerr << "vil_stream_fstream::Could not open [" << fn << "]\n";
49  }
50 #endif // 0
51 }
52 
53 #if defined(_WIN32) && VXL_USE_WIN_WCHAR_T
54 vil_stream_fstream::vil_stream_fstream(wchar_t const* fn, char const* mode):
55  flags_(modeflags(mode)),
56  f_(fn, flags_ | std::ios::binary), // need ios::binary on windows.
57  end_( -1 )
58 {
59  id_ = ++id;
60 }
61 #endif //defined(_WIN32) && VXL_USE_WIN_WCHAR_T
62 
63 #if 0
65  f_(f.rdbuf()->fd()),
66  end_( -1 )
67 {
68 }
69 #endif // 0
70 
72 {
73  xerr << "vil_stream_fstream# " << id_ << " being deleted\n";
74 }
75 
77 {
78  assert(id > 0);
79  //assures that cast (below) will be ok
80  assert( n <= std::numeric_limits<std::streamoff>::max() );
81 
82  if (!(flags_ & std::ios::out)) {
83  std::cerr << "vil_stream_fstream: write failed, not a std::ostream\n";
84  return 0;
85  }
86 
87  vil_streampos a = tell();
88  xerr << "write " << n << std::endl;
89  f_.write((char const*)buf, (std::streamoff)n);
90  if (!f_.good())
91  std::cerr << ("vil_stream_fstream: ERROR: write failed!\n");
92  vil_streampos b = tell();
93  f_.flush();
94  return b-a;
95 }
96 
97 
99 {
100  assert(id > 0);
101  //assures that cast (below) will be ok
102  assert( n <= std::numeric_limits<std::streamoff>::max() );
103 
104  if (!(flags_ & std::ios::in))
105  return 0;
106 
107  vil_streampos a = tell();
108  xerr << "read " << n << std::endl;
109  f_.read((char *)buf, (std::streamoff)n);
110 
111  // fsm This is for gcc 2.95 :
112  // If we try to read more data than is in the file, the good()
113  // function will return false even though bad() returns false
114  // too. The stream is actually fine but we need to clear the
115  // eof flag to use it again.
116  // iscott@man It does something similar under Windows, but has the added
117  // advantage, of making tell() return a sensible value (instead
118  // of -1)
119  if (!f_.good() && !f_.bad() && f_.eof())
120  f_.clear(); // allows subsequent operations
121 
122  vil_streampos b = tell();
123 
124  vil_streampos numread = b-a;
125  if (b < a) { xerr << "urgh!\n"; return numread; }
126  if (numread != n) { xerr << "only read " << numread << std::endl; }
127  return numread;
128 }
129 
131 {
132  assert(id > 0);
133  if (flags_ & std::ios::in) {
134  xerr << "tellg\n";
135  return f_.tellg();
136  }
137 
138  if (flags_ & std::ios::out) {
139  xerr << "tellp\n";
140  return f_.tellp();
141  }
142 
143  assert(false); // did you get here? use at least one of std::ios::in, std::ios::out.
144  return (vil_streampos)(-1L);
145 }
146 
148 {
149  assert(id > 0);
150  //assures that cast (below) will be ok
151  assert( position <= std::numeric_limits< std::streamoff >::max() );
152 
153  bool fi = (flags_ & std::ios::in) != 0;
154  bool fo = (flags_ & std::ios::out) != 0;
155 
156  if (fi && fo) {
157  xerr << "seekg and seekp to " << position << std::endl;
158  if (position != vil_streampos(f_.tellg())) {
159  f_.seekg((std::streamoff)position);
160  f_.seekp((std::streamoff)position);
161  assert(f_.good());
162  }
163  }
164 
165  else if (fi) {
166  xerr << "seek to " << position << std::endl;
167  if (position != vil_streampos(f_.tellg())) {
168  f_.seekg((std::streamoff)position);
169  assert(f_.good());
170  }
171  }
172 
173  else if (fo) {
174  xerr << "seekp to " << position << std::endl;
175  std::streamoff at = f_.tellp();
176  if (position != at) {
177  xerr << "seekp to " << position << ", at " << (long)f_.tellp() << std::endl;
178  f_.seekp((std::streamoff)position);
179  assert(f_.good());
180  }
181  }
182  else
183  assert(false); // did you get here? use at least one of std::ios::in, std::ios::out.
184 }
185 
187 {
188  // if not already computed, do so
189  if ( end_ == -1 ) {
190  std::streampos curr = f_.tellg();
191  f_.seekg( 0, std::ios::end );
192  end_ = f_.tellg();
193  f_.seekg( curr );
194  }
195 
196  return end_;
197 }
std::ios::openmode flags_
vil_streampos file_size() const override
Amount of data in the stream.
vil_streampos write(void const *buf, vil_streampos n) override
Write n bytes from buf. Returns number of bytes written.
vil_streampos tell() const override
Return file pointer.
vil_streampos read(void *buf, vil_streampos n) override
Read n bytes into buf. Returns number of bytes read.
A vil_stream implementation using std::fstream.
vxl_int_32 vil_streampos
Definition: vil_stream.h:16
#define xerr
void seek(vil_streampos position) override
Goto file pointer.
vil_stream_fstream(char const *filename, char const *mode)