Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 117 additions & 45 deletions include/dbcppp/Iterator.h
Original file line number Diff line number Diff line change
@@ -1,102 +1,174 @@

#pragma once

#include <functional>
#include <iterator>

namespace dbcppp
{
template <class T>
class Iterator
template <class T, class P, typename F>
class Iterator final
{
public:
using self_t = Iterator<T>;
using self_t = Iterator<T, P, F>;
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = const value_type*;
using reference = const value_type&;
using get_t = std::function<reference (std::size_t)>;
using pointer = value_type*;
using reference = value_type&;

Iterator(get_t get, std::size_t i)
: _get(get)
constexpr Iterator(P parent, F get, difference_type i) noexcept
: _parent(parent)
, _get(std::move(get))
, _i(i)
{}
reference operator*() const
inline reference operator*() const
{
return (_parent->*_get)(static_cast<size_t>(_i));
}
inline pointer operator->() const
{
return _get(_i);
return &(_parent->*_get)(static_cast<size_t>(_i));
}
pointer operator->() const
inline reference operator[](difference_type o) const
{
return &_get(_i);
return *(*this + o);
}
self_t& operator++()
constexpr self_t& operator++() noexcept
{
_i++;
++_i;
return *this;
}
self_t operator+(std::size_t o)
constexpr self_t& operator--() noexcept
{
return {_get, _i + o};
--_i;
return *this;
}
self_t operator-(std::size_t o)
constexpr self_t operator++(int) noexcept
{
return {_get, _i + o};
self_t old = *this;
++_i;
return std::move(old);
}
difference_type operator-(const self_t& rhs)
constexpr self_t operator--(int) noexcept
{
self_t old = *this;
--_i;
return std::move(old);
}
constexpr self_t operator+(difference_type o) const noexcept
{
return {_parent, _get, _i + o};
}
constexpr self_t operator-(difference_type o) const noexcept
{
return {_parent, _get, _i - o};
}
constexpr difference_type operator-(const self_t& rhs) const noexcept
{
return _i - rhs._i;
}
self_t& operator+=(std::size_t o)
constexpr self_t& operator+=(difference_type o) noexcept
{
_i += o;
return *this;
}
self_t& operator-=(std::size_t o)
constexpr self_t& operator-=(difference_type o) noexcept
{
_i -= o;
return *this;
}

bool operator==(const self_t& rhs) const
constexpr bool operator==(const self_t& rhs) const noexcept
{
return _i == rhs._i;
}
bool operator!=(const self_t& rhs) const
constexpr bool operator!=(const self_t& rhs) const noexcept
{
return !(*this == rhs);
}
constexpr bool operator<(const self_t& rhs) const noexcept
{
return _i < rhs._i;
}
constexpr bool operator>(const self_t& rhs) const noexcept
{
return _i > rhs._i;
}
constexpr bool operator<=(const self_t& rhs) const noexcept
{
return _i <= rhs._i;
}
constexpr bool operator>=(const self_t& rhs) const noexcept
{
return _i >= rhs._i;
}

private:
get_t _get;
std::size_t _i;
P _parent;
F _get;
difference_type _i;
};
template <class Iterator>
class Iterable
template<class T, class P, typename F>
class Iterable final
{
public:
Iterable(Iterator begin, Iterator end)
: _begin(begin)
, _end(end)
using value_type = const T;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = Iterator<T, P, F>;
using const_iterator = Iterator<const T, P, F>;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;

constexpr Iterable(P parent, F get, size_t size) noexcept
: _parent(std::move(parent))
, _get(std::move(get))
, _size(std::move(size))
{}
Iterator& begin()
inline reference operator[](std::size_t o) const
{
return (_parent->*_get)(o);
}
constexpr iterator begin() noexcept
{
return iterator(_parent, _get, 0);
}
constexpr iterator end() noexcept
{
return iterator(_parent, _get, _size);
}
constexpr const_iterator cbegin() const noexcept
{
return const_iterator(_parent, _get, 0);
}
constexpr const_iterator cend() const noexcept
{
return const_iterator(_parent, _get, static_cast<difference_type>(_size));
}
constexpr const_iterator begin() const noexcept
{
return cbegin();
}
constexpr const_iterator end() const noexcept
{
return cend();
}
constexpr size_type size() const noexcept
{
return _begin;
return _size;
}
Iterator& end()
constexpr bool empty() const noexcept
{
return _end;
return _size == 0;
}

private:
Iterator _begin;
Iterator _end;
P _parent;
F _get;
size_t _size;
};
}
#define DBCPPP_MAKE_ITERABLE(ClassName, Name, Type) \
auto Name() const \
{ \
auto get = std::bind(&ClassName::Name##_Get, this, std::placeholders::_1); \
Iterator<Type> begin(get, 0); \
Iterator<Type> end(get, Name##_Size()); \
return Iterable(begin, end); \
#define DBCPPP_MAKE_ITERABLE(ClassName, Name, Type) \
inline Iterable<const Type, const ClassName*, decltype(&ClassName::Name##_Get)> Name() const noexcept \
{ \
return {this, &ClassName::Name##_Get, Name##_Size()}; \
}
3 changes: 3 additions & 0 deletions include/dbcppp/Message.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ namespace dbcppp
virtual const std::string& Comment() const = 0;
virtual const ISignalGroup& SignalGroups_Get(std::size_t i) const = 0;
virtual uint64_t SignalGroups_Size() const = 0;
/// \brief Optional multiplexor signal when this message is using simple multiplexing with a single switch.
///
/// For advanced multiplexing support, ISignal::SignalMultiplexerValues needs to be followed instead.
virtual const ISignal* MuxSignal() const = 0;

DBCPPP_MAKE_ITERABLE(IMessage, MessageTransmitters, std::string);
Expand Down
25 changes: 22 additions & 3 deletions include/dbcppp/Signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ namespace dbcppp
};
enum class EMultiplexer
{
NoMux, MuxSwitch, MuxValue
NoMux,
MuxSwitch = 1,
MuxValue = 2,
// For advanced multiplexing with ISignalMultiplexerValue, nesting is possible.
// This results in signals being both a multiplexor switch and a multiplexed value.
MuxSwitchAndValue = MuxSwitch | MuxValue
};
enum class EByteOrder
{
Expand All @@ -44,7 +49,7 @@ namespace dbcppp
{
Integer, Float, Double
};

static std::unique_ptr<ISignal> Create(
uint64_t message_size
, std::string&& name
Expand All @@ -65,13 +70,21 @@ namespace dbcppp
, std::string&& comment
, EExtendedValueType extended_value_type
, std::vector<std::unique_ptr<ISignalMultiplexerValue>>&& signal_multiplexer_values);

virtual std::unique_ptr<ISignal> Clone() const = 0;

virtual ~ISignal() = default;
virtual const std::string& Name() const = 0;
virtual EMultiplexer MultiplexerIndicator() const = 0;
/// \brief Single multiplexor value for simple multiplexing.
///
/// Invalid if ISignal::SignalMultiplexerValues is not empty.
virtual uint64_t MultiplexerSwitchValue() const = 0;
/// \brief Least significant bit of the signal.
///
/// \note DBC uses the least signficant bit as start bit for both big and little endian.
/// This means that for big endian, the StartBit points into the highest byte.
/// This differs from FIBEX/Autosar where big endian signals are instead using the least significant bit in the lowest byte as offset.
virtual uint64_t StartBit() const = 0;
virtual uint64_t BitSize() const = 0;
virtual EByteOrder ByteOrder() const = 0;
Expand Down Expand Up @@ -121,6 +134,12 @@ namespace dbcppp
DBCPPP_MAKE_ITERABLE(ISignal, Receivers, std::string);
DBCPPP_MAKE_ITERABLE(ISignal, ValueEncodingDescriptions, IValueEncodingDescription);
DBCPPP_MAKE_ITERABLE(ISignal, AttributeValues, IAttribute);

/// \brief Mapping of this multiplexed signal to specific value ranges of a selected multiplexor switch signals.
///
/// Requires EMultiplexer::MuxValue to be set in MultiplexerIndicator in order to be valid.
/// If empty, simple multiplexing rules by ISignal::MultiplexerSwitchValue and IMessage::MuxSignal apply instead.
/// If not empty, all listed multiplexor signals must match the specified value ranges simultaniously.
DBCPPP_MAKE_ITERABLE(ISignal, SignalMultiplexerValues, ISignalMultiplexerValue);

protected:
Expand Down
2 changes: 1 addition & 1 deletion include/dbcppp/SignalMultiplexerValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
#include <memory>
#include <vector>
#include <functional>
#include <cstdint>

#include "Iterator.h"

namespace dbcppp
{
// Map from values of the multiplexor signal ISignalMultiplexerValue::SwitchName to the parent multiplexed ISignal.
class ISignalMultiplexerValue
{
public:
Expand Down
18 changes: 11 additions & 7 deletions src/DBCAST2Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,16 +351,20 @@ static auto getSignals(const G_Network& gnet, const G_Message& m, Cache const& c
uint64_t multiplexer_switch_value = 0;
if (s.multiplexer_indicator)
{
auto m = *s.multiplexer_indicator;
if (m.substr(0, 1) == "M")
const auto& m = *s.multiplexer_indicator;
if (auto mux_value_pos = m.find('m', 0); mux_value_pos != std::string::npos)
{
multiplexer_indicator = ISignal::EMultiplexer::MuxSwitch;
multiplexer_indicator = ISignal::EMultiplexer(
std::underlying_type_t<ISignal::EMultiplexer>(multiplexer_indicator) |
std::underlying_type_t<ISignal::EMultiplexer>(ISignal::EMultiplexer::MuxValue));
multiplexer_switch_value = std::atoi(m.c_str() + mux_value_pos + 1);
}
else
if (m.find('M', 0) != std::string::npos)
{
multiplexer_indicator = ISignal::EMultiplexer::MuxValue;
std::string value = m.substr(1, m.size());
multiplexer_switch_value = std::atoi(value.c_str());
multiplexer_indicator =
ISignal::EMultiplexer(
std::underlying_type_t<ISignal::EMultiplexer>(multiplexer_indicator) |
std::underlying_type_t<ISignal::EMultiplexer>(ISignal::EMultiplexer::MuxSwitch));
}
}

Expand Down
Loading