#include "precompiled.h" #include "0ad_warning_disable.h" # include # include # include # include "sr_input.h" # include "sr_string.h" # include "sr_array.h" //# define SR_USE_TRACE1 //Parser //# define SR_USE_TRACE2 //Init # include "sr_trace.h" # define ISNULL _type==(srbyte)TypeNull # define ISFILE _type==(srbyte)TypeFile # define ISSTRING _type==(srbyte)TypeString //=============================== SrInput ================================= struct SrInput::UngetData { struct Token { char* string; srbyte type; }; SrArray character; // unget buffer for char reading SrArray token; // unget buffer for token reading void init (); }; void SrInput::UngetData::init () { character.size(0); while ( token.size() ) delete token.pop().string; } void SrInput::_init ( char c ) { _size = 0; _curline = 0; _comment_style = c; _type = (srbyte) TypeNull; _last_error = (srbyte) NoError; _last_token_type = 0; _max_token_size = 256; _lowercase_tokens = 1; // true _skipped_spaces = 0; _unget = new UngetData; _filename = 0; } SrInput::SrInput ( char com ) { SR_TRACE2 ("Default Constructor"); _init ( com ); } SrInput::SrInput ( const char *buff, char com ) { SR_TRACE2 ("String Constructor"); _init ( com ); if ( buff ) { _cur.s = buff; _ini.s = buff; _size = (int)strlen ( buff ); _curline = 1; _type = (srbyte) TypeString; } } // static utility function: static void get_size ( FILE *fp, int &size, int &start ) { start = (int)ftell(fp); fseek ( fp, 0, SEEK_END ); size = (int)ftell(fp) - start; fseek ( fp, start, SEEK_SET ); } SrInput::SrInput ( FILE *file, char com ) { SR_TRACE2 ("File Constructor"); _init ( com ); if ( file ) { _cur.f = file; _curline = 1; _type = (srbyte) TypeFile; get_size ( file, _size, _ini.f ); } } SrInput::SrInput ( const char* filename, const char* mode, char com ) { SR_TRACE2 ("File2 Constructor"); _init ( com ); FILE* file = fopen ( filename, mode ); sr_string_set ( _filename, filename ); if ( file ) { _cur.f = file; _curline = 1; _type = (srbyte) TypeFile; get_size ( file, _size, _ini.f ); } } SrInput::~SrInput () { close (); // close frees all data inside _unget, and frees _filename delete _unget; } void SrInput::init ( const char *buff ) { SR_TRACE2 ("Init with string"); close (); if ( buff ) { _cur.s = buff; _ini.s = buff; _size = (int)strlen ( buff ); _curline = 1; _type = (srbyte) TypeString; } } void SrInput::init ( FILE *file ) { SR_TRACE2 ("Init with file"); close (); if ( file ) { _cur.f = file; _curline = 1; _type = (srbyte) TypeFile; get_size ( file, _size, _ini.f ); } } void SrInput::init ( const char* filename, const char* mode ) { SR_TRACE2 ("Init with file2"); FILE* file = fopen ( filename, mode ); init ( file ); sr_string_set ( _filename, filename ); } void SrInput::close () { if ( ISFILE ) fclose ( _cur.f ); _size = 0; _curline = 0; _type = (srbyte) TypeNull; _last_error = (srbyte) NoError; _last_token = ""; _last_token_type = 0; _unget->init (); sr_string_set ( _filename, 0 ); } void SrInput::leave_file () { _type = (srbyte) TypeNull; close (); } FILE* SrInput::filept () { return _type==TypeFile? _cur.f:0; } bool SrInput::valid () const { return (ISNULL)? false : true; } bool SrInput::finished () { if ( _unget->character.size()>0 || _unget->token.size()>0 ) return false; else if ( ISFILE ) return pos()>=_size? true:false; else if ( ISSTRING ) return *(_cur.s)? false:true; else return true; } void SrInput::getall ( SrString& buf ) { if ( ISFILE ) { int s = size()-pos(); buf.capacity ( s+2 ); // need +2 to cope with pc text files fread ( (void*)(const char*)buf, sizeof(char), (size_t)s, _cur.f ); buf [ s+1 ] = 0; } else if ( ISSTRING ) { buf.set ( _cur.s ); _cur.s = _ini.s+_size; } } int SrInput::getline ( SrString& buf ) { int c; buf.len(0); do { c = get(); buf << (char)c; } while ( c!='\n' && c!=EOF ); return c; } int SrInput::getchar () { int c = EOF; if ( _unget->character.size()>0 ) { c = _unget->character.pop(); } else { if ( ISFILE ) c=fgetc(_cur.f); else if ( ISSTRING ) c = *_cur.s? *_cur.s++:EOF; } if ( c=='\n' ) _curline++; return c; } static void skip_c_comment ( SrInput *p ) { int c, d; while ( true ) { c = p->getchar(); if ( c=='/' ) // for nested comments { d = p->getchar(); if ( d=='*' ) skip_c_comment(p); else p->unget(d); } else if ( c=='*' ) { d = p->getchar(); if ( d=='/' ) return; else p->unget(d); } else if ( c<0 ) return; // EOF found in the middle of a comment will not cause an error. } } int SrInput::get () { int c = getchar(); if ( _comment_style==0 ) { return c; } else if ( _comment_style=='C' && c=='/' ) { int d = getchar(); if ( d=='*' ) { skip_c_comment(this); return get(); } else if ( d=='/' ) { skip_line (); return get(); } else unget(d); } else if ( c==_comment_style ) { skip_line (); return get(); } return c; } void SrInput::unget ( char c ) { if ( c=='\n' && _curline>0 ) _curline--; _unget->character.push() = c; } void SrInput::advance ( int n ) { while ( n-->0 ) if ( getchar()<0 ) break; } void SrInput::rewind () { if ( ISNULL ) return; _unget->init(); _curline = 1; if ( ISSTRING ) _cur.s = _ini.s; else fseek ( _cur.f, _ini.f, SEEK_SET ); } int SrInput::pos () { if ( ISFILE ) return ((int)ftell(_cur.f)) - _ini.f; else if ( ISSTRING ) return _cur.s - _ini.s; else return 0; } void SrInput::pos ( int pos ) { _unget->init(); if ( ISFILE ) fseek ( _cur.f, pos+_ini.f, SEEK_SET ); else if ( ISSTRING ) _cur.s = _ini.s+pos; } void SrInput::set_pos_and_update_cur_line ( int pos ) { _unget->init(); rewind (); advance ( pos ); } void SrInput::skip_line () { int c; do { c = getchar(); } while ( c!=EOF && c!='\n' ); } void SrInput::unget_token ( const char *token, SrInput::TokenType type ) { UngetData::Token& t = _unget->token.push(); t.string = 0; t.type = (srbyte) type; sr_string_set ( t.string, token ); } void SrInput::unget_token () { if ( _last_token_type!=EndOfFile ) unget_token ( _last_token, (TokenType)_last_token_type ); } bool SrInput::has_unget_data () const { return _unget->token.size()==0 && _unget->character.size()==0? false:true; } static char get_escape_char ( char c ) { switch ( c ) { case 'n' : return '\n'; case 't' : return '\t'; case '\n': return 0; // Just skip line default : return c; } } SrInput::TokenType SrInput::get_token ( SrString &buf ) { # define UNGET(c) if(c>0)unget(c) int i; int c = ' '; int size = _max_token_size; TokenType ret; _last_error = (srbyte) NoError; buf.capacity(size); if ( _unget->token.size()>0 ) { UngetData::Token& t = _unget->token.pop(); buf.set ( t.string ); delete t.string; return (TokenType) t.type; } buf[0] = buf[1] = 0; _skipped_spaces = 0; while ( c && isspace(c) ) // skip initial spaces; { c=get(); _skipped_spaces++; } if ( c==EOF ) { SR_TRACE1 ( "Got the End Of File!" ); ret = EndOfFile; } else if ( strchr(SR_INPUT_DELIMITERS,c) && c!='.' ) // '.' will be detected after checking a real { buf[0]=c; ret=Delimiter; SR_TRACE1 ( "Got a Delimiter: "< "< "<'? true:false; } bool SrInput::read_field ( SrString& name ) { name = ""; if ( getd()!='<' ) return false; name = gets(); if ( name=="" ) return false; if ( getd()!='>' ) return false; return true; } bool SrInput::close_field ( const SrString& name ) { if ( getd()!='<' ) return false; if ( getd()!='/' ) return false; if ( gets()!=name ) return false; if ( getd()!='>' ) return false; return true; } bool SrInput::skip_field ( const SrString& name ) { while ( true ) { if ( close_field(name) ) return true; if ( _last_token_type==EndOfFile ) return false; } } //================================= operators ================================== SrInput& operator>> ( SrInput& in, int& i ) { SrString& s = in.getn(); i = s.atoi(); return in; } SrInput& operator>> ( SrInput& in, sruint& i ) { SrString& s = in.getn(); i = (sruint)s.atoi(); return in; } SrInput& operator>> ( SrInput& in, srbyte& c ) { SrString& s = in.getn(); c = (srbyte)s.atoi(); return in; } SrInput& operator>> ( SrInput& in, float& f ) { SrString& s = in.getn(); f = s.atof(); return in; } SrInput& operator>> ( SrInput& in, double& d ) { SrString& s = in.getn(); d = s.atod(); return in; } SrInput& operator>> ( SrInput& in, char* st ) { SrString& s = in.gets(); strcpy ( st, s ); return in; } //============================ End of File ==============================