34 #include "canopen_error.h"
42 DEBUG_LOG(
"Creating empty value");
47 DEBUG_LOG(
"Creating uint8 value");
53 DEBUG_LOG(
"Creating uint16 value");
59 DEBUG_LOG(
"Creating uint32 value");
65 DEBUG_LOG(
"Creating uint64 value");
71 DEBUG_LOG(
"Creating int8 value");
77 DEBUG_LOG(
"Creating int16 value");
83 DEBUG_LOG(
"Creating int32 value");
89 DEBUG_LOG(
"Creating int64 value");
95 DEBUG_LOG(
"Creating real32 value");
101 DEBUG_LOG(
"Creating real64 value");
107 DEBUG_LOG(
"Creating boolean value");
108 type = Type::boolean;
113 DEBUG_LOG(
"Creating string value");
118 DEBUG_LOG(
"Creating string value");
122 Value::Value(
const std::vector<uint8_t>& value) : octet_string(value) {
123 DEBUG_LOG(
"Creating octet string value");
124 type = Type::octet_string;
131 if (
type != Type::string &&
type != Type::octet_string) {
134 if (data.size() != type_size) {
135 throw canopen_error(
"[Value constructor] Wrong byte vector size: data.size()="+std::to_string(data.size())
153 uint16 = (uint16_t)data[0] + ((uint16_t)data[1] << 8);
158 int16 = (int16_t)data[0] + ((int16_t)data[1] << 8);
163 uint32 = (uint32_t)data[0] + ((uint32_t)data[1] << 8) + ((uint32_t)data[2] << 16) + ((uint32_t)data[3] << 24);
168 int32 = (int32_t)data[0] + ((int32_t)data[1] << 8) + ((int32_t)data[2] << 16) + ((int32_t)data[3] << 24);
173 uint64 = (uint64_t)data[0] + ((uint64_t)data[1] << 8) + ((uint64_t)data[2] << 16) + ((uint64_t)data[3] << 24)
174 + ((uint64_t)data[4] << 32) + ((uint64_t)data[5] << 40) + ((uint64_t)data[6] << 48) + ((uint64_t)data[7] << 56);
179 int64 = (int64_t)data[0] + ((int64_t)data[1] << 8) + ((int64_t)data[2] << 16) + ((int64_t)data[3] << 24)
180 + ((int64_t)data[4] << 32) + ((int64_t)data[5] << 40) + ((int64_t)data[6] << 48) + ((int64_t)data[7] << 56);
186 const uint32_t val = (uint32_t)data[0] + ((uint32_t)data[1] << 8) + ((uint32_t)data[2] << 16) + ((uint32_t)data[3] << 24);
187 real32 =
reinterpret_cast<const float&
>(val);
193 const uint64_t val = (uint64_t)data[0] + ((uint64_t)data[1] << 8) + ((uint64_t)data[2] << 16) + ((uint64_t)data[3] << 24)
194 + ((uint64_t)data[4] << 32) + ((uint64_t)data[5] << 40) + ((uint64_t)data[6] << 48) + ((uint64_t)data[7] << 56);
195 real64 =
reinterpret_cast<const double&
>(val);
200 string = std::string(reinterpret_cast<char const*>(data.data()), data.size());
204 case Type::octet_string: {
209 case Type::boolean: {
210 boolean = (data[0]>0);
214 case Type::invalid: {
215 throw canopen_error(
"[Value constructor] Can't construct invalid value with this constructor.");
224 std::vector<uint8_t> result;
229 result.push_back(uint8);
234 result.push_back(uint16 & 0xFF);
235 result.push_back((uint16>>8) & 0xFF);
240 result.push_back(uint32 & 0xFF);
241 result.push_back((uint32>>8) & 0xFF);
242 result.push_back((uint32>>16) & 0xFF);
243 result.push_back((uint32>>24) & 0xFF);
248 result.push_back(uint64 & 0xFF);
249 result.push_back((uint64>>8) & 0xFF);
250 result.push_back((uint64>>16) & 0xFF);
251 result.push_back((uint64>>24) & 0xFF);
252 result.push_back((uint64>>32) & 0xFF);
253 result.push_back((uint64>>40) & 0xFF);
254 result.push_back((uint64>>48) & 0xFF);
255 result.push_back((uint64>>56) & 0xFF);
260 result.push_back(int8);
265 result.push_back(int16 & 0xFF);
266 result.push_back((int16>>8) & 0xFF);
271 result.push_back(int32 & 0xFF);
272 result.push_back((int32>>8) & 0xFF);
273 result.push_back((int32>>16) & 0xFF);
274 result.push_back((int32>>24) & 0xFF);
279 result.push_back(int64 & 0xFF);
280 result.push_back((int64>>8) & 0xFF);
281 result.push_back((int64>>16) & 0xFF);
282 result.push_back((int64>>24) & 0xFF);
283 result.push_back((int64>>32) & 0xFF);
284 result.push_back((int64>>40) & 0xFF);
285 result.push_back((int64>>48) & 0xFF);
286 result.push_back((int64>>56) & 0xFF);
292 const uint32_t val =
reinterpret_cast<const uint32_t&
>(real32);
293 result.push_back(val & 0xFF);
294 result.push_back((val>>8) & 0xFF);
295 result.push_back((val>>16) & 0xFF);
296 result.push_back((val>>24) & 0xFF);
302 const uint64_t val =
reinterpret_cast<const uint64_t&
>(real64);
303 result.push_back(val & 0xFF);
304 result.push_back((val>>8) & 0xFF);
305 result.push_back((val>>16) & 0xFF);
306 result.push_back((val>>24) & 0xFF);
307 result.push_back((val>>32) & 0xFF);
308 result.push_back((val>>40) & 0xFF);
309 result.push_back((val>>48) & 0xFF);
310 result.push_back((val>>56) & 0xFF);
314 case Type::boolean: {
315 result.push_back(
boolean?0x01:0x00);
320 for (
size_t i=0; i<
string.length(); ++i) {
321 result.push_back((uint8_t)
string[i]);
326 case Type::octet_string: {
331 case Type::invalid: {
332 throw canopen_error(
"[Value::get_bytes] Can't get bytes of invalid type.");
346 throw canopen_error(
"[Value::operator==] Comparing values of different type: "+Utils::type_to_string(type)+
" != "+Utils::type_to_string(other.type)+
".");
354 return uint8 == (uint8_t) other;
358 return uint16 == (uint16_t) other;
362 return uint32 == (uint32_t) other;
366 return uint64 == (uint64_t) other;
370 return int8 == (int8_t) other;
374 return int16 == (int16_t) other;
378 return int32 == (int32_t) other;
382 return int64 == (int64_t) other;
386 return real32 == (float) real32;
390 return real64 == (double) real64;
393 case Type::boolean: {
394 return boolean == (bool)
boolean;
398 return string == (std::string) other;
401 case Type::octet_string: {
406 case Type::invalid: {
407 throw canopen_error(
"[Value::operator==] Comparing invalid type.");
419 using namespace value_printer;
420 std::ostringstream stream;
421 stream << std::dec << *
this;
431 #define CO_VALUE_TYPE_CAST_OP(mtypeout, mtypein) \
432 Value::operator mtypeout() const { \
433 if (type != Type::mtypein ) { \
434 throw canopen_error("[Value cast operator] Illegal conversion from "+Utils::type_to_string(type)+" to " #mtypein "."); \
441 #define CO_VALUE_TYPE_CAST_OP_INT(mtype) CO_VALUE_TYPE_CAST_OP(mtype##_t, mtype)
443 CO_VALUE_TYPE_CAST_OP_INT(uint8);
444 CO_VALUE_TYPE_CAST_OP_INT(uint16);
445 CO_VALUE_TYPE_CAST_OP_INT(uint32);
446 CO_VALUE_TYPE_CAST_OP_INT(uint64);
447 CO_VALUE_TYPE_CAST_OP_INT(int8);
448 CO_VALUE_TYPE_CAST_OP_INT(int16);
449 CO_VALUE_TYPE_CAST_OP_INT(int32);
450 CO_VALUE_TYPE_CAST_OP_INT(int64);
451 CO_VALUE_TYPE_CAST_OP(
bool,
boolean);
452 CO_VALUE_TYPE_CAST_OP(
float, real32);
453 CO_VALUE_TYPE_CAST_OP(
double, real64);
454 CO_VALUE_TYPE_CAST_OP(std::string,
string);
455 CO_VALUE_TYPE_CAST_OP(std::vector<uint8_t>,
octet_string);
461 namespace value_printer {
462 std::ostream &operator<<(std::ostream &os,
Value val) {
467 return os << static_cast<uint32_t>(
static_cast<uint8_t
>(val));
471 return os << static_cast<uint16_t>(val);
475 return os << static_cast<uint32_t>(val);
479 return os << static_cast<uint64_t>(val);
484 return os << static_cast<uint32_t>(
static_cast<int8_t
>(val));
488 return os << static_cast<int16_t>(val);
492 return os << static_cast<int32_t>(val);
496 return os << static_cast<int64_t>(val);
500 return os << static_cast<float>(val);
504 return os << static_cast<double>(val);
507 case Type::boolean: {
508 return os << (static_cast<bool>(val)?
"TRUE":
"FALSE");
512 return os << static_cast<std::string>(val);
515 case Type::octet_string: {
529 return os <<
"[Unknown value type]";
bool operator!=(const Value &other) const
Compares not equal.
std::vector< uint8_t > get_bytes() const
Returns the byte representation (little-endian) as a vector.
std::string to_string() const
Returns the value as a printable string.
This is the base class of all types of exceptions thrown by the KaCanOpen library. It can be used directly like std::runtime_error if there isn't any more specific error class.
static std::string type_to_string(Type type)
Converts data types to a string.
Value()
Constructs an invalid value.
Type type
Tyoe of the value.
bool operator==(const Value &other) const
Compares equal.
static uint8_t get_type_size(Type type)
Returns the size of a data type in bytes.
This class contains a value to be stored in the object dictionary. The value can have one of the type...
std::vector< uint8_t > octet_string
The value if type==Type::octet_string It's seperate because std::vector is non-trivial and should not...