From 99369a08423d94bcb4931cec238391ba952caf21 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 15 Nov 2017 11:40:10 +0300 Subject: [PATCH] Using struct bit field for transit edge flags. --- .../routing_common_tests/transit_test.cpp | 9 ++++- routing_common/transit_serdes.hpp | 7 +++- routing_common/transit_types.cpp | 38 +++++++++++++++--- routing_common/transit_types.hpp | 40 +++++++++++-------- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/routing_common/routing_common_tests/transit_test.cpp b/routing_common/routing_common_tests/transit_test.cpp index 50fa4a1b3c..2f201fb4ea 100644 --- a/routing_common/routing_common_tests/transit_test.cpp +++ b/routing_common/routing_common_tests/transit_test.cpp @@ -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) diff --git a/routing_common/transit_serdes.hpp b/routing_common/transit_serdes.hpp index c1c59730d3..87b2f9608e 100644 --- a/routing_common/transit_serdes.hpp +++ b/routing_common/transit_serdes.hpp @@ -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 & vs, char const * /* name */ = nullptr) { diff --git a/routing_common/transit_types.cpp b/routing_common/transit_types.cpp index 5795bd71fd..41ebeb6347 100644 --- a/routing_common/transit_types.cpp +++ b/routing_common/transit_types.cpp @@ -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, diff --git a/routing_common/transit_types.hpp b/routing_common/transit_types.hpp index ed004803aa..a675f2d888 100644 --- a/routing_common/transit_types.hpp +++ b/routing_common/transit_types.hpp @@ -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(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