PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
PStream.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/devices/PStream.cpp
4// Purpose: Primary File Stream class
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27#include "PStream.h"
28#include "../utility/PError.h"
29#include <iostream>
30#include <fstream>
31#include <sstream>
32#include <list>
33#include <string>
34#include <algorithm>
35#include <sys/stat.h>
36
37using std::ostream;
38using std::fstream;
39using std::flush;
40using std::string;
41using std::cout;
42using namespace std; //Ugh...need this for ios_base?
43
45PStream::PStream(const string & filename, StreamDirection dir, StreamType type):
46 mStreamFileName(filename),
47 mStreamDirection(dir),
48 mStreamType(type)
49{
50
51 mCDT = CDT_FILESTREAM;
52 //Standard Constructor
53
54 //Now, create the stream with proper flags and ready it for
55 //input/output.
56
57 switch (mStreamDirection)
58 {
59 case sdRead:
60 mFileStream = new fstream(mStreamFileName.c_str(), ios_base::in);
61 if(!mFileStream->is_open())
62 {
63 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for reading. It may be in a location you do not have privilege to access.");
64 }
65
66 break;
67
68 case sdWrite:
69 struct stat stFileInfo;
70 int intStat;
71
72 // Attempt to get the file attributes
73 intStat = stat(mStreamFileName.c_str(),&stFileInfo);
74#if 0
75 cout << "file attributes: " << intStat << endl;
76 cout << "st_mode: "<< stFileInfo.st_mode << endl;
77 cout << "st_gid: "<< stFileInfo.st_gid << endl;
78 cout << "st_uid: "<< stFileInfo.st_uid << endl;
79#endif
80 mFileStream = new fstream(mStreamFileName.c_str(), ios_base::out);
81 if(!mFileStream->is_open())
82 {
83 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for writing. Its directory may not exist or it may be in a location you do not have privilege to access.");
84 }
85
86 break;
87
88 case sdAppend:
89 mFileStream = new fstream(mStreamFileName.c_str(), ios_base::out | ios_base::app);
90 if(!mFileStream->is_open())
91 {
92 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for appending. Its directory may not exist or it may be in a location you do not have privilege to access.");
93 }
94
95 break;
96 default:
97
98 //error
99 PError::SignalFatalError("Error occurred in PStream Constructor\n");
100 }
101 //Binary/ascii/unicode/etc could be done here as well.
102
103
104 //If we didn't manage to encode anything, call an error
105 if(!mFileStream)
106 {
107 PError::SignalFatalError("Error initiating file [" + mStreamFileName + ".");
108 }
109}
110
111
113{
114 mFileStream = NULL;
115}
116
117
118void PStream::Open(const string & filename, StreamDirection dir, StreamType type)
119{
120
121 mStreamFileName = filename;
122 mStreamDirection = dir;
123 mStreamType = type;
124
125 //Now, create the stream with proper flags and ready it for
126 //input/output.
127
128
129 if(mStreamDirection==sdRead)
130 {
131 mFileStream->open(mStreamFileName.c_str(), ios_base::in);
132 if(!mFileStream->is_open())
133 {
134 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for reading");
135 }
136 }
137 else if (mStreamDirection==sdWrite)
138 {
139 mFileStream->open(mStreamFileName.c_str(), ios_base::out);
140 if(!mFileStream->is_open())
141 {
142 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for writing");
143 }
144
145 }
146 else if (mStreamDirection == sdAppend)
147 {
148 mFileStream->open(mStreamFileName.c_str(), ios_base::out | ios_base::app);
149 if(!mFileStream->is_open())
150 {
151 PError::SignalFatalError("Unable to open file ["+ mStreamFileName+"] for appending");
152 }
153 }
154 else
155 {
156 //error
157 PError::SignalFatalError("Error occurred in PStream::Open");
158 }
159 //Binary/ascii/unicode/etc could be done here as well.
160
161
162 //If we didn't manage to encode anything, call an error
163 if(!mFileStream)
164 {
165 PError::SignalFatalError("Error initiating file [" + mStreamFileName + ".");
166 }
167
168}
169
170
172void PStream::WriteChar(const char character)
173{
174 if(mStreamDirection == sdWrite ||
175 mStreamDirection == sdAppend)
176 {
177 (*mFileStream) << character << flush;
178 }
179 else
180 {
181 PError::SignalFatalError("Error in PStream::WriteChar--trying to write a Read stream: "+ string(mStreamFileName) + ".");
182 }
183
184}
185
186
190void PStream::WriteBuffer(const string & buffer, unsigned int length)
191{
192
193 if(mStreamDirection == sdWrite ||
194 mStreamDirection == sdAppend)
195 {
196
197 int len = length < buffer.size()? length: (int)(buffer.size());
198 string tmp;
199 std::copy(buffer.begin(), buffer.begin()+len, tmp.begin());
200 (* mFileStream) << tmp << flush;
201
202 }
203 else
204 {
205 PError::SignalFatalError("Error in PStream::WriteBuffer--trying to write a Read stream: "+ string(mStreamFileName) + ".");
206 }
207}
208
209
211void PStream::WriteString(const string & buffer)
212{
213
214 if(mStreamDirection == sdWrite ||
215 mStreamDirection == sdAppend)
216 {
217 (* mFileStream) << buffer << flush;
218
219 }
220 else
221 {
222 PError::SignalFatalError("Error in PStream::WriteString--trying to write a Read stream: "+ string(mStreamFileName) + ".");
223 }
224
225}
226
227
231{
232 if(mStreamDirection == sdRead)
233 {
234
235 char tmp;
236 mFileStream->get(tmp);
237 return tmp;
238
239 }
240 else
241 {
242
243 PError::SignalFatalError("Error in PStream::ReadChar--trying to Read a Write stream\n");
244 return 0;
245 }
246}
247
248
249
251std::string PStream::ReadToken(const char separator)
252{
253 if(mStreamDirection == sdRead)
254 {
255
256 std::string tmpstring; //Create a stream to use to capture input.
257 char tmp;
258 while(!mFileStream->eof() )
259 {
260 tmp = mFileStream->peek();
261 if (Eol())
262 {
263 //mFileStream->get(tmp);
264 break;
265 }
266
267 else if(tmp == separator )
268 {
269 mFileStream->get(tmp);
270 break;
271 }
272 else
273 {
274 mFileStream->get(tmp);
275 tmpstring += tmp;
276 }
277 }
278 return tmpstring;
279 }
280 else
281 {
282 PError::SignalFatalError("Error in PStream::ReadToken--trying to Read a Write stream\n");
283 return 0;
284 }
285}
286
287
290std::string PStream::ReadLine()
291{
292 if(mStreamDirection == sdRead)
293 {
294 std::string tmpstring;
295 char tmp;
296 mFileStream->get(tmp);
297
298
299 while( !mFileStream->eof())
300 {
301 tmpstring += tmp;
302 if(tmp == 10) //10 is the newline character
303 break; //Break out if the next character is eol
304
305 mFileStream->get(tmp);
306 }
307
308
309 return tmpstring;
310 }
311
312 else
313 {
314 PError::SignalFatalError("Error in PStream::ReadLine--trying to Read a Write stream\n");
315 return 0;
316 }
317}
318
319
320
321// This reads a line from a stream, stripping the newline character from the end.
322//
324{
325 if(mStreamDirection == sdRead)
326 {
327 std::string tmpstring;
328 char tmp;
329 mFileStream->get(tmp);
330
331
332 while( !mFileStream->eof())
333 {
334
335 if(tmp == 10) //10 is the newline character
336 break; //Break out if the next character is eol
337
338 tmpstring += tmp;
339 mFileStream->get(tmp);
340 }
341
342
343 return tmpstring;
344 }
345
346 else
347 {
348 PError::SignalFatalError("Error in PStream::ReadLine--trying to Read a Write stream\n");
349 return 0;
350 }
351}
352
353
354
355
357{
358 // std::cout << "EOL:" << mFileStream->tellg() << "["<<mFileStream->peek()<<"]" << endl;
359 if(mFileStream->peek() == 10) //LF
360 return true;
361
362 if(mFileStream->peek() == 13) //CR (precedes an LF in DOS.
363 {
364
365
366 streampos curr = mFileStream->tellg();
367 mFileStream->seekg(1,ios_base::cur);//look forward one
368 //cout<< "Next character: " << mFileStream->peek() <<endl;
369 //std::cout<< "13 matchses:\n";
370 if(mFileStream->peek() == 10)
371 {
372
373 return true;
374 }
375 else
376 {
377 //reverse out of it if this happens to not be paired with a LF.
378 mFileStream->seekg(-1,ios_base::cur);
379 return true;
380 }
381 }
382 if(mFileStream->eof()) //EOF --treat as an EOL.)
383 return true;
384
385 return false;
386}
387
389{
390 return mFileStream->eof();
391}
392
393//This closes an open stream.
395{
396 mFileStream->close();
397 return true;
398}
399
402{
403 // Standard Destructor
404
405}
406
407
408ostream & PStream::SendToStream(ostream & out) const
409{
410 out << "<Generic File Stream>" << flush;
411 return out;
412}
413
414
415 //overloaded generic PEBLObjectBase methods
416bool PStream::SetProperty(std::string name, Variant v)
417{
418 if(name=="FILENAME")
419 {
420 PEBLObjectBase::SetProperty("FILENAME",v);
421 }else if(name=="DIRECTION")
422 {
423 PEBLObjectBase::SetProperty("DIRECTION",v);
424 }
425 return true;
426}
427
428
429
430Variant PStream::GetProperty(std::string name)const
431{
432 //PEBLObjectBase::PrintProperties(cout);
433 return PEBLObjectBase::GetProperty(name);
434}
435
436
437
439{
440 return ValidateProperty(name);
441}
442
443
445{
446
447 if(name == "FILENAME" || name=="DIRECTION")
448 {
449 return OVE_VALID;
450 }else
451 {
452
454 }
455}
456
#define NULL
Definition BinReloc.cpp:317
ObjectValidationError
Definition PEBLObject.h:37
@ OVE_INVALID_PROPERTY_NAME
Definition PEBLObject.h:40
@ OVE_VALID
Definition PEBLObject.h:39
@ CDT_FILESTREAM
Definition PEBLObject.h:51
StreamDirection
Definition PStream.h:37
@ sdAppend
Definition PStream.h:40
@ sdWrite
Definition PStream.h:39
@ sdRead
Definition PStream.h:38
StreamType
Definition PStream.h:46
virtual bool SetProperty(std::string name, Variant v)
Variant GetProperty(std::string) const
void WriteChar(const char character)
This method sends a single character to the stream.
Definition PStream.cpp:172
virtual std::ostream & SendToStream(std::ostream &out) const
Definition PStream.cpp:408
void WriteBuffer(const std::string &buffer, unsigned int length)
Definition PStream.cpp:190
virtual ObjectValidationError ValidateProperty(std::string, Variant v) const
Definition PStream.cpp:438
bool Eof()
Definition PStream.cpp:388
virtual bool SetProperty(std::string, Variant v)
Definition PStream.cpp:416
std::string ReadLineClean()
Definition PStream.cpp:323
virtual ~PStream()
The Standard destructor.
Definition PStream.cpp:401
std::string ReadToken(const char separator)
This reads up until the next separator token (or eof character)
Definition PStream.cpp:251
PStream(const std::string &filename, StreamDirection dir, StreamType type)
The Standard constructor.
void WriteString(const std::string &buffer)
This method just writes the char* string to the stream.
Definition PStream.cpp:211
virtual Variant GetProperty(std::string) const
Definition PStream.cpp:430
bool Eol()
Definition PStream.cpp:356
void Open(const std::string &filename, StreamDirection dir, StreamType type)
Definition PStream.cpp:118
bool Close()
Definition PStream.cpp:394
std::string ReadLine()
Definition PStream.cpp:290
char ReadChar()
Definition PStream.cpp:230
void SignalFatalError(const std::string &message)