token_stream.cpp

Go to the documentation of this file.
00001 /*
00002  * token_stream.cpp
00003  *
00004  * Copyright (c) 2003 Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Implementation of various token stream objects.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "token_stream.h"               // always include our own header first
00036 
00037 #include "common/wave_ex.h"
00038 
00039 
00040 ////////////////////////////////////////////////////////////////////////////////
00041 //
00042 //      static helper methods
00043 //
00044 ////////////////////////////////////////////////////////////////////////////////
00045 
00046 static bool
00047 isBogus
00048 (
00049 IN char a
00050 )
00051 {
00052         return ('\r' == a);
00053 }
00054 
00055 
00056 
00057 ////////////////////////////////////////////////////////////////////////////////
00058 //
00059 //      public API
00060 //
00061 ////////////////////////////////////////////////////////////////////////////////
00062 
00063 void
00064 getNextToken
00065 (
00066 IO std::istream& stream,
00067 OUT std::string& token,
00068 IN bool respect_quotes,
00069 IN bool * eof
00070 )
00071 {
00072         ASSERT(!eof || !*eof, "passed-in eof flag is already true?");
00073 
00074         if (!stream.good()) {
00075                 DPRINTF("bad stream?");
00076                 WAVE_EX(wex);
00077                 wex << "Bad input stream in getNextToken()";
00078         }
00079         token = "";
00080         char a;
00081 
00082         // skip comments
00083         while (true) {
00084                 a = ' ';
00085                 while (isspace(a) && !stream.eof()) {
00086                         stream.get(a);
00087                 }
00088 
00089                 if (stream.eof()) {
00090                         if (eof) {
00091                                 *eof = true;
00092                                 return;
00093                         }
00094                         WAVE_EX(wex);
00095                         wex << "Unexpected end of stream in getNextToken()";
00096                 }
00097 
00098                 // skip comments
00099                 if ('#' != a)
00100                         break;  // not a comment, can exit
00101 
00102                 while ('\n' != a && !stream.eof()) {
00103                         stream.get(a);
00104                 }
00105                 if (stream.eof()) {
00106                         if (eof) {
00107                                 *eof = true;
00108                                 return;
00109                         }
00110                         WAVE_EX(wex);
00111                         wex << "Unexpected end of stream in getNextToken()";
00112                 }
00113         }
00114 
00115         // got a non-comment, non-space character.  Keep going
00116         bool in_quotes = false;
00117         if ('\"' == a ) {
00118                 if (respect_quotes) {
00119                         in_quotes = true;
00120                 }
00121         }
00122         while (true) {
00123                 if (('\"' !=a || !in_quotes) && !isBogus(a)) {
00124                         token += a;
00125                 }
00126                 if (stream.eof()) {
00127                         if (in_quotes) {
00128                                 DPRINTF("eof while reading quoted string");
00129                                 WAVE_EX(wex);
00130                                 wex << "Unexpected end of stream while reading quoted string.";
00131                         }
00132                         break;  // end of stream
00133                 }
00134 
00135                 // read next character
00136                 stream.get(a);
00137                 if (stream.eof()) {
00138                         break;          // end of input stream
00139                 }
00140                 if (in_quotes) {
00141                         if ('\"' == a)
00142                                 break;  // end of quoted string
00143                         continue;       // keep reading
00144                 }
00145                 if (isspace(a))
00146                         break;          // end of token
00147         }
00148 
00149         // success!
00150         // DPRINTF("read token: '%s'", token.c_str());
00151 }
00152 
00153 
00154 
00155 void
00156 expectToken
00157 (
00158 IO std::istream& stream,
00159 IN const char * expect
00160 )
00161 {
00162         ASSERT(expect, "null expected token");
00163 
00164         std::string token;
00165         try {
00166                 getNextToken(stream, token);
00167                 if (expect != token) {
00168                         WAVE_EX(wex);
00169                         wex << "Read token '" << token << "' instead.";
00170                 }
00171         } catch (std::exception& e) {
00172                 WAVE_EX(wex);
00173                 wex << "Expected token '" << expect << "', but encountered failure: ";
00174                 wex << e.what();
00175         }
00176 }
00177 
00178 
00179 
00180 float
00181 readFloat
00182 (
00183 IN std::istream& stream,
00184 IO std::string& token
00185 )
00186 {
00187         ASSERT(stream.good(), "bad?");
00188         getNextToken(stream, token);
00189         return atof(token.c_str());
00190 }
00191 
00192 
00193 
00194 int
00195 readInteger
00196 (
00197 IN std::istream& stream,
00198 IO std::string& token
00199 )
00200 {
00201         ASSERT(stream.good(), "bad?");
00202         getNextToken(stream, token);
00203         return atoi(token.c_str());
00204 }
00205 
00206 
00207 
00208 long
00209 readLong
00210 (
00211 IN std::istream& stream,
00212 IO std::string& token
00213 )
00214 {
00215         ASSERT(stream.good(), "bad?");
00216         getNextToken(stream, token);
00217         return atol(token.c_str());
00218 }
00219 
00220 
00221 
00222 short
00223 readShort
00224 (
00225 IN std::istream& stream,
00226 IO std::string& token
00227 )
00228 {
00229         ASSERT(stream.good(), "bad?");
00230         getNextToken(stream, token);
00231         return (short) atoi(token.c_str());
00232 }
00233