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 <pelib/AmplOutputData.hpp> 00022 #include <pelib/Vector.hpp> 00023 #include <pelib/Scalar.hpp> 00024 #include <pelib/CastException.hpp> 00025 00026 #ifndef PELIB_AMPLOUTPUTVECTOR 00027 #define PELIB_AMPLOUTPUTVECTOR 00028 00029 #define debug(var) std::cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << std::endl; 00030 00031 namespace pelib 00032 { 00034 template <class Key, class Value> 00035 class AmplOutputVector: public AmplOutputData 00036 { 00038 typedef std::map<Key, Value> VectorType; 00039 00040 public: 00044 AmplOutputVector(bool strict = true) 00045 { 00046 this->strict = strict; 00047 } 00048 00050 virtual 00051 AmplOutputVector* 00052 clone() const 00053 { 00054 return new AmplOutputVector(); 00055 } 00056 00058 virtual 00059 std::string 00060 getDetailedPattern() 00061 { 00062 return "(\\w[\\w\\d_]*)\\s*\\[\\*\\]\\s*:=\\s*((?:[-+\\w\\d][-\\w\\d_+\\.]*\\s+[-+\\w\\d][-\\w\\d_\\.+]*[\\s\\n]+)+)"; 00063 } 00064 00066 virtual 00067 std::string 00068 getGlobalPattern() 00069 { 00070 return "\\w[\\w\\d_]*\\s*\\[\\*\\]\\s*:=.+"; 00071 } 00072 00077 virtual 00078 AlgebraData* 00079 parse(std::istream &in) 00080 { 00081 VectorType values; 00082 00083 std::string str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); 00084 //std::cerr << str << std::endl; 00085 //std::cerr << std::string("(?:.*?)").append(getDetailedPattern()) << std::endl; 00086 boost::cmatch match; // = AlgebraDataParser::match(std::string("(?:.*?)").append(getDetailedPattern()), str); 00087 if(!boost::regex_match(str.c_str(), match, boost::regex(std::string("(?:.*?)").append(getDetailedPattern())))) 00088 { 00089 throw ParseException(std::string("String \"").append(str).append("\" doesn't match regex \"").append(getDetailedPattern()).append("\". ")); 00090 } 00091 00092 boost::regex param_vector("(?:\\s*([^\\s]+)\\s+([^\\s]+))"); 00093 std::string remain = match[2]; 00094 const int subs[] = {1, 2}; 00095 boost::sregex_token_iterator iter = make_regex_token_iterator(remain, param_vector, subs, boost::regex_constants::match_default); 00096 boost::sregex_token_iterator end; 00097 00098 int integer_values = 0, total_values = 0; 00099 for(; iter != end; ++iter ) 00100 { 00101 Key key; 00102 Value value; 00103 00104 std::string key_str = *iter++; 00105 std::string val_str = *iter; 00106 00107 try 00108 { 00109 key = AlgebraDataParser::convert<Key>(key_str, strict); 00110 } catch(NoDecimalFloatException &e) 00111 { 00112 std::ostringstream ss; 00113 ss << e.getValue(); 00114 throw ParseException(std::string("Asked a decimal conversion, but \"").append(ss.str()).append("\" is integer.")); 00115 } 00116 00117 try 00118 { 00119 value = AlgebraDataParser::convert<Value>(val_str, strict); 00120 } catch(NoDecimalFloatException &e) 00121 { 00122 float float_value = e.getValue(); 00123 std::stringstream ss; 00124 ss << float_value; 00125 ss >> value; 00126 integer_values++; 00127 } 00128 00129 values.insert(std::pair<Key, Value>(key, value)); 00130 total_values++; 00131 } 00132 00133 // If all values could have been parsed as integer, then this is obviously an integer vector rather to a float one 00134 if(integer_values == total_values) 00135 { 00136 //throw NoDecimalFloatException(std::string("Vector only composed of integer-parsable values."), 0); 00137 throw ParseException(std::string("Vector only composed of integer-parsable values.")); 00138 } 00139 00140 return new Vector<Key, Value>(match[1], values); 00141 } 00142 00147 virtual 00148 void 00149 dump(std::ostream &o, const AlgebraData *data) const 00150 { 00151 const Vector<Key, Value> *vector = dynamic_cast<const Vector<Key, Value>*>(data); 00152 if(vector == NULL) throw CastException("parameter \"data\" was not of type \"Vector<Key, Value>\"."); 00153 00154 o << vector->getName() << " [*] := " << std::endl; 00155 00156 // warning: "iter++" makes valgrind unhappy, dealing with free'd memory 00157 for(typename std::map<Key, Value>::const_iterator iter = vector->getValues().begin(); iter != vector->getValues().end(); iter++) 00158 { 00159 o << iter->first << "\t" << iter->second << std::endl; 00160 } 00161 00162 o << ";" << std::endl; 00163 } 00164 00165 protected: 00167 bool strict; 00168 private: 00169 }; 00170 } 00171 00172 #undef debug 00173 #endif