Using struct bit field for transit edge flags.

This commit is contained in:
Vladimir Byko-Ianko 2017-11-15 11:40:10 +03:00 committed by mpimenov
parent 44ab61e68d
commit 99369a0842
4 changed files with 70 additions and 24 deletions

View file

@ -227,11 +227,18 @@ UNIT_TEST(Transit_EdgeSerialization)
TEST(edge.IsValid(), (edge));
}
{
Edge edge(1 /* start stop id */, 2 /* finish stop id */, 123 /* weight */, 11 /* line id */,
Edge edge(1 /* start stop id */, 2 /* finish stop id */, 123 /* weight */, kInvalidLineId,
true /* transfer */, {} /* shape ids */);
TestSerialization(edge);
TEST(edge.IsValid(), (edge));
}
{
Edge edge(1 /* start stop id */, 2 /* finish stop id */, 123 /* weight */, 11 /* line id */,
true /* transfer */, {} /* shape ids */);
TestSerialization(edge);
// Note. A transfer edge (transfer == true) with a valid line id is not allowable.
TEST(!edge.IsValid(), (edge));
}
}
UNIT_TEST(Transit_TransferSerialization)

View file

@ -261,7 +261,12 @@ public:
(*this)(e.m_shapeIds);
}
void operator()(EdgeFlags & f, char const * /* name */ = nullptr) { (*this)(f.m_flags); }
void operator()(EdgeFlags & f, char const * /* name */ = nullptr)
{
uint8_t flags = 0;
(*this)(flags);
f.SetFlags(flags);
}
void operator()(vector<m2::PointD> & vs, char const * /* name */ = nullptr)
{

View file

@ -227,15 +227,41 @@ bool ShapeId::IsValid() const
}
// EdgeFlags --------------------------------------------------------------------------------------
void EdgeFlags::SetBit(bool bit, uint8_t bitMask)
EdgeFlags::EdgeFlags()
: m_transfer(0)
, m_isShapeIdsEmpty(0)
, m_isShapeIdsSingle(0)
, m_isShapeIdsSame(0)
, m_isShapeIdsReversed(0)
{
if (bit)
m_flags |= bitMask;
else
m_flags &= ~bitMask;
}
string DebugPrint(EdgeFlags const & f) { return strings::to_string(f.GetFlags()); }
uint8_t EdgeFlags::GetFlags() const
{
return m_transfer + m_isShapeIdsEmpty * kEmptyShapeIdsMask +
m_isShapeIdsSingle * kSingleShapeIdMask + m_isShapeIdsSame * kShapeIdIsSameMask +
m_isShapeIdsReversed * kShapeIdIsReversedMask;
}
void EdgeFlags::SetFlags(uint8_t flags)
{
m_transfer = GetBit(flags, kTransferMask);
m_isShapeIdsEmpty = GetBit(flags, kEmptyShapeIdsMask);
m_isShapeIdsSingle = GetBit(flags, kSingleShapeIdMask);
m_isShapeIdsSame = GetBit(flags, kShapeIdIsSameMask);
m_isShapeIdsReversed = GetBit(flags, kShapeIdIsReversedMask);
}
string DebugPrint(EdgeFlags const & f)
{
std::ostringstream ss;
ss << "EdgeFlags [m_transfer:" << f.IsTransfer();
ss << ", m_isShapeIdsEmpty:" << f.IsEmptyShapeIds();
ss << ", m_isShapeIdsSingle:" << f.IsSingleShapeId();
ss << ", m_isShapeIdsSame:" << f.IsShapeIdTheSame();
ss << ", m_isShapeIdsReversed:" << f.IsShapeIdReversed() << "]";
return ss.str();
}
// Edge -------------------------------------------------------------------------------------------
Edge::Edge(StopId stop1Id, StopId stop2Id, Weight weight, LineId lineId, bool transfer,

View file

@ -260,45 +260,53 @@ class EdgeFlags
public:
DECLARE_TRANSIT_TYPE_FRIENDS
bool IsTransfer() const { return IsBit(kTransferMask); }
void SetTransfer(bool transfer) { SetBit(transfer, kTransferMask); }
EdgeFlags();
bool IsTransfer() const { return m_transfer == 1; }
void SetTransfer(bool transfer) { m_transfer = BoolToUint(transfer); }
/// \returns true if |Edge::m_shapeIds| is empty.
bool IsEmptyShapeIds() const { return IsBit(kEmptyShapeIdsMask); }
void SetEmptyShapeIds(bool emptyShapeIds) { SetBit(emptyShapeIds, kEmptyShapeIdsMask); }
bool IsEmptyShapeIds() const { return m_isShapeIdsEmpty == 1; }
void SetEmptyShapeIds(bool emptyShapeIds) { m_isShapeIdsEmpty = BoolToUint(emptyShapeIds); }
/// \returns true if |Edge::m_shapeIds| contains only one item.
bool IsSingleShapeId() const { return IsBit(kSingleShapeIdMask); }
void SetSingleShapeId(bool singleShapeId) { SetBit(singleShapeId, kSingleShapeIdMask); }
bool IsSingleShapeId() const { return m_isShapeIdsSingle == 1; }
void SetSingleShapeId(bool singleShapeId) { m_isShapeIdsSingle = BoolToUint(singleShapeId); }
/// \note It's valid only if IsSingleShapeId() returns true.
/// \returns true if
/// |Edge::m_stop1Id == m_shapeIds[0].m_stop1Id && Edge::m_stop2Id == m_shapeIds[0].m_stop2Id|.
bool IsShapeIdTheSame() const { return IsBit(kShapeIdIsTheSameMask); }
void SetShapeIdTheSame(bool same) { SetBit(same, kShapeIdIsTheSameMask); }
bool IsShapeIdTheSame() const { return m_isShapeIdsSame == 1; }
void SetShapeIdTheSame(bool same) { m_isShapeIdsSame = BoolToUint(same); }
/// \note It's valid only if IsSingleShapeId() returns true.
/// \returns true if
/// |Edge::m_stop1Id == m_shapeIds[0].m_stop2Id && Edge::m_stop2Id == m_shapeIds[0].m_stop1Id|.
bool IsShapeIdReversed() const { return IsBit(kShapeIdIsReversedMask); }
void SetShapeIdReversed(bool reversed) { SetBit(reversed, kShapeIdIsReversedMask); }
bool IsShapeIdReversed() const { return m_isShapeIdsReversed == 1; }
void SetShapeIdReversed(bool reversed) { m_isShapeIdsReversed = BoolToUint(reversed); }
uint8_t GetFlags() const { return m_flags; }
void SetFlags(uint8_t flags) { m_flags = flags; }
uint8_t GetFlags() const;
void SetFlags(uint8_t flags);
private:
bool IsBit(uint8_t bitMask) const { return m_flags & bitMask; }
void SetBit(bool bit, uint8_t bitMask);
uint8_t BoolToUint(bool b) { return static_cast<uint8_t>(b ? 1 : 0); }
uint8_t GetBit(uint8_t flags, uint8_t mask) { return BoolToUint(flags & mask); }
static uint8_t constexpr kTransferMask = 1;
static uint8_t constexpr kEmptyShapeIdsMask = (1 << 1);
static uint8_t constexpr kSingleShapeIdMask = (1 << 2);
static uint8_t constexpr kShapeIdIsTheSameMask = (1 << 3);
static uint8_t constexpr kShapeIdIsSameMask = (1 << 3);
static uint8_t constexpr kShapeIdIsReversedMask = (1 << 4);
uint8_t m_flags = 0;
uint8_t m_transfer : 1;
uint8_t m_isShapeIdsEmpty : 1;
uint8_t m_isShapeIdsSingle : 1;
uint8_t m_isShapeIdsSame : 1;
uint8_t m_isShapeIdsReversed : 1;
};
static_assert(sizeof(EdgeFlags) == 1, "Wrong EdgeFlags size.");
std::string DebugPrint(EdgeFlags const & f);
class Edge