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/AmplInputData.hpp> 00024 #include <pelib/Set.hpp> 00025 #include <pelib/CastException.hpp> 00026 00027 #ifndef PELIB_AMPLINPUTSET 00028 #define PELIB_AMPLINPUTSET 00029 00030 #define debug(var) std::cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << std::endl; 00031 00032 namespace pelib 00033 { 00035 template <class Value, class Key = size_t> 00036 class AmplInputSet: public AmplInputData 00037 { 00039 typedef std::set<Value, std::less<Value>, std::allocator<Value> > SetType; 00040 00041 public: 00045 AmplInputSet(bool strict = true) 00046 { 00047 this->strict = strict; 00048 } 00049 00051 virtual 00052 AmplInputSet* 00053 clone() const 00054 { 00055 return new AmplInputSet(); 00056 } 00057 00061 virtual 00062 AlgebraData* 00063 parse(std::istream &in) 00064 { 00065 SetType values; 00066 std::string str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); 00067 00068 // TODO: investigate why using AlgebraDataParser results in random results 00069 boost::cmatch match; 00070 if(!boost::regex_match(str.c_str(), match, boost::regex(getDetailedPattern()))) 00071 { 00072 throw ParseException(std::string("String \"").append(str).append("\" doesn't match regex \"").append(getDetailedPattern()).append("\". ")); 00073 } 00074 //boost::cmatch match(AlgebraDataParser::match(getDetailedPattern(), str)); 00075 //boost::cmatch match = AlgebraDataParser::match(getDetailedPattern(), str); 00076 00077 boost::regex param_set("\\s*([^\\s]+)"); 00078 std::string keystr = match[2]; 00079 std::string remain = match[3]; 00080 const int subs[] = {1}; 00081 boost::sregex_token_iterator iter = make_regex_token_iterator(remain, param_set, subs, boost::regex_constants::match_default); 00082 boost::sregex_token_iterator end; 00083 00084 int integer_values = 0, total_values = 0; 00085 for(; iter != end; ++iter ) 00086 { 00087 Value value; 00088 00089 try 00090 { 00091 value = AlgebraDataParser::convert<Value>(*iter, strict); 00092 } 00093 catch(NoDecimalFloatException &e) 00094 { 00095 std::stringstream ss; 00096 ss << e.getValue(); 00097 ss >> value; 00098 integer_values++; 00099 } 00100 00101 values.insert(value); 00102 total_values++; 00103 } 00104 00105 // If all values could have been parsed as integer, then this is obviously an integer vector rather to a float one 00106 if(integer_values == total_values) 00107 { 00108 //throw NoDecimalFloatException(std::string("Set only composed of integer-parsable values."), 0); 00109 throw ParseException(std::string("Set only composed of integer-parsable values.")); 00110 } 00111 00112 if(keystr.compare(std::string()) == 0) 00113 { 00114 return new Set<Value>(match[1], values); 00115 } 00116 else 00117 { 00118 Key key; 00119 00120 try 00121 { 00122 key = AlgebraDataParser::convert<Key>(keystr, strict); 00123 } 00124 catch(NoDecimalFloatException &e) 00125 { 00126 std::stringstream ss; 00127 ss << e.getValue(); 00128 ss >> key; 00129 } 00130 00131 return new Set<Value, Key>(match[1], key, values); 00132 } 00133 } 00134 00139 virtual 00140 void 00141 dump(std::ostream &o, const AlgebraData *data) const 00142 { 00143 const Set<Value, Key> *set = dynamic_cast<const Set<Value>*>(data); 00144 if(set == NULL) throw CastException("parameter \"data\" was not of type \"Set<Value>\"."); 00145 00146 for(typename Set<Value, Key>::SetOfSetsType::const_iterator i = set->getSubsets().begin(); i != set->getSubsets().end(); i++) 00147 { 00148 if(set->isOneSet()) 00149 { 00150 o << "set " << set->getName() << " :="; 00151 } 00152 else 00153 { 00154 o << "set " << set->getName() << "[" << i->first << "] :="; 00155 } 00156 00157 SetType values = i->second; 00158 for(typename std::set<Value>::const_iterator iter = values.begin(); iter != values.end(); iter++) 00159 { 00160 o << " " << *iter; 00161 } 00162 00163 o << ";" << std::endl; 00164 } 00165 } 00166 00168 virtual 00169 std::string 00170 getDetailedPattern() 00171 { 00172 return "set\\s*([^\\s\\n\\[\\]]+)\\s*(?:\\[([^\\s\\n]+)\\])?\\s*:=(.+)"; 00173 } 00174 00176 virtual 00177 std::string 00178 getGlobalPattern() 00179 { 00180 return "set\\s*[^\\s\\n\\[\\]]+\\s*(?:\\[[^\\s\\n]+\\])?\\s*:=.+"; 00181 } 00182 00183 protected: 00185 bool strict; 00186 private: 00187 }; 00188 } 00189 00190 #undef debug 00191 #endif