diff --git a/utils/solvers/c++/onelab.h b/utils/solvers/c++/onelab.h index bebb05fce22ca02271d7e44900bd6a4e968aace6..b3ec2a9d0122c1eeaffac6edb68d1bbf6bf927a3 100644 --- a/utils/solvers/c++/onelab.h +++ b/utils/solvers/c++/onelab.h @@ -27,6 +27,8 @@ #ifndef _ONELAB_H_ #define _ONELAB_H_ +#include <time.h> +#include <stdio.h> #include <string> #include <vector> #include <set> @@ -53,7 +55,9 @@ namespace onelab{ std::string _help; // clients that use this parameter std::set<std::string> _clients; - // flag to check if the parameter has been changed since the last run() + // flag to check if the value of the parameter has been changed since the + // last computation (normally this is reset after all the clients have been + // run) bool _changed; // should the parameter be visible in the interface? bool _visible; @@ -125,7 +129,7 @@ namespace onelab{ const std::set<std::string> &getClients() const { return _clients; } static char charSep() { return '\0'; } static double maxNumber() { return 1e200; } - static std::string version() { return "1.02"; } + static std::string version() { return "1.03"; } static std::string getNextToken(const std::string &msg, std::string::size_type &first, char separator=charSep()) @@ -159,6 +163,7 @@ namespace onelab{ << sanitize(getName()) << charSep() << sanitize(getLabel()) << charSep() << sanitize(getHelp()) << charSep() + << (getChanged() ? 1 : 0) << charSep() << (getVisible() ? 1 : 0) << charSep() << (getReadOnly() ? 1 : 0) << charSep() << _attributes.size() << charSep(); @@ -180,6 +185,7 @@ namespace onelab{ setName(getNextToken(msg, pos)); setLabel(getNextToken(msg, pos)); setHelp(getNextToken(msg, pos)); + setChanged(atoi(getNextToken(msg, pos).c_str())); setVisible(atoi(getNextToken(msg, pos).c_str())); setReadOnly(atoi(getNextToken(msg, pos).c_str())); int numAttributes = atoi(getNextToken(msg, pos).c_str()); @@ -202,6 +208,45 @@ namespace onelab{ type = getNextToken(msg, first); name = getNextToken(msg, first); } + static bool fromFile(std::vector<std::string> &msg, + const std::string &fileName) + { + msg.clear(); + FILE *fp = fopen(fileName.c_str(), "rb"); + if(!fp) return false; + char tmp[1000]; + if(!fgets(tmp, sizeof(tmp), fp)) return false; // first line is comment + while(!feof(fp)){ + int numc = 0; + if(!fscanf(fp, "%d ", &numc)) break; // space is important + if(!numc) break; + msg.push_back(""); + for(int i = 0; i < numc; i++) + msg.back() += fgetc(fp); + if(!fgets(tmp, sizeof(tmp), fp)) break; // end of line + } + fclose(fp); + return true; + } + static bool toFile(const std::vector<std::string> &msg, + const std::string &fileName, + const std::string &creator) + { + FILE *fp = fopen(fileName.c_str(), "wb"); + if(!fp) return false; + time_t now; + time(&now); + fprintf(fp, "OneLab database created by %s on %s", + creator.c_str(), ctime(&now)); + for(unsigned int i = 0; i < msg.size(); i++){ + fprintf(fp, "%d ", (int)msg[i].size()); + for(unsigned int j = 0; j < msg[i].size(); j++) + fputc(msg[i][j], fp); + fputc('\n', fp); + } + fclose(fp); + return true; + } }; class parameterLessThan{ @@ -663,17 +708,42 @@ namespace onelab{ (*it)->setChanged(changed); return true; } - // serialize the parameter space (optinally only serialize those parameters + // serialize the parameter space (optionally only serialize those parameters // that depend on the given client) - std::string toChar(const std::string &client="") const + std::vector<std::string> toChar(const std::string &client="") const { - std::string s; + std::vector<std::string> s; std::set<parameter*> ps; _getAllParameters(ps); for(std::set<parameter*>::const_iterator it = ps.begin(); it != ps.end(); it++) - if(client.empty() || (*it)->hasClient(client)) s += (*it)->toChar() + "\n"; + if(client.empty() || (*it)->hasClient(client)) + s.push_back((*it)->toChar()); return s; } + // unserialize the parameter space + bool fromChar(const std::vector<std::string> &msg, const std::string &client="") + { + for(unsigned int i = 0; i < msg.size(); i++){ + std::string version, type, name; + onelab::parameter::getInfoFromChar(msg[i], version, type, name); + if(onelab::parameter::version() != version) return false; + if(type == "number"){ + onelab::number p; p.fromChar(msg[i]); set(p, client); + } + else if(type == "string"){ + onelab::string p; p.fromChar(msg[i]); set(p, client); + } + else if(type == "region"){ + onelab::region p; p.fromChar(msg[i]); set(p, client); + } + else if(type == "function"){ + onelab::function p; p.fromChar(msg[i]); set(p, client); + } + else + return false; + } + return true; + } }; // The onelab client: a class that communicates with the onelab server. Each @@ -713,6 +783,52 @@ namespace onelab{ virtual bool get(std::vector<string> &ps, const std::string &name="") = 0; virtual bool get(std::vector<region> &ps, const std::string &name="") = 0; virtual bool get(std::vector<function> &ps, const std::string &name="") = 0; + std::vector<std::string> toChar() + { + std::vector<std::string> out; + std::vector<number> n; get(n); + for(unsigned int i = 0; i < n.size(); i++) out.push_back(n[i].toChar()); + std::vector<number> s; get(s); + for(unsigned int i = 0; i < s.size(); i++) out.push_back(s[i].toChar()); + std::vector<region> r; get(r); + for(unsigned int i = 0; i < r.size(); i++) out.push_back(r[i].toChar()); + std::vector<region> f; get(f); + for(unsigned int i = 0; i < f.size(); i++) out.push_back(f[i].toChar()); + return out; + } + bool fromChar(const std::vector<std::string> &msg) + { + for(unsigned int i = 0; i < msg.size(); i++){ + std::string version, type, name; + onelab::parameter::getInfoFromChar(msg[i], version, type, name); + if(onelab::parameter::version() != version) return false; + if(type == "number"){ + onelab::number p; p.fromChar(msg[i]); set(p); + } + else if(type == "string"){ + onelab::string p; p.fromChar(msg[i]); set(p); + } + else if(type == "region"){ + onelab::region p; p.fromChar(msg[i]); set(p); + } + else if(type == "function"){ + onelab::function p; p.fromChar(msg[i]); set(p); + } + else + return false; + } + return true; + } + bool toFile(const std::string &fileName) + { + return parameter::toFile(toChar(), fileName, getName()); + } + bool fromFile(const std::string &fileName) + { + std::vector<std::string> msg; + if(parameter::fromFile(msg, fileName)) return fromChar(msg); + return false; + } }; // The onelab server: a singleton that stores the parameter space and @@ -764,11 +880,25 @@ namespace onelab{ { return _parameterSpace.getChanged(client); } - std::string toChar(const std::string &client="") + unsigned int getNumParameters(){ return _parameterSpace.getNumParameters(); } + std::vector<std::string> toChar(const std::string &client="") { return _parameterSpace.toChar(client); } - unsigned int getNumParameters(){ return _parameterSpace.getNumParameters(); } + bool fromChar(const std::vector<std::string> &msg, const std::string &client="") + { + return _parameterSpace.fromChar(msg, client); + } + bool toFile(const std::string &fileName, const std::string &client="") + { + return parameter::toFile(toChar(client), fileName, "onelab server"); + } + bool fromFile(const std::string &fileName, const std::string &client="") + { + std::vector<std::string> msg; + if(parameter::fromFile(msg, fileName)) return fromChar(msg, client); + return false; + } }; class localClient : public client{