FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

ISstream.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "ISstream.H"
00027 #include <OpenFOAM/int.H>
00028 #include <OpenFOAM/token.H>
00029 #include <cctype>
00030 
00031 
00032 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
00033 
00034 char Foam::ISstream::nextValid()
00035 {
00036     char c = 0;
00037 
00038     while (true)
00039     {
00040         // Get next non-whitespace character
00041         while (get(c) && isspace(c))
00042         {}
00043 
00044         // Return if stream is bad
00045         if (bad() || isspace(c))
00046         {
00047             return 0;
00048         }
00049 
00050         // Is this the start of a C/C++ comment?
00051         if (c == '/')
00052         {
00053             // If cannot get another character, return this one
00054             if (!get(c))
00055             {
00056                 return '/';
00057             }
00058 
00059             if (c == '/')
00060             {
00061                 // This is the start of a C++ style one-line comment
00062                 while (get(c) && c != '\n')
00063                 {}
00064             }
00065             else if (c == '*')
00066             {
00067                 // This is the start of a C style comment
00068                 while (true)
00069                 {
00070                     if (get(c) && c == '*')
00071                     {
00072                         if (get(c) && c == '/')
00073                         {
00074                             break;
00075                         }
00076                         else
00077                         {
00078                             putback(c);
00079                         }
00080                     }
00081 
00082                     if (!good())
00083                     {
00084                         return 0;
00085                     }
00086                 }
00087             }
00088             else  // A lone '/' so return it.
00089             {
00090                 putback(c);
00091                 return '/';
00092             }
00093         }
00094         else  // c is a valid character so return it
00095         {
00096             return c;
00097         }
00098     }
00099 }
00100 
00101 
00102 Foam::Istream& Foam::ISstream::read(token& t)
00103 {
00104     static char numberBuffer[100];
00105 
00106     // Return the put back token if it exists
00107     if (Istream::getBack(t))
00108     {
00109         return *this;
00110     }
00111 
00112     // Assume that the streams supplied are in working order.
00113     // Lines are counted by '\n'
00114 
00115     // Get next 'valid character': i.e. proceed through any white space
00116     // and/or comments until a semantically valid character is hit upon.
00117 
00118     char c = nextValid();
00119 
00120     // Set the line number of this token to the current stream line number
00121     t.lineNumber() = lineNumber();
00122 
00123     // return on error
00124     if (!c)
00125     {
00126         t.setBad();
00127         return *this;
00128     }
00129 
00130     // Analyse input starting with this character.
00131     switch (c)
00132     {
00133         // First check for punctuation characters.
00134 
00135         case token::END_STATEMENT :
00136         case token::BEGIN_LIST :
00137         case token::END_LIST :
00138         case token::BEGIN_SQR :
00139         case token::END_SQR :
00140         case token::BEGIN_BLOCK :
00141         case token::END_BLOCK :
00142         case token::COLON :
00143         case token::COMMA :
00144         case token::ASSIGN :
00145         case token::ADD :
00146      // case token::SUBTRACT : // Handled later as the posible start of a number
00147         case token::MULTIPLY :
00148         case token::DIVIDE :
00149         {
00150             t = token::punctuationToken(c);
00151             return *this;
00152         }
00153 
00154         // Strings: enclosed by double quotes.
00155         case token::BEGIN_STRING :
00156         {
00157             putback(c);
00158             string* sPtr = new string;
00159 
00160             if (!read(*sPtr).bad())
00161             {
00162                 t = sPtr;
00163             }
00164             else
00165             {
00166                 delete sPtr;
00167                 t.setBad();
00168             }
00169             return *this;
00170         }
00171 
00172         // Numbers: do not distinguish at this point between Types.
00173         case '-' :
00174         case '.' :
00175         case '0' : case '1' : case '2' : case '3' : case '4' :
00176         case '5' : case '6' : case '7' : case '8' : case '9' :
00177         {
00178             bool isScalar = false;
00179 
00180             if (c == '.')
00181             {
00182                 isScalar = true;
00183             }
00184 
00185             int i=0;
00186             numberBuffer[i++] = c;
00187 
00188             while
00189             (
00190                 is_.get(c)
00191              && (
00192                     isdigit(c)
00193                  || c == '.'
00194                  || c == 'e'
00195                  || c == 'E'
00196                  || c == '+'
00197                  || c == '-'
00198                 )
00199             )
00200             {
00201                 numberBuffer[i++] = c;
00202 
00203                 if (!isdigit(c))
00204                 {
00205                     isScalar = true;
00206                 }
00207             }
00208             numberBuffer[i] = '\0';
00209 
00210             setState(is_.rdstate());
00211 
00212             if (!is_.bad())
00213             {
00214                 is_.putback(c);
00215 
00216                 if (i == 1 && numberBuffer[0] == '-')
00217                 {
00218                     t = token::punctuationToken(token::SUBTRACT);
00219                 }
00220                 else if (isScalar)
00221                 {
00222                     t = scalar(atof(numberBuffer));
00223                 }
00224                 else
00225                 {
00226                     long lt = atol(numberBuffer);
00227                     t = label(lt);
00228 
00229                     // If the integer is too large to be represented as a label
00230                     // return it as a scalar
00231                     if (t.labelToken() != lt)
00232                     {
00233                         isScalar = true;
00234                         t = scalar(atof(numberBuffer));
00235                     }
00236                 }
00237             }
00238             else
00239             {
00240                 t.setBad();
00241             }
00242 
00243             return *this;
00244         }
00245 
00246         // Should be a word (which can be a single character)
00247         default:
00248         {
00249             putback(c);
00250             word* wPtr = new word;
00251 
00252             if (!read(*wPtr).bad())
00253             {
00254                 if (token::compound::isCompound(*wPtr))
00255                 {
00256                     t = token::compound::New(*wPtr, *this).ptr();
00257                     delete wPtr;
00258                 }
00259                 else
00260                 {
00261                     t = wPtr;
00262                 }
00263             }
00264             else
00265             {
00266                 delete wPtr;
00267                 t.setBad();
00268             }
00269             return *this;
00270         }
00271     }
00272 }
00273 
00274 
00275 Foam::Istream& Foam::ISstream::read(char& c)
00276 {
00277     c = nextValid();
00278     return *this;
00279 }
00280 
00281 
00282 Foam::Istream& Foam::ISstream::read(word& str)
00283 {
00284     static const int maxLen = 1024;
00285     static const int errLen = 80; // truncate error message for readability
00286     static char buf[maxLen];
00287 
00288     register int i = 0;
00289     register int bc = 0;
00290     char c;
00291 
00292     while (get(c) && word::valid(c))
00293     {
00294         if (fail())
00295         {
00296             if (i < maxLen-1)
00297             {
00298                 buf[i] = '\0';
00299             }
00300             else
00301             {
00302                 buf[maxLen-1] = '\0';
00303             }
00304             buf[errLen] = '\0';
00305 
00306             FatalIOErrorIn("ISstream::read(word&)", *this)
00307                 << "problem while reading word '" << buf << "'\n"
00308                 << exit(FatalIOError);
00309 
00310             return *this;
00311         }
00312 
00313         if (i >= maxLen)
00314         {
00315             buf[maxLen-1] = '\0';
00316             buf[errLen] = '\0';
00317 
00318             FatalIOErrorIn("ISstream::read(word&)", *this)
00319                 << "word '" << buf << "' ...\n"
00320                 << "    is too long (max. " << maxLen << " characters)"
00321                 << exit(FatalIOError);
00322 
00323             return *this;
00324         }
00325 
00326         if (c == token::BEGIN_LIST)
00327         {
00328             bc++;
00329         }
00330         else if (c == token::END_LIST)
00331         {
00332             bc--;
00333 
00334             if (bc == -1)
00335             {
00336                 break;
00337             }
00338         }
00339 
00340         buf[i++] = c;
00341     }
00342 
00343     if (i == 0)
00344     {
00345         FatalIOErrorIn("ISstream::read(word&)", *this)
00346             << "invalid first character found : " << c
00347             << exit(FatalIOError);
00348     }
00349 
00350     buf[i] = '\0';        // Terminator
00351     str = buf;
00352     putback(c);
00353 
00354     return *this;
00355 }
00356 
00357 
00358 Foam::Istream& Foam::ISstream::read(string& str)
00359 {
00360     static const int maxLen = 1024;
00361     static const int errLen = 80; // truncate error message for readability
00362     static char buf[maxLen];
00363 
00364     char c;
00365 
00366     if (!get(c))
00367     {
00368         buf[0] = '\0';
00369 
00370         FatalIOErrorIn("ISstream::read(string&)", *this)
00371             << "cannot read start of string"
00372             << exit(FatalIOError);
00373 
00374         return *this;
00375     }
00376 
00377     char endTok = token::END_STRING;
00378 
00379     // Note, we could also handle single-quoted strings here (if desired)
00380     if (c != token::BEGIN_STRING)
00381     {
00382         buf[0] = '\0';
00383 
00384         FatalIOErrorIn("ISstream::read(string&)", *this)
00385             << "Incorrect start of string character"
00386             << exit(FatalIOError);
00387 
00388         return *this;
00389     }
00390 
00391     register int i = 0;
00392     bool escaped = false;
00393 
00394     while (get(c))
00395     {
00396         if (c == endTok)
00397         {
00398             if (escaped)
00399             {
00400                 escaped = false;
00401                 i--;    // overwrite backslash
00402             }
00403             else
00404             {
00405                 // done reading string
00406                 buf[i] = '\0';
00407                 str = buf;
00408                 return *this;
00409             }
00410         }
00411         else if (c == token::NL)
00412         {
00413             if (escaped)
00414             {
00415                 escaped = false;
00416                 i--;    // overwrite backslash
00417             }
00418             else
00419             {
00420                 buf[i] = '\0';
00421                 buf[errLen] = '\0';
00422 
00423                 FatalIOErrorIn("ISstream::read(string&)", *this)
00424                     << "found '\\n' while reading string \""
00425                     << buf << "...\""
00426                     << exit(FatalIOError);
00427 
00428                 return *this;
00429             }
00430         }
00431         else if (c == '\\')
00432         {
00433             escaped = !escaped;    // toggle state (retains backslashes)
00434         }
00435         else
00436         {
00437             escaped = false;
00438         }
00439 
00440         buf[i] = c;
00441         if (i++ == maxLen)
00442         {
00443             buf[maxLen-1] = '\0';
00444             buf[errLen] = '\0';
00445 
00446             FatalIOErrorIn("ISstream::read(string&)", *this)
00447                 << "string \"" << buf << "...\"\n"
00448                 << "    is too long (max. " << maxLen << " characters)"
00449                 << exit(FatalIOError);
00450 
00451             return *this;
00452         }
00453     }
00454 
00455 
00456     // don't worry about a dangling backslash if string terminated prematurely
00457     buf[i] = '\0';
00458     buf[errLen] = '\0';
00459 
00460     FatalIOErrorIn("ISstream::read(string&)", *this)
00461         << "problem while reading string \"" << buf << "...\""
00462         << exit(FatalIOError);
00463 
00464     return *this;
00465 }
00466 
00467 
00468 Foam::Istream& Foam::ISstream::read(label& val)
00469 {
00470     is_ >> val;
00471     setState(is_.rdstate());
00472     return *this;
00473 }
00474 
00475 
00476 Foam::Istream& Foam::ISstream::read(floatScalar& val)
00477 {
00478     is_ >> val;
00479     setState(is_.rdstate());
00480     return *this;
00481 }
00482 
00483 
00484 Foam::Istream& Foam::ISstream::read(doubleScalar& val)
00485 {
00486     is_ >> val;
00487     setState(is_.rdstate());
00488     return *this;
00489 }
00490 
00491 
00492 // read binary block
00493 Foam::Istream& Foam::ISstream::read(char* buf, std::streamsize count)
00494 {
00495     if (format() != BINARY)
00496     {
00497         FatalIOErrorIn("ISstream::read(char*, std::streamsize)", *this)
00498             << "stream format not binary"
00499             << exit(FatalIOError);
00500     }
00501 
00502     readBegin("binaryBlock");
00503     is_.read(buf, count);
00504     readEnd("binaryBlock");
00505 
00506     setState(is_.rdstate());
00507 
00508     return *this;
00509 }
00510 
00511 
00512 Foam::Istream& Foam::ISstream::rewind()
00513 {
00514     stream().rdbuf()->pubseekpos(0);
00515 
00516     return *this;
00517 }
00518 
00519 
00520 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00521 
00522 
00523 std::ios_base::fmtflags Foam::ISstream::flags() const
00524 {
00525     return is_.flags();
00526 }
00527 
00528 
00529 std::ios_base::fmtflags Foam::ISstream::flags(const ios_base::fmtflags f)
00530 {
00531     return is_.flags(f);
00532 }
00533 
00534 
00535 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines