PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PStream.h 00004 // Copyright (C) 1998 Pascal Vincent 00005 // Copyright (C) 1999-2001 Pascal Vincent, Yoshua Bengio and 00006 // University of Montreal 00007 // Copyright (C) 2002 Frederic Morin, Xavier Saint-Mleux, Pascal Vincent 00008 // Copyright (C) 2007 Xavier Saint-Mleux, ApSTAT Technologies inc. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are met: 00012 // 00013 // 1. Redistributions of source code must retain the above copyright 00014 // notice, this list of conditions and the following disclaimer. 00015 // 00016 // 2. Redistributions in binary form must reproduce the above copyright 00017 // notice, this list of conditions and the following disclaimer in the 00018 // documentation and/or other materials provided with the distribution. 00019 // 00020 // 3. The name of the authors may not be used to endorse or promote 00021 // products derived from this software without specific prior written 00022 // permission. 00023 // 00024 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00025 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00026 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00027 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00028 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00029 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00030 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00031 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00032 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 // 00035 // This file is part of the PLearn library. For more information on the PLearn 00036 // library, go to the PLearn Web site at www.plearn.org 00037 00038 #ifndef PStream_INC 00039 #define PStream_INC 00040 00044 #define PSTREAM_BUF_SIZE 100 00045 00046 #include <map> 00047 #include <set> 00048 #include <sstream> 00049 #include <fstream> 00050 #include <limits> 00051 #include <plearn/base/byte_order.h> 00052 #include <plearn/base/pl_hash_fun.h> 00053 #include <plearn/base/plerror.h> 00054 #include <plearn/base/pl_stdint.h> 00055 #include "PStream_util.h" 00056 #include "PStreamBuf.h" 00057 #include "StdPStreamBuf.h" 00058 00059 namespace PLearn { 00060 00061 using namespace std; 00062 00063 00064 // for readBinaryNumAs 00065 template<bool x> struct chkUnsigned 00066 { template<class I> static bool notOk(I& y) { return false; } }; 00067 template<> struct chkUnsigned<true> 00068 { template<class I> static bool notOk(I& y) { return y<0; } }; 00069 00070 00088 class PStream : public PP<PStreamBuf> 00089 { 00090 public: 00092 typedef PStream& (*pl_pstream_manip)(PStream&); 00093 00094 private: 00095 00096 typedef PP<PStreamBuf> inherited; 00097 typedef PStreamBuf streambuftype; 00098 00099 public: 00100 00101 // norman: check for win32 00102 #if __GNUC__ < 3 && !defined(WIN32) 00103 00104 typedef int streamsize; 00105 typedef ios ios_base; 00106 #endif 00107 00113 enum mode_t 00114 { 00116 plearn_ascii, 00118 plearn_binary, 00121 raw_ascii, 00123 raw_binary, 00126 pretty_ascii 00127 }; 00128 00129 00133 enum compr_mode_t { 00135 compr_none, 00137 compr_double_as_float, 00139 compr_sparse, 00141 compr_lossy_sparse 00142 }; 00143 00144 public: 00146 mode_t inmode; 00147 00149 // bitset<32> pl_stream_flags_in; 00150 00152 map<unsigned int, void *> copies_map_in; 00153 00155 mode_t outmode; 00156 00158 // bitset<32> pl_stream_flags_out; 00159 00161 map<void *, unsigned int> copies_map_out; 00162 00163 private: 00165 const char* format_float; 00166 00168 const char* format_double; 00169 00171 static const char* format_float_default; 00172 00174 static const char* format_double_default; 00175 00176 public: 00180 bool implicit_storage; 00181 00183 compr_mode_t compression_mode; 00184 00187 bool remote_plearn_comm; 00188 00190 static bool windows_endl; 00191 public: 00192 00193 PStream(); 00194 00196 PStream(streambuftype* sb); 00197 00199 PStream(istream* pin_, bool own_pin_=false); 00200 00202 PStream(ostream* pout_, bool own_pout_=false); 00203 00205 PStream(iostream* pios_, bool own_pios_=false); 00206 00208 PStream(istream* pin_, ostream* pout_, bool own_pin_=false, 00209 bool own_pout_=false); 00210 00212 00214 virtual ~PStream(); 00215 00216 inline void setBufferCapacities(streamsize inbuf_capacity, 00217 streamsize outbuf_capacity, 00218 streamsize unget_capacity) 00219 { 00220 ptr->setBufferCapacities(inbuf_capacity, 00221 outbuf_capacity, 00222 unget_capacity); 00223 } 00224 00225 inline mode_t setInMode(mode_t m) 00226 { 00227 mode_t oldmode = inmode; 00228 inmode = m; 00229 return oldmode; 00230 } 00231 00232 inline mode_t setOutMode(mode_t m) 00233 { 00234 mode_t oldmode = outmode; 00235 outmode = m; 00236 return oldmode; 00237 } 00238 00239 inline void setMode(mode_t m) 00240 { inmode = m; outmode = m; } 00241 00242 inline void clearOutMap() 00243 { copies_map_out.clear(); } 00244 00245 inline void clearInMap() 00246 { copies_map_in.clear(); } 00247 00248 inline void clearInOutMaps() 00249 { 00250 clearInMap(); 00251 clearOutMap(); 00252 } 00253 00258 mode_t switchToPLearnOutMode(); 00259 00260 PStream& operator>>(mode_t m) 00261 { 00262 inmode = m; 00263 return *this; 00264 } 00265 00266 PStream& operator<<(mode_t m) 00267 { 00268 outmode = m; 00269 return *this; 00270 } 00271 00273 static PStream::mode_t parseModeT(const string& str); 00274 00275 public: 00276 //op()'s: re-init with different underlying stream(s) 00277 00278 PStream& operator=(const PStream& pios); 00279 00280 PStream& operator=(streambuftype* streambuf) 00281 { 00282 inherited::operator=(streambuf); 00283 return *this; 00284 } 00285 00286 bool operator==(const PStream& other) 00287 { return PP<PStreamBuf>::operator==(other); } 00288 00289 00290 void writeAsciiNum(char x); 00291 void writeAsciiNum(unsigned char x); 00292 void writeAsciiNum(signed char x); 00293 void writeAsciiNum(short x); 00294 void writeAsciiNum(unsigned short x); 00295 void writeAsciiNum(int x); 00296 void writeAsciiNum(unsigned int x); 00297 void writeAsciiNum(long x); 00298 void writeAsciiNum(unsigned long x); 00299 void writeAsciiNum(long long x); 00300 void writeAsciiNum(unsigned long long x); 00301 void writeAsciiNum(float x); 00302 void writeAsciiNum(double x); 00303 00304 void readAsciiNum(char &x); 00305 void readAsciiNum(unsigned char &x); 00306 void readAsciiNum(signed char &x); 00307 void readAsciiNum(short &x); 00308 void readAsciiNum(unsigned short &x); 00309 void readAsciiNum(int &x); 00310 void readAsciiNum(unsigned int &x); 00311 void readAsciiNum(long &x); 00312 void readAsciiNum(unsigned long &x); 00313 void readAsciiNum(long long &x); 00314 void readAsciiNum(unsigned long long &x); 00315 void readAsciiNum(float &x); 00316 void readAsciiNum(double &x); 00317 00319 void writeAsciiHexNum(unsigned char x); 00320 00323 template<class I> 00324 void writeBinaryNum(I x) 00325 { 00326 #ifdef BIGENDIAN 00327 put(TypeTraits<I>::big_endian_typecode()); 00328 #else 00329 put(TypeTraits<I>::little_endian_typecode()); 00330 #endif 00331 write((char*)&x, sizeof(I)); 00332 } 00333 00335 template<class I, class J> 00336 void readBinaryNumAs(J& x, bool inverted_byte_order) 00337 { 00338 I y; 00339 read(reinterpret_cast<char*>(&y), sizeof(I)); 00340 if (inverted_byte_order) 00341 endianswap(&y); 00342 #ifdef __INTEL_COMPILER 00343 #pragma warning(disable:1682) 00344 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 00345 // integral type (potential portability problem)", but the conversion is 00346 // explicit here. 00347 #endif 00348 x = static_cast<J>(y); 00349 00350 // Check if there was a conversion problem (sign or overflow) 00351 00352 if (static_cast<I>(x) != y 00353 || (!(numeric_limits<J>::is_signed) 00354 && chkUnsigned<numeric_limits<I>::is_signed>::notOk(y))) 00355 { 00356 std::stringstream error; 00357 error << "In PStream::readBinaryNumAs, overflow error: " << std::endl 00358 << "unable to read value \"" << y << "\"" 00359 << "into a " << TypeTraits<I>::name() << std::endl; 00360 00361 PLERROR( error.str().c_str() ); 00362 } 00363 #ifdef __INTEL_COMPILER 00364 #pragma warning(default:1682) 00365 #endif 00366 } 00367 00369 template<class I> 00370 void readBinaryNum(I &x, unsigned char typecode) 00371 { 00372 // If typecode corresponds to I's typecode 00373 if (typecode==TypeTraits<I>::little_endian_typecode()) 00374 { 00375 read(reinterpret_cast<char*>(&x), sizeof(I)); 00376 #ifdef BIGENDIAN 00377 endianswap(&x); 00378 #endif 00379 } 00380 else if (typecode==TypeTraits<I>::big_endian_typecode()) 00381 { 00382 read(reinterpret_cast<char*>(&x), sizeof(I)); 00383 #ifdef LITTLEENDIAN 00384 endianswap(&x); 00385 #endif 00386 } 00387 // Else, we need to try all the different types 00388 else if (typecode==TypeTraits<int8_t>::little_endian_typecode()) 00389 readBinaryNumAs<int8_t>(x, false); 00390 else if (typecode==TypeTraits<uint8_t>::little_endian_typecode()) 00391 readBinaryNumAs<uint8_t>(x, false); 00392 else if (typecode==TypeTraits<int16_t>::little_endian_typecode()) 00393 readBinaryNumAs<int16_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00394 else if (typecode==TypeTraits<int16_t>::big_endian_typecode()) 00395 readBinaryNumAs<int16_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00396 else if (typecode==TypeTraits<uint16_t>::little_endian_typecode()) 00397 readBinaryNumAs<uint16_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00398 else if (typecode==TypeTraits<uint16_t>::big_endian_typecode()) 00399 readBinaryNumAs<uint16_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00400 else if (typecode==TypeTraits<int32_t>::little_endian_typecode()) 00401 readBinaryNumAs<int32_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00402 else if (typecode==TypeTraits<int32_t>::big_endian_typecode()) 00403 readBinaryNumAs<int32_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00404 else if (typecode==TypeTraits<uint32_t>::little_endian_typecode()) 00405 readBinaryNumAs<uint32_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00406 else if (typecode==TypeTraits<uint32_t>::big_endian_typecode()) 00407 readBinaryNumAs<uint32_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00408 else if (typecode==TypeTraits<int64_t>::little_endian_typecode()) 00409 readBinaryNumAs<int64_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00410 else if (typecode==TypeTraits<int64_t>::big_endian_typecode()) 00411 readBinaryNumAs<int64_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00412 else if (typecode==TypeTraits<uint64_t>::little_endian_typecode()) 00413 readBinaryNumAs<uint64_t>(x, byte_order()==BIG_ENDIAN_ORDER); 00414 else if (typecode==TypeTraits<uint64_t>::big_endian_typecode()) 00415 readBinaryNumAs<uint64_t>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00416 else if (typecode==TypeTraits<float>::little_endian_typecode()) 00417 readBinaryNumAs<float>(x, byte_order()==BIG_ENDIAN_ORDER); 00418 else if (typecode==TypeTraits<float>::big_endian_typecode()) 00419 readBinaryNumAs<float>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00420 else if (typecode==TypeTraits<double>::little_endian_typecode()) 00421 readBinaryNumAs<double>(x, byte_order()==BIG_ENDIAN_ORDER); 00422 else if (typecode==TypeTraits<double>::big_endian_typecode()) 00423 readBinaryNumAs<double>(x, byte_order()==LITTLE_ENDIAN_ORDER); 00424 else 00425 PLERROR("In PStream readBinaryNum: Unknown typecode '%c' (%x)", 00426 typecode, typecode); 00427 } 00428 00429 inline bool eof() const 00430 { return ptr->eof(); } 00431 00432 bool good() const 00433 { return ptr && ptr->good(); } 00434 00435 /***** 00436 * DEPRECATED: this implicit conversion is too dangerous! 00437 * use .good() instead. 00438 operator bool() const 00439 { return good(); } 00440 */ 00441 /***** 00442 * operator void*() causes a compile error ON PURPOSE! (ambiguous w/ PP<T>::operator T*()) 00443 * The implicit conversion of a PStream to a bool or pointer is 00444 * too dangerous to be allowed; please use PStream::good() (or PP<T>::isNotNull()) instead. 00445 * EXAMPLE of a flawed conversion to bool: 00446 * enum Machin { Truc, Bidule }; 00447 * Machin mon_machin; 00448 * pin >> mon_machin; // OOPS!!! converts pin to bool and applies operator>>(int,int), a shift... 00449 */ operator void*() const // DO NOT USE IT; FAILS ON PURPOSE! 00451 { PLERROR("!?! this should have failed at compile time !?!"); return 0; } 00452 00454 // This operator is required for compilation under Visual C++. 00455 bool operator !() const 00456 { return !good(); } 00457 00465 const char* getFloatFormat() const { return format_float; } 00466 const char* getDoubleFormat() const { return format_double; } 00467 void setFloatFormat(const char* f) { format_float = f; } 00468 void setDoubleFormat(const char* f) { format_double = f; } 00469 00473 inline int get() 00474 { return ptr->get(); } 00475 00477 inline PStream& get(char& c) 00478 { 00479 c = (char)ptr->get(); 00480 return *this; 00481 } 00482 00484 inline PStream& getline(string& line, char delimitor='\n') 00485 { 00486 line.clear(); 00487 int c = get(); 00488 while (c != EOF && c != delimitor) 00489 { 00490 line += (char)c; 00491 c = get(); 00492 } 00493 return *this; 00494 } 00495 00496 inline string getline() 00497 { string s; getline(s); return s; } 00498 00502 inline int peek() 00503 { return ptr->peek(); } 00504 00506 inline PStream& putback(char c) 00507 { 00508 ptr->putback(c); 00509 return *this; 00510 } 00511 00515 inline PStream& unget() 00516 { 00517 ptr->unget(); 00518 return *this; 00519 } 00520 00521 inline PStream& unread(const char* p, streamsize n) 00522 { 00523 ptr->unread(p,n); 00524 return *this; 00525 } 00526 00527 inline PStream& unread(const char* p) 00528 { return unread(p, streamsize(strlen(p))); } 00529 00530 inline PStream& unread(const string& s) 00531 { return unread(s.data(), streamsize(s.length())); } 00532 00533 00534 inline PStream& read(char* s, streamsize n) 00535 { 00536 ptr->read(s,n); 00537 return *this; 00538 } 00539 00540 inline PStream& read(string& s, streamsize n) 00541 { 00542 char* buf = new char[n]; 00543 string::size_type nread = ptr->read(buf, n); 00544 s.assign(buf, nread); 00545 delete[] buf; 00546 return *this; 00547 } 00548 00550 string readAll(); 00551 00554 void readExpected(char expect); 00555 00560 void readExpected(char* expect); 00561 00565 void readExpected(const string& expect); 00566 00572 streamsize readUntil(char* buf, streamsize n, char stop_char); 00573 00579 streamsize readUntil(char* buf, streamsize n, const char* stop_chars); 00580 00581 inline PStream& write(const char* s, streamsize n) 00582 { 00583 ptr->write(s,n); 00584 return *this; 00585 } 00586 00587 inline PStream& put(char c) 00588 { 00589 ptr->put(c); 00590 return *this; 00591 } 00592 00593 inline PStream& put(unsigned char c) 00594 { 00595 write(reinterpret_cast<char *>(&c), sizeof(c)); 00596 return *this; 00597 } 00598 inline PStream& put(int x) { return put((char)x); } 00599 00600 inline PStream& flush() 00601 { 00602 ptr->flush(); 00603 return *this; 00604 } 00605 00606 inline PStream& endl() 00607 { 00608 if(windows_endl) 00609 put('\r'); 00610 put('\n'); 00611 flush(); 00612 return *this; 00613 } 00614 00615 // These are convenient method for writing raw strings 00616 // (whatever the outmode): 00617 inline PStream& write(const char* s) 00618 { 00619 write(s, streamsize(strlen(s))); 00620 return *this; 00621 } 00622 00623 inline PStream& write(const string& s) 00624 { 00625 write(s.data(), streamsize(s.length())); 00626 return *this; 00627 } 00628 00629 // Useful skip functions 00630 00632 void skipRestOfLine(); 00633 00635 void skipBlanks(); 00636 00638 void skipBlanksAndComments(); 00639 00641 void skipBlanksAndCommentsAndSeparators(); 00642 00644 void skipAll(const char* chars_to_skip); 00645 00657 int smartReadUntilNext(const string& stoppingsymbols, 00658 string& characters_read, 00659 bool ignore_brackets=false, 00660 bool skip_comments=true); 00661 00663 int count(char c); 00664 00665 // operator>>'s for base types 00666 PStream& operator>>(float &x); 00667 PStream& operator>>(double &x); 00668 PStream& operator>>(string &x); 00669 // read string in already allocated char[] 00670 PStream& operator>>(char* x); 00671 PStream& operator>>(char &x); 00672 PStream& operator>>(signed char &x); 00673 PStream& operator>>(unsigned char &x); 00674 PStream& operator>>(bool &x); 00675 PStream& operator>>(short &x); 00676 PStream& operator>>(unsigned short &x); 00677 PStream& operator>>(int &x); 00678 PStream& operator>>(unsigned int &x); 00679 PStream& operator>>(long &x); 00680 PStream& operator>>(unsigned long &x); 00681 PStream& operator>>(long long &x); 00682 PStream& operator>>(unsigned long long &x); 00683 PStream& operator>>(pl_pstream_manip func) 00684 { return (*func)(*this); } 00685 00686 // operator<<'s for base types 00687 PStream& operator<<(float x); 00688 PStream& operator<<(double x); 00689 00692 PStream& operator<<(const char *x); 00693 00695 PStream& operator<<(const void *x); 00696 00700 PStream& operator<<(const string &x); 00701 00702 PStream& operator<<(char x); 00703 PStream& operator<<(signed char x); 00704 PStream& operator<<(unsigned char x); 00705 00706 // Note: If you get mysterious mesages of problems with const bool 00707 // resolutions, then a workaround might be to not declare <<(bool) as a 00708 // method, but as an inline function 00709 PStream& operator<<(bool x); 00710 PStream& operator<<(short x); 00711 PStream& operator<<(unsigned short x); 00712 PStream& operator<<(int x); 00713 PStream& operator<<(unsigned int x); 00714 PStream& operator<<(long x); 00715 PStream& operator<<(unsigned long x); 00716 PStream& operator<<(long long x); 00717 PStream& operator<<(unsigned long long x); 00718 PStream& operator<<(pl_pstream_manip func) { return (*func)(*this); } 00719 00720 }; 00721 00723 PStream& get_pin(); 00724 PStream& get_pout(); 00725 PStream& get_pio(); 00726 PStream& get_perr(); 00727 PStream& get_pnull(); 00728 00729 00730 extern PStream pin; 00731 extern PStream pout; 00732 extern PStream pio; 00733 extern PStream perr; 00734 extern PStream pnull; 00735 00736 // Simulation of <<flush <<endl and >>ws ... 00737 00738 extern PStream& flush(PStream& out); 00739 extern PStream& endl(PStream& out); 00740 extern PStream& ws(PStream& out); 00741 00742 // But inject the standard ones as well to keep them usable!!! 00743 using std::flush; 00744 using std::endl; 00745 using std::ws; 00746 00749 string pgetline(PStream& in); 00750 00751 00752 /***** 00753 * op>> & op<< for generic pointers 00754 */ 00755 00756 template <class T> 00757 inline PStream& operator>>(PStream& in, T*& x) 00758 { 00759 00760 in.skipBlanksAndCommentsAndSeparators(); 00761 if (in.peek() == '*') 00762 { 00763 in.get(); // Eat '*' 00764 unsigned int id; 00765 in >> id; 00766 // don't skip blanks before we need to read something else 00767 // (read might block). 00768 //in.skipBlanksAndCommentsAndSeparators(); 00769 if (id==0) 00770 x = 0; 00771 else 00772 { 00773 in.skipBlanksAndCommentsAndSeparators(); 00774 if (in.peek() == '-') 00775 { 00776 in.get(); // Eat '-' 00777 char cc = in.get(); 00778 if(cc != '>') // Eat '>' 00779 PLERROR("In PStream::operator>>(T*&) Wrong format. Expecting \"*%d->\" but got \"*%d-%c\".", id, id, cc); 00780 // don't skip blanks before we need to read something else 00781 // (read might block). 00782 //in.skipBlanksAndCommentsAndSeparators(); 00783 if(!x) 00784 x = new T(); 00785 in.skipBlanksAndCommentsAndSeparators(); 00786 in >> *x; 00787 // don't skip blanks before we need to read something else 00788 // (read might block). 00789 //in.skipBlanksAndCommentsAndSeparators(); 00790 in.copies_map_in[id]= x; 00791 } 00792 else 00793 { 00794 // Find it in map and return ptr; 00795 map<unsigned int, void *>::iterator it = 00796 in.copies_map_in.find(id); 00797 if (it == in.copies_map_in.end()) 00798 PLERROR("In PStream::operator>>(T*&) object (ptr) to be read with id='%d' " 00799 "has not been previously defined", id); 00800 x = static_cast<T *>(it->second); 00801 } 00802 } 00803 } 00804 else 00805 { 00806 in >> *x; 00807 // don't skip blanks before we need to read something else 00808 // (read might block). 00809 //in.skipBlanksAndCommentsAndSeparators(); 00810 } 00811 00812 return in; 00813 } 00814 00815 00816 template <class T> 00817 inline PStream& operator<<(PStream& out, T const * const & x) 00818 { 00819 if(x) 00820 { 00821 map<void *, unsigned int>::iterator it = 00822 out.copies_map_out.find(const_cast<T*&>(x)); 00823 if (it == out.copies_map_out.end()) 00824 { 00825 int id = (int)out.copies_map_out.size()+1; 00826 out.put('*'); 00827 out << id; 00828 out.write("->"); 00829 out.copies_map_out[const_cast<T*&>(x)] = id; 00830 out << *x; 00831 } 00832 else 00833 { 00834 out.put('*'); 00835 out << it->second; 00836 out.put(' '); 00837 } 00838 } 00839 else 00840 out.write("*0 "); 00841 return out; 00842 } 00843 00844 template <class T> 00845 inline PStream& operator>>(PStream& in, const T*& x) 00846 { 00847 PLERROR("operator>>(PStream&, const T*&) should never be used! (object pointed is const)"); 00848 return in; 00849 } 00850 00851 template <class T> 00852 inline PStream& operator>>(PStream& in, PP<T> &o) 00853 { 00854 T *ptr; 00855 if (o.isNull()) 00856 ptr = 0; 00857 else 00858 ptr = o; 00859 in >> ptr; 00860 o = ptr; 00861 return in; 00862 } 00863 00864 template <class T> 00865 inline PStream& operator<<(PStream& out, const PP<T> &o) 00866 { 00867 T *ptr = static_cast<T *>(o); 00868 out << const_cast<const T * &>(ptr); 00869 return out; 00870 } 00871 00872 template <class T> 00873 inline PStream& operator<<(PStream& out, T*& ptr) 00874 { 00875 out << const_cast<T const * const &>(ptr); 00876 return out; 00877 } 00878 00879 00880 // Serialization of pairs in the form: 00881 // first : second 00882 00883 template<class A,class B> 00884 inline PStream& operator<<(PStream& out, const pair<A,B>& x) 00885 { 00886 // new format (same as for tuple) 00887 out.put('('); 00888 out << x.first; 00889 out.write(", "); 00890 out << x.second; 00891 out.put(')'); 00892 00893 #if 0 00894 // old deprecated format 00895 switch(out.outmode) 00896 { 00897 case PStream::raw_ascii: 00898 case PStream::pretty_ascii: 00899 case PStream::plearn_ascii: 00900 out << x.first; 00901 out.write(": "); 00902 out << x.second; 00903 out.put(' '); 00904 break; 00905 case PStream::plearn_binary: 00906 out.put((char)0x16); 00907 out << x.first << x.second; 00908 break; 00909 default: 00910 PLERROR("PStream mode not supported"); 00911 } 00912 #endif 00913 00914 return out; 00915 } 00916 00917 template <typename S, typename T> 00918 inline PStream& operator>>(PStream& in, pair<S, T> &x) 00919 { 00920 in.skipBlanksAndCommentsAndSeparators(); 00921 int c = in.peek(); 00922 if(c==0x16) // binary pair 00923 { 00924 in.get(); // eat the header byte 00925 in >> x.first >> x.second; 00926 } 00927 else if(c=='(') // it's the parenthesized (first, second) format 00928 { 00929 in.get(); 00930 in.skipBlanksAndComments(); 00931 in >> x.first; 00932 in.skipBlanksAndCommentsAndSeparators(); 00933 in >> x.second; 00934 in.skipBlanksAndComments(); 00935 in.readExpected(')'); 00936 } 00937 else // suppose it's ascii, separated by : 00938 { 00939 in >> x.first; 00940 in.skipBlanksAndComments(); 00941 if(in.get()!=':'){ 00942 //we can't use NORMAL_LOG as can't include pl_log.h 00943 // can't include pl_log.h as it include PStream.h 00944 // and PStream.h would include pl_log.h(recursive include) 00945 //idem for tostring.h 00946 perr<<"For the following error, the first half of the pair is '"<<x.first<<"'"<<endl; 00947 PLERROR("In operator>>(PStream& in, pair<S, T> &x) expected ':' to separate the 2 halves of the pair"); 00948 } 00949 in.skipBlanksAndComments(); 00950 in >> x.second; 00951 } 00952 return in; 00953 } 00954 00955 00956 // Serialization of map types 00957 00958 template<class MapT> 00959 void writeMap(PStream& out, const MapT& m) 00960 { 00961 typename MapT::const_iterator it = m.begin(); 00962 typename MapT::const_iterator itend = m.end(); 00963 00964 // PStream::mode_t curmode = out.switchToPLearnOutMode(); 00965 00966 out.put('{'); 00967 if(!m.empty()) 00968 { 00969 // write the first item 00970 out << it->first; 00971 out.write(": "); 00972 out << it->second; 00973 ++it; 00974 while(it!=itend) 00975 { 00976 out.write(", "); 00977 out << it->first; 00978 out.write(": "); 00979 out << it->second; 00980 ++it; 00981 } 00982 } 00983 out.put('}'); 00984 00985 // out.setOutMode(curmode); 00986 } 00987 00988 template<class MapT> 00989 void readMap(PStream& in, MapT& m) 00990 { 00991 m.clear(); 00992 in.skipBlanksAndCommentsAndSeparators(); 00993 int c = in.get(); 00994 if(c!='{') 00995 PLERROR("In readMap(Pstream& in, MapT& m) expected '{' but read %c",c); 00996 in.skipBlanksAndCommentsAndSeparators(); 00997 c = in.peek(); // do we have a '}' ? 00998 while(c!='}') 00999 { 01000 pair<typename MapT::key_type, typename MapT::mapped_type> val; 01001 in >> val.first; 01002 in.skipBlanksAndCommentsAndSeparators(); 01003 c = in.get(); 01004 if(c!=':') 01005 PLERROR("In readMap(Pstream& in, MapT& m) separator between key and value must be ':', but I read a '%c'",c); 01006 in.skipBlanksAndCommentsAndSeparators(); 01007 in >> val.second; 01008 m.insert(val); 01009 in.skipBlanksAndCommentsAndSeparators(); 01010 c = in.peek(); // do we have a '}' ? 01011 } 01012 in.get(); // eat the '}' 01013 } 01014 01015 inline PStream& operator>>(PStream& in, CopiesMap&) 01016 { 01017 PLERROR("PLearn::CopiesMap cannot be serialized."); 01018 return in; 01019 } 01020 inline PStream& operator<<(PStream& out, const CopiesMap&) 01021 { 01022 PLERROR("PLearn::CopiesMap cannot be [un]serialized."); 01023 return out; 01024 } 01025 01026 template<class Key, class Value, class Compare, class Alloc> 01027 inline PStream& operator<<(PStream& out, 01028 const map<Key, Value, Compare, Alloc>& m) 01029 { 01030 writeMap(out, m); 01031 return out; 01032 } 01033 01034 template<class Key, class Value, class Compare, class Alloc> 01035 inline PStream& operator>>(PStream& in, map<Key, Value, Compare, Alloc>& m) 01036 { 01037 readMap(in, m); 01038 return in; 01039 } 01040 01041 template<class Key, class Value, class Compare, class Alloc> 01042 inline PStream& operator<<(PStream& out, 01043 const multimap<Key, Value, Compare, Alloc>& m) 01044 { 01045 writeMap(out, m); 01046 return out; 01047 } 01048 01049 template<class Key, class Value, class Compare, class Alloc> 01050 inline PStream& operator>>(PStream& in, 01051 multimap<Key, Value, Compare, Alloc>& m) 01052 { 01053 readMap(in, m); 01054 return in; 01055 } 01056 01057 01058 template<class Key, class Value, class Compare, class Alloc> 01059 inline PStream& operator<<(PStream& out, 01060 const hash_map<Key, Value, Compare, Alloc>& m) 01061 { 01062 writeMap(out, m); 01063 return out; 01064 } 01065 01066 template<class Key, class Value, class Compare, class Alloc> 01067 inline PStream& operator>>(PStream& in, 01068 hash_map<Key, Value, Compare, Alloc>& m) 01069 { 01070 readMap(in, m); 01071 return in; 01072 } 01073 01074 template<class Key, class Value, class Compare, class Alloc> 01075 inline PStream& operator<<(PStream& out, 01076 const hash_multimap<Key, Value, Compare, Alloc>& m) 01077 { 01078 writeMap(out, m); 01079 return out; 01080 } 01081 01082 template<class Key, class Value, class Compare, class Alloc> 01083 inline PStream& operator>>(PStream& in, 01084 hash_multimap<Key, Value, Compare, Alloc>& m) 01085 { 01086 readMap(in, m); 01087 return in; 01088 } 01089 01090 01092 /* These methods are there only to simplify the writing of operator<< and 01093 operator>> and should not be called by user code directly */ 01094 01095 template<class Iterator> 01096 void binwrite_(PStream& out, Iterator it, unsigned int n) 01097 { 01098 PStream::mode_t outmode = out.outmode; // store previous outmode 01099 if(outmode!=PStream::raw_binary && outmode!=PStream::plearn_binary) 01100 out.outmode = PStream::plearn_binary; 01101 while(n--) 01102 { 01103 out << *it; 01104 ++it; 01105 } 01106 out.outmode = outmode; // restore previous outmode 01107 } 01108 01109 inline void binwrite_(PStream& out, const bool* x, unsigned int n) 01110 { 01111 while(n--) 01112 { 01113 if(*x++) 01114 out.put('1'); 01115 else 01116 out.put('0'); 01117 } 01118 } 01119 01120 inline void binwrite_(PStream& out, const char* x, unsigned int n) 01121 { out.write((char*)x, streamsize(n*sizeof(char))); } 01122 inline void binwrite_(PStream& out, char* x, unsigned int n) 01123 { out.write((char*)x, streamsize(n*sizeof(char))); } 01124 01125 inline void binwrite_(PStream& out, const signed char* x, unsigned int n) 01126 { out.write((char*)x, streamsize(n*sizeof(signed char))); } 01127 inline void binwrite_(PStream& out, signed char* x, unsigned int n) 01128 { out.write((char*)x, streamsize(n*sizeof(signed char))); } 01129 01130 inline void binwrite_(PStream& out, const unsigned char* x, unsigned int n) 01131 { out.write((char*)x, streamsize(n*sizeof(unsigned char))); } 01132 inline void binwrite_(PStream& out, unsigned char* x, unsigned int n) 01133 { out.write((char*)x, streamsize(n*sizeof(unsigned char))); } 01134 01135 inline void binwrite_(PStream& out, const short* x, unsigned int n) 01136 { out.write((char*)x, streamsize(n*sizeof(short))); } 01137 inline void binwrite_(PStream& out, short* x, unsigned int n) 01138 { out.write((char*)x, streamsize(n*sizeof(short))); } 01139 01140 inline void binwrite_(PStream& out, const unsigned short* x, unsigned int n) 01141 { out.write((char*)x, streamsize(n*sizeof(unsigned short))); } 01142 inline void binwrite_(PStream& out, unsigned short* x, unsigned int n) 01143 { out.write((char*)x, streamsize(n*sizeof(unsigned short))); } 01144 01145 inline void binwrite_(PStream& out, const int* x, unsigned int n) 01146 { out.write((char*)x, streamsize(n*sizeof(int))); } 01147 inline void binwrite_(PStream& out, int* x, unsigned int n) 01148 { out.write((char*)x, streamsize(n*sizeof(int))); } 01149 01150 inline void binwrite_(PStream& out, const unsigned int* x, unsigned int n) 01151 { out.write((char*)x, streamsize(n*sizeof(unsigned int))); } 01152 inline void binwrite_(PStream& out, unsigned int* x, unsigned int n) 01153 { out.write((char*)x, streamsize(n*sizeof(unsigned int))); } 01154 01155 inline void binwrite_(PStream& out, const long* x, unsigned int n) 01156 { out.write((char*)x, streamsize(n*sizeof(long))); } 01157 inline void binwrite_(PStream& out, long* x, unsigned int n) 01158 { out.write((char*)x, streamsize(n*sizeof(long))); } 01159 01160 inline void binwrite_(PStream& out, const unsigned long* x, unsigned int n) 01161 { out.write((char*)x, streamsize(n*sizeof(unsigned long))); } 01162 inline void binwrite_(PStream& out, unsigned long* x, unsigned int n) 01163 { out.write((char*)x, streamsize(n*sizeof(unsigned long))); } 01164 01165 inline void binwrite_(PStream& out, const long long* x, unsigned int n) 01166 { out.write((char*)x, streamsize(n*sizeof(long long))); } 01167 inline void binwrite_(PStream& out, long long* x, unsigned int n) 01168 { out.write((char*)x, streamsize(n*sizeof(long long))); } 01169 01170 inline void binwrite_(PStream& out, const unsigned long long* x, unsigned int n) 01171 { out.write((char*)x, streamsize(n*sizeof(unsigned long long))); } 01172 inline void binwrite_(PStream& out, unsigned long long* x, unsigned int n) 01173 { out.write((char*)x, streamsize(n*sizeof(unsigned long long))); } 01174 01175 inline void binwrite_(PStream& out, const float* x, unsigned int n) 01176 { out.write((char*)x, streamsize(n*sizeof(float))); } 01177 inline void binwrite_(PStream& out, float* x, unsigned int n) 01178 { out.write((char*)x, streamsize(n*sizeof(float))); } 01179 01180 inline void binwrite_(PStream& out, const double* x, unsigned int n) 01181 { out.write((char*)x, streamsize(n*sizeof(double))); } 01182 inline void binwrite_(PStream& out, double* x, unsigned int n) 01183 { out.write((char*)x, streamsize(n*sizeof(double))); } 01184 01185 // The typecode indicates the type and format of the elements in the stream 01186 01187 template<class Iterator> 01188 void binread_(PStream& in, Iterator it, unsigned int n, unsigned char typecode) 01189 { 01190 if(typecode!=0xFF) 01191 PLERROR("In binread_ : bug! A specialised binread_ should have been called for a typecode other than the 'generic' 0xFF"); 01192 01193 while(n--) 01194 { 01195 in >> *it; 01196 ++it; 01197 } 01198 } 01199 01200 01203 template<class I, class J> 01204 void binread_as(PStream& in, J* x, unsigned int n, bool inverted_byte_order) 01205 { 01206 I y; 01207 while(n--) 01208 { 01209 in.read(reinterpret_cast<char*>(&y), sizeof(I)); 01210 if (inverted_byte_order) 01211 endianswap(&y); 01212 01213 #ifdef __INTEL_COMPILER 01214 #pragma warning(disable:1682) 01215 // Yes, I know that "implicit conversion of a 64-bit integral type to a smaller 01216 // integral type (potential portability problem)", but the conversion is 01217 // explicit here. 01218 #endif 01219 *x = static_cast<J>(y); 01220 #ifdef __INTEL_COMPILER 01221 #pragma warning(default:1682) 01222 #endif 01223 ++x; 01224 } 01225 } 01226 01227 void binread_(PStream& in, bool* x, unsigned int n, unsigned char typecode); 01228 01229 inline void binread_(PStream& in, char* x, 01230 unsigned int n, unsigned char typecode) 01231 { 01232 // big endian and little endian have the same typecodes 01233 // so we need to check only one for consistency 01234 01235 if(typecode!=TypeTraits<char>::little_endian_typecode() 01236 && typecode!=TypeTraits<unsigned char>::little_endian_typecode()) 01237 PLERROR("In binread_ incompatible typecode"); 01238 01239 in.read((char*)x, n); 01240 } 01241 01242 inline void binread_(PStream& in, signed char* x, unsigned int n, 01243 unsigned char typecode) 01244 { binread_(in, (char *)x, n, typecode); } 01245 01246 inline void binread_(PStream& in, unsigned char* x, unsigned int n, 01247 unsigned char typecode) 01248 { binread_(in, (char *)x, n, typecode); } 01249 01250 void binread_(PStream& in, short* x, unsigned int n, unsigned char typecode); 01251 void binread_(PStream& in, unsigned short* x, unsigned int n, 01252 unsigned char typecode); 01253 void binread_(PStream& in, int* x, unsigned int n, unsigned char typecode); 01254 void binread_(PStream& in, unsigned int* x, unsigned int n, 01255 unsigned char typecode); 01256 void binread_(PStream& in, long* x, unsigned int n, unsigned char typecode); 01257 void binread_(PStream& in, unsigned long* x, unsigned int n, 01258 unsigned char typecode); 01259 void binread_(PStream& in, long long* x, unsigned int n, 01260 unsigned char typecode); 01261 void binread_(PStream& in, unsigned long long* x, unsigned int n, 01262 unsigned char typecode); 01263 void binread_(PStream& in, float* x, unsigned int n, unsigned char typecode); 01264 void binread_(PStream& in, double* x, unsigned int n, unsigned char typecode); 01265 01266 01267 template<class SequenceType> 01268 void writeSequence(PStream& out, const SequenceType& seq) 01269 { 01270 // norman: added explicit cast 01271 uint32_t n = (uint32_t)seq.size(); 01272 typename SequenceType::const_iterator it = seq.begin(); 01273 01274 switch(out.outmode) 01275 { 01276 case PStream::raw_ascii: 01277 while(n--) 01278 { 01279 out << *it; 01280 out.put(' '); 01281 ++it; 01282 } 01283 break; 01284 01285 case PStream::pretty_ascii: 01286 out.write("[ "); 01287 while(n--) 01288 { 01289 out << *it; 01290 if(n>0) 01291 out.write(", "); 01292 ++it; 01293 } 01294 out.write(" ] "); 01295 break; 01296 01297 case PStream::raw_binary: 01298 binwrite_(out, it, n); 01299 break; 01300 01301 case PStream::plearn_ascii: 01302 out << n; 01303 out.write("[ "); 01304 while(n--) 01305 { 01306 out << *it; 01307 ++it; 01308 } 01309 out.write("] "); 01310 break; 01311 01312 case PStream::plearn_binary: 01313 { 01314 unsigned char typecode; 01315 if(byte_order()==LITTLE_ENDIAN_ORDER) 01316 { 01317 out.put((char)0x12); // 1D little-endian 01318 typecode = TypeTraits<typename SequenceType::value_type> 01319 ::little_endian_typecode(); 01320 } 01321 else 01322 { 01323 out.put((char)0x13); // 1D big-endian 01324 typecode = TypeTraits<typename SequenceType::value_type> 01325 ::big_endian_typecode(); 01326 } 01327 01328 // write typecode 01329 out.put(typecode); 01330 01331 // write length in raw_binary 01332 out.write((char*)&n, sizeof(n)); 01333 01334 // write the data 01335 binwrite_(out, it, n); 01336 } 01337 break; 01338 01339 default: 01340 PLERROR("In PStream::writeSequence(Iterator& it, int n) unknown outmode!!!!!!!!!"); 01341 break; 01342 } 01343 } 01344 01345 01347 01357 template<class SequenceType> 01358 void readSequence(PStream& in, SequenceType& seq) 01359 { 01360 switch(in.inmode) 01361 { 01362 case PStream::raw_ascii: 01363 { 01364 // norman: added explicit cast 01365 int n = (int)seq.size(); 01366 typename SequenceType::iterator it = seq.begin(); 01367 while(n--) 01368 { 01369 in.skipBlanks(); 01370 in >> *it; 01371 // don't skip blanks before we need to read something else 01372 // (read might block). 01373 //in.skipBlanks(); 01374 ++it; 01375 } 01376 } 01377 break; 01378 case PStream::raw_binary: 01379 { 01380 int n = (int)seq.size(); 01381 typename SequenceType::iterator it = seq.begin(); 01382 while(n--) 01383 { 01384 in >> *it; 01385 ++it; 01386 } 01387 } 01388 break; 01389 01390 case PStream::plearn_ascii: 01391 case PStream::plearn_binary: 01392 { 01393 in.skipBlanksAndComments(); 01394 int c = in.peek(); 01395 if (c == EOF) 01396 PLERROR("In PStream.h / readSequence - The input stream is empty"); 01397 else if(c=='[') // read until ']' 01398 { 01399 in.get(); // skip '[' 01400 seq.resize(0); 01401 in.skipBlanksAndCommentsAndSeparators(); 01402 while(in.peek()!=']' && in.peek()!=EOF && !in.eof()) 01403 { 01404 typename SequenceType::value_type x; 01405 in >> x; 01406 seq.push_back(x); 01407 in.skipBlanksAndCommentsAndSeparators(); 01408 } 01409 if (in.peek()==EOF || in.eof()) 01410 PLERROR("Reading stream, unmatched left bracket [, missing ]"); 01411 in.get(); // skip ']' 01412 } 01413 else if(isdigit(c)) 01414 { 01415 unsigned int n; 01416 in >> n; 01417 in.skipBlanksAndComments(); 01418 c = in.get(); 01419 if(c!='[') 01420 PLERROR("Error in readSequence(SequenceType& seq), expected '[', read '%c'",c); 01421 // don't skip blanks before we need to read something else 01422 // (read might block). 01423 //in.skipBlanksAndCommentsAndSeparators(); 01424 seq.resize((typename SequenceType::size_type) n); 01425 if (n>0) 01426 { 01427 typename SequenceType::iterator it = seq.begin(); 01428 while(n--) 01429 { 01430 in.skipBlanksAndCommentsAndSeparators(); 01431 in >> *it; 01432 // don't skip blanks before we need to read something else 01433 // (read might block). 01434 //in.skipBlanksAndCommentsAndSeparators(); 01435 ++it; 01436 } 01437 } 01438 in.skipBlanksAndCommentsAndSeparators(); 01439 c = in.get(); 01440 if(c!=']') 01441 PLERROR("Error in readSequence(SequenceType& seq), expected ']', read '%c'",c); 01442 01443 } 01444 else if(c==0x12 || c==0x13) // it's a generic binary 1D sequence 01445 { 01446 in.get(); // eat c 01447 unsigned char typecode = in.get(); 01448 unsigned int l; 01449 in.read((char*)&l,sizeof(l)); 01450 01451 bool inverted_byte_order = 01452 ((c==0x12 && byte_order()==BIG_ENDIAN_ORDER) 01453 || (c==0x13 && byte_order()==LITTLE_ENDIAN_ORDER) ); 01454 01455 if(inverted_byte_order) 01456 endianswap(&l); 01457 seq.resize((typename SequenceType::size_type) l); 01458 binread_(in, seq.begin(), l, typecode); 01459 } 01460 else 01461 PLERROR("In readSequence(SequenceType& seq) '%c' not a proper first character in the header of a sequence!",c); 01462 } 01463 break; 01464 01465 default: 01466 PLERROR("In PStream::operator>> unknown inmode!!!!!!!!!"); 01467 break; 01468 } 01469 01470 } 01471 01472 // Default behavior for write() and read() is 01473 // to call corresponding operator<<() or operator>>() 01474 // on PStream. 01475 01476 template<class T> 01477 inline void write(ostream& out_, const T& o) 01478 { 01479 PStream out(&out_); 01480 out << o; 01481 } 01482 01483 template<class T> 01484 inline void read(istream& in_, T& o) 01485 { 01486 PStream in(&in_); 01487 in >> o; 01488 } 01489 01490 template<class T> 01491 inline void read(const string& stringval, T& x) 01492 { 01493 istringstream in_(stringval); 01494 PStream in(&in_); 01495 in >> x; 01496 } 01497 01498 01499 // STL containers: 01500 01501 template <class T> inline PStream & 01502 operator>>(PStream &in, vector<T> &v) 01503 { readSequence(in, v); return in; } 01504 01505 template <class T> inline PStream & 01506 operator<<(PStream &out, const vector<T> &v) 01507 { writeSequence(out, v); return out; } 01508 01509 // Serialization of map types 01510 01511 template<class SetT> 01512 void writeSet(PStream& out, const SetT& s) 01513 { 01514 typename SetT::const_iterator it = s.begin(); 01515 typename SetT::const_iterator itend = s.end(); 01516 01517 out.put('['); 01518 while(it!=itend) 01519 { 01520 out << *it; 01521 ++it; 01522 if (it != itend) 01523 out.write(", "); 01524 } 01525 out.put(']'); 01526 } 01527 01528 template<class SetT> 01529 void readSet(PStream& in, SetT& s) 01530 { 01531 s.clear(); 01532 in.skipBlanksAndCommentsAndSeparators(); 01533 int c = in.get(); 01534 if(c!='[') 01535 PLERROR("In readSet(Pstream& in, SetT& s) expected '[' but read %c",c); 01536 in.skipBlanksAndCommentsAndSeparators(); 01537 c = in.peek(); // do we have a ']' ? 01538 while(c!=']') 01539 { 01540 typename SetT::value_type val; 01541 in >> val; 01542 s.insert(val); 01543 in.skipBlanksAndCommentsAndSeparators(); 01544 c = in.peek(); // do we have a ']' ? 01545 } 01546 in.get(); // eat the ']' 01547 } 01548 01549 template <class T> inline PStream & 01550 operator>>(PStream &in, set<T> &v) 01551 { readSet(in, v); return in; } 01552 01553 template <class T> inline PStream & 01554 operator<<(PStream &out, const set<T> &v) 01555 { writeSet(out, v); return out; } 01556 01557 01558 01559 // Serialization of priority_queue types 01560 01561 template<class PriorityQueueT> 01562 void writePriorityQueue(PStream& out, const PriorityQueueT& pq) 01563 { 01564 PriorityQueueT pq2(pq); 01565 out.put('['); 01566 while(!pq2.empty()) 01567 { 01568 typename PriorityQueueT::value_type val; 01569 val = pq2.top(); 01570 out << val; 01571 pq2.pop(); 01572 if (!pq2.empty()) 01573 out.write(", "); 01574 } 01575 out.put(']'); 01576 } 01577 01578 template<class PriorityQueueT> 01579 void readPriorityQueue(PStream& in, PriorityQueueT& pq) 01580 { 01581 PLCHECK(pq.empty()); 01582 in.skipBlanksAndCommentsAndSeparators(); 01583 int c = in.get(); 01584 if(c!='[') 01585 PLERROR("In readPriorityQueue(Pstream& in, PriorityQueueT& pq) expected '[' but read %c",c); 01586 in.skipBlanksAndCommentsAndSeparators(); 01587 c = in.peek(); // do we have a ']' ? 01588 while(c!=']') 01589 { 01590 typename PriorityQueueT::value_type val; 01591 in >> val; 01592 pq.push(val); 01593 in.skipBlanksAndCommentsAndSeparators(); 01594 c = in.peek(); // do we have a ']' ? 01595 } 01596 in.get(); // eat the ']' 01597 } 01598 01599 template <class T> inline PStream & 01600 operator>>(PStream &in, priority_queue<T> &v) 01601 { readPriorityQueue(in, v); return in; } 01602 01603 template <class T> inline PStream & 01604 operator<<(PStream &out, const priority_queue<T> &v) 01605 { writePriorityQueue(out, v); return out; } 01606 01608 class PIFStream: public PStream 01609 { 01610 public: 01611 PIFStream(const string& fname, ios_base::openmode m = ios_base::in) 01612 :PStream(new ifstream(fname.c_str()),true) 01613 { 01614 PLDEPRECATED("PIFStream is deprecated. Use the openFile function instead."); 01615 } 01616 }; 01617 01619 class POFStream: public PStream 01620 { 01621 public: 01622 POFStream(const string& fname, 01623 ios_base::openmode m = ios_base::out | ios_base::trunc) 01624 :PStream(new ofstream(fname.c_str()),true) 01625 { 01626 PLDEPRECATED("POFStream is deprecated. Use the openFile function instead."); 01627 } 01628 }; 01629 01630 01632 class PIStringStream: public PStream 01633 { 01634 public: 01635 PIStringStream(const string& s) 01636 :PStream(new istringstream(s), true /* own it */) 01637 { 01638 PLDEPRECATED("PIStringStream is deprecated. Use the openString function instead."); 01639 } 01640 }; 01641 01642 01643 } // namespace PLearn 01644 01645 #endif //ndef PStream_INC 01646 01647 01648 /* 01649 Local Variables: 01650 mode:c++ 01651 c-basic-offset:4 01652 c-file-style:"stroustrup" 01653 c-file-offsets:((innamespace . 0)(inline-open . 0)) 01654 indent-tabs-mode:nil 01655 fill-column:79 01656 End: 01657 */ 01658 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :