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)
78 StaticAssert<(NumElements > 0)>::
check();
83 return first_ + Traits::computeElementIndexAtRowCol(row, col);
89 for (ElementIterator it = first_; index <
NumElements; ++it, ++index)
102 for (ElementIterator it = first_; index <
NumElements; ++it, ++index)
104 if (!Traits::isIndexOnDiagonal(index) && !
isCloseToZero(*it))
108 if (Traits::isIndexOnDiagonal(index) && !
areClose(*it, *first_))
119 for (ElementIterator it = first_; index <
NumElements; ++it, ++index)
121 if (!Traits::isIndexOnDiagonal(index) && !
isCloseToZero(*it))
131 for (
int i = 0; i < Traits::NumRowsCols; ++i)
133 for (
int k = 0; k < Traits::NumRowsCols; ++k)
137 !
areClose(*accessElementAtRowCol(i, k),
138 *accessElementAtRowCol(k, i)))
149 if (areAllElementsNan())
151 return PackingModeEmpty;
155 return PackingModeScalar;
159 return PackingModeDiagonal;
163 return PackingModeSymmetric;
165 return PackingModeFull;
170 template <
unsigned Size>
177 enum { SizeBitLen = 0 };
182 SizeType
size()
const {
return SizeType(Size); }
183 SizeType
capacity()
const {
return SizeType(Size); }
191 if (pos < SizeType(Size))
195 #if UAVCAN_EXCEPTIONS 196 throw std::out_of_range(
"uavcan::Array");
199 return SizeType(Size - 1U);
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
288 (ArrayMode == ArrayModeDynamic)
295 template <
typename U>
298 if (ArrayMode != ArrayModeDynamic)
313 using Base::capacity;
323 StaticAssert<IsStringLike>::check();
325 const_cast<BufferType&
>(data_)[size()] = 0;
326 return reinterpret_cast<const char*
>(data_);
337 ValueType&
at(SizeType pos) {
return data_[Base::validateRange(pos)]; }
338 const ValueType&
at(SizeType pos)
const {
return data_[Base::validateRange(pos)]; }
344 const ValueType&
operator[](SizeType pos)
const {
return at(pos); }
349 ValueType*
begin() {
return data_; }
350 const ValueType*
begin()
const {
return data_; }
351 ValueType*
end() {
return data_ + Base::size(); }
352 const ValueType*
end()
const {
return data_ + Base::size(); }
353 ValueType&
front() {
return at(0U); }
354 const ValueType&
front()
const {
return at(0U); }
355 ValueType&
back() {
return at((Base::size() == 0U) ? 0U : SizeType(Base::size() - 1U)); }
356 const ValueType&
back()
const {
return at((Base::size() == 0U) ? 0U : SizeType(Base::size() - 1U)); }
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;
669 enum { IsDynamic = ArrayMode == ArrayModeDynamic };
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;
727 void resize(SizeType new_size,
const ValueType& filler)
729 if (new_size > size())
731 SizeType cnt = SizeType(new_size - size());
737 else if (new_size < size())
739 SizeType cnt = SizeType(size() - new_size);
756 resize(new_size, ValueType());
763 template <
typename R>
765 sizeof((*(reinterpret_cast<const R*>(0)))[0]),
bool>::Type
766 operator==(
const R& rhs)
const 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();
841 push_back(ValueType(*chr++));
852 StaticAssert<Base::IsStringLike>::check();
853 StaticAssert<IsDynamic>::check();
860 push_back(ValueType(*chr++));
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();
893 StaticAssert<sizeof(A() >=
A(0))>::
check();
895 (
sizeof(
A) <=
sizeof(
long long))>::check();
904 ValueType*
const ptr = Base::end();
906 const SizeType max_size = SizeType(capacity() - size());
909 const int ret =
snprintf(reinterpret_cast<char*>(ptr), SizeType(max_size + 1U), format, value);
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)
974 ValueType matrix[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);
1045 ValueType matrix[MaxSize];
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>
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
Reference at(SizeType pos)
ArrayBase::SizeType SizeType
UAVCAN_EXPORT EnableIf<!IsSameType< R, Array< T, ArrayMode, MaxSize > >::Result, bool >::Type operator!=(const R &rhs, const Array< T, ArrayMode, MaxSize > &lhs)
void appendFormatted(const char *const format, const A value)
int decodeImpl(ScalarCodec &codec, const TailArrayOptimizationMode tao_mode, TrueType)
Dynamic.
const char * c_str() const
struct UAVCAN_EXPORT Select
ValueType & at(SizeType pos)
Base::SizeType SizeType
Minimal width size type.
SizeType capacity() const
EnableIf< sizeof((reinterpret_cast< const R * >0)) -> size()) &&sizeof((*(reinterpret_cast< const R *>(0)))[0])
Array< IntegerSpec< 8, SignednessUnsigned, CastModeSaturate >, ArrayModeDynamic, MaxSize > Type
const ValueType & operator[](SizeType pos) const
EnableIf< sizeof(U(0) >=U())>::Type initialize(int)
static int computeElementIndexAtRowCol(int row, int col)
void unpackSquareMatrix()
const ValueType & at(SizeType pos) const
bool at(SizeType pos) const
UAVCAN_EXPORT bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
static void stream(Stream &s, const ArrayType &array, int level)
ElementIterator accessElementAtRowCol(int row, int col) const
static void genericStreamImpl(Stream &s, const ArrayType &array, int, SelectorPrimitives)
UAVCAN_EXPORT void handleFatalError(const char *msg)
void push_back(const ValueType &value)
class UAVCAN_EXPORT YamlStreamer
void packSquareMatrixImpl(const InputIter src_row_major)
const ValueType & front() const
Reference operator[](SizeType pos)
static void genericStreamImpl(Stream &s, const ArrayType &array, int level, SelectorObjects)
void convertToLowerCaseASCII()
void convertToUpperCaseASCII()
EnableIf< sizeof((reinterpret_cast< const R * >0)) -> bool ::Type isClose(const R &rhs) const
int encodeImpl(ScalarCodec &codec, const TailArrayOptimizationMode tao_mode, FalseType) const
Static.
UAVCAN_EXPORT bool isCloseToZero(const T &x)
SquareMatrixAnalyzer(ElementIterator first_element_iterator)
static void streamPrimitives(Stream &s, const ArrayType &array)
static bool isOptimizedTailArray(TailArrayOptimizationMode tao_mode)
BooleanType< false > FalseType
void packSquareMatrix(const ScalarType(&src_row_major)[MaxSize])
SizeType validateRange(SizeType pos) const
Array< T, ArrayMode, MaxSize > ArrayType
bool operator[](SizeType pos) const
SelfType & operator=(const char *chr)
StorageType< IntegerSpec< IntegerBitLen< EnumMax< MaxSize, 2 >::Result >::Result, SignednessUnsigned, CastModeSaturate > >::Type SizeType
UAVCAN_EXPORT EnableIf<!IsSameType< R, Array< T, ArrayMode, MaxSize > >::Result, bool >::Type operator==(const R &rhs, const Array< T, ArrayMode, MaxSize > &lhs)
void resize(SizeType new_size)
bool operator<(const R &rhs) const
BitSet< MaxSize >::Reference Reference
SizeType validateRange(SizeType pos) const
SelfType & operator+=(const char *chr)
Array< T, ArrayMode, MaxSize_ > SelfType
void resize(SizeType new_size, const ValueType &filler)
TailArrayOptimizationMode
UAVCAN_EXPORT const T & min(const T &a, const T &b)
StorageType< IntegerSpec< IntegerBitLen< EnumMax< Size, 2 >::Result >::Result, SignednessUnsigned, CastModeSaturate > >::Type SizeType
bool operator!=(const R &rhs) const
const ValueType * begin() const
void unpackSquareMatrixImpl(const OutputIter dst_row_major) const
static void fill(T(&a)[Size], R value)
const ValueType * end() const
bool areAllElementsNan() const
StorageType< T >::Type ValueType
Select< ArrayMode==ArrayModeDynamic, DynamicArrayBase< MaxSize >, StaticArrayBase< MaxSize > >::Result Base
static void genericStreamImpl(Stream &s, const ArrayType &array, int, SelectorStringLike)
SizeType capacity() const
PackingMode detectOptimalPackingMode() const
const ValueType & back() const
ArrayImpl< T, ArrayMode, MaxSize > SelfType
ValueType & operator[](SizeType pos)
ArrayImpl< T, ArrayMode, MaxSize_ > Base
int encodeImpl(ScalarCodec &codec, const TailArrayOptimizationMode tao_mode, TrueType) const
Dynamic.
UAVCAN_EXPORT void fill_n(OutputIt first, std::size_t n, const T &value)
IntegerSpec< IntegerBitLen< MaxSize >::Result, SignednessUnsigned, CastModeSaturate > RawEncodedSizeType
IntegerSpec< IntegerBitLen< Size >::Result, SignednessUnsigned, CastModeSaturate > RawEncodedSizeType
static bool isIndexOnDiagonal(unsigned index)
void unpackSquareMatrix(ScalarType(&dst_row_major)[MaxSize]) const
bool operator[](std::size_t pos) const
Select< ArrayMode==ArrayModeDynamic, DynamicArrayBase< MaxSize >, StaticArrayBase< MaxSize > >::Result ArrayBase
static int encode(const SelfType &array, ScalarCodec &codec, const TailArrayOptimizationMode tao_mode)
static int decode(SelfType &array, ScalarCodec &codec, const TailArrayOptimizationMode tao_mode)
struct UAVCAN_EXPORT StaticAssert
const ValueType * const_iterator
UAVCAN_EXPORT bool areClose(const L &left, const R &right)
SquareMatrixTraits< NumElements > Traits
static void extendDataTypeSignature(DataTypeSignature &signature)
int decodeImpl(ScalarCodec &codec, const TailArrayOptimizationMode tao_mode, FalseType)
Static.
static void streamCharacters(Stream &s, const ArrayType &array)
int snprintf(char *out, std::size_t maxlen, const char *format,...)
static bool isNiceCharacter(int c)
StorageType< T >::Type ValueType
This is the actual stored element type.
T RawValueType
This may be not the same as the element type.
bool operator==(const char *chr) const
const ElementIterator first_
SelfType & operator+=(const Array< T, RhsArrayMode, RhsMaxSize > &rhs)
static const uavcan::int16_t ErrLogic
Internal logic error.