mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-11 09:33:34 +08:00
String-like behavior for arrays
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <cstring>
|
||||
#include <uavcan/internal/impl_constants.hpp>
|
||||
#include <uavcan/internal/util.hpp>
|
||||
#include <uavcan/internal/marshal/type_util.hpp>
|
||||
@@ -113,7 +114,12 @@ class ArrayImpl : public StaticIf<ArrayMode == ArrayModeDynamic,
|
||||
DynamicArrayBase<MaxSize>,
|
||||
StaticArrayBase<MaxSize> >::Result Base;
|
||||
|
||||
typename StorageType<T>::Type data_[MaxSize];
|
||||
public:
|
||||
enum { IsStringLike = IsIntegerSpec<T>::Result && (T::MaxBitLen == 8 || T::MaxBitLen == 7) };
|
||||
|
||||
private:
|
||||
typedef typename StorageType<T>::Type BufferType[MaxSize + (IsStringLike ? 1 : 0)];
|
||||
BufferType data_;
|
||||
|
||||
template <typename U>
|
||||
typename EnableIf<sizeof(U(0) == U())>::Type initialize(int) { std::fill(data_, data_ + MaxSize, U()); }
|
||||
@@ -128,6 +134,14 @@ public:
|
||||
|
||||
ArrayImpl() { initialize<ValueType>(0); }
|
||||
|
||||
const char* c_str() const
|
||||
{
|
||||
StaticAssert<IsStringLike>::check();
|
||||
assert(size() < (MaxSize + 1));
|
||||
const_cast<BufferType&>(data_)[size()] = 0; // Ad-hoc string termination
|
||||
return reinterpret_cast<const char*>(data_);
|
||||
}
|
||||
|
||||
ValueType& at(SizeType pos) { return data_[validateRange(pos)]; }
|
||||
const ValueType& at(SizeType pos) const { return data_[Base::validateRange(pos)]; }
|
||||
|
||||
@@ -167,6 +181,8 @@ class ArrayImpl<IntegerSpec<1, SignednessUnsigned, CastMode>, ArrayMode, MaxSize
|
||||
StaticArrayBase<MaxSize> >::Result ArrayBase;
|
||||
|
||||
public:
|
||||
enum { IsStringLike = 0 };
|
||||
|
||||
typedef typename std::bitset<MaxSize>::reference Reference;
|
||||
typedef typename ArrayBase::SizeType SizeType;
|
||||
|
||||
@@ -328,8 +344,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Comparison operators
|
||||
*/
|
||||
template <typename R>
|
||||
bool operator==(const R& rhs) const
|
||||
typename EnableIf<sizeof(((const R*)(0U))->size()) && sizeof((*((const R*)(0U)))[0]), bool>::Type
|
||||
operator==(const R& rhs) const
|
||||
{
|
||||
if (size() != rhs.size())
|
||||
return false;
|
||||
@@ -338,10 +358,52 @@ public:
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const char* ch) const
|
||||
{
|
||||
if (ch == NULL)
|
||||
return false;
|
||||
return std::strcmp(Base::c_str(), ch) == 0;
|
||||
}
|
||||
|
||||
template <typename R> bool operator!=(const R& rhs) const { return !operator==(rhs); }
|
||||
|
||||
/*
|
||||
* Assign/append operators
|
||||
*/
|
||||
SelfType& operator=(const char* ch)
|
||||
{
|
||||
StaticAssert<Base::IsStringLike>::check();
|
||||
StaticAssert<IsDynamic>::check();
|
||||
Base::clear();
|
||||
while (*ch)
|
||||
push_back(*ch++);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SelfType& operator+=(const char* ch)
|
||||
{
|
||||
StaticAssert<Base::IsStringLike>::check();
|
||||
StaticAssert<IsDynamic>::check();
|
||||
while (*ch)
|
||||
push_back(*ch++);
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef ValueType value_type;
|
||||
typedef SizeType size_type;
|
||||
};
|
||||
|
||||
template <typename R, typename T, ArrayMode ArrayMode, unsigned int MaxSize>
|
||||
inline bool operator==(const R& rhs, const Array<T, ArrayMode, MaxSize>& lhs)
|
||||
{
|
||||
return lhs.operator==(rhs);
|
||||
}
|
||||
|
||||
template <typename R, typename T, ArrayMode ArrayMode, unsigned int MaxSize>
|
||||
inline bool operator!=(const R& rhs, const Array<T, ArrayMode, MaxSize>& lhs)
|
||||
{
|
||||
return lhs.operator!=(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,4 +109,11 @@ class IntegerSpec<1, SignednessSigned, CastMode>; // Invalid instantiation
|
||||
template <Signedness Signedness, CastMode CastMode>
|
||||
class IntegerSpec<0, Signedness, CastMode>; // Invalid instantiation
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct IsIntegerSpec { enum { Result = 0 }; };
|
||||
|
||||
template <unsigned int BitLen, Signedness Signedness, CastMode CastMode>
|
||||
struct IsIntegerSpec<IntegerSpec<BitLen, Signedness, CastMode> > { enum { Result = 1 }; };
|
||||
|
||||
}
|
||||
|
||||
@@ -208,6 +208,8 @@ TEST(Array, Basic)
|
||||
|
||||
ASSERT_TRUE(a1 == v1);
|
||||
ASSERT_FALSE(a1 != v1);
|
||||
ASSERT_TRUE(v1 == a1);
|
||||
ASSERT_FALSE(v1 != a1);
|
||||
ASSERT_FALSE(a1 < v1);
|
||||
|
||||
v1[0] = 9000;
|
||||
@@ -621,3 +623,90 @@ TEST(Array, StaticEncodeDecodeErrors)
|
||||
ASSERT_EQ(0, A::decode(a, sc_rd, uavcan::TailArrayOptEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Array, Copyability)
|
||||
{
|
||||
typedef Array<IntegerSpec<1, SignednessUnsigned, CastModeSaturate>, ArrayModeDynamic, 5> OneBitArray;
|
||||
typedef Array<IntegerSpec<8, SignednessUnsigned, CastModeSaturate>, ArrayModeDynamic, 255> EightBitArray;
|
||||
typedef Array<OneBitArray, ArrayModeDynamic, 255> A;
|
||||
typedef Array<EightBitArray, ArrayModeDynamic, 255> B;
|
||||
typedef EightBitArray C;
|
||||
|
||||
A a;
|
||||
B b;
|
||||
C c;
|
||||
|
||||
A a2 = a;
|
||||
B b2 = b;
|
||||
C c2 = c;
|
||||
|
||||
ASSERT_TRUE(a == a2);
|
||||
ASSERT_TRUE(b == b2);
|
||||
ASSERT_TRUE(c == c2);
|
||||
|
||||
a.push_back(OneBitArray());
|
||||
b.push_back(EightBitArray());
|
||||
c.push_back(42);
|
||||
|
||||
ASSERT_TRUE(a != a2);
|
||||
ASSERT_TRUE(b != b2);
|
||||
ASSERT_TRUE(c != c2);
|
||||
|
||||
a2 = a;
|
||||
b2 = b;
|
||||
c2 = c;
|
||||
|
||||
ASSERT_TRUE(a2 == a);
|
||||
ASSERT_TRUE(b2 == b);
|
||||
ASSERT_TRUE(c2 == c);
|
||||
}
|
||||
|
||||
|
||||
TEST(Array, Strings)
|
||||
{
|
||||
typedef Array<IntegerSpec<8, SignednessUnsigned, CastModeSaturate>, ArrayModeDynamic, 32> A8;
|
||||
typedef Array<IntegerSpec<7, SignednessUnsigned, CastModeSaturate>, ArrayModeDynamic, 32> A7;
|
||||
|
||||
A8 a8;
|
||||
A8 a8_2;
|
||||
A7 a7;
|
||||
|
||||
ASSERT_TRUE(a8 == a7);
|
||||
// cppcheck-suppress duplicateExpression
|
||||
ASSERT_TRUE(a8 == a8);
|
||||
// cppcheck-suppress duplicateExpression
|
||||
ASSERT_TRUE(a7 == a7);
|
||||
ASSERT_TRUE(a8 == "");
|
||||
ASSERT_TRUE(a7 == "");
|
||||
|
||||
a8 = "Hello world!";
|
||||
a7 = "123";
|
||||
ASSERT_TRUE(a8 == "Hello world!");
|
||||
ASSERT_TRUE(a7 == "123");
|
||||
|
||||
a8 = "Our sun is dying.";
|
||||
a7 = "456";
|
||||
ASSERT_TRUE("Our sun is dying." == a8);
|
||||
ASSERT_TRUE("456" == a7);
|
||||
|
||||
a8 += " 123456";
|
||||
a8 += "-789";
|
||||
ASSERT_TRUE("Our sun is dying. 123456-789" == a8);
|
||||
|
||||
ASSERT_TRUE(a8_2 == "");
|
||||
ASSERT_TRUE(a8_2.empty());
|
||||
ASSERT_TRUE(a8_2 != a8);
|
||||
a8_2 = a8;
|
||||
ASSERT_TRUE(a8_2 == "Our sun is dying. 123456-789");
|
||||
ASSERT_TRUE(a8_2 == a8);
|
||||
|
||||
/*
|
||||
* c_str()
|
||||
*/
|
||||
ASSERT_STREQ("", A8().c_str());
|
||||
ASSERT_STREQ("", A7().c_str());
|
||||
ASSERT_STREQ("Our sun is dying. 123456-789", a8_2.c_str());
|
||||
ASSERT_STREQ("Our sun is dying. 123456-789", a8.c_str());
|
||||
ASSERT_STREQ("456", a7.c_str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user