/* Copyright (c) 1997-2006 Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany) http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version: http://www.gnu.org/licenses/gpl.txt. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef _POLYMAKE_PLAIN_PARSER_H #define _POLYMAKE_PLAIN_PARSER_H "$Project: polymake $$Id: PlainParser.h 7315 2006-04-02 21:37:53Z gawrilow $" #include #include #include #ifndef _POLYMAKE_GENERIC_IO_H # include #endif class Rational; namespace pm { template class PlainListCursor; template class PlainCompositeCursor; class PlainParserCommon { protected: mutable std::istream *is; char *saved_egptr; PlainParserCommon(const PlainParserCommon& other) : is(other.is), saved_egptr(other.saved_egptr) { other.is=0; } explicit PlainParserCommon(std::istream& is_arg) : is(&is_arg), saved_egptr(0) { } public: ~PlainParserCommon() { if (is && saved_egptr) restore_input_range(saved_egptr); } template void fallback(Data& x) { *is >> x; } void finish() const { } bool at_end(); void get_scalar(double&); void get_scalar(Rational&); void get_string(std::string&, char delim); int count_lines(); int count_all_lines(); protected: char* set_temp_range(char opening, char closing); void set_range(char opening, char closing) { saved_egptr=set_temp_range(opening,closing); } void discard_range(char closing); void discard_temp_range(char closing, char *egptr) { discard_range(closing); restore_input_range(egptr); } int count_words(); int count_braced(char opening, char closing); int count_leading(char); char* set_input_range(int offset); void restore_input_range(char *egptr); void skip_temp_range(char *egptr); char* save_read_pos(); void restore_read_pos(char *pos); public: void skip_item(); void skip_rest(); }; template ::model> struct composite_depth { static const int value=0; }; template struct composite_depth { static const int value= composite_depth::elements, 0>::type>::value + 1; }; template class PlainParser : public PlainParserCommon, public GenericInputImpl< PlainParser >, public GenericIOoptions< PlainParser, Options > { public: PlainParser(std::istream& is_arg) : PlainParserCommon(is_arg) { } typedef ostream_wrapper wrapper; template struct list_cursor { typedef PlainListCursor::type::value_type, typename wrapper::template list_cursor::cursor_options> type; }; template struct composite_cursor { typedef PlainCompositeCursor::cursor_options> type; }; template typename list_cursor::type begin_list(Object*) const { return typename list_cursor::type(*this->is); } template typename composite_cursor::type begin_composite(Object*) const { return typename composite_cursor::type(*this->is); } operator void* () const { return this->is->good() ? (void*)this : 0; } bool operator! () const { return !this->is->good(); } }; template inline PlainParser& operator>> (GenericInput< PlainParser >& is, double& x) { is.top().get_scalar(x); return is.top(); } template inline PlainParser& operator>> (GenericInput< PlainParser >& is, Rational& x) { is.top().get_scalar(x); return is.top(); } template inline PlainParser& getline (PlainParser& is, std::string& s, char delim='\n') { is.get_string(s,delim); return is; } template inline PlainParser& operator>> (GenericInput< PlainParser >& is, std::string& s) { is.top().get_string(s,0); return is.top(); } template class PlainCursor : public PlainParserCommon { protected: char *start_pos; static const char opening=extract_int_param::value, closing=extract_int_param::value, separator=extract_int_param::value; static const bool is_temp=extract_bool_param::value; public: PlainCursor(std::istream& is_arg) : PlainParserCommon(is_arg), start_pos(0) { if (is_temp) start_pos=save_read_pos(); if (opening) set_range(opening, closing); } ~PlainCursor() { if (is_temp) restore_read_pos(start_pos); } void finish() { if (closing) discard_range(closing); } bool at_end() { return PlainParserCommon::at_end() && (finish(), true); } PlainParser* operator-> () { return static_cast*>(static_cast(this)); } }; template class PlainCompositeCursor : public PlainCursor, public GenericInputImpl< PlainCompositeCursor >, public GenericIOoptions< PlainCompositeCursor, Options > { typedef PlainCursor super; public: PlainCompositeCursor(std::istream& is_arg) : super(is_arg) { } private: template void cleanup(type2type) { } template void cleanup(type2type< ignore >) { if (!identical::value) super::skip_item(); } public: template void operator>> (Data& data) { *this->operator->() >> data; cleanup(type2type()); } }; template class PlainListCursor : public PlainCursor, public GenericInputImpl< PlainListCursor >, public GenericIOoptions< PlainListCursor, Options, 1 > { typedef PlainCursor super; typedef ostream_wrapper wrapper; static const bool has_sparse_representation=extract_bool_param::value; protected: int _size; char *pair_egptr; int size(is_scalar) { return this->count_words(); } int size(nothing) // e.g. graph incidence line { return this->count_words(); } int size(is_container) { typedef typename wrapper::template list_cursor defs; return defs::opening ? this->count_braced(defs::opening, defs::closing) : super::opening ? this->count_lines() : this->count_all_lines(); } int size(is_composite) { typedef typename wrapper::template composite_cursor defs; return defs::opening ? this->count_braced(defs::opening, defs::closing) : super::separator=='\n' ? super::opening ? this->count_lines() : this->count_all_lines() : this->count_words(); } public: typedef Value value_type; PlainListCursor(std::istream& is_arg) : super(is_arg), _size(-1), pair_egptr(0) { if (!super::opening && object_traits::total_dimension==0) this->set_range(0, '\n'); } int size() { if (_size<0) _size=size(typename object_traits::model()); return _size; } protected: template static int missing_parens(Model) { return 0; } static int missing_parens(is_composite) { typedef typename wrapper::template composite_cursor defs; return defs::opening == 0; } bool _sparse_representation() { const int own_missing=missing_parens(typename object_traits::model()); return this->count_leading('(') == composite_depth::value - own_missing + 1; } public: int index() { if (!ignore_in_composite::value) { if (has_sparse_representation) pair_egptr=this->set_temp_range('(', ')'); else this->is->setstate(std::ios::failbit); } int i; *this->is >> i; return i; } int get_dim() { int d=index(); this->discard_temp_range(')', pair_egptr); pair_egptr=0; return d; } bool sparse_representation() { return extract_type_param::specified ? has_sparse_representation : _sparse_representation(); } int dim() { return !ignore_in_composite::value && sparse_representation() ? this->set_option(SparseRepresentation()).get_dim() : size(); } private: template void cleanup(type2type) { if (has_sparse_representation) { this->discard_temp_range(')', pair_egptr); pair_egptr=0; } } void cleanup(type2type) { } template void cleanup(type2type< ignore >) { if (!identical::value) skip_item(); } public: template void operator>> (Data& x) { *this->operator->() >> x; cleanup(type2type()); } void skip_item() { if (has_sparse_representation && pair_egptr) { this->skip_temp_range(pair_egptr); pair_egptr=0; } else { super::skip_item(); } } }; } // end namespace pm #endif // _POLYMAKE_PLAIN_PARSER_H // Local Variables: // mode:C++ // End: