21 #include <visiontransfer/parameterserialization.h> 22 #include <visiontransfer/tokenizer.h> 27 using namespace param;
29 std::string escapeString(
const std::string& str) {
31 s = std::regex_replace(s, std::regex(
"\\\\"),
"\\\\");
32 s = std::regex_replace(s, std::regex(
"\\n"),
"\\n");
33 s = std::regex_replace(s, std::regex(
"\\t"),
"\\t");
37 std::string unescapeString(
const std::string& str) {
39 s = std::regex_replace(s, std::regex(
"([^\\\\])\\\\t"),
"$1\t");
40 s = std::regex_replace(s, std::regex(
"([^\\\\])\\\\n"),
"$1\n");
41 s = std::regex_replace(s, std::regex(
"\\\\\\\\"),
"\\\\");
46 void ParameterSerialization::serializeParameterFullUpdate(std::stringstream& ss,
const Parameter& param) {
48 ss <<
"I\t" << param.getUid() <<
"\t";
50 switch (param.getAccessForConfig()) {
51 case Parameter::ACCESS_READWRITE: ss <<
"2\t";
break;
52 case Parameter::ACCESS_READONLY: ss <<
"1\t";
break;
55 switch (param.getAccessForApi()) {
56 case Parameter::ACCESS_READWRITE: ss <<
"2\t";
break;
57 case Parameter::ACCESS_READONLY: ss <<
"1\t";
break;
61 ss << ((int) param.getInteractionHint()) <<
"\t";
63 ss << (param.getIsModified() ?
"1" :
"0") <<
"\t";
65 ss << param.getName() <<
"\t";
67 ss << param.getModuleName() <<
"\t";
69 ss << param.getCategoryName() <<
"\t";
71 switch (param.getType()) {
72 case ParameterValue::TYPE_INT:
75 case ParameterValue::TYPE_DOUBLE:
78 case ParameterValue::TYPE_BOOL:
81 case ParameterValue::TYPE_STRING:
84 case ParameterValue::TYPE_SAFESTRING:
87 case ParameterValue::TYPE_TENSOR:
90 case ParameterValue::TYPE_COMMAND:
99 ss << param.getUnit() <<
"\t";
101 ss << escapeString(param.getDescription()) <<
"\t";
103 if (!param.isTensor()) {
104 ss << param.getDefault<std::string>() <<
"\t";
106 auto shape = param.getTensorShape();
107 ss << param.getTensorDimension() <<
" ";
108 for (
unsigned int i=0; i<param.getTensorDimension(); ++i) {
109 ss << shape[i] <<
" ";
112 if (param.hasDefault()) {
113 for (
auto e: param.getTensorDefaultData()) {
114 if (first) first =
false;
116 ss << std::setprecision(std::numeric_limits<double>::max_digits10 - 1) << e;
120 for (
int i=0; i<(int) param.getTensorNumElements(); ++i) {
121 if (first) first =
false;
129 if (param.isScalar()) {
130 if (param.hasRange()) {
131 ss << param.getMin<std::string>() <<
"\t";
132 ss << param.getMax<std::string>() <<
"\t";
136 if (param.hasIncrement()) {
137 ss << param.getIncrement<std::string>() <<
"\t";
145 auto opts = param.getOptions<std::string>();
146 for (
unsigned int i=0; i<opts.size(); ++i) {
151 auto descrs = param.getOptionDescriptions();
152 for (
unsigned int i=0; i<descrs.size(); ++i) {
158 if (!param.isTensor()) {
159 if (param.hasCurrent()) {
160 ss << param.getCurrent<std::string>();
162 ss << param.getDefault<std::string>();
165 auto shape = param.getTensorShape();
166 ss << param.getTensorDimension() <<
" ";
167 for (
unsigned int i=0; i<param.getTensorDimension(); ++i) {
168 ss << shape[i] <<
" ";
171 if (param.hasCurrent()) {
172 for (
auto e: param.getTensorData()) {
173 if (first) first =
false;
175 ss << std::setprecision(std::numeric_limits<double>::max_digits10 - 1) << e;
179 for (
int i=0; i<(int) param.getTensorNumElements(); ++i) {
180 if (first) first =
false;
189 Parameter ParameterSerialization::deserializeParameterFullUpdate(
const std::vector<std::string>& toks) {
192 tokrSemi.separators({
";"});
193 if (toks.size() < 19) {
194 throw std::runtime_error(
"deserializeParameterFullUpdate: parameter info string tokens missing");
197 if (toks[0] !=
"I")
throw std::runtime_error(
"deserializeParameterFullUpdate: attempted deserialization of a non-parameter");
200 if (toks[1].size() < 1)
throw std::runtime_error(
"deserializeParameterFullUpdate: malformed UID field");
201 Parameter param = Parameter(toks[1]);
203 if (toks[2].size() != 1)
throw std::runtime_error(
"deserializeParameterFullUpdate: malformed access field");
205 param.setAccessForConfig(Parameter::ACCESS_READWRITE);
206 }
else if (toks[2]==
"1") {
207 param.setAccessForConfig(Parameter::ACCESS_READONLY);
209 param.setAccessForConfig(Parameter::ACCESS_NONE);
212 if (toks[3].size() != 1)
throw std::runtime_error(
"deserializeParameterFullUpdate: malformed access field");
214 param.setAccessForApi(Parameter::ACCESS_READWRITE);
215 }
else if (toks[3]==
"1") {
216 param.setAccessForApi(Parameter::ACCESS_READONLY);
218 param.setAccessForApi(Parameter::ACCESS_NONE);
221 int hint = atol(toks[4].c_str());
222 if ((hint<-1) || (hint>1)) {
223 throw std::runtime_error(
"deserializeParameterFullUpdate: invalid interaction hint");
226 param.setIsModified(toks[5] ==
"1");
228 param.setName(toks[6]);
229 param.setModuleName(toks[7]);
230 param.setCategoryName(toks[8]);
232 if (toks[9].size() != 1)
throw std::runtime_error(
"deserializeParameterFullUpdate: malformed type field");
233 char typ = toks[9][0];
234 bool isTensor = typ ==
'T';
236 case 'i': param.setType(ParameterValue::TYPE_INT);
break;
237 case 'd': param.setType(ParameterValue::TYPE_DOUBLE);
break;
238 case 'b': param.setType(ParameterValue::TYPE_BOOL);
break;
239 case 's': param.setType(ParameterValue::TYPE_STRING);
break;
240 case 'S': param.setType(ParameterValue::TYPE_SAFESTRING);
break;
241 case 'T': param.setType(ParameterValue::TYPE_TENSOR);
break;
242 case 'C': param.setType(ParameterValue::TYPE_COMMAND);
break;
243 default:
throw std::runtime_error(
"deserializeParameterFullUpdate: unhandled type");
246 param.setUnit(toks[10]);
247 param.setDescription(unescapeString(toks[11]));
250 param.setDefault<std::string>(toks[12]);
253 if (param.isScalar()) {
254 if ((toks[13].size()>0) && (toks[13]!=
"-") &&
255 (toks[14].size()>0) && (toks[14]!=
"-")) {
256 param.setRange<std::string>(toks[13], toks[14]);
258 if ((toks[15].size()>0) && (toks[15]!=
"-")) {
259 param.setIncrement<std::string>(toks[15]);
264 auto optvals = tokrSemi.tokenize(toks[16]);
265 auto optdescrs = tokrSemi.tokenize(toks[17]);
266 if ((optvals.size() > 0) && (optvals[0] !=
"")) {
267 param.setOptions<std::string>(optvals, optdescrs);
272 param.setCurrent<std::string>(toks[18]);
274 auto dataToks = tokr.tokenize(toks[18]);
275 if (dataToks.size() < 1) {
276 throw std::runtime_error(
"deserializeParameterFullUpdate: tensor with empty specification");
278 int dim = atol(dataToks[0].c_str());
279 if (dataToks.size() < (
unsigned long) 1+dim) {
280 throw std::runtime_error(
"deserializeParameterFullUpdate: tensor with incomplete specification");
282 std::vector<unsigned int> shape;
283 for (
int i=0; i<dim; ++i) {
284 shape.push_back((
unsigned int) atol(dataToks[1+i].c_str()));
286 param.setAsTensor(shape);
287 int tensorsize = param.getTensorNumElements();
288 if (dataToks.size() != (
unsigned long) tensorsize + 1 + dim) {
289 throw std::runtime_error(
"deserializeParameterFullUpdate: tensor with mismatching data size");
291 std::vector<double> data;
292 for (
int i=0; i<tensorsize; ++i) {
293 data.push_back(atof(dataToks[i+1+dim].c_str()));
295 param.setTensorData(data);
304 void ParameterSerialization::serializeParameterValueChange(std::stringstream& ss,
const Parameter& param) {
305 if (param.isScalar()) {
306 ss <<
"V" <<
"\t" << param.getUid() <<
"\t" << (param.getIsModified()?
"1":
"0") <<
"\t" << param.getCurrent<std::string>();
309 ss <<
"V" <<
"\t" << param.getUid() <<
"\t" << (param.getIsModified()?
"1":
"0") <<
"\t";
310 auto shape = param.getTensorShape();
311 ss << param.getTensorDimension() <<
" ";
312 for (
unsigned int i=0; i<param.getTensorDimension(); ++i) {
313 ss << shape[i] <<
" ";
316 for (
auto e: param.getTensorData()) {
317 if (first) first =
false;
319 ss << std::setprecision(std::numeric_limits<double>::max_digits10 - 1) << e;
324 void ParameterSerialization::deserializeParameterValueChange(
const std::vector<std::string>& toks, Parameter& param) {
326 if (toks.size() < 4)
throw std::runtime_error(
"deserializeParameterValueChange: incomplete data");
328 if (toks[0] !=
"V")
throw std::runtime_error(
"deserializeParameterValueChange: cannot deserialize, not a value change");
329 if (toks[1] != param.getUid())
throw std::runtime_error(
"deserializeParameterValueChange: UID mismatch (bug)");
330 param.setIsModified(toks[2] ==
"1");
331 if (param.isTensor()) {
332 auto dataToks = tokr.tokenize(toks[3]);
333 if (dataToks.size() < 1) {
334 throw std::runtime_error(
"deserializeParameterValueChange: tensor with empty specification");
336 int dim = atol(dataToks[0].c_str());
337 if (dataToks.size() < (
unsigned long) 1+dim) {
338 throw std::runtime_error(
"deserializeParameterValueChange: tensor with incomplete specification");
341 int tensorsize = param.getTensorNumElements();
343 for (
int i=0; i<dim; ++i) {
344 elems *= (
unsigned int) atol(dataToks[1+i].c_str());
346 if (elems != tensorsize) {
348 throw std::runtime_error(
"deserializeParameterValueChange: tensor with mismatching shape");
350 if (dataToks.size() != (
unsigned long) tensorsize + 1 + dim) {
352 throw std::runtime_error(
"deserializeParameterValueChange: tensor with mismatching data size");
354 std::vector<double> data;
355 for (
int i=0; i<tensorsize; ++i) {
356 data.push_back(atof(dataToks[i+1+dim].c_str()));
358 param.setTensorData(data);
363 param.setCurrent<std::string>(toks[3]);
367 void ParameterSerialization::serializeAsyncResult(std::stringstream& ss,
const std::string& requestId,
bool success,
const std::string& message) {
368 ss <<
"R\t" << requestId <<
"\t" << (success?
"1\t":
"0\t") << message;
371 void ParameterSerialization::deserializeAsyncResult(
const std::vector<std::string>& toks, std::string& requestId,
bool& success, std::string& message) {
372 if (toks.size() < 4)
throw std::runtime_error(
"deserializeAsyncResult: incomplete data");
373 if (toks[0] !=
"R")
throw std::runtime_error(
"deserializeAsyncResult: cannot deserialize, not an async result");
375 success = (toks[2] ==
"1");