5 #ifndef UAVCAN_MARSHAL_ARRAY_HPP_INCLUDED
6 #define UAVCAN_MARSHAL_ARRAY_HPP_INCLUDED
20 #ifndef UAVCAN_CPP_VERSION
21 # error UAVCAN_CPP_VERSION
24 #ifndef UAVCAN_EXCEPTIONS
25 # error UAVCAN_EXCEPTIONS
40 template <
unsigned NumElements_>
45 enum {
NumRowsCols = CompileTimeIntSqrt<NumElements>::Result };
58 template <
typename ElementIterator,
unsigned NumElements>
76 :
first_(first_element_iterator)
170 template <
unsigned Size>
177 enum { SizeBitLen = 0 };
195 #if UAVCAN_EXCEPTIONS
196 throw std::out_of_range(
"uavcan::Array");
205 template <
unsigned MaxSize>
227 #if UAVCAN_EXCEPTIONS
228 throw std::out_of_range(
"uavcan::Array");
231 return SizeType((size_ == 0U) ? 0U : (size_ - 1U));
237 if (size_ >= MaxSize)
239 (void)validateRange(MaxSize);
256 enum { SizeBitLen = RawEncodedSizeType::BitLen };
275 template <
typename T, ArrayMode ArrayMode,
unsigned MaxSize>
277 DynamicArrayBase<MaxSize>, StaticArrayBase<MaxSize> >::Result
295 template <
typename U>
313 using Base::capacity;
323 StaticAssert<IsStringLike>::check();
325 const_cast<BufferType&
>(data_)[size()] = 0;
326 return reinterpret_cast<const char*
>(data_);
361 template <
typename R>
378 template <
unsigned MaxSize, ArrayMode ArrayMode, CastMode CastMode>
381 ,
public Select<ArrayMode == ArrayModeDynamic, DynamicArrayBase<MaxSize>, StaticArrayBase<MaxSize> >::Result
387 enum { IsStringLike = 0 };
392 using ArrayBase::size;
393 using ArrayBase::capacity;
411 template <
typename T, ArrayMode ArrayMode>
class ArrayImpl<T,
ArrayMode, 0>;
423 template <
typename T, ArrayMode ArrayMode,
unsigned MaxSize_>
437 for (
SizeType i = 0; i < size(); i++)
439 const bool last_item = i == (size() - 1);
440 const int res = RawValueType::encode(Base::at(i), codec, last_item ? tao_mode :
TailArrayOptDisabled);
451 StaticAssert<IsDynamic>::check();
452 const bool self_tao_enabled = isOptimizedTailArray(tao_mode);
453 if (!self_tao_enabled)
473 for (
SizeType i = 0; i < size(); i++)
475 const bool last_item = i == (size() - 1);
477 const int res = RawValueType::decode(value, codec, last_item ? tao_mode :
TailArrayOptDisabled);
488 # pragma GCC diagnostic push
489 # pragma GCC diagnostic ignored "-Wtype-limits"
493 StaticAssert<IsDynamic>::check();
495 if (isOptimizedTailArray(tao_mode))
509 if (size() == MaxSize_)
511 return -ErrInvalidMarshalData;
525 if (
static_cast<unsigned>(sz) > MaxSize_)
527 return -ErrInvalidMarshalData;
534 return decodeImpl(codec, tao_mode,
FalseType());
540 # pragma GCC diagnostic pop
543 template <
typename InputIter>
546 StaticAssert<IsDynamic>::check();
551 const Analyzer analyzer(src_row_major);
553 switch (analyzer.detectOptimalPackingMode())
555 case Analyzer::PackingModeEmpty:
559 case Analyzer::PackingModeScalar:
561 this->push_back(
ValueType(*src_row_major));
564 case Analyzer::PackingModeDiagonal:
566 for (
int i = 0; i < Analyzer::NumRowsCols; i++)
568 this->push_back(
ValueType(*analyzer.accessElementAtRowCol(i, i)));
572 case Analyzer::PackingModeSymmetric:
574 for (
int row = 0; row < Analyzer::NumRowsCols; row++)
576 for (
int col = row; col < Analyzer::NumRowsCols; col++)
578 this->push_back(
ValueType(*analyzer.accessElementAtRowCol(row, col)));
581 UAVCAN_ASSERT(this->size() == Analyzer::NumElementsInTriangle);
584 case Analyzer::PackingModeFull:
586 InputIter it = src_row_major;
587 for (
unsigned index = 0; index < MaxSize; index++, it++)
601 template <
typename ScalarType,
typename OutputIter>
604 StaticAssert<IsDynamic>::check();
607 if (this->size() == Traits::NumRowsCols || this->size() == 1)
609 OutputIter it = dst_row_major;
610 for (
unsigned index = 0; index < MaxSize; index++)
612 if (Traits::isIndexOnDiagonal(index))
614 const SizeType source_index =
SizeType((this->size() == 1) ? 0 : (index / Traits::NumRowsCols));
615 *it++ = ScalarType(this->at(source_index));
619 *it++ = ScalarType(0);
623 else if (this->size() == Traits::NumElementsInTriangle)
625 OutputIter it = dst_row_major;
627 for (
int row = 0; row < Traits::NumRowsCols; row++)
629 for (
int col = 0; col < Traits::NumRowsCols; col++)
633 *it++ = ScalarType(this->at(source_index));
640 *it++ = *(dst_row_major + Traits::computeElementIndexAtRowCol(col, row));
644 UAVCAN_ASSERT(source_index == Traits::NumElementsInTriangle);
646 else if (this->size() == MaxSize)
648 OutputIter it = dst_row_major;
649 for (
SizeType index = 0; index < MaxSize; index++)
651 *it++ = ScalarType(this->at(index));
667 using Base::capacity;
670 enum { MaxSize = MaxSize_ };
673 MinBitLen = (IsDynamic == 0)
674 ? (
static_cast<unsigned>(RawValueType::MinBitLen) *
static_cast<unsigned>(MaxSize))
679 MaxBitLen =
static_cast<unsigned>(Base::SizeBitLen) +
680 static_cast<unsigned>(RawValueType::MaxBitLen) *
static_cast<unsigned>(MaxSize)
709 RawValueType::extendDataTypeSignature(signature);
712 bool empty()
const {
return size() == 0; }
721 Base::at(
SizeType(size() - 1)) = value;
729 if (new_size > size())
737 else if (new_size < size())
763 template <
typename R>
765 sizeof((*(
reinterpret_cast<const R*
>(0)))[0]),
bool>::Type
768 if (size() != rhs.size())
772 for (
SizeType i = 0; i < size(); i++)
774 if (!(Base::at(i) == rhs[i]))
789 template <
typename R>
791 sizeof((*(
reinterpret_cast<const R*
>(0)))[0]),
bool>::Type
794 if (size() != rhs.size())
798 for (
SizeType i = 0; i < size(); i++)
818 return std::strncmp(Base::c_str(), chr, MaxSize) == 0;
832 StaticAssert<Base::IsStringLike>::check();
833 StaticAssert<IsDynamic>::check();
852 StaticAssert<Base::IsStringLike>::check();
853 StaticAssert<IsDynamic>::check();
868 template <uavcan::ArrayMode RhsArrayMode,
unsigned RhsMaxSize>
872 StaticAssert<IsDynamic>::check();
873 for (
typename Rhs::SizeType i = 0; i < rhs.
size(); i++)
887 template <
typename A>
890 StaticAssert<Base::IsStringLike>::check();
891 StaticAssert<IsDynamic>::check();
895 (
sizeof(
A) <=
sizeof(
long long))>::check();
911 for (
int i = 0; i <
min(ret,
int(max_size)); i++)
928 StaticAssert<Base::IsStringLike>::check();
930 for (
SizeType i = 0; i < size(); i++)
932 const int x = Base::at(i);
933 if ((
x <=
'z') && (
x >=
'a'))
935 Base::at(i) =
static_cast<ValueType>(
x + (
'Z' -
'z'));
942 StaticAssert<Base::IsStringLike>::check();
944 for (
SizeType i = 0; i < size(); i++)
946 const int x = Base::at(i);
947 if ((
x <=
'Z') && (
x >=
'A'))
949 Base::at(i) =
static_cast<ValueType>(
x - (
'Z' -
'z'));
959 template <
typename ScalarType>
962 packSquareMatrixImpl<const ScalarType*>(src_row_major);
972 if (this->size() == MaxSize)
975 for (
SizeType i = 0; i < MaxSize; i++)
977 matrix[i] = this->at(i);
979 packSquareMatrix(matrix);
981 else if (this->size() == 0)
987 #if UAVCAN_EXCEPTIONS
988 throw std::out_of_range(
"uavcan::Array::packSquareMatrix()");
1005 template <
typename R>
1007 sizeof((
reinterpret_cast<const R*
>(0))->size())>::Type
1008 packSquareMatrix(
const R& src_row_major)
1010 if (src_row_major.size() == MaxSize)
1012 packSquareMatrixImpl(src_row_major.begin());
1014 else if (src_row_major.size() == 0)
1020 #if UAVCAN_EXCEPTIONS
1021 throw std::out_of_range(
"uavcan::Array::packSquareMatrix()");
1033 template <
typename ScalarType>
1036 unpackSquareMatrixImpl<ScalarType, ScalarType*>(dst_row_major);
1046 unpackSquareMatrix(matrix);
1049 for (
unsigned i = 0; i < MaxSize; i++)
1051 this->push_back(matrix[i]);
1062 template <
typename R>
1064 sizeof((
reinterpret_cast<const R*
>(0))->size())>::Type
1065 unpackSquareMatrix(R& dst_row_major)
const
1067 if (dst_row_major.size() == MaxSize)
1069 #if UAVCAN_CPP_VERSION > UAVCAN_CPP03
1070 typedef typename RemoveReference<decltype(*dst_row_major.begin())>::Type RhsValueType;
1071 unpackSquareMatrixImpl<RhsValueType>(dst_row_major.begin());
1073 unpackSquareMatrixImpl<typename R::value_type>(dst_row_major.begin());
1078 #if UAVCAN_EXCEPTIONS
1079 throw std::out_of_range(
"uavcan::Array::unpackSquareMatrix()");
1098 template <
typename R,
typename T, ArrayMode ArrayMode,
unsigned MaxSize>
1103 return lhs.operator==(rhs);
1106 template <
typename R,
typename T, ArrayMode ArrayMode,
unsigned MaxSize>
1108 inline typename EnableIf<!IsSameType<R, Array<T, ArrayMode, MaxSize> >::Result,
bool>::Type
1111 return lhs.operator!=(rhs);
1119 template <
unsigned MaxSize>
1130 template <
typename T, ArrayMode ArrayMode,
unsigned MaxSize>
1137 if (c >= 32 && c <= 126)
1141 static const char Good[] = {
'\n',
'\r',
'\t'};
1142 for (
unsigned i = 0; i <
sizeof(Good) /
sizeof(Good[0]); i++)
1152 template <
typename Stream>
1159 if ((i + 1) < array.
size())
1167 template <
typename Stream>
1173 const int c = array.
at(i);
1174 if (c < 32 || c > 126)
1176 char nibbles[2] = {char((c >> 4) & 0xF), char(c & 0xF)};
1177 for (
int k = 0; k < 2; k++)
1179 nibbles[k] = char(nibbles[k] +
'0');
1180 if (nibbles[k] >
'9')
1182 nibbles[k] = char(nibbles[k] +
'A' -
'9' - 1);
1185 s <<
"\\x" << nibbles[0] << nibbles[1];
1189 if (c ==
'"' || c ==
'\\')
1199 struct SelectorStringLike { };
1200 struct SelectorPrimitives { };
1201 struct SelectorObjects { };
1203 template <
typename Stream>
1206 bool printable_only =
true;
1209 if (!isNiceCharacter(array[i]))
1211 printable_only =
false;
1217 streamCharacters(
s, array);
1221 streamPrimitives(
s, array);
1223 streamCharacters(
s, array);
1227 template <
typename Stream>
1230 streamPrimitives(
s, array);
1233 template <
typename Stream>
1244 for (
int pos = 0; pos <
level; pos++)
1257 template <
typename Stream>
1260 typedef typename Select<ArrayType::IsStringLike, SelectorStringLike,
1261 typename Select<IsPrimitiveType<typename ArrayType::RawValueType>::Result,
1263 SelectorObjects>::Result >::Result Type;
1264 genericStreamImpl(
s, array,
level, Type());
1270 #endif // UAVCAN_MARSHAL_ARRAY_HPP_INCLUDED