00001 #ifndef Impala_Util_PropertySet_h
00002 #define Impala_Util_PropertySet_h
00003
00004 #include "Basis/String.h"
00005 #include "Util/StringParser.h"
00006 #include "Util/IOBuffer.h"
00007 #include "Persistency/File.h"
00008
00009 namespace Impala
00010 {
00011 namespace Util
00012 {
00013
00014 class PropertySet
00015 {
00016 public:
00017
00018
00019
00020 PropertySet()
00021 {
00022 }
00023
00028 PropertySet(CString definition)
00029 {
00030 Parse(definition);
00031 }
00032
00033 void
00034 Clear()
00035 {
00036 mNames.clear();
00037 mValues.clear();
00038 }
00039
00040 void
00041 Parse(CString definition)
00042 {
00043 Clear();
00044 std::istringstream iss(definition);
00045
00046 while(!iss.eof())
00047 {
00048 String pair;
00049 iss >> pair;
00050 if (pair.length() > 0)
00051 {
00052 String::size_type pos = pair.find('=');
00053 if(pos == String::npos)
00054 break;
00055 String name;
00056 String value;
00057 name = pair.substr(0,pos);
00058 value = pair.substr(pos+1);
00059 Add(name, value);
00060 }
00061 }
00062
00063 }
00064
00065 String
00066 GetString(CString name, const String defaultValue = "") const
00067 {
00068 for (int i=0 ; i<mNames.size() ; i++)
00069 if (mNames[i] == name)
00070 return mValues[i];
00071 return defaultValue;
00072 }
00073
00074 double
00075 GetDouble(CString name, double defaultValue = 0.) const
00076 {
00077 String val = GetString(name);
00078 if (val == "")
00079 return defaultValue;
00080 return atof(val);
00081 }
00082
00083 int
00084 GetInt(CString name, int defaultValue = 0) const
00085 {
00086 String val = GetString(name);
00087 if (val == "")
00088 return defaultValue;
00089 return atoi(val);
00090 }
00091
00092 bool
00093 GetBool(CString name, bool defaultValue = false) const
00094 {
00095 String val = GetString(name);
00096 if (val == "")
00097 return defaultValue;
00098 return StringToBool(val);
00099 }
00100
00101 void
00102 Remove(CString name)
00103 {
00104 for (int i=mNames.size()-1 ; i>=0 ; i--)
00105 {
00106 if (mNames[i] == name)
00107 {
00108 mNames.erase(mNames.begin()+i);
00109 mValues.erase(mValues.begin()+i);
00110 }
00111 }
00112 }
00113
00115 int
00116 Add(CString name, double value)
00117 {
00118 return Add(name, MakeString(value));
00119 }
00120
00122 int
00123 Add(CString name, CString value)
00124 {
00125 int i;
00126 for (i=0 ; i<mNames.size() ; i++)
00127 {
00128 if (mNames[i] == name)
00129 {
00130 mValues[i] = value;
00131 return i;
00132 }
00133 }
00134 mNames.push_back(name);
00135 mValues.push_back(value);
00136 return i;
00137 }
00138
00139 void
00140 Print(std::ostream& os) const
00141 {
00142 for (int i=0 ; i<mNames.size() ; i++)
00143 os << mNames[i] << "=" << mValues[i] << " ";
00144 }
00145
00146 void
00147 Print(IOBuffer* buf) const
00148 {
00149 String res;
00150 for (int i=0 ; i<mNames.size() ; i++)
00151 res += mNames[i] + "=" + mValues[i] + " ";
00152 buf->Puts(res);
00153 }
00154
00155 String
00156 GetDescription() const
00157 {
00158 std::ostringstream oss;
00159 Print(oss);
00160 return oss.str();
00161 }
00162
00163 int
00164 Size() const
00165 {
00166 return mNames.size();
00167 }
00168
00169 String
00170 GetName(int i) const
00171 {
00172 return mNames[i];
00173 }
00174
00175 String
00176 GetValue(int i) const
00177 {
00178 return mValues[i];
00179 }
00180
00181 int
00182 GetIndexOfName(CString name) const
00183 {
00184 for (int i=0 ; i<mNames.size() ; i++)
00185 if (mNames[i] == name)
00186 return i;
00187 return Size();
00188 }
00189
00190 int
00191 Diff(const PropertySet* arg) const
00192 {
00193 if (Size() != arg->Size())
00194 {
00195 ILOG_ERROR("Diff: Size differs: " << Size() << " vs " <<
00196 arg->Size());
00197 return 1;
00198 }
00199 int nDiff = 0;
00200 for (int i=0 ; i<Size() ; i++)
00201 {
00202 String name = GetName(i);
00203 int argIndex = arg->GetIndexOfName(name);
00204 if (argIndex == arg->Size())
00205 {
00206 ILOG_DEBUG("arg doesn't have " << name);
00207 nDiff++;
00208 continue;
00209 }
00210 String value = GetValue(i);
00211 String argValue = arg->GetValue(argIndex);
00212 if (value != argValue)
00213 {
00214 ILOG_DEBUG("prop " << name << " differs " << value <<
00215 " vs " << argValue);
00216 nDiff++;
00217 }
00218 }
00219 if (nDiff > 0)
00220 ILOG_ERROR("Found " << nDiff << " differences");
00221 return nDiff;
00222 }
00223
00224 private:
00225
00226 std::vector<String> mNames;
00227 std::vector<String> mValues;
00228
00229 ILOG_CLASS;
00230 };
00231
00232 ILOG_CLASS_INIT(PropertySet, Impala.Util);
00233
00234 void
00235 Append(PropertySet* dst, const PropertySet* src)
00236 {
00237 for (int i=0 ; i<src->Size() ; i++)
00238 dst->Add(src->GetName(i), src->GetValue(i));
00239 }
00240
00241 void
00242 Read(PropertySet* props, IOBuffer* buf)
00243 {
00244 ILOG_FUNCTION(Impala.Util.PropertySet.Read);
00245 if (buf == 0 || !buf->Valid())
00246 {
00247 ILOG_ERROR("Invalid io buffer");
00248 return;
00249 }
00250 String line = buf->ReadLine();
00251 if (line.find(':', 0) != String::npos)
00252 {
00253
00254 StringParser p(line);
00255 String s = p.GetString(':', true);
00256 if (s != "value")
00257 {
00258 ILOG_ERROR("Parse error in bestfile: "<< s <<" unexpected");
00259 return;
00260 }
00261 props->Add("value", p.GetDouble());
00262 line = buf->ReadLine();
00263 }
00264
00265
00266 PropertySet readProps(line);
00267 Append(props, &readProps);
00268 }
00269
00270 bool
00271 Read(PropertySet* props, Persistency::File file)
00272 {
00273 ILOG_FUNCTION(Impala.Util.PropertySet.Read);
00274 IOBuffer* buf = file.GetReadBuffer();
00275 if (buf)
00276 {
00277 Read(props, buf);
00278 delete buf;
00279 return true;
00280 }
00281 return false;
00282 }
00283
00284 bool
00285 Write(PropertySet* props, IOBuffer* buf)
00286 {
00287 ILOG_FUNCTION(Impala.Util.PropertySet.Write);
00288 if(buf == 0 || !buf->Valid())
00289 {
00290 ILOG_ERROR("invalid io buffer");
00291 return false;
00292 }
00293 buf->Puts(props->GetDescription());
00294 return true;
00295 }
00296
00297 bool
00298 Write(PropertySet* props, Persistency::File file)
00299 {
00300 IOBuffer* buf = file.GetWriteBuffer();
00301 if (buf)
00302 {
00303 Write(props, buf);
00304 delete buf;
00305 return true;
00306 }
00307 return false;
00308 }
00309
00310 std::ostream&
00311 operator<< (std::ostream& os, const PropertySet& ps)
00312 {
00313 ps.Print(os);
00314 return os;
00315 }
00316
00317 }
00318 }
00319
00320 #endif
00321