PLearn 0.1
PStream.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PStream.cc
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 #include <limits>
00039 #include "PStream.h"
00040 #include "NullPStreamBuf.h"
00041 #include "PrPStreamBuf.h"
00042 #include <plearn/math/pl_math.h>
00043 #include <nspr/prio.h>
00044 #include <ctype.h>
00045 #include <plearn/io/pl_log.h>
00046 
00047 
00048 // This is probably an ugly hack to get it to work under Visual Studio.
00049 #if defined(WIN32) && !defined(__CYGWIN__)
00050 #define snprintf _snprintf
00051 #endif
00052 
00053 namespace PLearn {
00054 using namespace std;
00055 
00056 // Default format string for floats and doubles
00057 const char* PStream::format_float_default  = "%.8g";
00058 //We put 15 decimal. We need 10 for the precision of double
00059 // + 4 as when the g format print as 0.0004... we need more digit.
00060 //Probably 14 was enought, but I put 15 as I was not sur of the border case.
00061 //Old version with 18 decimal printed value as 0.008659999999999999
00062 // are now printed as 0.00866(take less space and are more readable).
00063 const char* PStream::format_double_default = "%.15g";
00064 bool PStream::windows_endl = false;
00065 // Initialization for pin, pout, ...
00066 
00067 PStream& get_pnull()
00068 {
00069     static PStream pnull = new NullPStreamBuf();
00070     return pnull;
00071 }
00072 
00073 PStream pnull = get_pnull();
00074 
00075 PStream& get_pin()
00076 {
00077     static bool initialized = false;
00078     static PStream pin = new
00079         PrPStreamBuf(PR_GetSpecialFD(PR_StandardInput),0);
00080     if(!initialized)
00081     {
00082         pin.setMode(PStream::raw_ascii); // raw_ascii default mode
00083         initialized = true;
00084     }
00085     return pin;
00086 }
00087 
00088 PStream pin = get_pin();
00089 
00090 PStream& get_pout()
00091 {
00092     static bool initialized = false;
00093     static PStream pout = new PrPStreamBuf(0,
00094                                            PR_GetSpecialFD(PR_StandardOutput));
00095     if(!initialized)
00096     {
00097         pout.setMode(PStream::raw_ascii); // raw_ascii default mode
00098         initialized = true;
00099     }
00100     return pout;
00101 }
00102 
00103 PStream pout = get_pout();
00104 
00105 PStream& get_pio()
00106 {
00107     static bool initialized = false;
00108     static PStream pio = new
00109         PrPStreamBuf(PR_GetSpecialFD(PR_StandardInput),
00110                      PR_GetSpecialFD(PR_StandardOutput));
00111     if(!initialized)
00112     {
00113         pio.setMode(PStream::raw_ascii); // raw_ascii default mode
00114         initialized = true;
00115     }
00116     return pio;
00117 }
00118 
00119 PStream pio = get_pio();
00120 
00121 PStream& get_perr()
00122 {
00123     static bool initialized = false;
00124     static PStream perr = new PrPStreamBuf(0,
00125                                            PR_GetSpecialFD(PR_StandardError));
00126     if(!initialized)
00127     {
00128         perr.setMode(PStream::raw_ascii); // raw_ascii default mode
00129         initialized = true;
00130         perr.setBufferCapacities(0,0,0);  // perr is unbuffered by default
00131     }
00132     return perr;
00133 }
00134 
00135 PStream perr = get_perr();
00136 
00137 PStream& flush(PStream& out)
00138 {
00139     out.flush();
00140     return out;
00141 }
00142 
00143 PStream& endl(PStream& out)
00144 {
00145     out.endl();
00146     return out;
00147 }
00148 
00149 PStream& ws(PStream& in)
00150 {
00151     switch(in.inmode) {
00152     case PStream::raw_ascii:
00153     case PStream::pretty_ascii:
00154     case PStream::raw_binary:
00155         in.skipBlanks();
00156         break;
00157     case PStream::plearn_ascii:
00158     case PStream::plearn_binary:
00159         // Also skip comments.
00160         in.skipBlanksAndComments();
00161         break;
00162     default:
00163         PLERROR("In ws(PStream& in) - in's inmode is not supported");
00164     }
00165     return in;
00166 }
00167 
00168 string pgetline(PStream& in)
00169 {
00170     string line;
00171     in.getline(line);
00172     // remove any trailing \n and \r
00173     string::size_type pos = line.length();
00174     while(pos>=1 && (line[pos - 1]=='\r' || line[pos - 1]=='\n'))
00175         pos--;
00176     return line.substr(0,pos);
00177 }
00178 
00179 PStream::PStream()
00180     :inherited(0),
00181      inmode(plearn_ascii),
00182      outmode(plearn_ascii),
00183      format_float (format_float_default),
00184      format_double(format_double_default),
00185      implicit_storage(true),
00186      compression_mode(compr_none),
00187      remote_plearn_comm(false)
00188 {}
00189 
00190 PStream::PStream(streambuftype* sb)
00191     :inherited(sb),
00192      inmode(plearn_ascii),
00193      outmode(plearn_ascii),
00194      format_float (format_float_default),
00195      format_double(format_double_default),
00196      implicit_storage(true),
00197      compression_mode(compr_none),
00198      remote_plearn_comm(false)
00199 {}
00200 
00201 
00203 PStream::PStream(istream* pin_, bool own_pin_)
00204     :inherited(new StdPStreamBuf(pin_,own_pin_)),
00205      inmode(plearn_ascii),
00206      outmode(plearn_ascii),
00207      format_float (format_float_default),
00208      format_double(format_double_default),
00209      implicit_storage(true),
00210      compression_mode(compr_none),
00211      remote_plearn_comm(false)
00212 {}
00214 
00215 PStream::PStream(ostream* pout_, bool own_pout_)
00216     :inherited(new StdPStreamBuf(pout_,own_pout_)),
00217      inmode(plearn_ascii),
00218      outmode(plearn_ascii),
00219      format_float (format_float_default),
00220      format_double(format_double_default),
00221      implicit_storage(true),
00222      compression_mode(compr_none),
00223      remote_plearn_comm(false)
00224 {}
00225 
00227 PStream::PStream(iostream* pios_, bool own_pios_)
00228     :inherited(new StdPStreamBuf(pios_,own_pios_)),
00229      inmode(plearn_ascii),
00230      outmode(plearn_ascii),
00231      format_float (format_float_default),
00232      format_double(format_double_default),
00233      implicit_storage(true),
00234      compression_mode(compr_none),
00235      remote_plearn_comm(false)
00236 {}
00237 
00239 PStream::PStream(istream* pin_, ostream* pout_, bool own_pin_, bool own_pout_)
00240     :inherited(new StdPStreamBuf(pin_,pout_,own_pin_,own_pout_)),
00241      inmode(plearn_ascii),
00242      outmode(plearn_ascii),
00243      format_float (format_float_default),
00244      format_double(format_double_default),
00245      implicit_storage(true),
00246      compression_mode(compr_none),
00247      remote_plearn_comm(false)
00248 {}
00249 
00251 // ~PStream //
00253 PStream::~PStream()
00254 { }
00255 
00257 // switchToPLearnOutMode //
00259 PStream::mode_t PStream::switchToPLearnOutMode()
00260 {
00261     mode_t oldmode = outmode;
00262     switch(outmode)
00263     {
00264     case PStream::raw_ascii:
00265     case PStream::pretty_ascii:
00266         outmode = PStream::plearn_ascii;
00267         break;
00268     case PStream::raw_binary:
00269         outmode = PStream::plearn_binary;
00270         break;
00271     default:
00272         break;
00273     }
00274     return oldmode;
00275 }
00276 
00278 // parseModeT //
00280 PStream::mode_t PStream::parseModeT(const string& str_mode){
00281     PStream::mode_t mode;
00282     if(str_mode.empty()) {
00283         PLDEPRECATED("The use of an empty string as PStream mode to default to"
00284                 " 'plearn_ascii' is deprecated, please use 'plearn_ascii' "
00285                 "directly");
00286         mode = PStream::plearn_ascii;
00287     } else if(str_mode=="plearn_ascii")
00288         mode = PStream::plearn_ascii;
00289     else if(str_mode=="plearn_binary")
00290         mode = PStream::plearn_binary;
00291     else
00292         PLERROR("In PStream::parseModeT(%s): invalid mode",
00293                 str_mode.c_str());
00294     return mode;
00295 }
00297 // readAll //
00299 
00300 string PStream::readAll()
00301 {
00302     const int bufsz= 4096;
00303     char buf[bufsz];
00304     string s= "";
00305     int nread= ptr->read(buf, bufsz);
00306     while(nread > 0)
00307     {
00308         s.append(buf, nread);
00309         nread= ptr->read(buf, bufsz);
00310     }
00311     return s;
00312 }
00313 
00315 // readExpected //
00317 
00318 void PStream::readExpected(char expect)
00319 {
00320     int c = get();
00321     if(c!=expect)
00322         PLERROR("In readExpected : expected %c, but read %c",expect,c);
00323 }
00324 
00325 void PStream::readExpected(char* expect)
00326 {
00327     for(char c = *expect; c!=0; c=*expect++)
00328         readExpected(c);
00329 }
00330 
00331 void PStream::readExpected(const string& expect)
00332 {
00333     int l = int(expect.size());
00334     for(int i=0; i<l; i++)
00335         readExpected(expect[i]);
00336 }
00337 
00338 
00339 streamsize PStream::readUntil(char* buf, streamsize n, char stop_char)
00340 {
00341     streamsize nread = 0;
00342 
00343     while(nread<n)
00344     {
00345         int c = get();
00346         if(c==EOF)
00347             break;
00348         if((char)c == stop_char)
00349         {
00350             putback(c);
00351             break;
00352         }
00353         *buf++ = (char)c;
00354         ++nread;
00355     }
00356 
00357     return nread;
00358 }
00359 
00360 streamsize PStream::readUntil(char* buf, streamsize n, const char* stop_chars)
00361 {
00362     streamsize nread = 0;
00363 
00364     while(nread<n)
00365     {
00366         int c = get();
00367         if(c==EOF)
00368             break;
00369         if(strchr(stop_chars, c))
00370         {
00371             putback(c);
00372             break;
00373         }
00374         *buf++ = (char)c;
00375         ++nread;
00376     }
00377 
00378     return nread;
00379 }
00380 
00381 int PStream::smartReadUntilNext(const string& stoppingsymbols, string& characters_read, bool ignore_brackets, bool skip_comments)
00382 {
00383     int c;
00384     while( (c=get()) != EOF)
00385     {
00386         if(stoppingsymbols.find(c)!=string::npos)
00387             break;
00388         else if(skip_comments && c=='#')  // skip until end of line
00389             skipRestOfLine();
00390         else
00391         {
00392             if(characters_read.length() == characters_read.capacity())
00393                 characters_read.reserve(characters_read.length()*2); //don't realloc&copy every time a char is appended...
00394             characters_read+= static_cast<char>(c);
00395 
00396             switch(c)
00397             {
00398             case '(':
00399                 smartReadUntilNext(")", characters_read, ignore_brackets, skip_comments);
00400                 characters_read+= ')';
00401                 break;
00402             case '[':
00403                 if(!ignore_brackets)
00404                 {
00405                     smartReadUntilNext("]", characters_read, ignore_brackets, skip_comments);
00406                     characters_read+= ']';
00407                 }
00408                 break;
00409             case '{':
00410                 smartReadUntilNext("}", characters_read, ignore_brackets, skip_comments);
00411                 characters_read+= '}';
00412                 break;
00413             case '"':
00414                 smartReadUntilNext("\"", characters_read, ignore_brackets, false);
00415                 characters_read+= '"';          
00416                 break; 
00417             case '\\':   // we consider backslash an escape character, 
00418                 c=get(); // thus the next character is read and appended without being interpreted
00419                 if(c!=EOF)
00420                     characters_read += static_cast<char>(c);
00421                 break;
00422             }
00423         }
00424     }
00425     return c;
00426 }
00427 
00429 void PStream::skipAll(const char* chars_to_skip)
00430 {
00431     int c = get();
00432     while(c!=EOF && strchr(chars_to_skip, c))
00433         c = get();
00434     if(c!=EOF)
00435         putback(c);
00436 }
00437 
00438 // reads everything until '\n' (also consumes the '\n')
00439 void PStream::skipRestOfLine()
00440 {
00441     int c = get();
00442     while(c!='\n' && c!=EOF)
00443         c=get();
00444 }
00445 
00446 void PStream::skipBlanks()
00447 {
00448     int c = get();
00449     while(c!=EOF && (c==' ' || c=='\t' || c=='\n' || c=='\r'))
00450         c = get();
00451     if(c!=EOF)
00452         putback(c);
00453 }
00454 
00455 void PStream::skipBlanksAndComments()
00456 {
00457     int c = get();
00458     while(c!=EOF)
00459     {
00460         if(c=='#')
00461             skipRestOfLine();
00462         else if(c!=' ' && c!='\t' && c!='\n' && c!='\r')
00463             break;
00464         c = get();
00465     }
00466     if(c!=EOF)
00467         putback(c);
00468 }
00469 
00470 void PStream::skipBlanksAndCommentsAndSeparators()
00471 {
00472     int c = get();
00473     while(c!=EOF)
00474     {
00475         if(c=='#')
00476             skipRestOfLine();
00477         else if(c!=' ' && c!='\t' && c!='\n' && c!='\r' && c!=';' && c!=',')
00478             break;
00479         c = get();
00480     }
00481     if(c!=EOF)
00482         putback(c);
00483 }
00484 
00486 // count //
00488 int PStream::count(char c) {
00489     char ch = get();
00490     int counter = 0;
00491     while (ch != EOF) {
00492         if (ch == c)
00493             counter++;
00494         ch = get();
00495     }
00496     return counter;
00497 }
00498 
00499 void PStream::writeAsciiHexNum(unsigned char x)
00500 {
00501     int d = x>>4;
00502     put(d<0x0A ?(d+'0') :(d-0x0A+'A'));
00503     d = x & 0x0F;
00504     put(d<0x0A ?(d+'0') :(d-0x0A+'A'));
00505 }
00506 
00507 
00508 void PStream::writeAsciiNum(char x)
00509 {
00510     char tmpbuf[PSTREAM_BUF_SIZE];
00511     snprintf(tmpbuf, sizeof(tmpbuf), "%d", (int)x);
00512     write(tmpbuf, streamsize(strlen(tmpbuf)));
00513 }
00514 
00515 void PStream::writeAsciiNum(unsigned char x)
00516 {
00517     char tmpbuf[PSTREAM_BUF_SIZE];
00518     snprintf(tmpbuf, sizeof(tmpbuf), "%d", (int)x);
00519     write(tmpbuf, streamsize(strlen(tmpbuf)));
00520 }
00521 
00522 void PStream::writeAsciiNum(signed char x)
00523 {
00524     char tmpbuf[PSTREAM_BUF_SIZE];
00525     snprintf(tmpbuf, sizeof(tmpbuf), "%d", (int)x);
00526     write(tmpbuf, streamsize(strlen(tmpbuf)));
00527 }
00528 
00529 void PStream::writeAsciiNum(short x)
00530 {
00531     char tmpbuf[PSTREAM_BUF_SIZE];
00532     snprintf(tmpbuf, sizeof(tmpbuf), "%hd", x);
00533     write(tmpbuf, streamsize(strlen(tmpbuf)));
00534 }
00535 
00536 void PStream::writeAsciiNum(unsigned short x)
00537 {
00538     char tmpbuf[PSTREAM_BUF_SIZE];
00539     snprintf(tmpbuf, sizeof(tmpbuf), "%hu", x);
00540     write(tmpbuf, streamsize(strlen(tmpbuf)));
00541 }
00542 
00543 void PStream::writeAsciiNum(int x)
00544 {
00545     char tmpbuf[PSTREAM_BUF_SIZE];
00546     snprintf(tmpbuf, sizeof(tmpbuf), "%d", x);
00547     write(tmpbuf, streamsize(strlen(tmpbuf)));
00548 }
00549 
00550 void PStream::writeAsciiNum(unsigned int x)
00551 {
00552     char tmpbuf[PSTREAM_BUF_SIZE];
00553     snprintf(tmpbuf, sizeof(tmpbuf), "%u", x);
00554     write(tmpbuf, streamsize(strlen(tmpbuf)));
00555 }
00556 
00557 void PStream::writeAsciiNum(long x)
00558 {
00559     char tmpbuf[PSTREAM_BUF_SIZE];
00560     snprintf(tmpbuf, sizeof(tmpbuf), "%ld", x);
00561     write(tmpbuf, streamsize(strlen(tmpbuf)));
00562 }
00563 
00564 void PStream::writeAsciiNum(unsigned long x)
00565 {
00566     char tmpbuf[PSTREAM_BUF_SIZE];
00567     snprintf(tmpbuf, sizeof(tmpbuf), "%lu", x);
00568     write(tmpbuf, streamsize(strlen(tmpbuf)));
00569 }
00570 
00571 void PStream::writeAsciiNum(long long x)
00572 {
00573     long long zero(0);
00574     if(x>=zero)
00575         writeAsciiNum((unsigned long long)x);
00576     else
00577     {
00578         put('-');
00579         writeAsciiNum((unsigned long long) -x);
00580     }
00581 }
00582 
00583 void PStream::writeAsciiNum(unsigned long long x)
00584 {
00585     unsigned long long zero(0);
00586     if(x==zero)
00587         put('0');
00588     else
00589     {
00590         char buf[30];
00591         char* p = buf+29;
00592         int n = 0;
00593         while(x>zero)
00594         {
00595             *p-- = '0'+char(x%10);
00596             x /= 10;
00597             ++n;
00598         }
00599         ++p;
00600         write(p,n);
00601     }
00602 }
00603 
00604 void PStream::writeAsciiNum(float x)
00605 {
00606     if(is_missing(x))
00607         write("nan");
00608     else if (isinf(x)) {
00609         if (x < 0)
00610             write("-inf");
00611         else
00612             write("inf");
00613     }
00614     else
00615     {
00616         char tmpbuf[PSTREAM_BUF_SIZE];
00617         snprintf(tmpbuf, sizeof(tmpbuf), format_float, x);
00618         write(tmpbuf, streamsize(strlen(tmpbuf)));
00619     }
00620 }
00621 
00622 void PStream::writeAsciiNum(double x)
00623 {
00624     if(is_missing(x))
00625         write("nan");
00626     else if (isinf(x)) {
00627         if (x < 0)
00628             write("-inf");
00629         else
00630             write("inf");
00631     }
00632     else
00633     {
00634         char tmpbuf[PSTREAM_BUF_SIZE];
00635         snprintf(tmpbuf, sizeof(tmpbuf), format_double, x);
00636         write(tmpbuf, streamsize(strlen(tmpbuf)));
00637     }
00638 }
00639 
00640 void PStream::readAsciiNum(char &x)
00641 {
00642     long dx;
00643     readAsciiNum(dx);
00644     x = char(dx);
00645 }
00646 
00647 void PStream::readAsciiNum(unsigned char &x)
00648 {
00649     long dx;
00650     readAsciiNum(dx);
00651     x = (unsigned char)(dx);
00652 }
00653 
00654 void PStream::readAsciiNum(signed char &x)
00655 {
00656     long dx;
00657     readAsciiNum(dx);
00658     x = (signed char)(dx);
00659 }
00660 
00661 void PStream::readAsciiNum(short &x)
00662 {
00663     long dx;
00664     readAsciiNum(dx);
00665     x = short(dx);
00666 }
00667 
00668 void PStream::readAsciiNum(unsigned short &x)
00669 {
00670     unsigned long dx;
00671     readAsciiNum(dx);
00672     x = (unsigned short)(dx);
00673 }
00674 
00675 void PStream::readAsciiNum(int &x)
00676 {
00677     long dx;
00678     readAsciiNum(dx);
00679     x = int(dx);
00680 }
00681 
00682 void PStream::readAsciiNum(unsigned int &x)
00683 {
00684     unsigned long dx;
00685     readAsciiNum(dx);
00686     x = (unsigned int)(dx);
00687 }
00688 
00689 void PStream::readAsciiNum(long &x)
00690 {
00691     skipBlanks();
00692     x = 0;
00693     char c = get();
00694     bool negate = false;
00695     if (c == '-')
00696     {
00697         negate = true;
00698         c = get();
00699     }
00700     else if (c == '+')
00701         c = get();
00702 
00703     if(!isdigit(c))
00704         PLERROR("In readAsciiNum: not a valid ascii number, expected a digit, but read %c (ascii code %d)",c,c);
00705 
00706     do
00707     {
00708         x = x*10 + c-'0';
00709         c = get();
00710     } while(isdigit(c));
00711 
00712     unget();
00713     if(negate)
00714         x = -x;
00715 }
00716 
00717 void PStream::readAsciiNum(unsigned long &x)
00718 {
00719     skipBlanks();
00720     x = 0;
00721     char c = get();
00722     while(isdigit(c))
00723     {
00724         x = x*10 + c-'0';
00725         c = get();
00726     }
00727     unget();
00728 }
00729 
00730 void PStream::readAsciiNum(long long &x)
00731 {
00732     skipBlanks();
00733     x = 0;
00734     char c = get();
00735     bool negate = false;
00736     if (c == '-')
00737     {
00738         negate = true;
00739         c = get();
00740     }
00741     else if (c == '+')
00742         c = get();
00743 
00744     if(!isdigit(c))
00745         PLERROR("In readAsciiNum: not a valid ascii number, expected a digit, but read %c (ascii code %d)",c,c);
00746 
00747     do
00748     {
00749         x *= 10;
00750         x += c-'0';
00751         c = get();
00752     } while(isdigit(c));
00753 
00754     unget();
00755     if(negate)
00756         x = -x;
00757 }
00758 
00759 void PStream::readAsciiNum(unsigned long long &x)
00760 {
00761     skipBlanks();
00762     x = 0;
00763     char c = get();
00764     while(isdigit(c))
00765     {
00766         x *= 10;
00767         x += c-'0';
00768         c = get();
00769     }
00770     unget();
00771 }
00772 
00773 void PStream::readAsciiNum(float &x)
00774 {
00775     double dx;
00776     readAsciiNum(dx);
00777     x = float(dx);
00778 }
00779 
00780 void PStream::readAsciiNum(double &x)
00781 {
00782     static const char* error_msg = "Bug while reading file and expecting a double";
00783     char tmpbuf[PSTREAM_BUF_SIZE];
00784     skipBlanks();
00785     int l=0;
00786     bool opposite = false;
00787 
00788     char c = get();
00789     if (c == '-') {
00790         tmpbuf[l++] = c;
00791         opposite = true;
00792         c = get();
00793     }
00794     else if (c == '+') // skip + sign
00795         c = get();
00796 
00797     bool E_seen= false;
00798     bool sign_seen= false;
00799     bool dot_seen= false;
00800 
00801     switch(c)
00802     {
00803     case '?':
00804         x = MISSING_VALUE;
00805         break;
00806     case 'n':
00807     case 'N':
00808         if(toupper(get())=='A' && toupper(get())=='N')
00809             x = MISSING_VALUE;
00810         else
00811             PLERROR(error_msg);
00812         break;
00813     case 'i':
00814     case 'I':
00815         if (toupper(get())=='N' && toupper(get())=='F')
00816         {
00817             x = numeric_limits<double>::infinity();
00818             if(opposite)
00819                 x = -x;
00820         }
00821         else
00822             PLERROR(error_msg);
00823         break ;
00824     default:
00825         while(isdigit(c)
00826               || ((c=='e' || c=='E') && !E_seen) //only one E
00827               || ((c=='-' || c=='+') && E_seen && !sign_seen)//one sign, after E
00828               || (c=='.' && !E_seen && !dot_seen))//one dot, before E
00829         {
00830             if(c=='e' || c=='E') E_seen= true;
00831             if(c=='+' || c=='-') sign_seen= true;
00832             if(c=='.') dot_seen= true;
00833             tmpbuf[l++] = c;
00834             c = get();
00835         }
00836         tmpbuf[l] = '\0';
00837         unget();
00838         sscanf(tmpbuf,"%lf",&x);
00839         if(l==0)
00840             PLERROR("In PStream::readAsciiNum - we read (%c) while we "
00841                     "expected a digit", c);
00842         break;
00843     }
00844 }
00845 
00846 
00847 PStream& PStream::operator=(const PStream& pios)
00848 {
00849     if(this != &pios)
00850     {
00851         inherited::operator=((const inherited&)pios);
00852         inmode = pios.inmode;
00853         outmode = pios.outmode;
00854         implicit_storage = pios.implicit_storage;
00855         compression_mode = pios.compression_mode;
00856     }
00857     return *this;
00858 }
00859 
00860 // Implementation of operator>>'s
00861 
00862 PStream& PStream::operator>>(char &x)
00863 {
00864     switch(inmode)
00865     {
00866     case raw_binary:
00867         get(x);
00868         break;
00869     case pretty_ascii:
00870     case raw_ascii:
00871         skipBlanks();
00872         get(x);
00873         break;
00874     case plearn_ascii:
00875     case plearn_binary:
00876         skipBlanksAndCommentsAndSeparators();
00877         get(x);
00878         if (x == '\'')  // ascii case (between single quotes)
00879         {
00880             get(x);
00881             get();
00882         }
00883         else if (x == 0x01)  // plearn_binary case
00884             get(x);
00885         break;
00886     default:
00887         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
00888         break;
00889     }
00890     return *this;
00891 }
00892 
00893 PStream& PStream::operator>>(signed char &x)
00894 {
00895     char c;
00896     operator>>(c);
00897     x = (signed char)c;
00898     return *this;
00899 }
00900 
00901 PStream& PStream::operator>>(unsigned char &x)
00902 {
00903     switch(inmode)
00904     {
00905     case raw_binary:
00906         read(reinterpret_cast<char *>(&x), sizeof(unsigned char));
00907         break;
00908     case raw_ascii:
00909         skipBlanks();
00910         read(reinterpret_cast<char *>(&x), sizeof(unsigned char));
00911         break;
00912     case pretty_ascii:
00913     case plearn_ascii:
00914     case plearn_binary:
00915     {
00916         skipBlanksAndCommentsAndSeparators();
00917         char c = get();
00918         if (c == '\'')  // ascii
00919         {
00920             read(reinterpret_cast<char *>(&x), sizeof(unsigned char));
00921             get();
00922         }
00923         else if (c == 0x02)  // plearn_binary
00924             read(reinterpret_cast<char *>(&x), sizeof(unsigned char));
00925         else
00926             x = (unsigned char)c;
00927         break;
00928     }
00929     default:
00930         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
00931         break;
00932     }
00933     return *this;
00934 }
00935 
00936 PStream& PStream::operator>>(char *x)
00937 {
00938     if(!x)
00939         PLERROR("In PStream::operator>>(char*) character array must already be allocated to put the read string in");
00940 
00941     switch(inmode)
00942     {
00943     case PStream::raw_ascii:
00944     case PStream::raw_binary:
00945     case PStream::pretty_ascii:
00946     {
00947         skipBlanksAndComments();
00948         int i=0; // pos within the string
00949         int c = get();
00950         while (c!=EOF && wordseparators().find(c)==string::npos) // as long as we don't meet a wordseparator (or eof)...
00951         {
00952             x[i++] = static_cast<char>(c);
00953             c = get();
00954         }
00955         x[i++] = 0;
00956         unget();
00957     }
00958     break;
00959     case PStream::plearn_ascii:
00960     case PStream::plearn_binary:
00961     {
00962         skipBlanksAndComments();
00963         int c = peek();
00964         int i=0; // pos within the string
00965         if(c=='"') // it's a quoted string "..."
00966         {
00967             c = get(); // skip the quote
00968             c = get(); // get the next character
00969             while(c!='"' && c!=EOF)
00970             {
00971                 if(c=='\\') // escaped character
00972                 {
00973                     c = get();
00974                     switch (c)
00975                     {
00976                     case 'n':
00977                         x[i++] = '\n';
00978                         break;
00979                     case 't':
00980                         x[i++] = '\t';
00981                         break;
00982                     case 'r':
00983                         x[i++] = '\r';
00984                         break;
00985                     case '0':
00986                         x[i++] = '\0';
00987                         break;
00988                     case 'a':
00989                         x[i++] = '\a';
00990                         break;
00991                     case 'b':
00992                         x[i++] = '\b';
00993                         break;
00994                     case 'v':
00995                         x[i++] = '\v';
00996                         break;
00997                     case 'f':
00998                         x[i++] = '\f';
00999                         break;
01000 
01001                     default:
01002                         x[i++] = static_cast<char>(c);
01003                         break;
01004                     }
01005                 }
01006                 else
01007                     x[i++]= static_cast<char>(c);
01008 
01009                 c = get();
01010             }
01011             if(c==EOF)
01012                 PLERROR("In read(istream&, char*) unterminated quoted string");
01013             if(!isspace(c))
01014                 putback(c);
01015         }
01016         else // it's a single word without quotes
01017         {
01018             c= get();
01019             while(c != EOF && wordseparators().find(c)==string::npos) // as long as we don't meet a wordseparator (or eof)...
01020             {
01021                 x[i++]= static_cast<char>(c);
01022                 c= get();
01023             }
01024             if(!isspace(c))
01025                 unget();
01026         }
01027         x[i++] = 0;
01028     }
01029     break;
01030     default:
01031         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01032         break;
01033     }
01034     return *this;
01035 }
01036 
01037 PStream& PStream::operator>>(string& x)
01038 {
01039     switch(inmode)
01040     {
01041     case PStream::raw_ascii:
01042     case PStream::raw_binary:
01043     case PStream::pretty_ascii:
01044     {
01045         skipBlanksAndComments();
01046         int c = get();
01047         x.clear();
01048         // As long as we don't meet a (raw) wordseparator (or eof)...
01049         while (c!=EOF && raw_wordseparators().find(c)==string::npos)
01050         {
01051             x += static_cast<char>(c);
01052             c = get();
01053         }
01054         unget();
01055     }
01056     break;
01057     case PStream::plearn_ascii:
01058     case PStream::plearn_binary:
01059     {
01060         skipBlanksAndComments();
01061         int c = peek();
01062         if(c=='"') // it's a quoted string "..."
01063         {
01064             x.resize(0);
01065             c = get(); // skip the quote
01066             c = get(); // get the next character
01067             while(c!='"' && c!=EOF)
01068             {
01069                 if(c=='\\') // escaped character
01070                 {
01071                     c = get();
01072                     switch (c)
01073                     {
01074                     case 'n':
01075                         x += '\n';
01076                         break;
01077                     case 't':
01078                         x += '\t';
01079                         break;
01080                     case 'r':
01081                         x += '\r';
01082                         break;
01083                     case '0':
01084                         x += '\0';
01085                         break;
01086                     case 'a':
01087                         x += '\a';
01088                         break;
01089                     case 'b':
01090                         x += '\b';
01091                         break;
01092                     case 'v':
01093                         x += '\v';
01094                         break;
01095                     case 'f':
01096                         x += '\f';
01097                         break;
01098 
01099                     default:
01100                         x += static_cast<char>(c);
01101                         break;
01102                     }
01103                 }
01104                 else
01105                     x += static_cast<char>(c);
01106 
01107                 c = get();
01108             }
01109             if(c==EOF)
01110                 PLERROR("In read(istream&, string&) unterminated quoted string");
01111             c = get();
01112             if(!isspace(c)) // skip following blank if any
01113                 unget();
01114         }
01115         else // it's a single word without quotes
01116         {
01117             x.resize(0);
01118             c= get();
01119             while(c != EOF && wordseparators().find(c)==string::npos) // as long as we don't meet a wordseparator (or eof)...
01120             {
01121                 x+= static_cast<char>(c);
01122                 c= get();
01123             }
01124             if(!isspace(c))
01125                 unget();
01126         }
01127     }
01128     break;
01129     default:
01130         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01131         break;
01132     }
01133     return *this;
01134 }
01135 
01136 PStream& PStream::operator>>(bool &x)
01137 {
01138     int parsed = -1;
01139 
01140     char c;
01141     switch(inmode)
01142     {
01143     case raw_ascii:
01144     case pretty_ascii:
01145     case raw_binary:
01146     case plearn_ascii:
01147     case plearn_binary:
01148         skipBlanksAndCommentsAndSeparators();
01149         c = get();
01150         if(c=='1')
01151             parsed = 1;
01152 
01153         else if(c=='0')
01154             parsed = 0;
01155 
01156         else if(c=='T')
01157         {
01158             char r = get();
01159             char u = get();
01160             char e = get();
01161             if ( r == 'r' && u == 'u' && e == 'e' )
01162                 parsed = 1;
01163         }
01164 
01165         else if(c=='F')
01166         {
01167             char a = get();
01168             char l = get();
01169             char s = get();
01170             char e = get();
01171             if ( a == 'a' && l == 'l' && s == 's' && e == 'e' )
01172                 parsed = 0;
01173         }
01174 
01175         if ( parsed == -1 )
01176             PLERROR("In PStream::operator>>(bool &x) wrong format for bool, must be one "
01177                     "of characters 0 or 1 or unquoted strings True or False" );
01178         else
01179             x = (parsed != 0);
01180         break;
01181 
01182     default:
01183         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01184         break;
01185     }
01186     return *this;
01187 }
01188 
01189 PStream& PStream::operator>>(short &x)
01190 {
01191     switch(inmode)
01192     {
01193     case raw_ascii:
01194     case pretty_ascii:
01195         skipBlanks();
01196         readAsciiNum(x);
01197         break;
01198     case raw_binary:
01199         read(reinterpret_cast<char *>(&x), sizeof(short));
01200         break;
01201     case plearn_ascii:
01202     case plearn_binary:
01203     {
01204         skipBlanksAndCommentsAndSeparators();
01205         int c = get();
01206         if(c>0x00 && c<0x20)  // plearn_binary
01207         {
01208             readBinaryNum(x, c);
01209         }
01210         else  // plearn_ascii
01211         {
01212             unget();
01213             readAsciiNum(x);
01214         }
01215         break;
01216     }
01217     default:
01218         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01219         break;
01220     }
01221     return *this;
01222 }
01223 
01224 PStream& PStream::operator>>(unsigned short &x)
01225 {
01226     switch(inmode)
01227     {
01228     case raw_ascii:
01229     case pretty_ascii:
01230         skipBlanks();
01231         readAsciiNum(x);
01232         break;
01233     case raw_binary:
01234         read(reinterpret_cast<char *>(&x), sizeof(unsigned short));
01235         break;
01236     case plearn_ascii:
01237     case plearn_binary:
01238     {
01239         skipBlanksAndCommentsAndSeparators();
01240         int c = get();
01241         if(c>0x00 && c<0x20)  // plearn_binary
01242         {
01243             readBinaryNum(x, c);
01244         }
01245         else  // plearn_ascii
01246         {
01247             unget();
01248             readAsciiNum(x);
01249         }
01250         break;
01251     }
01252     default:
01253         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01254         break;
01255     }
01256     return *this;
01257 }
01258 
01259 PStream& PStream::operator>>(int &x)
01260 {
01261     switch(inmode)
01262     {
01263     case raw_ascii:
01264     case pretty_ascii:
01265         skipBlanks();
01266         readAsciiNum(x);
01267         break;
01268     case raw_binary:
01269         read(reinterpret_cast<char *>(&x), sizeof(int));
01270         break;
01271     case plearn_ascii:
01272     case plearn_binary:
01273     {
01274         skipBlanksAndCommentsAndSeparators();
01275         int c = get();
01276         if(c>0x00 && c<0x20)  // plearn_binary
01277         {
01278             readBinaryNum(x, c);
01279         }
01280         else  // plearn_ascii
01281         {
01282             unget();
01283             readAsciiNum(x);
01284         }
01285         break;
01286     }
01287     default:
01288         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01289         break;
01290     }
01291     return *this;
01292 }
01293 
01294 PStream& PStream::operator>>(unsigned int &x)
01295 {
01296     switch(inmode)
01297     {
01298     case raw_ascii:
01299     case pretty_ascii:
01300         skipBlanks();
01301         readAsciiNum(x);
01302         break;
01303     case raw_binary:
01304         read(reinterpret_cast<char *>(&x), sizeof(unsigned int));
01305         break;
01306     case plearn_ascii:
01307     case plearn_binary:
01308     {
01309         skipBlanksAndCommentsAndSeparators();
01310         int c = get();
01311         if(c>0x00 && c<0x20)  // plearn_binary
01312         {
01313             readBinaryNum(x, c);
01314         }
01315         else  // plearn_ascii
01316         {
01317             unget();
01318             readAsciiNum(x);
01319         }
01320         break;
01321     }
01322     default:
01323         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01324         break;
01325     }
01326     return *this;
01327 }
01328 
01329 PStream& PStream::operator>>(long &x)
01330 {
01331     switch(inmode)
01332     {
01333     case raw_ascii:
01334     case pretty_ascii:
01335         skipBlanks();
01336         readAsciiNum(x);
01337         break;
01338     case raw_binary:
01339         read(reinterpret_cast<char *>(&x), sizeof(long));
01340         break;
01341     case plearn_ascii:
01342     case plearn_binary:
01343     {
01344         skipBlanksAndCommentsAndSeparators();
01345         int c = get();
01346         if(c>0x00 && c<0x20)  // plearn_binary
01347         {
01348             readBinaryNum(x, c);
01349         }
01350         else  // plearn_ascii
01351         {
01352             unget();
01353             readAsciiNum(x);
01354         }
01355         break;
01356     }
01357     default:
01358         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01359         break;
01360     }
01361     return *this;
01362 }
01363 
01364 PStream& PStream::operator>>(unsigned long &x)
01365 {
01366     switch(inmode)
01367     {
01368     case raw_ascii:
01369     case pretty_ascii:
01370         skipBlanks();
01371         readAsciiNum(x);
01372         break;
01373     case raw_binary:
01374         read(reinterpret_cast<char *>(&x), sizeof(unsigned long));
01375         break;
01376     case plearn_ascii:
01377     case plearn_binary:
01378     {
01379         skipBlanksAndCommentsAndSeparators();
01380         int c = get();
01381         if(c>0x00 && c<0x20)  // plearn_binary
01382         {
01383             readBinaryNum(x, c);
01384         }
01385         else  // plearn_ascii
01386         {
01387             unget();
01388             readAsciiNum(x);
01389         }
01390         break;
01391     }
01392     default:
01393         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01394         break;
01395     }
01396     return *this;
01397 }
01398 
01399 PStream& PStream::operator>>(long long &x)
01400 {
01401     switch(inmode)
01402     {
01403     case raw_ascii:
01404     case pretty_ascii:
01405         skipBlanks();
01406         readAsciiNum(x);
01407         break;
01408     case raw_binary:
01409         read(reinterpret_cast<char *>(&x), sizeof(long long));
01410         break;
01411     case plearn_ascii:
01412     case plearn_binary:
01413     {
01414         skipBlanksAndCommentsAndSeparators();
01415         int c = get();
01416         if(c>0x00 && c<0x20)  // plearn_binary
01417         {
01418             readBinaryNum(x, c);
01419         }
01420         else  // plearn_ascii
01421         {
01422             unget();
01423             readAsciiNum(x);
01424         }
01425         break;
01426     }
01427     default:
01428         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01429         break;
01430     }
01431     return *this;
01432 }
01433 
01434 PStream& PStream::operator>>(unsigned long long &x)
01435 {
01436     switch(inmode)
01437     {
01438     case raw_ascii:
01439     case pretty_ascii:
01440         skipBlanks();
01441         readAsciiNum(x);
01442         break;
01443     case raw_binary:
01444         read(reinterpret_cast<char *>(&x), sizeof(unsigned long long));
01445         break;
01446     case plearn_ascii:
01447     case plearn_binary:
01448     {
01449         skipBlanksAndCommentsAndSeparators();
01450         int c = get();
01451         if(c>0x00 && c<0x20)  // plearn_binary
01452         {
01453             readBinaryNum(x, c);
01454         }
01455         else  // plearn_ascii
01456         {
01457             unget();
01458             readAsciiNum(x);
01459         }
01460         break;
01461     }
01462     default:
01463         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01464         break;
01465     }
01466     return *this;
01467 }
01468 
01469 PStream& PStream::operator>>(float &x)
01470 {
01471     switch(inmode)
01472     {
01473     case raw_ascii:
01474     case pretty_ascii:
01475         skipBlanks();
01476         readAsciiNum(x);
01477         break;
01478     case raw_binary:
01479         read(reinterpret_cast<char *>(&x), sizeof(float));
01480         break;
01481     case plearn_ascii:
01482     case plearn_binary:
01483     {
01484         skipBlanksAndCommentsAndSeparators();
01485         int c = get();
01486         if(c>0x00 && c<0x20)  // plearn_binary
01487         {
01488             readBinaryNum(x, c);
01489         }
01490         else  // plearn_ascii
01491         {
01492             unget();
01493             readAsciiNum(x);
01494         }
01495         break;
01496     }
01497     default:
01498         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01499         break;
01500     }
01501     return *this;
01502 }
01503 
01504 PStream& PStream::operator>>(double &x)
01505 {
01506     switch(inmode)
01507     {
01508     case raw_ascii:
01509     case pretty_ascii:
01510         skipBlanks();
01511         readAsciiNum(x);
01512         break;
01513     case raw_binary:
01514         read(reinterpret_cast<char *>(&x), sizeof(double));
01515         break;
01516     case plearn_ascii:
01517     case plearn_binary:
01518     {
01519         skipBlanksAndCommentsAndSeparators();
01520         int c = get();
01521         if(c>0x00 && c<0x20)  // plearn_binary
01522         {
01523             readBinaryNum(x, c);
01524         }
01525         else  // ascii
01526         {
01527             unget();
01528             readAsciiNum(x);
01529         }
01530         break;
01531     }
01532     default:
01533         PLERROR("In PStream::operator>>  unknown inmode!!!!!!!!!");
01534         break;
01535     }
01536     return *this;
01537 }
01538 
01539 
01540 // Implementation of operator<<'s
01541 
01542 PStream& PStream::operator<<(char x)
01543 {
01544     switch(outmode)
01545     {
01546     case raw_ascii:
01547     case raw_binary:
01548     case pretty_ascii:
01549         put(x);
01550         break;
01551     case plearn_ascii:
01552         put('\'');
01553         put(x);
01554         put('\'');
01555         put(' ');
01556         break;
01557     case plearn_binary:
01558         writeBinaryNum(x);
01559         break;
01560     default:
01561         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01562         break;
01563     }
01564     return *this;
01565 }
01566 
01567 PStream& PStream::operator<<(signed char x)
01568 {
01569     operator<<(char(x));
01570     return *this;
01571 }
01572 
01573 PStream& PStream::operator<<(unsigned char x)
01574 {
01575     switch(outmode)
01576     {
01577     case raw_ascii:
01578         put(x);
01579         put(' ');
01580         break;
01581     case raw_binary:
01582         put(x);
01583         break;
01584     case pretty_ascii:
01585     case plearn_ascii:
01586         put('\'');
01587         put(x);
01588         put('\'');
01589         put(' ');
01590         break;
01591     case plearn_binary:
01592         writeBinaryNum(x);
01593         break;
01594     default:
01595         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01596         break;
01597     }
01598     return *this;
01599 }
01600 
01601 PStream& PStream::operator<<(const char *x)
01602 {
01603     int l = (int)strlen(x);
01604     switch(outmode)
01605     {
01606     case PStream::raw_ascii:
01607     case PStream::pretty_ascii:
01608     case PStream::raw_binary:
01609         write(x);
01610         break;
01611 
01612     case PStream::plearn_ascii:
01613     case PStream::plearn_binary:
01614     {
01615         put('"');
01616         for(int i=0; i<l; i++)
01617         {
01618             char c = x[i];
01619             if(c=='"' || c=='\\') // escape quote and backslash
01620                 put('\\');
01621             put(c);
01622         }
01623         put('"');
01624         put(' ');
01625     }
01626     break;
01627 
01628     default:
01629         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01630         break;
01631     }
01632     return *this;
01633 }
01634 
01635 PStream& PStream::operator<<(const void* x)
01636 {
01637     switch(outmode)
01638     {
01639     case PStream::raw_ascii:
01640     case PStream::pretty_ascii:
01641     case PStream::raw_binary:
01642     case PStream::plearn_ascii:
01643     case PStream::plearn_binary:
01644     {
01645         char buffer[1000];
01646         snprintf(buffer, 1000, "%p ", x);
01647         buffer[999] = '\0';
01648         write(buffer);
01649         break;
01650     }
01651     default:
01652         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01653         break;
01654     }
01655     return *this;
01656 }
01657 
01658 
01659 // TODO What if the string contains a word separator ??
01660 PStream& PStream::operator<<(const string &x)
01661 {
01662     const char* array = x.c_str();
01663     operator<<(array);
01664     return *this;
01665 }
01666 
01667 PStream& PStream::operator<<(bool x)
01668 {
01669     switch(outmode)
01670     {
01671     case plearn_ascii:
01672         if(x)
01673             put('1');
01674         else
01675             put('0');
01676         put(' ');
01677         break;
01678     case raw_ascii:
01679     case pretty_ascii:
01680     case raw_binary:
01681     case plearn_binary:
01682         if(x)
01683             put('1');
01684         else
01685             put('0');
01686         break;
01687     default:
01688         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01689         break;
01690     }
01691     return *this;
01692 }
01693 
01694 PStream& PStream::operator<<(short x)
01695 {
01696     switch(outmode)
01697     {
01698     case raw_binary:
01699         write(reinterpret_cast<char *>(&x), sizeof(short));
01700         break;
01701     case raw_ascii:
01702     case pretty_ascii:
01703         writeAsciiNum(x);
01704         break;
01705     case plearn_ascii:
01706         writeAsciiNum(x);
01707         put(' ');
01708         break;
01709     case plearn_binary:
01710         writeBinaryNum(x);
01711         break;
01712     default:
01713         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01714         break;
01715     }
01716     return *this;
01717 }
01718 
01719 PStream& PStream::operator<<(unsigned short x)
01720 {
01721     switch(outmode)
01722     {
01723     case raw_binary:
01724         write(reinterpret_cast<char *>(&x), sizeof(unsigned short));
01725         break;
01726     case raw_ascii:
01727     case pretty_ascii:
01728         writeAsciiNum(x);
01729         break;
01730     case plearn_ascii:
01731         writeAsciiNum(x);
01732         put(' ');
01733         break;
01734     case plearn_binary:
01735         writeBinaryNum(x);
01736         break;
01737     default:
01738         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01739         break;
01740     }
01741     return *this;
01742 }
01743 
01744 PStream& PStream::operator<<(int x)
01745 {
01746     switch(outmode)
01747     {
01748     case raw_binary:
01749         write(reinterpret_cast<char *>(&x), sizeof(int));
01750         break;
01751     case raw_ascii:
01752     case pretty_ascii:
01753         writeAsciiNum(x);
01754         break;
01755     case plearn_ascii:
01756         writeAsciiNum(x);
01757         put(' ');
01758         break;
01759     case plearn_binary:
01760         writeBinaryNum(x);
01761         break;
01762     default:
01763         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01764         break;
01765     }
01766     return *this;
01767 }
01768 
01769 PStream& PStream::operator<<(unsigned int x)
01770 {
01771     switch(outmode)
01772     {
01773     case raw_binary:
01774         write(reinterpret_cast<char *>(&x), sizeof(unsigned int));
01775         break;
01776     case raw_ascii:
01777     case pretty_ascii:
01778         writeAsciiNum(x);
01779         break;
01780     case plearn_ascii:
01781         writeAsciiNum(x);
01782         put(' ');
01783         break;
01784     case plearn_binary:
01785         writeBinaryNum(x);
01786         break;
01787     default:
01788         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01789         break;
01790     }
01791     return *this;
01792 }
01793 
01794 PStream& PStream::operator<<(long x)
01795 {
01796     switch(outmode)
01797     {
01798     case raw_binary:
01799         write(reinterpret_cast<char *>(&x), sizeof(long));
01800         break;
01801     case raw_ascii:
01802     case pretty_ascii:
01803         writeAsciiNum(x);
01804         break;
01805     case plearn_ascii:
01806         writeAsciiNum(x);
01807         put(' ');
01808         break;
01809     case plearn_binary:
01810         writeBinaryNum(x);
01811         break;
01812     default:
01813         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01814         break;
01815     }
01816     return *this;
01817 }
01818 
01819 PStream& PStream::operator<<(unsigned long x)
01820 {
01821     switch(outmode)
01822     {
01823     case raw_binary:
01824         write(reinterpret_cast<char *>(&x), sizeof(unsigned long));
01825         break;
01826     case raw_ascii:
01827     case pretty_ascii:
01828         writeAsciiNum(x);
01829         break;
01830     case plearn_ascii:
01831         writeAsciiNum(x);
01832         put(' ');
01833         break;
01834     case plearn_binary:
01835         writeBinaryNum(x);
01836         break;
01837     default:
01838         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01839         break;
01840     }
01841     return *this;
01842 }
01843 
01844 PStream& PStream::operator<<(long long x)
01845 {
01846     switch(outmode)
01847     {
01848     case raw_binary:
01849         write(reinterpret_cast<char *>(&x), sizeof(long long));
01850         break;
01851     case raw_ascii:
01852     case pretty_ascii:
01853         writeAsciiNum(x);
01854         break;
01855     case plearn_ascii:
01856         writeAsciiNum(x);
01857         put(' ');
01858         break;
01859     case plearn_binary:
01860         writeBinaryNum(x);
01861         break;
01862     default:
01863         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01864         break;
01865     }
01866     return *this;
01867 }
01868 
01869 PStream& PStream::operator<<(unsigned long long x)
01870 {
01871     switch(outmode)
01872     {
01873     case raw_binary:
01874         write(reinterpret_cast<char *>(&x), sizeof(unsigned long long));
01875         break;
01876     case raw_ascii:
01877     case pretty_ascii:
01878         writeAsciiNum(x);
01879         break;
01880     case plearn_ascii:
01881         writeAsciiNum(x);
01882         put(' ');
01883         break;
01884     case plearn_binary:
01885         writeBinaryNum(x);
01886         break;
01887     default:
01888         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01889         break;
01890     }
01891     return *this;
01892 }
01893 
01894 PStream& PStream::operator<<(float x)
01895 {
01896     switch(outmode)
01897     {
01898     case raw_binary:
01899         write(reinterpret_cast<char *>(&x), sizeof(float));
01900         break;
01901     case raw_ascii:
01902     case pretty_ascii:
01903         writeAsciiNum(x);
01904         break;
01905     case plearn_ascii:
01906         writeAsciiNum(x);
01907         put(' ');
01908         break;
01909     case plearn_binary:
01910         writeBinaryNum(x);
01911         break;
01912     default:
01913         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01914         break;
01915     }
01916     return *this;
01917 }
01918 
01919 PStream& PStream::operator<<(double x)
01920 {
01921     switch(outmode)
01922     {
01923     case raw_binary:
01924         write(reinterpret_cast<char *>(&x), sizeof(double));
01925         break;
01926     case raw_ascii:
01927     case pretty_ascii:
01928         writeAsciiNum(x);
01929         break;
01930     case plearn_ascii:
01931         writeAsciiNum(x);
01932         put(' ');
01933         break;
01934     case plearn_binary:
01935         writeBinaryNum(x);
01936         break;
01937     default:
01938         PLERROR("In PStream::operator<<  unknown outmode!!!!!!!!!");
01939         break;
01940     }
01941     return *this;
01942 }
01943 
01944 
01945 void binread_(PStream& in, bool* x,
01946               unsigned int n, unsigned char typecode)
01947 {
01948     if(typecode!=TypeTraits<bool>::little_endian_typecode())
01949         PLERROR("In binread_ incompatible typecode");
01950 
01951     while(n--)
01952     {
01953         int c = in.get();
01954         if(c=='0')
01955             *x = false;
01956         else if(c=='1')
01957             *x = true;
01958         else
01959             PLERROR("In binread_(PStream& in, bool* x, unsigned int n, unsigned char typecode): "
01960                     "read invalid value for a boolean: should be '1' or '0', not %c", c);
01961         ++x;
01962     }
01963 }
01964 
01965 #define IMPLEMENT_NUMTYPE_BINREAD_(NUMTYPE)                                 \
01966 void binread_(PStream& in, NUMTYPE* x,                                      \
01967               unsigned int n, unsigned char typecode)                       \
01968 {                                                                           \
01969     /* If typecode corresponds to NUMTYPE's typecode */                     \
01970     if (typecode==TypeTraits<NUMTYPE>::little_endian_typecode())            \
01971     {                                                                       \
01972         in.read(reinterpret_cast<char*>(x), streamsize(n*sizeof(NUMTYPE))); \
01973         if (byte_order()==BIG_ENDIAN_ORDER)                                 \
01974             endianswap(x,n);                                                \
01975     }                                                                       \
01976     else if (typecode==TypeTraits<NUMTYPE>::big_endian_typecode())          \
01977     {                                                                       \
01978         in.read(reinterpret_cast<char*>(x), streamsize(n*sizeof(NUMTYPE))); \
01979         if (byte_order()==LITTLE_ENDIAN_ORDER)                              \
01980             endianswap(x,n);                                                \
01981     }                                                                       \
01982     /* Else, we need to try all the different types */                      \
01983     else if (typecode==TypeTraits<int8_t>::little_endian_typecode())        \
01984         binread_as<int8_t>(in, x, n, false);                                \
01985     else if (typecode==TypeTraits<uint8_t>::little_endian_typecode())       \
01986         binread_as<uint8_t>(in, x, n, false);                               \
01987     else if (typecode==TypeTraits<int16_t>::little_endian_typecode())       \
01988         binread_as<int16_t>(in, x, n, false);                               \
01989     else if (typecode==TypeTraits<uint16_t>::little_endian_typecode())      \
01990         binread_as<uint16_t>(in, x, n, false);                              \
01991     else if (typecode==TypeTraits<int32_t>::little_endian_typecode())       \
01992         binread_as<int32_t>(in, x, n, false);                               \
01993     else if (typecode==TypeTraits<uint32_t>::little_endian_typecode())      \
01994         binread_as<uint32_t>(in, x, n, false);                              \
01995     else if (typecode==TypeTraits<int64_t>::little_endian_typecode())       \
01996         binread_as<int64_t>(in, x, n, false);                               \
01997     else if (typecode==TypeTraits<uint64_t>::little_endian_typecode())      \
01998         binread_as<uint64_t>(in, x, n, false);                              \
01999     else if (typecode==TypeTraits<float>::little_endian_typecode())         \
02000         binread_as<float>(in, x, n, false);                                 \
02001     else if (typecode==TypeTraits<double>::little_endian_typecode())        \
02002         binread_as<double>(in, x, n, false);                                \
02003     else                                                                    \
02004         PLERROR("In binread_: Unknown typecode '%c' (%x)",                  \
02005                 typecode, typecode);                                        \
02006 }
02007 
02008 IMPLEMENT_NUMTYPE_BINREAD_(short)
02009 IMPLEMENT_NUMTYPE_BINREAD_(unsigned short)
02010 IMPLEMENT_NUMTYPE_BINREAD_(int)
02011 IMPLEMENT_NUMTYPE_BINREAD_(unsigned int)
02012 IMPLEMENT_NUMTYPE_BINREAD_(long)
02013 IMPLEMENT_NUMTYPE_BINREAD_(unsigned long)
02014 IMPLEMENT_NUMTYPE_BINREAD_(long long)
02015 IMPLEMENT_NUMTYPE_BINREAD_(unsigned long long)
02016 IMPLEMENT_NUMTYPE_BINREAD_(float)
02017 IMPLEMENT_NUMTYPE_BINREAD_(double)
02018 
02019 } //end of namespace PLearn
02020 
02021 
02022 /*
02023   Local Variables:
02024   mode:c++
02025   c-basic-offset:4
02026   c-file-style:"stroustrup"
02027   c-file-offsets:((innamespace . 0)(inline-open . 0))
02028   indent-tabs-mode:nil
02029   fill-column:79
02030   End:
02031 */
02032 // 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