onelab.h (getdp-3.4.0-source.tgz) | : | onelab.h (getdp-3.5.0-source.tgz) | ||
---|---|---|---|---|
// ONELAB - Copyright (C) 2011-2021 Universite de Liege - Universite catholique | // ONELAB - Copyright (C) 2011-2022 Universite de Liege - Universite catholique | |||
// de Louvain | // de Louvain | |||
// | // | |||
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy | |||
// of this software and associated documentation files (the "Software"), to deal | // of this software and associated documentation files (the "Software"), to deal | |||
// in the Software without restriction, including without limitation the rights | // in the Software without restriction, including without limitation the rights | |||
// to use, copy, modify, merge, publish, distribute, and/or sell copies of the | // to use, copy, modify, merge, publish, distribute, and/or sell copies of the | |||
// Software, and to permit persons to whom the Software is furnished to do so, | // Software, and to permit persons to whom the Software is furnished to do so, | |||
// provided that the above copyright notice(s) and this permission notice appear | // provided that the above copyright notice(s) and this permission notice appear | |||
// in all copies of the Software and that both the above copyright notice(s) and | // in all copies of the Software and that both the above copyright notice(s) and | |||
// this permission notice appear in supporting documentation. | // this permission notice appear in supporting documentation. | |||
skipping to change at line 100 | skipping to change at line 100 | |||
void setName(const std::string &name) { _name = name; } | void setName(const std::string &name) { _name = name; } | |||
void setLabel(const std::string &label) { _label = label; } | void setLabel(const std::string &label) { _label = label; } | |||
void setHelp(const std::string &help) { _help = help; } | void setHelp(const std::string &help) { _help = help; } | |||
void setChanged(int changed, const std::string &client = "") | void setChanged(int changed, const std::string &client = "") | |||
{ | { | |||
if(client.size()) { | if(client.size()) { | |||
auto it = _clients.find(client); | auto it = _clients.find(client); | |||
if(it != _clients.end()) it->second = changed; | if(it != _clients.end()) it->second = changed; | |||
} | } | |||
else { | else { | |||
for(auto it = _clients.begin(); | for(auto it = _clients.begin(); it != _clients.end(); it++) | |||
it != _clients.end(); it++) | ||||
it->second = changed; | it->second = changed; | |||
} | } | |||
} | } | |||
void setChangedValue(int value) { _changedValue = value; } | void setChangedValue(int value) { _changedValue = value; } | |||
void setNeverChanged(bool never) | void setNeverChanged(bool never) | |||
{ | { | |||
_changedValue = never ? 0 : defaultChangedValue(); | _changedValue = never ? 0 : defaultChangedValue(); | |||
} | } | |||
void setVisible(bool visible) { _visible = visible; } | void setVisible(bool visible) { _visible = visible; } | |||
void setReadOnly(bool readOnly) { _readOnly = readOnly; } | void setReadOnly(bool readOnly) { _readOnly = readOnly; } | |||
skipping to change at line 183 | skipping to change at line 182 | |||
{ | { | |||
if(client.size()) { | if(client.size()) { | |||
auto it = _clients.find(client); | auto it = _clients.find(client); | |||
if(it != _clients.end()) | if(it != _clients.end()) | |||
return it->second; | return it->second; | |||
else | else | |||
return 0; | return 0; | |||
} | } | |||
else { | else { | |||
int changed = 0; | int changed = 0; | |||
for(auto it = _clients.begin(); | for(auto it = _clients.begin(); it != _clients.end(); it++) { | |||
it != _clients.end(); it++) { | ||||
changed = std::max(changed, it->second); | changed = std::max(changed, it->second); | |||
} | } | |||
return changed; | return changed; | |||
} | } | |||
} | } | |||
int getChangedValue() const { return _changedValue; } | int getChangedValue() const { return _changedValue; } | |||
bool getNeverChanged() const { return _changedValue ? false : true; } | bool getNeverChanged() const { return _changedValue ? false : true; } | |||
bool getVisible() const { return _visible; } | bool getVisible() const { return _visible; } | |||
bool getReadOnly() const { return _readOnly; } | bool getReadOnly() const { return _readOnly; } | |||
std::string getAttribute(const std::string &key) const | std::string getAttribute(const std::string &key) const | |||
{ | { | |||
auto it = | auto it = _attributes.find(key); | |||
_attributes.find(key); | ||||
if(it != _attributes.end()) return it->second; | if(it != _attributes.end()) return it->second; | |||
return ""; | return ""; | |||
} | } | |||
const std::map<std::string, std::string> &getAttributes() const | const std::map<std::string, std::string> &getAttributes() const | |||
{ | { | |||
return _attributes; | return _attributes; | |||
} | } | |||
const std::map<std::string, int> &getClients() const { return _clients; } | const std::map<std::string, int> &getClients() const { return _clients; } | |||
static char charSep() { return '\0'; } | static char charSep() { return '\0'; } | |||
static double maxNumber() { return 1e200; } | static double maxNumber() { return 1e200; } | |||
skipping to change at line 265 | skipping to change at line 262 | |||
} | } | |||
virtual std::string toChar() const | virtual std::string toChar() const | |||
{ | { | |||
std::ostringstream sstream; | std::ostringstream sstream; | |||
sstream << version() << charSep() << getType() << charSep() | sstream << version() << charSep() << getType() << charSep() | |||
<< sanitize(getName()) << charSep() << sanitize(getLabel()) | << sanitize(getName()) << charSep() << sanitize(getLabel()) | |||
<< charSep() << sanitize(getHelp()) << charSep() | << charSep() << sanitize(getHelp()) << charSep() | |||
<< getChangedValue() << charSep() << (getVisible() ? 1 : 0) | << getChangedValue() << charSep() << (getVisible() ? 1 : 0) | |||
<< charSep() << (getReadOnly() ? 1 : 0) << charSep() | << charSep() << (getReadOnly() ? 1 : 0) << charSep() | |||
<< _attributes.size() << charSep(); | << _attributes.size() << charSep(); | |||
for(auto it = | for(auto it = _attributes.begin(); it != _attributes.end(); it++) | |||
_attributes.begin(); | ||||
it != _attributes.end(); it++) | ||||
sstream << sanitize(it->first) << charSep() << sanitize(it->second) | sstream << sanitize(it->first) << charSep() << sanitize(it->second) | |||
<< charSep(); | << charSep(); | |||
sstream << getClients().size() << charSep(); | sstream << getClients().size() << charSep(); | |||
for(auto it = getClients().begin(); | for(auto it = getClients().begin(); it != getClients().end(); it++) | |||
it != getClients().end(); it++) | ||||
sstream << sanitize(it->first) << charSep() << (it->second ? 1 : 0) | sstream << sanitize(it->first) << charSep() << (it->second ? 1 : 0) | |||
<< charSep(); | << charSep(); | |||
return sstream.str(); | return sstream.str(); | |||
} | } | |||
virtual std::string::size_type fromChar(const std::string &msg) | virtual std::string::size_type fromChar(const std::string &msg) | |||
{ | { | |||
std::string::size_type pos = 0; | std::string::size_type pos = 0; | |||
if(getNextToken(msg, pos) != version()) return 0; | if(getNextToken(msg, pos) != version()) return 0; | |||
if(getNextToken(msg, pos) != getType()) return 0; | if(getNextToken(msg, pos) != getType()) return 0; | |||
setName(getNextToken(msg, pos)); | setName(getNextToken(msg, pos)); | |||
skipping to change at line 357 | skipping to change at line 351 | |||
<< ", \"name\":\"" << sanitizeJSON(getName()) << "\""; | << ", \"name\":\"" << sanitizeJSON(getName()) << "\""; | |||
if(getLabel().size()) | if(getLabel().size()) | |||
sstream << ", \"label\":\"" << sanitizeJSON(getLabel()) << "\""; | sstream << ", \"label\":\"" << sanitizeJSON(getLabel()) << "\""; | |||
if(getHelp().size()) | if(getHelp().size()) | |||
sstream << ", \"help\":\"" << sanitizeJSON(getHelp()) << "\""; | sstream << ", \"help\":\"" << sanitizeJSON(getHelp()) << "\""; | |||
sstream << ", \"changedValue\":" << getChangedValue() | sstream << ", \"changedValue\":" << getChangedValue() | |||
<< ", \"visible\":" << (getVisible() ? "true" : "false") | << ", \"visible\":" << (getVisible() ? "true" : "false") | |||
<< ", \"readOnly\":" << (getReadOnly() ? "true" : "false"); | << ", \"readOnly\":" << (getReadOnly() ? "true" : "false"); | |||
if(_attributes.size()) { | if(_attributes.size()) { | |||
sstream << ", \"attributes\":{ "; | sstream << ", \"attributes\":{ "; | |||
for(auto it = | for(auto it = _attributes.begin(); it != _attributes.end(); it++) { | |||
_attributes.begin(); | ||||
it != _attributes.end(); it++) { | ||||
if(it != _attributes.begin()) sstream << ", "; | if(it != _attributes.begin()) sstream << ", "; | |||
sstream << "\"" << sanitizeJSON(it->first) << "\":\"" | sstream << "\"" << sanitizeJSON(it->first) << "\":\"" | |||
<< sanitizeJSON(it->second) << "\""; | << sanitizeJSON(it->second) << "\""; | |||
} | } | |||
sstream << " }"; | sstream << " }"; | |||
} | } | |||
if(getClients().size()) { | if(getClients().size()) { | |||
sstream << ", \"clients\":{ "; | sstream << ", \"clients\":{ "; | |||
for(auto it = | for(auto it = getClients().begin(); it != getClients().end(); it++) { | |||
getClients().begin(); | ||||
it != getClients().end(); it++) { | ||||
if(it != getClients().begin()) sstream << ", "; | if(it != getClients().begin()) sstream << ", "; | |||
sstream << "\"" << sanitizeJSON(it->first) << "\":" << it->second; | sstream << "\"" << sanitizeJSON(it->first) << "\":" << it->second; | |||
} | } | |||
sstream << " }"; | sstream << " }"; | |||
} | } | |||
return sstream.str(); | return sstream.str(); | |||
} | } | |||
#if defined(HAVE_PICOJSON) | #if defined(HAVE_PICOJSON) | |||
virtual bool fromJSON(const picojson::value::object &par) | virtual bool fromJSON(const picojson::value::object &par) | |||
{ | { | |||
for(auto it = par.begin(); | for(auto it = par.begin(); it != par.end(); ++it) { | |||
it != par.end(); ++it) { | ||||
if(it->first == "name") { | if(it->first == "name") { | |||
if(!it->second.is<std::string>()) return false; | if(!it->second.is<std::string>()) return false; | |||
setName(it->second.get<std::string>()); | setName(it->second.get<std::string>()); | |||
} | } | |||
else if(it->first == "label") { | else if(it->first == "label") { | |||
if(!it->second.is<std::string>()) return false; | if(!it->second.is<std::string>()) return false; | |||
setLabel(it->second.get<std::string>()); | setLabel(it->second.get<std::string>()); | |||
} | } | |||
else if(it->first == "help") { | else if(it->first == "help") { | |||
if(!it->second.is<std::string>()) return false; | if(!it->second.is<std::string>()) return false; | |||
skipping to change at line 411 | skipping to change at line 400 | |||
setVisible(it->second.get<bool>()); | setVisible(it->second.get<bool>()); | |||
} | } | |||
else if(it->first == "readOnly") { | else if(it->first == "readOnly") { | |||
if(!it->second.is<bool>()) return false; | if(!it->second.is<bool>()) return false; | |||
setReadOnly(it->second.get<bool>()); | setReadOnly(it->second.get<bool>()); | |||
} | } | |||
else if(it->first == "attributes") { | else if(it->first == "attributes") { | |||
if(!it->second.is<picojson::object>()) return false; | if(!it->second.is<picojson::object>()) return false; | |||
const picojson::value::object &obj = | const picojson::value::object &obj = | |||
it->second.get<picojson::object>(); | it->second.get<picojson::object>(); | |||
for(auto i = obj.begin(); | for(auto i = obj.begin(); i != obj.end(); ++i) { | |||
i != obj.end(); ++i) { | ||||
std::string key(i->first); | std::string key(i->first); | |||
if(!i->second.is<std::string>()) return false; | if(!i->second.is<std::string>()) return false; | |||
setAttribute(key, i->second.get<std::string>()); | setAttribute(key, i->second.get<std::string>()); | |||
} | } | |||
} | } | |||
else if(it->first == "clients") { | else if(it->first == "clients") { | |||
if(!it->second.is<picojson::object>()) return false; | if(!it->second.is<picojson::object>()) return false; | |||
const picojson::value::object &obj = | const picojson::value::object &obj = | |||
it->second.get<picojson::object>(); | it->second.get<picojson::object>(); | |||
for(auto i = obj.begin(); | for(auto i = obj.begin(); i != obj.end(); ++i) { | |||
i != obj.end(); ++i) { | ||||
std::string client(i->first); | std::string client(i->first); | |||
if(!i->second.is<double>()) return false; | if(!i->second.is<double>()) return false; | |||
addClient(client, (int)i->second.get<double>()); | addClient(client, (int)i->second.get<double>()); | |||
} | } | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
#endif | #endif | |||
}; | }; | |||
skipping to change at line 518 | skipping to change at line 505 | |||
double getMax() const { return _max; } | double getMax() const { return _max; } | |||
double getStep() const { return _step; } | double getStep() const { return _step; } | |||
int getIndex() const { return _index; } | int getIndex() const { return _index; } | |||
const std::vector<double> &getChoices() const { return _choices; } | const std::vector<double> &getChoices() const { return _choices; } | |||
const std::map<double, std::string> &getValueLabels() const | const std::map<double, std::string> &getValueLabels() const | |||
{ | { | |||
return _valueLabels; | return _valueLabels; | |||
} | } | |||
std::string getValueLabel(double value) const | std::string getValueLabel(double value) const | |||
{ | { | |||
auto it = | auto it = _valueLabels.find(value); | |||
_valueLabels.find(value); | ||||
if(it != _valueLabels.end()) return it->second; | if(it != _valueLabels.end()) return it->second; | |||
return ""; | return ""; | |||
} | } | |||
void update(const number &p) | void update(const number &p) | |||
{ | { | |||
addClients(p.getClients()); | addClients(p.getClients()); | |||
setLabel(p.getLabel()); | setLabel(p.getLabel()); | |||
setHelp(p.getHelp()); | setHelp(p.getHelp()); | |||
setVisible(p.getVisible()); | setVisible(p.getVisible()); | |||
setReadOnly(p.getReadOnly()); | setReadOnly(p.getReadOnly()); | |||
skipping to change at line 562 | skipping to change at line 548 | |||
std::ostringstream sstream; | std::ostringstream sstream; | |||
sstream.precision(16); | sstream.precision(16); | |||
sstream << parameter::toChar() << _values.size() << charSep(); | sstream << parameter::toChar() << _values.size() << charSep(); | |||
for(std::size_t i = 0; i < _values.size(); i++) | for(std::size_t i = 0; i < _values.size(); i++) | |||
sstream << _values[i] << charSep(); | sstream << _values[i] << charSep(); | |||
sstream << _min << charSep() << _max << charSep() << _step << charSep() | sstream << _min << charSep() << _max << charSep() << _step << charSep() | |||
<< _index << charSep() << _choices.size() << charSep(); | << _index << charSep() << _choices.size() << charSep(); | |||
for(std::size_t i = 0; i < _choices.size(); i++) | for(std::size_t i = 0; i < _choices.size(); i++) | |||
sstream << _choices[i] << charSep(); | sstream << _choices[i] << charSep(); | |||
sstream << _valueLabels.size() << charSep(); | sstream << _valueLabels.size() << charSep(); | |||
for(auto it = | for(auto it = _valueLabels.begin(); it != _valueLabels.end(); it++) { | |||
_valueLabels.begin(); | ||||
it != _valueLabels.end(); it++) { | ||||
sstream << it->first << charSep() << sanitize(it->second) << charSep(); | sstream << it->first << charSep() << sanitize(it->second) << charSep(); | |||
} | } | |||
return sstream.str(); | return sstream.str(); | |||
} | } | |||
std::string::size_type fromChar(const std::string &msg) | std::string::size_type fromChar(const std::string &msg) | |||
{ | { | |||
std::string::size_type pos = parameter::fromChar(msg); | std::string::size_type pos = parameter::fromChar(msg); | |||
if(!pos) return 0; | if(!pos) return 0; | |||
_values.resize(atoi(getNextToken(msg, pos).c_str())); | _values.resize(atoi(getNextToken(msg, pos).c_str())); | |||
for(std::size_t i = 0; i < _values.size(); i++) | for(std::size_t i = 0; i < _values.size(); i++) | |||
skipping to change at line 612 | skipping to change at line 596 | |||
if(_choices.size()) { | if(_choices.size()) { | |||
sstream << ", \"choices\":[ "; | sstream << ", \"choices\":[ "; | |||
for(std::size_t i = 0; i < _choices.size(); i++) { | for(std::size_t i = 0; i < _choices.size(); i++) { | |||
if(i) sstream << ", "; | if(i) sstream << ", "; | |||
sstream << _choices[i]; | sstream << _choices[i]; | |||
} | } | |||
sstream << " ]"; | sstream << " ]"; | |||
} | } | |||
if(_valueLabels.size()) { | if(_valueLabels.size()) { | |||
sstream << ", \"valueLabels\":{ "; | sstream << ", \"valueLabels\":{ "; | |||
for(auto it = | for(auto it = _valueLabels.begin(); it != _valueLabels.end(); it++) { | |||
_valueLabels.begin(); | ||||
it != _valueLabels.end(); it++) { | ||||
if(it != _valueLabels.begin()) sstream << ", "; | if(it != _valueLabels.begin()) sstream << ", "; | |||
sstream << "\"" << sanitizeJSON(it->second) << "\":" << it->first; | sstream << "\"" << sanitizeJSON(it->second) << "\":" << it->first; | |||
} | } | |||
sstream << " }"; | sstream << " }"; | |||
} | } | |||
sstream << " }"; | sstream << " }"; | |||
return sstream.str(); | return sstream.str(); | |||
} | } | |||
bool fromJSON(const std::string &json) | bool fromJSON(const std::string &json) | |||
{ | { | |||
skipping to change at line 644 | skipping to change at line 626 | |||
fromJSON(par); | fromJSON(par); | |||
return true; | return true; | |||
} | } | |||
#endif | #endif | |||
return false; | return false; | |||
} | } | |||
#if defined(HAVE_PICOJSON) | #if defined(HAVE_PICOJSON) | |||
bool fromJSON(const picojson::value::object &par) | bool fromJSON(const picojson::value::object &par) | |||
{ | { | |||
if(!parameter::fromJSON(par)) return false; | if(!parameter::fromJSON(par)) return false; | |||
for(auto it = par.begin(); | for(auto it = par.begin(); it != par.end(); ++it) { | |||
it != par.end(); ++it) { | ||||
if(it->first == "values") { | if(it->first == "values") { | |||
if(!it->second.is<picojson::array>()) return false; | if(!it->second.is<picojson::array>()) return false; | |||
const picojson::value::array &arr = it->second.get<picojson::array>(); | const picojson::value::array &arr = it->second.get<picojson::array>(); | |||
_values.resize(arr.size()); | _values.resize(arr.size()); | |||
for(std::size_t i = 0; i < arr.size(); i++) { | for(std::size_t i = 0; i < arr.size(); i++) { | |||
if(!arr[i].is<double>()) return false; | if(!arr[i].is<double>()) return false; | |||
_values[i] = arr[i].get<double>(); | _values[i] = arr[i].get<double>(); | |||
} | } | |||
} | } | |||
else if(it->first == "min") { | else if(it->first == "min") { | |||
skipping to change at line 684 | skipping to change at line 665 | |||
_choices.resize(arr.size()); | _choices.resize(arr.size()); | |||
for(std::size_t i = 0; i < arr.size(); i++) { | for(std::size_t i = 0; i < arr.size(); i++) { | |||
if(!arr[i].is<double>()) return false; | if(!arr[i].is<double>()) return false; | |||
_choices[i] = arr[i].get<double>(); | _choices[i] = arr[i].get<double>(); | |||
} | } | |||
} | } | |||
else if(it->first == "valueLabels") { | else if(it->first == "valueLabels") { | |||
if(!it->second.is<picojson::object>()) return false; | if(!it->second.is<picojson::object>()) return false; | |||
const picojson::value::object &obj = | const picojson::value::object &obj = | |||
it->second.get<picojson::object>(); | it->second.get<picojson::object>(); | |||
for(auto i = obj.begin(); | for(auto i = obj.begin(); i != obj.end(); ++i) { | |||
i != obj.end(); ++i) { | ||||
if(!i->second.is<double>()) return false; | if(!i->second.is<double>()) return false; | |||
_valueLabels[i->second.get<double>()] = i->first; | _valueLabels[i->second.get<double>()] = i->first; | |||
} | } | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
#endif | #endif | |||
}; | }; | |||
skipping to change at line 733 | skipping to change at line 713 | |||
{ | { | |||
_choices = choices; | _choices = choices; | |||
} | } | |||
std::string getType() const { return "string"; } | std::string getType() const { return "string"; } | |||
const std::string &getValue() const | const std::string &getValue() const | |||
{ | { | |||
static std::string n(""); | static std::string n(""); | |||
if(_values.empty()) return n; | if(_values.empty()) return n; | |||
return _values[0]; | return _values[0]; | |||
} | } | |||
std::string getValueAsString() const | std::string getValueAsString() const { return getValue(); } | |||
{ | ||||
return getValue(); | ||||
} | ||||
const std::vector<std::string> &getValues() const { return _values; } | const std::vector<std::string> &getValues() const { return _values; } | |||
int getNumValues() const { return (int)_values.size(); } | int getNumValues() const { return (int)_values.size(); } | |||
const std::string &getKind() const { return _kind; } | const std::string &getKind() const { return _kind; } | |||
const std::vector<std::string> &getChoices() const { return _choices; } | const std::vector<std::string> &getChoices() const { return _choices; } | |||
void update(const string &p) | void update(const string &p) | |||
{ | { | |||
addClients(p.getClients()); | addClients(p.getClients()); | |||
setLabel(p.getLabel()); | setLabel(p.getLabel()); | |||
setHelp(p.getHelp()); | setHelp(p.getHelp()); | |||
setVisible(p.getVisible()); | setVisible(p.getVisible()); | |||
skipping to change at line 834 | skipping to change at line 811 | |||
fromJSON(par); | fromJSON(par); | |||
return true; | return true; | |||
} | } | |||
#endif | #endif | |||
return false; | return false; | |||
} | } | |||
#if defined(HAVE_PICOJSON) | #if defined(HAVE_PICOJSON) | |||
bool fromJSON(const picojson::value::object &par) | bool fromJSON(const picojson::value::object &par) | |||
{ | { | |||
if(!parameter::fromJSON(par)) return false; | if(!parameter::fromJSON(par)) return false; | |||
for(auto it = par.begin(); | for(auto it = par.begin(); it != par.end(); ++it) { | |||
it != par.end(); ++it) { | ||||
if(it->first == "values") { | if(it->first == "values") { | |||
if(!it->second.is<picojson::array>()) return false; | if(!it->second.is<picojson::array>()) return false; | |||
const picojson::value::array &arr = it->second.get<picojson::array>(); | const picojson::value::array &arr = it->second.get<picojson::array>(); | |||
_values.resize(arr.size()); | _values.resize(arr.size()); | |||
for(std::size_t i = 0; i < arr.size(); i++) { | for(std::size_t i = 0; i < arr.size(); i++) { | |||
if(!arr[i].is<std::string>()) return false; | if(!arr[i].is<std::string>()) return false; | |||
_values[i] = arr[i].get<std::string>(); | _values[i] = arr[i].get<std::string>(); | |||
} | } | |||
} | } | |||
else if(it->first == "kind") { | else if(it->first == "kind") { | |||
skipping to change at line 879 | skipping to change at line 855 | |||
std::set<string *, parameterLessThan> _strings; | std::set<string *, parameterLessThan> _strings; | |||
std::mutex _mutex; | std::mutex _mutex; | |||
// delete a parameter from the parameter space | // delete a parameter from the parameter space | |||
template <class T> | template <class T> | |||
bool _clear(const std::string &name, const std::string &client, | bool _clear(const std::string &name, const std::string &client, | |||
std::set<T *, parameterLessThan> &ps) | std::set<T *, parameterLessThan> &ps) | |||
{ | { | |||
if(name.empty() && client.size()) { | if(name.empty() && client.size()) { | |||
std::vector<T *> toDelete; | std::vector<T *> toDelete; | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end();) { | |||
it != ps.end();) { | ||||
T *p = *it; | T *p = *it; | |||
if(p->hasClient(client)) { | if(p->hasClient(client)) { | |||
ps.erase(it++); // to avoid invalid iterator | ps.erase(it++); // to avoid invalid iterator | |||
delete p; | delete p; | |||
} | } | |||
else { | else { | |||
it++; | it++; | |||
} | } | |||
} | } | |||
} | } | |||
skipping to change at line 939 | skipping to change at line 914 | |||
// get the parameter matching the given name, or all the parameters in the | // get the parameter matching the given name, or all the parameters in the | |||
// category if no name is given. If we find a given parameter by name, we | // category if no name is given. If we find a given parameter by name, we | |||
// add the client requesting the parameter to the list of clients for this | // add the client requesting the parameter to the list of clients for this | |||
// parameter. This would also need to be locked. | // parameter. This would also need to be locked. | |||
template <class T> | template <class T> | |||
bool _get(std::vector<T> &p, const std::string &name, | bool _get(std::vector<T> &p, const std::string &name, | |||
const std::string &client, std::set<T *, parameterLessThan> &ps) | const std::string &client, std::set<T *, parameterLessThan> &ps) | |||
{ | { | |||
p.clear(); | p.clear(); | |||
if(name.empty()) { | if(name.empty()) { | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) p.push_back(**it); | |||
it != ps.end(); it++) | ||||
p.push_back(**it); | ||||
} | } | |||
else { | else { | |||
T tmp(name); | T tmp(name); | |||
auto it = ps.find(&tmp); | auto it = ps.find(&tmp); | |||
if(it != ps.end()) { | if(it != ps.end()) { | |||
if(client.size()){ | if(client.size()) { | |||
_mutex.lock(); | _mutex.lock(); | |||
(*it)->addClient(client, parameter::defaultChangedValue()); | (*it)->addClient(client, parameter::defaultChangedValue()); | |||
_mutex.unlock(); | _mutex.unlock(); | |||
} | } | |||
p.push_back(**it); | p.push_back(**it); | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
template <class T> | template <class T> | |||
T *_getPtr(std::string name, const std::string client, | T *_getPtr(std::string name, const std::string client, | |||
std::set<T *, parameterLessThan> ps) | std::set<T *, parameterLessThan> ps) | |||
{ | { | |||
T tmp(name); | T tmp(name); | |||
auto it = ps.find(&tmp); | auto it = ps.find(&tmp); | |||
if(it != ps.end()) { | if(it != ps.end()) { | |||
if(client.size()){ | if(client.size()) { | |||
_mutex.lock(); | _mutex.lock(); | |||
(*it)->addClient(client, parameter::defaultChangedValue()); | (*it)->addClient(client, parameter::defaultChangedValue()); | |||
_mutex.unlock(); | _mutex.unlock(); | |||
} | } | |||
return *it; | return *it; | |||
} | } | |||
return nullptr; | return nullptr; | |||
} | } | |||
public: | public: | |||
parameterSpace() {} | parameterSpace() {} | |||
~parameterSpace() { clear(); } | ~parameterSpace() { clear(); } | |||
void clear(const std::string &name = "", const std::string &client = "") | void clear(const std::string &name = "", const std::string &client = "") | |||
{ | { | |||
if(name.empty() && client.empty()) { | if(name.empty() && client.empty()) { | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) delete *it; | |||
it != ps.end(); it++) | ||||
delete *it; | ||||
_numbers.clear(); | _numbers.clear(); | |||
_strings.clear(); | _strings.clear(); | |||
} | } | |||
else { | else { | |||
bool done = _clear(name, client, _numbers); | bool done = _clear(name, client, _numbers); | |||
if(!done) done = _clear(name, client, _strings); | if(!done) done = _clear(name, client, _strings); | |||
} | } | |||
} | } | |||
bool set(const number &p, const std::string &client = "") | bool set(const number &p, const std::string &client = "") | |||
{ | { | |||
skipping to change at line 1026 | skipping to change at line 997 | |||
void getPtr(string **ptr, const std::string &name, | void getPtr(string **ptr, const std::string &name, | |||
const std::string &client = "") | const std::string &client = "") | |||
{ | { | |||
*ptr = _getPtr(name, client, _strings); | *ptr = _getPtr(name, client, _strings); | |||
} | } | |||
void getAllParameters(std::set<parameter *, parameterLessThan> &ps) const | void getAllParameters(std::set<parameter *, parameterLessThan> &ps) const | |||
{ | { | |||
ps.insert(_numbers.begin(), _numbers.end()); | ps.insert(_numbers.begin(), _numbers.end()); | |||
ps.insert(_strings.begin(), _strings.end()); | ps.insert(_strings.begin(), _strings.end()); | |||
} | } | |||
int getNumParameters() | int getNumParameters() { return (int)(_numbers.size() + _strings.size()); } | |||
{ | ||||
return (int)(_numbers.size() + _strings.size()); | ||||
} | ||||
void getParameterNames(std::vector<std::string> &names, | void getParameterNames(std::vector<std::string> &names, | |||
const std::string &search = "") const | const std::string &search = "") const | |||
{ | { | |||
names.clear(); | names.clear(); | |||
if(search.empty()) { | if(search.empty()) { | |||
for(auto &p : _numbers) names.push_back(p->getName()); | for(auto &p : _numbers) names.push_back(p->getName()); | |||
for(auto &p : _strings) names.push_back(p->getName()); | for(auto &p : _strings) names.push_back(p->getName()); | |||
} | } | |||
else{ | else { | |||
try{ | try { | |||
for(auto &p : _numbers) { | for(auto &p : _numbers) { | |||
if(std::regex_search(p->getName(), std::regex(search))) | if(std::regex_search(p->getName(), std::regex(search))) | |||
names.push_back(p->getName()); | names.push_back(p->getName()); | |||
} | } | |||
for(auto &p : _strings) { | for(auto &p : _strings) { | |||
if(std::regex_search(p->getName(), std::regex(search))) | if(std::regex_search(p->getName(), std::regex(search))) | |||
names.push_back(p->getName()); | names.push_back(p->getName()); | |||
} | } | |||
} | } catch(...) { | |||
catch(...) { | ||||
} | } | |||
} | } | |||
} | } | |||
// check if at least one parameter depends on the given client | // check if at least one parameter depends on the given client | |||
bool hasClient(const std::string &client) const | bool hasClient(const std::string &client) const | |||
{ | { | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) | |||
it != ps.end(); it++) | ||||
if((*it)->hasClient(client)) return true; | if((*it)->hasClient(client)) return true; | |||
return false; | return false; | |||
} | } | |||
// check if some parameters have changed (optionnally only check the | // check if some parameters have changed (optionnally only check the | |||
// parameters that depend on a given client) | // parameters that depend on a given client) | |||
int getChanged(const std::string &client = "") const | int getChanged(const std::string &client = "") const | |||
{ | { | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
int changed = 0; | int changed = 0; | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) { | |||
it != ps.end(); it++) { | ||||
changed = std::max(changed, (*it)->getChanged(client)); | changed = std::max(changed, (*it)->getChanged(client)); | |||
} | } | |||
return changed; | return changed; | |||
} | } | |||
// set the changed flag for all the parameters that depend on the given | // set the changed flag for all the parameters that depend on the given | |||
// client (or for all parameters if no client name is provided) | // client (or for all parameters if no client name is provided) | |||
void setChanged(int changed, const std::string &client = "") | void setChanged(int changed, const std::string &client = "") | |||
{ | { | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) | |||
it != ps.end(); it++) | ||||
(*it)->setChanged(changed, client); | (*it)->setChanged(changed, client); | |||
} | } | |||
void thresholdChanged(int threshold, const std::string &client = "") | void thresholdChanged(int threshold, const std::string &client = "") | |||
{ | { | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = ps.begin(); | for(auto it = ps.begin(); it != ps.end(); it++) { | |||
it != ps.end(); it++) { | ||||
int changed = (*it)->getChanged(client); | int changed = (*it)->getChanged(client); | |||
if(changed > threshold) (*it)->setChanged(threshold, client); | if(changed > threshold) (*it)->setChanged(threshold, client); | |||
} | } | |||
} | } | |||
// serialize the parameter space (optionally only serialize those parameters | // serialize the parameter space (optionally only serialize those parameters | |||
// that depend on the given client) | // that depend on the given client) | |||
std::vector<std::string> toChar(const std::string &client = "") const | std::vector<std::string> toChar(const std::string &client = "") const | |||
{ | { | |||
std::vector<std::string> s; | std::vector<std::string> s; | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = | for(auto it = ps.begin(); it != ps.end(); it++) | |||
ps.begin(); | ||||
it != ps.end(); it++) | ||||
if(client.empty() || (*it)->hasClient(client)) { | if(client.empty() || (*it)->hasClient(client)) { | |||
if((*it)->getAttribute("NotInDb") != "True") | if((*it)->getAttribute("NotInDb") != "True") | |||
s.push_back((*it)->toChar()); | s.push_back((*it)->toChar()); | |||
} | } | |||
return s; | return s; | |||
} | } | |||
// unserialize the parameter space | // unserialize the parameter space | |||
bool fromChar(const std::vector<std::string> &msg, | bool fromChar(const std::vector<std::string> &msg, | |||
const std::string &client = "") | const std::string &client = "") | |||
{ | { | |||
skipping to change at line 1150 | skipping to change at line 1111 | |||
std::string t(ctime(&now)); | std::string t(ctime(&now)); | |||
t.resize(t.size() - 1); | t.resize(t.size() - 1); | |||
json.clear(); | json.clear(); | |||
json += "{ \"onelab\":{\n"; | json += "{ \"onelab\":{\n"; | |||
json += " \"creator\":\"" + creator + "\",\n"; | json += " \"creator\":\"" + creator + "\",\n"; | |||
json += " \"date\":\"" + t + "\",\n"; | json += " \"date\":\"" + t + "\",\n"; | |||
json += " \"version\":\"" + parameter::version() + "\",\n"; | json += " \"version\":\"" + parameter::version() + "\",\n"; | |||
json += " \"parameters\":[\n"; | json += " \"parameters\":[\n"; | |||
std::set<parameter *, parameterLessThan> ps; | std::set<parameter *, parameterLessThan> ps; | |||
getAllParameters(ps); | getAllParameters(ps); | |||
for(auto it = | for(auto it = ps.begin(); it != ps.end(); it++) { | |||
ps.begin(); | ||||
it != ps.end(); it++) { | ||||
if(it != ps.begin()) json += ",\n"; | if(it != ps.begin()) json += ",\n"; | |||
if(client.empty() || (*it)->hasClient(client)) { | if(client.empty() || (*it)->hasClient(client)) { | |||
if((*it)->getAttribute("NotInDb") != "True") { | if((*it)->getAttribute("NotInDb") != "True") { | |||
json += " " + (*it)->toJSON(); | json += " " + (*it)->toJSON(); | |||
} | } | |||
} | } | |||
} | } | |||
json += "\n ] }\n}\n"; | json += "\n ] }\n}\n"; | |||
return true; | return true; | |||
} | } | |||
bool fromJSON(const std::string &json, const std::string &client = "") | bool fromJSON(const std::string &json, const std::string &client = "") | |||
{ | { | |||
#if defined(HAVE_PICOJSON) | #if defined(HAVE_PICOJSON) | |||
picojson::value v; | picojson::value v; | |||
std::string err = picojson::parse(v, json); | std::string err = picojson::parse(v, json); | |||
if(err.size()) return false; | if(err.size()) return false; | |||
if(v.is<picojson::object>()){ // full database or single parameter | if(v.is<picojson::object>()) { // full database or single parameter | |||
const picojson::value::object &obj = v.get<picojson::object>(); | const picojson::value::object &obj = v.get<picojson::object>(); | |||
auto it = obj.find("onelab"); | auto it = obj.find("onelab"); | |||
if(it != obj.end()){ // full database | if(it != obj.end()) { // full database | |||
if(!it->second.is<picojson::object>()) return false; | if(!it->second.is<picojson::object>()) return false; | |||
const picojson::value::object &db = it->second.get<picojson::object>() | const picojson::value::object &db = | |||
; | it->second.get<picojson::object>(); | |||
for(auto j = db.begin(); j != db.end(); ++j) { | for(auto j = db.begin(); j != db.end(); ++j) { | |||
if(j->first == "version") { | if(j->first == "version") { | |||
if(!j->second.is<std::string>()) return false; | if(!j->second.is<std::string>()) return false; | |||
if(j->second.get<std::string>() != parameter::version()) | if(j->second.get<std::string>() != parameter::version()) | |||
return false; | return false; | |||
} | } | |||
else if(j->first == "parameters") { | else if(j->first == "parameters") { | |||
if(!j->second.is<picojson::array>()) return false; | if(!j->second.is<picojson::array>()) return false; | |||
const picojson::value::array &arr = j->second.get<picojson::array> | const picojson::value::array &arr = | |||
(); | j->second.get<picojson::array>(); | |||
for(std::size_t k = 0; k < arr.size(); k++) { | for(std::size_t k = 0; k < arr.size(); k++) { | |||
if(!arr[k].is<picojson::object>()) return false; | if(!arr[k].is<picojson::object>()) return false; | |||
const picojson::value::object &par = arr[k].get<picojson::object | const picojson::value::object &par = | |||
>(); | arr[k].get<picojson::object>(); | |||
if(!fromJSON(par, client)) return false; | if(!fromJSON(par, client)) return false; | |||
} | } | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
else{ // single parameter | else { // single parameter | |||
return fromJSON(obj, client); | return fromJSON(obj, client); | |||
} | } | |||
} | } | |||
else if(v.is<picojson::array>()){ // array of parameters | else if(v.is<picojson::array>()) { // array of parameters | |||
const picojson::value::array &arr = v.get<picojson::array>(); | const picojson::value::array &arr = v.get<picojson::array>(); | |||
for(std::size_t k = 0; k < arr.size(); k++) { | for(std::size_t k = 0; k < arr.size(); k++) { | |||
if(!arr[k].is<picojson::object>()) return false; | if(!arr[k].is<picojson::object>()) return false; | |||
const picojson::value::object &par = arr[k].get<picojson::object>(); | const picojson::value::object &par = arr[k].get<picojson::object>(); | |||
if(!fromJSON(par, client)) return false; | if(!fromJSON(par, client)) return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
else{ | else { | |||
return false; | return false; | |||
} | } | |||
#else | #else | |||
return false; | return false; | |||
#endif | #endif | |||
} | } | |||
#if defined(HAVE_PICOJSON) | #if defined(HAVE_PICOJSON) | |||
bool fromJSON(const picojson::value::object &par, const std::string &client | bool fromJSON(const picojson::value::object &par, | |||
= "") | const std::string &client = "") | |||
{ | { | |||
auto it = par.find("type"); | auto it = par.find("type"); | |||
if(it == par.end()) return false; | if(it == par.end()) return false; | |||
if(it->second.to_str() == "number") { | if(it->second.to_str() == "number") { | |||
number p; | number p; | |||
p.fromJSON(par); | p.fromJSON(par); | |||
set(p, client); | set(p, client); | |||
return true; | return true; | |||
} | } | |||
else if(it->second.to_str() == "string") { | else if(it->second.to_str() == "string") { | |||
skipping to change at line 1394 | skipping to change at line 1357 | |||
_parameterSpace.setChanged(changed, client); | _parameterSpace.setChanged(changed, client); | |||
} | } | |||
int getChanged(const std::string &client = "") | int getChanged(const std::string &client = "") | |||
{ | { | |||
return _parameterSpace.getChanged(client); | return _parameterSpace.getChanged(client); | |||
} | } | |||
void thresholdChanged(int value, const std::string &client = "") | void thresholdChanged(int value, const std::string &client = "") | |||
{ | { | |||
_parameterSpace.thresholdChanged(value, client); | _parameterSpace.thresholdChanged(value, client); | |||
} | } | |||
int getNumParameters() | int getNumParameters() { return _parameterSpace.getNumParameters(); } | |||
{ | ||||
return _parameterSpace.getNumParameters(); | ||||
} | ||||
void getParameterNames(std::vector<std::string> &names, | void getParameterNames(std::vector<std::string> &names, | |||
const std::string &search = "") const | const std::string &search = "") const | |||
{ | { | |||
_parameterSpace.getParameterNames(names, search); | _parameterSpace.getParameterNames(names, search); | |||
} | } | |||
std::vector<std::string> toChar(const std::string &client = "") | std::vector<std::string> toChar(const std::string &client = "") | |||
{ | { | |||
return _parameterSpace.toChar(client); | return _parameterSpace.toChar(client); | |||
} | } | |||
bool fromChar(const std::vector<std::string> &msg, | bool fromChar(const std::vector<std::string> &msg, | |||
skipping to change at line 1709 | skipping to change at line 1669 | |||
_gmshClient = nullptr; | _gmshClient = nullptr; | |||
} | } | |||
} | } | |||
GmshClient *getGmshClient() { return _gmshClient; } | GmshClient *getGmshClient() { return _gmshClient; } | |||
virtual bool isNetworkClient() { return true; } | virtual bool isNetworkClient() { return true; } | |||
virtual bool clear(const std::string &name = "") | virtual bool clear(const std::string &name = "") | |||
{ | { | |||
if(!_gmshClient) return false; | if(!_gmshClient) return false; | |||
std::string msg = name; | std::string msg = name; | |||
if(msg.empty()) msg = "*"; | if(msg.empty()) msg = "*"; | |||
_gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_CLEAR, (int)msg.size() | _gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_CLEAR, | |||
, | (int)msg.size(), &msg[0]); | |||
&msg[0]); | ||||
return true; | return true; | |||
} | } | |||
virtual bool set(const number &p) { return _set(p); } | virtual bool set(const number &p) { return _set(p); } | |||
virtual bool set(const string &p) { return _set(p); } | virtual bool set(const string &p) { return _set(p); } | |||
virtual bool get(std::vector<number> &ps, const std::string &name = "") | virtual bool get(std::vector<number> &ps, const std::string &name = "") | |||
{ | { | |||
return _get(ps, name); | return _get(ps, name); | |||
} | } | |||
virtual bool get(std::vector<string> &ps, const std::string &name = "") | virtual bool get(std::vector<string> &ps, const std::string &name = "") | |||
{ | { | |||
skipping to change at line 1786 | skipping to change at line 1746 | |||
#if !defined(BUILD_IOS) | #if !defined(BUILD_IOS) | |||
if(!_gmshClient) { | if(!_gmshClient) { | |||
int res = system(command.c_str()); | int res = system(command.c_str()); | |||
if(res) { | if(res) { | |||
// report error | // report error | |||
} | } | |||
return; | return; | |||
} | } | |||
#endif | #endif | |||
std::string msg = name + parameter::charSep() + command; | std::string msg = name + parameter::charSep() + command; | |||
_gmshClient->SendMessage(GmshSocket::GMSH_CONNECT, (int)msg.size(), &msg[0 | _gmshClient->SendMessage(GmshSocket::GMSH_CONNECT, (int)msg.size(), | |||
]); | &msg[0]); | |||
_numSubClients += 1; | _numSubClients += 1; | |||
} | } | |||
void runSubClient(const std::string &name, const std::string &command) | void runSubClient(const std::string &name, const std::string &command) | |||
{ | { | |||
runNonBlockingSubClient(name, command); | runNonBlockingSubClient(name, command); | |||
waitOnSubClients(); | waitOnSubClients(); | |||
} | } | |||
}; | }; | |||
} // namespace onelab | } // namespace onelab | |||
End of changes. 44 change blocks. | ||||
96 lines changed or deleted | 51 lines changed or added |