PLearn 0.1
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
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines