23 #include <visiontransfer/parametervalue.h>
24 #include <visiontransfer/internal/conversionhelpers.h>
26 namespace visiontransfer {
29 using namespace internal;
32 class ParameterValue::Pimpl {
35 Pimpl(
const Pimpl& other);
37 static void copyData(ParameterValue::Pimpl& dst,
const ParameterValue::Pimpl& src);
38 Pimpl& setType(ParameterValue::ParameterType t);
39 Pimpl& setTensorShape(
const std::vector<unsigned int>& shape);
40 bool isDefined()
const;
41 bool isUndefined()
const;
42 bool isTensor()
const;
43 bool isScalar()
const;
44 bool isCommand()
const;
45 unsigned int getTensorDimension()
const;
46 std::vector<unsigned int> getTensorShape()
const;
48 std::vector<double> getTensorData()
const;
50 std::vector<double>& getTensorDataReference() {
return tensorData; };
51 Pimpl& setTensorData(
const std::vector<double>& data);
52 unsigned int getTensorNumElements()
const;
53 unsigned int getTensorCurrentDataSize()
const;
54 ParameterValue::ParameterType getType()
const {
return type; }
55 double& tensorElementAt(
unsigned int x);
56 double& tensorElementAt(
unsigned int y,
unsigned int x);
57 double& tensorElementAt(
unsigned int z,
unsigned int y,
unsigned int x);
59 template<
typename T> Pimpl& setValue(T t);
60 template<
typename T> T getValue()
const;
61 template<
typename T> T getWithDefault(
const T& deflt)
const {
return (type==TYPE_UNDEFINED) ? deflt : getValue<T>(); }
65 std::string stringVal;
66 unsigned int tensorNumElements;
67 std::vector<unsigned int> tensorShape;
68 std::vector<double> tensorData;
70 ParameterValue::ParameterType type;
73 static std::string sanitizeString(
const std::string& s,
unsigned int maxLength=4096);
77 std::string ParameterValue::Pimpl::sanitizeString(
const std::string& s,
unsigned int maxLength ) {
78 std::ostringstream ss;
79 const std::string whitelist(
"-+_,.:@/ ");
81 for (
const char c: s) {
82 if (std::isalnum(c) || whitelist.find(c) != std::string::npos) {
87 if (++len > maxLength)
break;
92 void ParameterValue::Pimpl::copyData(ParameterValue::Pimpl& dst,
const ParameterValue::Pimpl& src) {
93 dst.numVal = src.numVal;
94 dst.stringVal = src.stringVal;
95 dst.tensorNumElements = src.tensorNumElements;
96 dst.tensorShape = src.tensorShape;
97 dst.tensorData = src.tensorData;
101 ParameterValue::Pimpl::Pimpl()
102 : numVal(0.0), type(TYPE_UNDEFINED)
105 ParameterValue::Pimpl::Pimpl(
const ParameterValue::Pimpl& other)
107 copyData(*
this, other);
109 ParameterValue::Pimpl::~Pimpl()
113 ParameterValue::Pimpl& ParameterValue::Pimpl::setType(ParameterValue::ParameterType t) {
118 ParameterValue::Pimpl& ParameterValue::Pimpl::setTensorShape(
const std::vector<unsigned int>& shape) {
119 unsigned int dims = (
unsigned int) shape.size();
121 throw std::runtime_error(
"Cannot create a zero-dimensional tensor");
124 for (
unsigned int i=0; i<dims; ++i) {
128 throw std::runtime_error(
"Cannot create a tensor with effective size 0");
130 tensorNumElements = elems;
132 tensorData.reserve(elems);
136 bool ParameterValue::Pimpl::isDefined()
const {
137 return (type!=TYPE_UNDEFINED);
139 bool ParameterValue::Pimpl::isUndefined()
const {
140 return (type==TYPE_UNDEFINED);
142 bool ParameterValue::Pimpl::isTensor()
const {
143 return type==TYPE_TENSOR;
145 bool ParameterValue::Pimpl::isScalar()
const {
148 bool ParameterValue::Pimpl::isCommand()
const {
149 return type==TYPE_COMMAND;
152 unsigned int ParameterValue::Pimpl::getTensorDimension()
const {
153 return (
unsigned int) tensorShape.size();
156 std::vector<unsigned int> ParameterValue::Pimpl::getTensorShape()
const {
160 std::vector<double> ParameterValue::Pimpl::getTensorData()
const {
164 ParameterValue::Pimpl& ParameterValue::Pimpl::setTensorData(
const std::vector<double>& data) {
165 if (data.size() != tensorNumElements)
throw std::runtime_error(
"ParameterValue::Pimpl::setTensorData(): wrong number of elements");
167 setType(ParameterType::TYPE_TENSOR);
170 std::ostringstream os;
171 for (
unsigned int i=0; i<getTensorNumElements(); ++i) {
175 stringVal = os.str();
179 unsigned int ParameterValue::Pimpl::getTensorNumElements()
const {
180 return tensorNumElements;
183 unsigned int ParameterValue::Pimpl::getTensorCurrentDataSize()
const {
184 return (
unsigned int) tensorData.size();
187 double& ParameterValue::Pimpl::tensorElementAt(
unsigned int x) {
192 if (tensorShape.size()==0)
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): not a tensor");
193 if (x>=tensorNumElements)
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): access out of bounds");
194 return tensorData[x];
196 double& ParameterValue::Pimpl::tensorElementAt(
unsigned int y,
unsigned int x) {
197 if (tensorShape.size()!=2)
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): not a tensor of dimension 2");
198 if (y>=tensorShape[0] || x>=tensorShape[1])
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): access out of bounds");
199 return tensorData[y*tensorShape[1] + x];
201 double& ParameterValue::Pimpl::tensorElementAt(
unsigned int z,
unsigned int y,
unsigned int x) {
202 if (tensorShape.size()!=3)
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): not a tensor of dimension 3");
203 if (z>=tensorShape[0] || y>=tensorShape[1] || x>=tensorShape[2])
throw std::runtime_error(
"ParameterValue::Pimpl::tensorElementAt(): access out of bounds");
204 return tensorData[z*tensorShape[1]*tensorShape[2] + y*tensorShape[2] + x];
210 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(
int t) {
212 switch (this->type) {
216 case TYPE_SAFESTRING:
222 numVal = (t==0) ? 0 : 1;
223 stringVal = (t==0) ?
"false" :
"true";
227 throw std::runtime_error(
"Cannot assign a raw scalar to a tensor parameter");
229 throw std::runtime_error(
"Cannot assign a value to an undefined parameter");
235 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(
bool t) {
237 switch (this->type) {
244 case TYPE_SAFESTRING:
247 numVal = (t==
false) ? 0 : 1;
248 stringVal = (t==
false) ?
"false" :
"true";
252 throw std::runtime_error(
"Cannot assign a raw scalar to a tensor parameter");
254 throw std::runtime_error(
"Cannot assign a value to an undefined parameter");
259 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(
double t) {
261 switch (this->type) {
264 case TYPE_SAFESTRING:
274 numVal = (t==0) ? 0 : 1;
275 stringVal = (t==0) ?
"false" :
"true";
279 throw std::runtime_error(
"Cannot assign a raw scalar to a tensor parameter");
281 throw std::runtime_error(
"Cannot assign a value to an undefined parameter");
287 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(
const char* t) {
289 switch (this->type) {
291 case TYPE_SAFESTRING:
293 stringVal = sanitizeString(t);
294 numVal = atof(stringVal.c_str());
306 if (!std::strncmp(
"true", t, 4) || !std::strncmp(
"True", t, 4)) {
308 }
else if (!std::strncmp(
"false", t, 5) || !std::strncmp(
"False", t, 5)) {
316 if (!std::strncmp(
"true", t, 4) || !std::strncmp(
"True", t, 4)) {
319 numVal = atol(t)==0 ? 0 : 1;
321 stringVal = (numVal==0.0) ?
"false" :
"true";
325 throw std::runtime_error(
"Cannot assign a raw scalar to a tensor parameter");
327 throw std::runtime_error(
"Cannot assign a value to an undefined parameter");
333 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(
const std::string& t) {
334 return setValue<const char*>(t.c_str());
337 ParameterValue::Pimpl& ParameterValue::Pimpl::setValue(std::string t) {
338 return setValue<const char*>(t.c_str());
343 int ParameterValue::Pimpl::getValue()
const {
344 switch (this->type) {
345 case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_BOOL:
348 case TYPE_SAFESTRING:
353 throw std::runtime_error(
"Attempted to get tensor parameter as scalar- undefined value");
360 double ParameterValue::Pimpl::getValue()
const {
361 switch (this->type) {
362 case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_BOOL:
363 return (
double) numVal;
365 case TYPE_SAFESTRING:
367 return (
double) numVal;
370 throw std::runtime_error(
"Attempted to get tensor parameter as scalar- undefined value");
377 bool ParameterValue::Pimpl::getValue()
const {
378 switch (this->type) {
379 case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_BOOL:
380 return (
bool) numVal;
382 case TYPE_SAFESTRING:
384 return (
bool) numVal;
387 throw std::runtime_error(
"Attempted to get tensor parameter as scalar- undefined value");
394 std::string ParameterValue::Pimpl::getValue()
const {
395 switch (this->type) {
396 case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_BOOL:
400 case TYPE_STRING:
case TYPE_SAFESTRING:
case TYPE_COMMAND:
410 const char* ParameterValue::Pimpl::getValue()
const {
411 switch (this->type) {
412 case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_BOOL:
416 case TYPE_STRING:
case TYPE_SAFESTRING:
case TYPE_COMMAND:
417 return stringVal.c_str();
431 ParameterValue::ParameterValue()
432 : pimpl(new ParameterValue::Pimpl())
436 ParameterValue::ParameterValue(
const ParameterValue& other)
437 : pimpl(new ParameterValue::Pimpl())
439 ParameterValue::Pimpl::copyData(*pimpl, *(other.pimpl));
442 ParameterValue::~ParameterValue() {
446 ParameterValue& ParameterValue::operator=(
const ParameterValue& other) {
447 ParameterValue::Pimpl::copyData(*pimpl, *(other.pimpl));
451 ParameterValue& ParameterValue::setType(ParameterValue::ParameterType t) {
456 ParameterValue& ParameterValue::setTensorShape(
const std::vector<unsigned int>& shape) {
457 pimpl->setTensorShape(shape);
461 bool ParameterValue::isDefined()
const {
462 return pimpl->isDefined();
465 bool ParameterValue::isUndefined()
const {
466 return pimpl->isUndefined();
468 bool ParameterValue::isTensor()
const {
469 return pimpl->isTensor();
471 bool ParameterValue::isScalar()
const {
472 return pimpl->isScalar();
474 bool ParameterValue::isCommand()
const {
475 return pimpl->isCommand();
477 unsigned int ParameterValue::getTensorDimension()
const {
478 return pimpl->getTensorDimension();
480 std::vector<unsigned int> ParameterValue::getTensorShape()
const {
481 return pimpl->getTensorShape();
485 return pimpl->getTensorData();
489 return pimpl->getTensorDataReference();
491 ParameterValue& ParameterValue::setTensorData(
const std::vector<double>& data) {
492 pimpl->setTensorData(data);
495 unsigned int ParameterValue::getTensorNumElements()
const {
496 return pimpl->getTensorNumElements();
498 unsigned int ParameterValue::getTensorCurrentDataSize()
const {
499 return pimpl->getTensorCurrentDataSize();
501 ParameterValue::ParameterType ParameterValue::getType()
const {
502 return pimpl->getType();
504 double& ParameterValue::tensorElementAt(
unsigned int x) {
505 return pimpl->tensorElementAt(x);
507 double& ParameterValue::tensorElementAt(
unsigned int y,
unsigned int x) {
508 return pimpl->tensorElementAt(y, x);
510 double& ParameterValue::tensorElementAt(
unsigned int z,
unsigned int y,
unsigned int x) {
511 return pimpl->tensorElementAt(z, y, x);
517 int ParameterValue::getValue()
const {
518 return pimpl->getValue<
int>();
521 bool ParameterValue::getValue()
const {
522 return pimpl->getValue<
bool>();
525 double ParameterValue::getValue()
const {
526 return pimpl->getValue<
double>();
529 std::string ParameterValue::getValue()
const {
530 return pimpl->getValue<std::string>();
533 const char* ParameterValue::getValue()
const {
534 return pimpl->getValue<
const char*>();
539 ParameterValue& ParameterValue::setValue(
int t) {
540 pimpl->setValue<
int>(t);
544 ParameterValue& ParameterValue::setValue(
bool t) {
545 pimpl->setValue<
bool>(t);
549 ParameterValue& ParameterValue::setValue(
double t) {
550 pimpl->setValue<
double>(t);
554 ParameterValue& ParameterValue::setValue(
const char* t) {
555 pimpl->setValue<
const char*>(t);
559 ParameterValue& ParameterValue::setValue(
const std::string& t) {
560 return setValue<const char*>(t.c_str());
563 ParameterValue& ParameterValue::setValue(std::string t) {
564 return setValue<const char*>(t.c_str());