Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

PStream.h

Go to the documentation of this file.
00001 // -*- C++ -*- 00002 00003 // PStream.h 00004 // Copyright (C) 1998 Pascal Vincent 00005 // Copyright (C) 1999-2001 Pascal Vincent, Yoshua Bengio and University of Montreal 00006 // Copyright (C) 2002 Frederic Morin, Xavier Saint-Mleux, Pascal Vincent 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are met: 00010 // 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 00014 // 2. Redistributions in binary form must reproduce the above copyright 00015 // notice, this list of conditions and the following disclaimer in the 00016 // documentation and/or other materials provided with the distribution. 00017 // 00018 // 3. The name of the authors may not be used to endorse or promote 00019 // products derived from this software without specific prior written 00020 // permission. 00021 // 00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 // This file is part of the PLearn library. For more information on the PLearn 00034 // library, go to the PLearn Web site at www.plearn.org 00035 00036 #ifndef PStream_INC 00037 #define PStream_INC 00038 00039 //#include <iosfwd> 00040 #include <map> 00041 #include <set> 00042 //#include <bitset> 00043 #include <sstream> 00044 #include <plearn/base/pl_hash_fun.h> 00045 //#include "PP.h" 00046 #include "PStream_util.h" 00047 #include <plearn/base/plerror.h> 00048 #include <fstream> 00049 //#include "TypeTraits.h" 00050 #include <plearn/base/byte_order.h> 00051 #include "fileutils.h" 00052 #include "PStreamBuf.h" 00053 #include "StdPStreamBuf.h" 00054 00055 // OLD MARKABLE STREAM HACK 00056 // #include "pl_streambuf.h" 00057 // #include "pl_fdstream.h" 00058 00059 00060 namespace PLearn { 00061 00062 using namespace std; 00063 00079 class PStream : public PPointable 00080 { 00081 public: 00083 typedef PStream& (*pl_pstream_manip)(PStream&); 00084 00086 /* 00087 typedef istream& (*pl_istream_manip_compat)(istream&); 00088 typedef ostream& (*pl_ostream_manip_compat)(ostream&); 00089 */ 00090 00091 // norman: check for win32 00092 #if __GNUC__ < 3 && !defined(WIN32) 00093 00094 typedef int streamsize; 00095 typedef ios ios_base; 00096 #endif 00097 00098 enum mode_t 00099 { 00100 plearn_ascii, //<! PLearn ascii serialization format (can be mixed with plearn_binary) 00101 plearn_binary, //<! PLearn binary serialization format (can be mixed with plearn_ascii) 00102 raw_ascii, //<! Raw C++ ascii output without additional separators (direct output to underlying ostream) 00103 raw_binary, //<! Simply writes the bytes as they are in memory. 00104 pretty_ascii //<! Ascii pretty print (in particular for Vec and Mat, formatted output without size info) 00105 }; 00106 00109 00112 enum compr_mode_t { 00113 compr_none, //<! No compression. 00114 compr_double_as_float, //<! In plearn_binary mode, store doubles as float 00115 compr_sparse, //<! PLearn 00116 compr_lossy_sparse //<! Also stores double as float 00117 }; 00118 00119 00120 protected: 00121 /* OLD MARKABLE STREAM HACK 00122 PP<pl_streambuf> the_inbuf; //<! markable input buffer 00123 PP<pl_fdstreambuf> the_fdbuf; //<! buffer on a POSIX file descriptor 00124 00125 istream* pin; //<! underlying input stream 00126 ostream* pout; //<! underlying output stream 00127 bool own_pin, own_pout; //<! true if {pin|pout} was created internally 00128 */ 00129 00130 PP<StdPStreamBuf> pstreambuf; 00131 00132 00133 public: 00134 mode_t inmode; //<! mode for input formatting 00135 // bitset<32> pl_stream_flags_in; //<! format flags for input 00136 map<unsigned int, void *> copies_map_in; //<! copies map for input 00137 mode_t outmode; //<! mode for output formatting 00138 // bitset<32> pl_stream_flags_out; //<! format flags for output 00139 map<void *, unsigned int> copies_map_out; //<! copies map for output 00140 00141 protected: 00142 /* OLD MARKABLE STREAM HACK 00145 streambuf* original_bufin, * original_bufout; 00146 */ 00147 00148 private: 00149 static char tmpbuf[100]; 00150 00151 public: 00154 bool implicit_storage; 00156 compr_mode_t compression_mode; 00157 00158 public: 00159 00161 PStream(); 00162 00164 PStream(istream* pin_, bool own_pin_=false); 00165 00167 PStream(ostream* pout_, bool own_pout_=false); 00168 00170 PStream(iostream* pios_, bool own_pios_=false); 00171 00173 PStream(istream* pin_, ostream* pout_, bool own_pin_=false, bool own_pout_=false); 00174 00176 00178 virtual ~PStream(); 00179 00180 inline void setInMode(mode_t m) { inmode = m; } 00181 inline void setOutMode(mode_t m) { outmode = m; } 00182 inline void setMode(mode_t m) { inmode = m; outmode = m; } 00183 00184 PStream& operator>>(mode_t m) { inmode = m; return *this; } 00185 PStream& operator<<(mode_t m) { outmode = m; return *this; } 00186 00187 public: 00188 //op()'s: re-init with different underlying stream(s) 00189 inline PStream& operator()(istream* pin) 00190 { pstreambuf->setIn(pin); return *this; } 00191 00192 inline PStream& operator()(ostream* pout) 00193 { pstreambuf->setOut(pout); return *this; } 00194 00195 inline PStream& operator()(iostream* pios) 00196 { pstreambuf->setIn(pios); pstreambuf->setOut(pios); return *this; } 00197 00198 inline PStream& operator()(istream* pin, ostream* pout) 00199 { pstreambuf->setIn(pin); pstreambuf->setOut(pout); return *this; } 00200 00201 PStream& operator=(const PStream& pios); 00202 00203 inline PStream& operator=(istream* pin) { return operator()(pin); } 00204 inline PStream& operator=(ostream* pout) { return operator()(pout); } 00205 inline PStream& operator=(iostream* pios) { return operator()(pios); } 00206 00207 inline PStream& operator()(const PStream& pios) { return operator=(pios); } 00208 00209 00210 void writeAsciiNum(char x); 00211 void writeAsciiNum(unsigned char x); 00212 void writeAsciiNum(signed char x); 00213 void writeAsciiNum(short x); 00214 void writeAsciiNum(unsigned short x); 00215 void writeAsciiNum(int x); 00216 void writeAsciiNum(unsigned int x); 00217 void writeAsciiNum(long x); 00218 void writeAsciiNum(unsigned long x); 00219 void writeAsciiNum(float x); 00220 void writeAsciiNum(double x); 00221 00222 void readAsciiNum(char &x); 00223 void readAsciiNum(unsigned char &x); 00224 void readAsciiNum(signed char &x); 00225 void readAsciiNum(short &x); 00226 void readAsciiNum(unsigned short &x); 00227 void readAsciiNum(int &x); 00228 void readAsciiNum(unsigned int &x); 00229 void readAsciiNum(long &x); 00230 void readAsciiNum(unsigned long &x); 00231 void readAsciiNum(float &x); 00232 void readAsciiNum(double &x); 00233 00235 void writeAsciiHexNum(unsigned char x); 00236 00238 // This implementation does not seem to work: commented out [Pascal] 00239 // inline operator bool() { return (!pin || *pin) && (!pout || *pout) && (pin || pout); } 00240 // This is a temporary fix [Pascal] 00241 inline operator bool() { return pstreambuf->rawin() && pstreambuf->rawin()->good() || pstreambuf->rawout() && pstreambuf->rawout()->good(); } 00242 00243 inline bool eof() const { return pstreambuf->rawin()->eof(); } 00244 inline bool good() const { return pstreambuf->rawin()->good() && pstreambuf->rawout()->good(); } 00245 00246 inline istream& _do_not_use_this_method_rawin_() { return *pstreambuf->rawin(); } //<! access to underlying istream 00247 00248 /****** 00249 * The folowing methods are 'forwarded' from {i|o}stream. 00250 */ 00251 inline int get() 00252 { 00253 #if STREAMBUFVER == 1 00254 return pstreambuf->get(); 00255 #else 00256 return pstreambuf->rawin()->get(); 00257 #endif 00258 } 00259 00260 inline PStream& get(char& c) 00261 { 00262 #if STREAMBUFVER == 1 00263 c = (char) pstreambuf->get(); 00264 #else 00265 pstreambuf->rawin()->get(c); 00266 #endif 00267 return *this; 00268 } 00269 00271 inline PStream& getline(string& line, char delimitor='\n') 00272 { 00273 #if STREAMBUFVER == 1 00274 line.clear(); 00275 int c = get(); 00276 while(c!=EOF && c!=delimitor) 00277 line.push_back((char)c); 00278 #else 00279 std::getline(*pstreambuf->rawin(), line, delimitor); 00280 #endif 00281 return *this; 00282 } 00283 00284 inline string getline() 00285 { string s; getline(s); return s; } 00286 00287 // inline int peek() { return pstreambuf->rawin()->peek(); } 00288 // The previous implementation does not seem to work, so we use this [Pascal]: 00289 00290 inline int peek() 00291 { 00292 #if STREAMBUFVER == 1 00293 return pstreambuf->peek(); 00294 #else 00295 int c = pstreambuf->rawin()->get(); 00296 pstreambuf->rawin()->unget(); 00297 return c; 00298 #endif 00299 } 00300 00301 inline PStream& putback(char c) 00302 { 00303 #if STREAMBUFVER == 1 00304 pstreambuf->unget(c); 00305 #else 00306 pstreambuf->rawin()->putback(c); 00307 #endif 00308 return *this; 00309 } 00310 00311 #if STREAMBUFVER == 1 00312 // we don<t define unget. Use putback(c) instead. 00313 #else 00314 inline PStream& unget() { pstreambuf->rawin()->unget(); return *this; } 00315 #endif 00316 00317 00318 inline PStream& read(char* s, streamsize n) 00319 { 00320 #if STREAMBUFVER == 1 00321 pstreambuf->read(s,n); 00322 return *this; 00323 00324 #else 00325 // The following line does not Work!!!! [Pascal] 00326 // pstreambuf->rawin()->read(s,n); 00327 // So it's temporarily replaced by this (ugly and slow): 00328 while (n) 00329 { 00330 int c = get(); 00331 if (c == EOF) break; 00332 *s++ = (char) c; 00333 n--; 00334 } 00335 return *this; 00336 #endif 00337 } 00338 00339 inline PStream& read(string& s, streamsize n) 00340 { 00341 char* buf = new char[n]; 00342 read(buf, n); 00343 s.assign(buf,n); 00344 delete[] buf; 00345 return *this; 00346 } 00347 00352 streamsize readUntil(char* buf, streamsize n, char stop_char); 00353 00358 streamsize readUntil(char* buf, streamsize n, const char* stop_chars); 00359 00360 inline PStream& write(const char* s, streamsize n) 00361 { 00362 #if STREAMBUFVER == 1 00363 pstreambuf->write(s,n); 00364 #else 00365 pstreambuf->rawout()->write(s,n); 00366 #endif 00367 return *this; 00368 } 00369 00370 inline PStream& put(char c) 00371 { 00372 #if STREAMBUFVER == 1 00373 pstreambuf->put(c); 00374 #else 00375 pstreambuf->rawout()->put(c); return *this; 00376 #endif 00377 } 00378 00379 inline PStream& put(unsigned char c) { write(reinterpret_cast<char *>(&c), sizeof(c)); return *this; } 00380 inline PStream& put(int x) { return put((char)x); } 00381 00382 inline PStream& flush() 00383 { 00384 #if STREAMBUFVER == 1 00385 pstreambuf->flush(); 00386 #else 00387 pstreambuf->rawout()->flush(); 00388 #endif 00389 return *this; 00390 } 00391 00392 inline PStream& endl() { put('\n'); flush(); return *this; } 00393 /******/ 00394 00395 // These are convenient method for writing raw strings (whatever the outmode): 00396 inline PStream& write(const char* s) 00397 { 00398 write(s, strlen(s)); 00399 return *this; 00400 } 00401 00402 inline PStream& write(const string& s) 00403 { 00404 write(s.data(),s.length()); 00405 return *this; 00406 } 00407 00408 #if STREAMBUFVER == 1 00409 // not the way to do it woth new PStreamBuf 00410 #else 00411 00412 inline void attach(int fd) 00413 { pstreambuf->attach(fd); } 00414 #endif 00415 00416 // Useful skip functions 00417 00419 void skipRestOfLine(); 00420 00422 void skipBlanks(); 00423 00425 void skipBlanksAndComments(); 00426 00428 void skipBlanksAndCommentsAndSeparators(); 00429 00431 void skipAll(const char* chars_to_skip); 00432 00440 int smartReadUntilNext(const string& stoppingsymbols, string& characters_read, bool ignore_brackets=false); 00441 00442 // operator>>'s for base types 00443 PStream& operator>>(bool &x); 00444 PStream& operator>>(float &x); 00445 PStream& operator>>(double &x); 00446 PStream& operator>>(string &x); 00447 PStream& operator>>(char* x); // read string in already allocated char[] 00448 PStream& operator>>(char &x); 00449 PStream& operator>>(signed char &x); 00450 PStream& operator>>(unsigned char &x); 00451 PStream& operator>>(int &x); 00452 PStream& operator>>(unsigned int &x); 00453 PStream& operator>>(long &x); 00454 PStream& operator>>(unsigned long &x); 00455 PStream& operator>>(short &x); 00456 PStream& operator>>(unsigned short &x); 00457 PStream& operator>>(pl_pstream_manip func) { return (*func)(*this); } 00458 00459 // operator<<'s for base types 00460 PStream& operator<<(float x); 00461 PStream& operator<<(double x); 00462 00465 PStream& operator<<(const char *x); 00466 00470 PStream& operator<<(const string &x); 00471 00472 PStream& operator<<(char x); 00473 PStream& operator<<(signed char x); 00474 PStream& operator<<(unsigned char x); 00475 PStream& operator<<(int x); 00476 PStream& operator<<(unsigned int x); 00477 PStream& operator<<(long x); 00478 PStream& operator<<(unsigned long x); 00479 PStream& operator<<(short x); 00480 PStream& operator<<(unsigned short x); 00481 PStream& operator<<(pl_pstream_manip func) { return (*func)(*this); } 00482 00483 #if STREAMBUFVER == 0 00486 inline pl_streambuf* pl_rdbuf() { return pstreambuf->pl_rdbuf(); } 00487 #endif 00488 00489 }; 00490 00491 00492 // Simulation of <<flush <<endl and >>ws ... 00493 00494 extern PStream& flush(PStream& out); 00495 extern PStream& endl(PStream& out); 00496 extern PStream& ws(PStream& out); 00497 00498 // But inject the standard ones as well to keep them usable!!! 00499 using std::flush; 00500 using std::endl; 00501 using std::ws; 00502 00503 00504 /***** 00505 * op>> & op<< for generic pointers 00506 */ 00507 00508 template <class T> 00509 inline PStream& operator>>(PStream& in, T*& x) 00510 { 00511 in.skipBlanksAndCommentsAndSeparators(); 00512 if (in.peek() == '*') 00513 { 00514 in.get(); // Eat '*' 00515 unsigned int id; 00516 in >> id; 00517 in.skipBlanksAndCommentsAndSeparators(); 00518 if (id==0) 00519 x = 0; 00520 else if (in.peek() == '-') 00521 { 00522 in.get(); // Eat '-' 00523 char cc = in.get(); 00524 if(cc != '>') // Eat '>' 00525 PLERROR("In PStream::operator>>(T*&) Wrong format. Expecting \"*%d->\" but got \"*%d-%c\".", id, id, cc); 00526 in.skipBlanksAndCommentsAndSeparators(); 00527 if(!x) 00528 x= new T(); 00529 in >> *x; 00530 in.skipBlanksAndCommentsAndSeparators(); 00531 in.copies_map_in[id]= x; 00532 } 00533 else 00534 { 00535 // Find it in map and return ptr; 00536 map<unsigned int, void *>::iterator it = in.copies_map_in.find(id); 00537 if (it == in.copies_map_in.end()) 00538 PLERROR("In PStream::operator>>(T*&) object (ptr) to be read has not been previously defined"); 00539 x= static_cast<T *>(it->second); 00540 } 00541 } 00542 else 00543 { 00544 in >> *x; 00545 in.skipBlanksAndCommentsAndSeparators(); 00546 } 00547 00548 return in; 00549 } 00550 00551 00552 template <class T> 00553 inline PStream& operator<<(PStream& out, const T*& x) 00554 { 00555 // cerr << "{ " << x << " : " << out.copies_map_out.size() << " } " << endl; 00556 if(x) 00557 { 00558 map<void *, unsigned int>::iterator it = out.copies_map_out.find(const_cast<T*&>(x)); 00559 if (it == out.copies_map_out.end()) 00560 { 00561 int id = (int)out.copies_map_out.size()+1; 00562 out.put('*'); 00563 out << id; 00564 out.write("->"); 00565 out.copies_map_out[const_cast<T*&>(x)] = id; 00566 out << *x; 00567 } 00568 else 00569 { 00570 out.put('*'); 00571 out << it->second; 00572 out.put(' '); 00573 } 00574 } 00575 else 00576 out.write("*0 "); 00577 return out; 00578 } 00579 00580 template <class T> 00581 inline PStream& operator>>(PStream& in, PP<T> &o) 00582 { 00583 T *ptr; 00584 if (o.isNull()) 00585 ptr = 0; 00586 else 00587 ptr = o; 00588 in >> ptr; 00589 o = ptr; 00590 return in; 00591 } 00592 00593 template <class T> 00594 inline PStream& operator<<(PStream& out, const PP<T> &o) 00595 { 00596 T *ptr = static_cast<T *>(o); 00597 out << const_cast<const T * &>(ptr); 00598 return out; 00599 } 00600 00601 template <class T> 00602 inline PStream& operator<<(PStream& out, T*& ptr) 00603 { 00604 out << const_cast<const T * &>(ptr); 00605 return out; 00606 } 00607 00608 inline PStream& operator<<(PStream& out, bool x) 00609 { 00610 switch(out.outmode) 00611 { 00612 case PStream::raw_binary: 00613 case PStream::raw_ascii: 00614 case PStream::pretty_ascii: 00615 if(x) 00616 out.put('1'); 00617 else 00618 out.put('0'); 00619 break; 00620 case PStream::plearn_ascii: 00621 if(x) 00622 out.put('1'); 00623 else 00624 out.put('0'); 00625 out.put(' '); 00626 break; 00627 case PStream::plearn_binary: 00628 out.put((char)0x12); 00629 if(x) 00630 out.put('1'); 00631 else 00632 out.put('0'); 00633 break; 00634 default: 00635 PLERROR("In PStream::operator<< unknown outmode!!!!!!!!!"); 00636 break; 00637 } 00638 return out; 00639 } 00640 00641 00642 00643 00644 // Serialization of pairs in the form: 00645 // first : second 00646 00647 template<class A,class B> 00648 inline PStream& operator<<(PStream& out, const pair<A,B>& x) 00649 { 00650 out << x.first; 00651 out.write(": "); 00652 out << x.second; 00653 out.put(' '); 00654 return out; 00655 } 00656 00657 template <typename S, typename T> 00658 inline PStream& operator>>(PStream& in, pair<S, T> &x) 00659 { 00660 in.skipBlanksAndCommentsAndSeparators(); 00661 in >> x.first; 00662 in.skipBlanksAndComments(); 00663 if(in.get()!=':') 00664 PLERROR("In operator>>(PStream& in, pair<S, T> &x) expected ':' to separate the 2 halves of the pair"); 00665 in.skipBlanksAndComments(); 00666 in >> x.second; 00667 return in; 00668 } 00669 00670 00671 // Serialization of map types 00672 00673 template<class MapT> 00674 void writeMap(PStream& out, const MapT& m) 00675 { 00676 typename MapT::const_iterator it = m.begin(); 00677 typename MapT::const_iterator itend = m.end(); 00678 00679 out.put('{'); 00680 if(!m.empty()) 00681 { 00682 // write the first item 00683 out << it->first; 00684 out.write(": "); 00685 out << it->second; 00686 ++it; 00687 while(it!=itend) 00688 { 00689 out.write(", "); 00690 out << it->first; 00691 out.write(": "); 00692 out << it->second; 00693 ++it; 00694 } 00695 } 00696 out.put('}'); 00697 } 00698 00699 template<class MapT> 00700 void readMap(PStream& in, MapT& m) 00701 { 00702 m.clear(); 00703 in.skipBlanksAndCommentsAndSeparators(); 00704 int c = in.get(); 00705 if(c!='{') 00706 PLERROR("In readMap(Pstream& in, MapT& m) expected '{' but read %c",c); 00707 in.skipBlanksAndCommentsAndSeparators(); 00708 c = in.peek(); // do we have a '}' ? 00709 while(c!='}') 00710 { 00711 pair<typename MapT::key_type, typename MapT::mapped_type> val; 00712 in >> val.first; 00713 in.skipBlanksAndCommentsAndSeparators(); 00714 c = in.get(); 00715 if(c!=':') 00716 PLERROR("In readMap(Pstream& in, MapT& m) separator between key and value must be ':', but I read a '%c'",c); 00717 in.skipBlanksAndCommentsAndSeparators(); 00718 in >> val.second; 00719 m.insert(val); 00720 in.skipBlanksAndCommentsAndSeparators(); 00721 c = in.peek(); // do we have a '}' ? 00722 } 00723 in.get(); // eat the '}' 00724 } 00725 00726 template<class Key, class Value> 00727 inline PStream& operator<<(PStream& out, const map<Key, Value>& m) 00728 { writeMap(out, m); return out; } 00729 00730 template<class Key, class Value> 00731 inline PStream& operator>>(PStream& in, map<Key, Value>& m) 00732 { readMap(in, m); return in; } 00733 00734 template<class Key, class Value> 00735 inline PStream& operator<<(PStream& out, const multimap<Key, Value>& m) 00736 { writeMap(out, m); return out; } 00737 00738 template<class Key, class Value> 00739 inline PStream& operator>>(PStream& in, multimap<Key, Value>& m) 00740 { readMap(in, m); return in; } 00741 00742 00743 template<class Key, class Value> 00744 inline PStream& operator<<(PStream& out, const hash_map<Key, Value>& m) 00745 { writeMap(out, m); return out; } 00746 00747 template<class Key, class Value> 00748 inline PStream& operator>>(PStream& in, hash_map<Key, Value>& m) 00749 { readMap(in, m); return in; } 00750 00751 template<class Key, class Value> 00752 inline PStream& operator<<(PStream& out, const hash_multimap<Key, Value>& m) 00753 { writeMap(out, m); return out; } 00754 00755 template<class Key, class Value> 00756 inline PStream& operator>>(PStream& in, hash_multimap<Key, Value>& m) 00757 { readMap(in, m); return in; } 00758 00759 00761 /* These methods are there only to simplify the writing of operator<< and operator>> and 00762 should not be called by user code directly */ 00763 00764 template<class Iterator> 00765 void binwrite_(PStream& out, Iterator& it, unsigned int n) 00766 { 00767 PStream::mode_t outmode = out.outmode; // store previous outmode 00768 if(outmode!=PStream::raw_binary && outmode!=PStream::plearn_binary) 00769 out.outmode = PStream::plearn_binary; 00770 while(n--) 00771 { 00772 out << *it; 00773 ++it; 00774 } 00775 out.outmode = outmode; // restore previous outmode 00776 } 00777 00778 inline void binwrite_(PStream& out, const bool* x, unsigned int n) 00779 { 00780 while(n--) 00781 { 00782 if(*x++) 00783 out.put('1'); 00784 else 00785 out.put('0'); 00786 } 00787 } 00788 00789 inline void binwrite_(PStream& out, const char* x, unsigned int n) 00790 { out.write((char*)x, n*sizeof(char)); } 00791 inline void binwrite_(PStream& out, char* x, unsigned int n) 00792 { out.write((char*)x, n*sizeof(char)); } 00793 00794 inline void binwrite_(PStream& out, const signed char* x, unsigned int n) 00795 { out.write((char*)x, n*sizeof(signed char)); } 00796 inline void binwrite_(PStream& out, signed char* x, unsigned int n) 00797 { out.write((char*)x, n*sizeof(signed char)); } 00798 00799 inline void binwrite_(PStream& out, const unsigned char* x, unsigned int n) 00800 { out.write((char*)x, n*sizeof(unsigned char)); } 00801 inline void binwrite_(PStream& out, unsigned char* x, unsigned int n) 00802 { out.write((char*)x, n*sizeof(unsigned char)); } 00803 00804 inline void binwrite_(PStream& out, const short* x, unsigned int n) 00805 { out.write((char*)x, n*sizeof(short)); } 00806 inline void binwrite_(PStream& out, short* x, unsigned int n) 00807 { out.write((char*)x, n*sizeof(short)); } 00808 00809 inline void binwrite_(PStream& out, const unsigned short* x, unsigned int n) 00810 { out.write((char*)x, n*sizeof(unsigned short)); } 00811 inline void binwrite_(PStream& out, unsigned short* x, unsigned int n) 00812 { out.write((char*)x, n*sizeof(unsigned short)); } 00813 00814 inline void binwrite_(PStream& out, const int* x, unsigned int n) 00815 { out.write((char*)x, n*sizeof(int)); } 00816 inline void binwrite_(PStream& out, int* x, unsigned int n) 00817 { out.write((char*)x, n*sizeof(int)); } 00818 00819 inline void binwrite_(PStream& out, const unsigned int* x, unsigned int n) 00820 { out.write((char*)x, n*sizeof(unsigned int)); } 00821 inline void binwrite_(PStream& out, unsigned int* x, unsigned int n) 00822 { out.write((char*)x, n*sizeof(unsigned int)); } 00823 00824 inline void binwrite_(PStream& out, const long* x, unsigned int n) 00825 { out.write((char*)x, n*sizeof(long)); } 00826 inline void binwrite_(PStream& out, long* x, unsigned int n) 00827 { out.write((char*)x, n*sizeof(long)); } 00828 00829 inline void binwrite_(PStream& out, const unsigned long* x, unsigned int n) 00830 { out.write((char*)x, n*sizeof(unsigned long)); } 00831 inline void binwrite_(PStream& out, unsigned long* x, unsigned int n) 00832 { out.write((char*)x, n*sizeof(unsigned long)); } 00833 00834 inline void binwrite_(PStream& out, const float* x, unsigned int n) 00835 { out.write((char*)x, n*sizeof(float)); } 00836 inline void binwrite_(PStream& out, float* x, unsigned int n) 00837 { out.write((char*)x, n*sizeof(float)); } 00838 00839 inline void binwrite_(PStream& out, const double* x, unsigned int n) 00840 { out.write((char*)x, n*sizeof(double)); } 00841 inline void binwrite_(PStream& out, double* x, unsigned int n) 00842 { out.write((char*)x, n*sizeof(double)); } 00843 00844 // The typecode indicates the type and format of the elements in the stream 00845 00846 template<class Iterator> 00847 void binread_(PStream& in, Iterator it, unsigned int n, unsigned char typecode) 00848 { 00849 if(typecode!=0xFF) 00850 PLERROR("In binread_ : bug! A specialised binread_ should have been called for a typecode other than the 'generic' 0xFF"); 00851 00852 while(n--) 00853 { 00854 in >> *it; 00855 ++it; 00856 } 00857 } 00858 00859 void binread_(PStream& in, bool* x, unsigned int n, unsigned char typecode); 00860 00861 inline void binread_(PStream& in, char* x, 00862 unsigned int n, unsigned char typecode) 00863 { 00864 // big endian and little endian have the same typecodes 00865 // so we need to check only one for consistency 00866 00867 if(typecode!=TypeTraits<char>::little_endian_typecode() 00868 && typecode!=TypeTraits<unsigned char>::little_endian_typecode()) 00869 PLERROR("In binread_ incompatible typecode"); 00870 00871 in.read((char*)x, n); 00872 } 00873 00874 inline void binread_(PStream& in, signed char* x, unsigned int n, unsigned char typecode) 00875 { binread_(in, (char *)x, n, typecode); } 00876 00877 inline void binread_(PStream& in, unsigned char* x, unsigned int n, unsigned char typecode) 00878 { binread_(in, (char *)x, n, typecode); } 00879 00880 void binread_(PStream& in, short* x, unsigned int n, unsigned char typecode); 00881 void binread_(PStream& in, unsigned short* x, unsigned int n, unsigned char typecode); 00882 void binread_(PStream& in, int* x, unsigned int n, unsigned char typecode); 00883 void binread_(PStream& in, unsigned int* x, unsigned int n, unsigned char typecode); 00884 void binread_(PStream& in, long* x, unsigned int n, unsigned char typecode); 00885 void binread_(PStream& in, unsigned long* x, unsigned int n, unsigned char typecode); 00886 void binread_(PStream& in, float* x, unsigned int n, unsigned char typecode); 00887 void binread_(PStream& in, double* x, unsigned int n, unsigned char typecode); 00888 00889 00890 template<class SequenceType> 00891 void writeSequence(PStream& out, const SequenceType& seq) 00892 { 00893 // norman: added explicit cast 00894 unsigned int n = (unsigned int)seq.size(); 00895 typename SequenceType::const_iterator it = seq.begin(); 00896 00897 switch(out.outmode) 00898 { 00899 case PStream::raw_ascii: 00900 while(n--) 00901 { 00902 out << *it; 00903 out.put(' '); 00904 ++it; 00905 } 00906 break; 00907 00908 case PStream::pretty_ascii: 00909 out.write("[ "); 00910 while(n--) 00911 { 00912 out << *it; 00913 if(n>0) 00914 out.write(", "); 00915 ++it; 00916 } 00917 out.write(" ] "); 00918 break; 00919 00920 case PStream::raw_binary: 00921 binwrite_(out, it, n); 00922 break; 00923 00924 case PStream::plearn_ascii: 00925 out << n; 00926 out.write("[ "); 00927 while(n--) 00928 { 00929 out << *it; 00930 ++it; 00931 } 00932 out.write("] "); 00933 break; 00934 00935 case PStream::plearn_binary: 00936 { 00937 unsigned char typecode; 00938 if(byte_order()==LITTLE_ENDIAN_ORDER) 00939 { 00940 out.put((char)0x12); // 1D little-endian 00941 typecode = TypeTraits<typename SequenceType::value_type>::little_endian_typecode(); 00942 } 00943 else 00944 { 00945 out.put((char)0x13); // 1D big-endian 00946 typecode = TypeTraits<typename SequenceType::value_type>::big_endian_typecode(); 00947 } 00948 00949 // write typecode 00950 out.put(typecode); 00951 00952 // write length in raw_binary 00953 out.write((char*)&n, sizeof(n)); 00954 00955 // write the data 00956 binwrite_(out, it, n); 00957 } 00958 break; 00959 00960 default: 00961 PLERROR("In PStream::writeSequence(Iterator& it, int n) unknown outmode!!!!!!!!!"); 00962 break; 00963 } 00964 } 00965 00966 00968 00976 template<class SequenceType> 00977 void readSequence(PStream& in, SequenceType& seq) 00978 { 00979 switch(in.inmode) 00980 { 00981 case PStream::raw_ascii: 00982 { 00983 // norman: added explicit cast 00984 int n = (int)seq.size(); 00985 typename SequenceType::iterator it = seq.begin(); 00986 while(n--) 00987 { 00988 in >> *it; 00989 in.skipBlanks(); 00990 ++it; 00991 } 00992 } 00993 break; 00994 case PStream::raw_binary: 00995 { 00996 int n = (int)seq.size(); 00997 typename SequenceType::iterator it = seq.begin(); 00998 while(n--) 00999 { 01000 in >> *it; 01001 ++it; 01002 } 01003 } 01004 break; 01005 01006 case PStream::plearn_ascii: 01007 case PStream::plearn_binary: 01008 { 01009 in.skipBlanksAndComments(); 01010 int c = in.peek(); 01011 if(c=='[') // read until ']' 01012 { 01013 in.get(); // skip '[' 01014 in.skipBlanksAndCommentsAndSeparators(); 01015 seq.resize(0); 01016 while(in.peek()!=']' && in.peek()!=EOF && !in.eof()) 01017 { 01018 typename SequenceType::value_type x; 01019 in >> x; 01020 seq.push_back(x); 01021 in.skipBlanksAndCommentsAndSeparators(); 01022 } 01023 if (in.peek()==EOF || in.eof()) 01024 PLERROR("Reading stream, unmatched left bracket [, missing ]"); 01025 in.get(); // skip ']' 01026 } 01027 else if(isdigit(c)) 01028 { 01029 unsigned int n; 01030 in >> n; 01031 in.skipBlanksAndComments(); 01032 c = in.get(); 01033 if(c!='[') 01034 PLERROR("Error in readSequence(SequenceType& seq), expected '[', read '%c'",c); 01035 in.skipBlanksAndCommentsAndSeparators(); 01036 seq.resize((typename SequenceType::size_type) n); 01037 if (n>0) 01038 { 01039 typename SequenceType::iterator it = seq.begin(); 01040 while(n--) 01041 { 01042 in >> *it; 01043 in.skipBlanksAndCommentsAndSeparators(); 01044 ++it; 01045 } 01046 } 01047 in.skipBlanksAndCommentsAndSeparators(); 01048 c = in.get(); 01049 if(c!=']') 01050 PLERROR("Error in readSequence(SequenceType& seq), expected ']', read '%c'",c); 01051 01052 } 01053 else if(c==0x12 || c==0x13) // it's a generic binary 1D sequence 01054 { 01055 in.get(); // eat c 01056 unsigned char typecode = in.get(); 01057 unsigned int l; 01058 in.read((char*)&l,sizeof(l)); 01059 01060 bool inverted_byte_order = ( (c==0x12 && byte_order()==BIG_ENDIAN_ORDER) 01061 || (c==0x13 && byte_order()==LITTLE_ENDIAN_ORDER) ); 01062 01063 if(inverted_byte_order) 01064 endianswap(&l); 01065 seq.resize((typename SequenceType::size_type) l); 01066 binread_(in, seq.begin(), l, typecode); 01067 } 01068 else 01069 PLERROR("In readSequence(SequenceType& seq) '%c' not a proper first character in the header of a sequence!",c); 01070 } 01071 break; 01072 01073 default: 01074 PLERROR("In PStream::operator>> unknown inmode!!!!!!!!!"); 01075 break; 01076 } 01077 01078 } 01079 01080 // Default behavior for write() and read() is 01081 // to call corresponding operator<<() or operator>>() 01082 // on PStream. 01083 01084 template<class T> 01085 inline void write(ostream& out_, const T& o) 01086 { 01087 PStream out(&out_); 01088 out << o; 01089 } 01090 01091 template<class T> 01092 inline void read(istream& in_, T& o) 01093 { 01094 PStream in(&in_); 01095 in >> o; 01096 } 01097 01098 template<class T> 01099 inline void read(const string& stringval, T& x) 01100 { 01101 istringstream in_(stringval); 01102 PStream in(&in_); 01103 in >> x; 01104 } 01105 01106 01107 // STL containers: 01108 01109 template <class T> inline PStream & 01110 operator>>(PStream &in, vector<T> &v) 01111 { readSequence(in, v); return in; } 01112 01113 template <class T> inline PStream & 01114 operator<<(PStream &out, const vector<T> &v) 01115 { writeSequence(out, v); return out; } 01116 01117 // Serialization of map types 01118 01119 template<class SetT> 01120 void writeSet(PStream& out, const SetT& s) 01121 { 01122 typename SetT::const_iterator it = s.begin(); 01123 typename SetT::const_iterator itend = s.end(); 01124 01125 out.put('['); 01126 while(it!=itend) 01127 { 01128 out << *it; 01129 ++it; 01130 if (it != itend) 01131 out.write(", "); 01132 } 01133 out.put(']'); 01134 } 01135 01136 template<class SetT> 01137 void readSet(PStream& in, SetT& s) 01138 { 01139 s.clear(); 01140 in.skipBlanksAndCommentsAndSeparators(); 01141 int c = in.get(); 01142 if(c!='[') 01143 PLERROR("In readSet(Pstream& in, SetT& s) expected '[' but read %c",c); 01144 in.skipBlanksAndCommentsAndSeparators(); 01145 c = in.peek(); // do we have a ']' ? 01146 while(c!=']') 01147 { 01148 typename SetT::value_type val; 01149 in >> val; 01150 in.skipBlanksAndCommentsAndSeparators(); 01151 s.insert(val); 01152 c = in.peek(); // do we have a ']' ? 01153 } 01154 in.get(); // eat the ']' 01155 } 01156 01157 template <class T> inline PStream & 01158 operator>>(PStream &in, set<T> &v) 01159 { readSet(in, v); return in; } 01160 01161 template <class T> inline PStream & 01162 operator<<(PStream &out, const set<T> &v) 01163 { writeSet(out, v); return out; } 01164 01165 01166 01167 // **************************************** 01168 // *** Generic save and load operations *** 01169 // **************************************** 01170 01171 template <class T> 01172 inline void load(const string &filepath, T &x) 01173 { 01174 ifstream in_(filepath.c_str()); 01175 if (!in_) 01176 PLERROR("Could not open file \"%s\" for reading", filepath.c_str()); 01177 PStream in(&in_); 01178 in >> x; 01179 } 01180 01182 template<class T> 01183 inline void save(const string& filepath, const T& x) 01184 { 01185 force_mkdir_for_file(filepath); 01186 01187 ofstream out_(filepath.c_str()); 01188 if(!out_) 01189 PLERROR("Could not open file %s for writing",filepath.c_str()); 01190 01191 PStream out(&out_); 01192 out << x; 01193 } 01194 01195 01196 // **** Useful PStream classes... **** 01197 // (these can be used similarly to ifstream, ofstream...) 01198 01199 class PIFStream: public PStream 01200 { 01201 public: 01202 PIFStream(const string& fname, ios_base::openmode m = ios_base::in) 01203 :PStream(new ifstream(fname.c_str()),true) 01204 {} 01205 }; 01206 01207 class POFStream: public PStream 01208 { 01209 public: 01210 POFStream(const string& fname, ios_base::openmode m = ios_base::out | ios_base::trunc) 01211 :PStream(new ofstream(fname.c_str()),true) 01212 {} 01213 }; 01214 01215 01216 // NOTE: This should ultimately be replaced by istringstream when we finally get rid of buggy gcc 2.96 01217 // or even better: our own version of the streambuf when we finally get rid of those annoying buggy C++ streams implementations. 01218 // So for now, consider this a "hack" (Pascal) 01219 01220 class PIStringStream: public PStream 01221 { 01222 public: 01223 PIStringStream(const string& s) 01224 :PStream(new istringstream(s)) {} 01225 }; 01226 01227 01228 } // namespace PLearn 01229 01230 #endif //ndef PStream_INC

Generated on Tue Aug 17 16:03:17 2004 for PLearn by doxygen 1.3.7