pelib
2.0.0
|
00001 /* 00002 Copyright 2015 Nicolas Melot 00003 00004 This file is part of Pelib. 00005 00006 Pelib is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 Pelib is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with Pelib. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 00021 #include <set> 00022 00023 #include <pelib/AmplOutputData.hpp> 00024 #include <pelib/Set.hpp> 00025 #include <pelib/Scalar.hpp> 00026 #include <pelib/CastException.hpp> 00027 00028 #ifndef PELIB_AMPLOUTPUTSET 00029 #define PELIB_AMPLOUTPUTSET 00030 00031 namespace pelib 00032 { 00033 /*** AMPL Output format parser and output class for pelib::Set class instances ***/ 00034 template <class Value, class Key = size_t> 00035 class AmplOutputSet: public AmplOutputData 00036 { 00037 /*** Internal format of data collection handled ***/ 00038 typedef std::set<Value, std::less<Value>, std::allocator<Value> > SetType; 00039 00040 public: 00044 AmplOutputSet(bool strict = true) 00045 { 00046 this->strict = strict; 00047 } 00048 00050 virtual 00051 AmplOutputSet* 00052 clone() const 00053 { 00054 return new AmplOutputSet(); 00055 } 00056 00058 virtual 00059 std::string 00060 getDetailedPattern() 00061 { 00062 return "set\\s*([^\\s\\n\\[\\]]+)\\s*(?:\\[([^\\s\\n]+)\\])?\\s*:=(.+)"; 00063 } 00064 00066 virtual 00067 std::string 00068 getGlobalPattern() 00069 { 00070 return "set\\s*[^\\s\\n\\[\\]]+\\s*(?:\\[[^\\s\\n]+\\])?\\s*:=.+"; 00071 } 00072 00076 virtual 00077 AlgebraData* 00078 parse(std::istream &in) 00079 { 00080 SetType values; 00081 00082 std::string str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); 00083 boost::cmatch match; // = AlgebraDataParser::match(getDetailedPattern(), str); 00084 if(!boost::regex_match(str.c_str(), match, boost::regex(getDetailedPattern()))) 00085 { 00086 throw ParseException(std::string("String \"").append(str).append("\" doesn't match regex \"").append(getDetailedPattern()).append("\". ")); 00087 } 00088 00089 boost::regex param_set("\\s*([^\\s]+)"); 00090 std::string keystr = match[2]; 00091 std::string remain = match[3]; 00092 const int subs[] = {1}; 00093 boost::sregex_token_iterator iter = make_regex_token_iterator(remain, param_set, subs, boost::regex_constants::match_default); 00094 boost::sregex_token_iterator end; 00095 00096 int integer_values = 0, total_values = 0; 00097 for(; iter != end; ++iter ) 00098 { 00099 Value value; 00100 00101 try 00102 { 00103 value = AlgebraDataParser::convert<Value>(*iter, strict); 00104 } 00105 catch(NoDecimalFloatException &e) 00106 { 00107 std::stringstream ss; 00108 ss << e.getValue(); 00109 ss >> value; 00110 integer_values++; 00111 } 00112 00113 values.insert(value); 00114 total_values++; 00115 } 00116 00117 // If all values could have been parsed as integer, then this is obviously an integer vector rather to a float one 00118 if(integer_values == total_values) 00119 { 00120 //throw NoDecimalFloatException(std::string("Set only composed of integer-parsable values."), 0); 00121 throw ParseException(std::string("Set only composed of integer-parsable values.")); 00122 } 00123 00124 if(keystr.compare(std::string()) == 0) 00125 { 00126 return new Set<Value>(match[1], values); 00127 } 00128 else 00129 { 00130 Key key; 00131 00132 try 00133 { 00134 key = AlgebraDataParser::convert<Key>(keystr, strict); 00135 } 00136 catch(NoDecimalFloatException &e) 00137 { 00138 std::stringstream ss; 00139 ss << e.getValue(); 00140 ss >> key; 00141 } 00142 00143 return new Set<Value, Key>(match[1], key, values); 00144 } 00145 } 00146 00151 virtual 00152 void 00153 dump(std::ostream &o, const AlgebraData *data) const 00154 { 00155 const Set<Value, Key> *set = dynamic_cast<const Set<Value>*>(data); 00156 if(set == NULL) throw CastException("parameter \"data\" was not of type \"Set<Value>\"."); 00157 00158 for(typename Set<Value, Key>::SetOfSetsType::const_iterator i = set->getSubsets().begin(); i != set->getSubsets().end(); i++) 00159 { 00160 if(set->isOneSet()) 00161 { 00162 o << "set " << set->getName() << " :="; 00163 } 00164 else 00165 { 00166 o << "set " << set->getName() << "[" << i->first << "] :="; 00167 } 00168 00169 SetType values = i->second; 00170 for(typename std::set<Value>::const_iterator iter = values.begin(); iter != values.end(); iter++) 00171 { 00172 o << " " << *iter; 00173 } 00174 00175 o << ";" << std::endl; 00176 } 00177 } 00178 00179 protected: 00181 bool strict; 00182 private: 00183 }; 00184 } 00185 00186 #endif