31#ifndef DW_FRAMEWORK_PORTDESCRIPTOR_HPP_
32#define DW_FRAMEWORK_PORTDESCRIPTOR_HPP_
34#include <dwshared/dwfoundation/dw/core/container/StringView.hpp>
36#include <dwshared/dwfoundation/dw/core/language/cxx20.hpp>
37#include <dwshared/dwfoundation/dw/core/language/Tuple.hpp>
38#include <dwshared/dwfoundation/dw/core/safety/Safety.hpp>
51template <
typename... Args>
55 return dw::core::make_tuple<Args...>(std::forward<Args>(args)...);
65template <
typename PortType,
size_t ArraySize,
size_t NameSize>
83 ,
name{std::move(name_)}
90#define DW_PORT_TYPE_NAME_STRING_VIEW_IMPL(TYPE_NAME_STR) TYPE_NAME_STR##_sv
91#define DW_PORT_TYPE_NAME_STRING_VIEW(TYPE_NAME) DW_PORT_TYPE_NAME_STRING_VIEW_IMPL(#TYPE_NAME)
92#define DW_DESCRIBE_PORT(TYPE_NAME, NAME, args...) dw::framework::describePort<TYPE_NAME, NAME.size()>(DW_PORT_TYPE_NAME_STRING_VIEW(TYPE_NAME), NAME, ##args)
94template <
typename PortType,
size_t NameSize>
106template <
typename PortType,
size_t NameSize>
110 dw::core::StringView typeName, dw::core::StringView name, dw::core::StringView comment)
112 return describePort<PortType, NameSize>(
119#define DW_DESCRIBE_PORT_ARRAY(TYPE_NAME, ARRAYSIZE, NAME, args...) dw::framework::describePortArray<TYPE_NAME, ARRAYSIZE, NAME.size()>(DW_PORT_TYPE_NAME_STRING_VIEW(TYPE_NAME), NAME, ##args)
124 typename std::enable_if_t<ArraySize != 0, void>* =
nullptr>
140 typename std::enable_if_t<ArraySize != 0, void>* =
nullptr>
143 dw::core::StringView typeName, dw::core::StringView name, dw::core::StringView comment)
145 return describePortArray<PortType, ArraySize, NameSize>(
155template <
typename Node>
160 return Node::describeInputPorts();
164template <
typename Node>
169 return Node::describeOutputPorts();
176 typename std::enable_if_t<Direction == PortDirection::INPUT, void>* =
nullptr>
181 return describeNodeInputPorts<Node>();
188 typename std::enable_if_t<Direction == PortDirection::OUTPUT, void>* =
nullptr>
193 return describeNodeOutputPorts<Node>();
199template <
typename Node, PortDirection Direction>
203 return dw::core::tuple_size<decltype(describePorts<Node, Direction>())>::value;
207template <
typename Node, PortDirection Direction,
size_t DescriptorIndex>
210 constexpr size_t array_length{dw::core::tuple_element_t<
212 decltype(describePorts<Node, Direction>())>::arraySize};
213 return array_length > 0;
218template <
typename Node, PortDirection Direction,
size_t DescriptorIndex>
222 constexpr size_t array_length{dw::core::tuple_element_t<
224 decltype(describePorts<Node, Direction>())>::arraySize};
226 if (0U == array_length)
235template <
typename Node, PortDirection Direction,
size_t DescriptorIndex>
238 constexpr PortBinding port_binding = dw::core::get<DescriptorIndex>(describePorts<Node, Direction>()).binding;
243template <
typename Node, PortDirection Direction,
size_t DescriptorIndex>
246 constexpr dw::core::StringView port_comment = dw::core::get<DescriptorIndex>(describePorts<Node, Direction>()).comment;
251template <
typename Node, PortDirection Direction,
size_t DescriptorIndex>
256 return typename dw::core::tuple_element_t<
258 decltype(describePorts<Node, Direction>())>::Type();
266 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
267 typename std::enable_if_t<DescriptorIndex == portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
269constexpr std::size_t portSize_()
276 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
277 typename std::enable_if_t<DescriptorIndex<portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
279 constexpr std::size_t portSize_()
281 return descriptorPortSize<Node, Direction, DescriptorIndex>() + portSize_<Node, Direction, DescriptorIndex + 1>();
286template <
typename Node, PortDirection Direction>
290 return detail::portSize_<Node, Direction, 0>();
298 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
size_t RemainingPortIndex,
299 typename std::enable_if_t<DescriptorIndex == portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
301constexpr std::size_t descriptorIndex_()
308 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
size_t RemainingPortIndex,
309 typename std::enable_if_t<DescriptorIndex<portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
311 constexpr std::size_t descriptorIndex_()
314 if (RemainingPortIndex < descriptorPortSize<Node, Direction, DescriptorIndex>())
322 constexpr size_t remainingPortIndex{RemainingPortIndex - descriptorPortSize<Node, Direction, DescriptorIndex>()};
324 return 1U + descriptorIndex_<Node, Direction, DescriptorIndex + 1, remainingPortIndex>();
329template <
typename Node, PortDirection Direction,
size_t PortIndex>
335 return detail::descriptorIndex_<
Node, Direction, 0, PortIndex - portSize<Node, PortDirection::INPUT>()>();
337 return detail::descriptorIndex_<Node, Direction, 0, PortIndex>();
340template <
typename Node, PortDirection Direction,
size_t PortIndex>
346 constexpr size_t index{descriptorIndex<Node, Direction, PortIndex>()};
347 return dw::core::get<index>(describePorts<Node, Direction>()).name;
354constexpr const size_t DECIMAL_BASE{10U};
356constexpr size_t numberOfDigits(
size_t number)
358 static_assert(std::numeric_limits<size_t>::digits10 <= std::numeric_limits<size_t>::max(),
"size_t number of digits exceeds size_t (not possible)");
370 number = number / DECIMAL_BASE;
378constexpr size_t getArrayNameSize(
size_t portNameSize,
size_t arrayIndex)
381 constexpr size_t MAX_SIZE_WITHOUT_BRACKETS{std::numeric_limits<size_t>::max() - 1U - 1U};
382 if (portNameSize >= MAX_SIZE_WITHOUT_BRACKETS)
384 throw std::runtime_error(
"Array name too long");
386 if (MAX_SIZE_WITHOUT_BRACKETS - portNameSize < numberOfDigits(arrayIndex))
388 throw std::runtime_error(
"Array name + digits for array index too long");
391 return portNameSize + 1U + numberOfDigits(arrayIndex) + 1U;
394template <
size_t NameSize,
size_t ArraySize>
396constexpr size_t getMaximumArrayNameSize()
398 static_assert(NameSize > 0U,
"Name size must not be zero");
399 static_assert(ArraySize > 0U,
"Array size must not be zero");
402 return getArrayNameSize(NameSize, ArraySize - 1U);
405template <
size_t NameSize,
size_t ArraySize>
406class PortNamesGenerator
409 static_assert(NameSize > 0U,
"Name size must not be zero");
410 static_assert(ArraySize > 0U,
"Array size must not be zero");
413 static_assert(std::numeric_limits<size_t>::max() / ArraySize > getMaximumArrayNameSize<NameSize, ArraySize>() + 1U,
"The storage size exceeds size_t");
417 static constexpr size_t StorageSize{ArraySize * (getMaximumArrayNameSize<NameSize, ArraySize>() + 1U)};
418 constexpr PortNamesGenerator(dw::core::StringView baseName)
421 if (baseName.size() > NameSize)
424 throw ExceptionWithStatus(DW_INTERNAL_ERROR,
"The passed string size ", baseName.size(),
" exceeds the template parameter NameSize ", NameSize);
428 for (
size_t arrayIndex{0U}; ArraySize != arrayIndex; ++arrayIndex)
431 for (
size_t j{0U}; j < baseName.size(); ++j)
434 data[i] = baseName[j];
436 dw::core::safeIncrement(i, 1U);
440 const char8_t OPENING_BRACKET{
'['};
442 data[i] = OPENING_BRACKET;
444 dw::core::safeIncrement(i, 1U);
446 size_t remainingValue{arrayIndex};
449 const size_t INDEX_LAST_DIGIT{dw::core::safeAdd(i, numberOfDigits(arrayIndex) - 1U).value()};
451 for (
size_t j{0U}; j < numberOfDigits(arrayIndex); ++j)
454 constexpr char8_t digits[10]{
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'};
457 data[INDEX_LAST_DIGIT - j] = digits[remainingValue % DECIMAL_BASE];
459 dw::core::safeIncrement(i, 1U);
460 remainingValue = remainingValue / DECIMAL_BASE;
463 const char8_t CLOSING_BRACKET{
']'};
465 data[i] = CLOSING_BRACKET;
467 dw::core::safeIncrement(i, 1U);
472 dw::core::safeIncrement(i, 1U);
477 i += numberOfDigits(ArraySize - 1U) - numberOfDigits(arrayIndex);
481 dw::core::StringView getName(
size_t arrayIndex)
const
483 if (arrayIndex >= ArraySize)
485 throw ExceptionWithStatus(DW_OUT_OF_BOUNDS,
"Array index ", arrayIndex,
" out of bound for array size ", ArraySize);
488 return dw::core::StringView(&data[arrayIndex * (getMaximumArrayNameSize<NameSize, ArraySize>() + 1U)], getArrayNameSize(NameSize, arrayIndex));
492 char8_t data[StorageSize];
497template <
typename Node, PortDirection Direction,
size_t PortIndex>
503 constexpr size_t index{descriptorIndex<Node, Direction, PortIndex>()};
505 constexpr auto desc{dw::core::get<index>(describePorts<Node, Direction>())};
506 static_assert(desc.arraySize > 0U,
"A port name with an array index argument is only applicable to array ports");
508 static const detail::PortNamesGenerator<desc.nameSize, desc.arraySize> generatedNames{desc.name};
509 return generatedNames.getName(arrayIndex);
513template <
typename Node, PortDirection Direction,
size_t PortIndex>
520 constexpr size_t index{descriptorIndex<Node, Direction, PortIndex>()};
521 return portDescriptorType<Node, Direction, index>();
525template <
typename Node, PortDirection Direction>
532 return portID >= portSize<Node, PortDirection::INPUT>() && portID < portSize<Node, PortDirection::INPUT>() + portSize<Node, Direction>();
534 return portID < portSize<Node, Direction>();
542 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
543 typename std::enable_if_t<DescriptorIndex == portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
544constexpr std::size_t portArraySize_(StringView identifier)
551 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
552 typename std::enable_if_t<DescriptorIndex<portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
554 constexpr std::size_t portArraySize_(StringView identifier)
556 constexpr auto descriptorName = dw::core::get<DescriptorIndex>(describePorts<Node, Direction>()).name;
557 if (descriptorName == identifier)
559 return descriptorPortSize<Node, Direction, DescriptorIndex>();
561 return portArraySize_<Node, Direction, DescriptorIndex + 1>(identifier);
566template <
typename Node, PortDirection Direction>
569 return detail::portArraySize_<Node, Direction, 0>(identifier);
578 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
579 typename std::enable_if_t<DescriptorIndex == portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
581constexpr std::size_t portIndex_(StringView identifier)
583 static_cast<void>(identifier);
589 return dw::framework::portSize<Node, PortDirection::OUTPUT>();
596 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
597 typename std::enable_if_t<DescriptorIndex<portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
599 constexpr std::size_t portIndex_(StringView identifier)
601 constexpr StringView descriptorName{dw::core::get<DescriptorIndex>(describePorts<Node, Direction>()).name};
602 if (descriptorName == identifier)
607 return descriptorPortSize<Node, Direction, DescriptorIndex>() + portIndex_<Node, Direction, DescriptorIndex + 1>(identifier);
612template <
typename Node, PortDirection Direction>
620 return portSize<Node, PortDirection::INPUT>() + detail::portIndex_<Node, Direction, 0>(identifier);
622 return detail::portIndex_<Node, Direction, 0>(identifier);
627template <
typename Node, PortDirection Direction>
630 constexpr size_t index = portIndex<Node, Direction>(identifier);
631 return isValidPortIndex<Node, Direction>(index);
639 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
640 typename std::enable_if_t<DescriptorIndex == portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
641constexpr std::size_t portDescriptorIndex_(StringView identifier)
648 typename Node,
PortDirection Direction,
size_t DescriptorIndex,
649 typename std::enable_if_t<DescriptorIndex<portDescriptorSize<Node, Direction>(),
void>* =
nullptr>
651 constexpr std::size_t portDescriptorIndex_(StringView identifier)
653 constexpr auto descriptorName = dw::core::get<DescriptorIndex>(describePorts<Node, Direction>()).name;
654 if (descriptorName == identifier)
658 return 1 + portDescriptorIndex_<Node, Direction, DescriptorIndex + 1>(identifier);
663template <
typename Node, PortDirection Direction>
666 return detail::portDescriptorIndex_<Node, Direction, 0>(identifier);
constexpr auto describePorts()
constexpr bool descriptorPortArray()
constexpr size_t portIndex(StringView identifier)
constexpr size_t descriptorPortSize()
constexpr auto describePortArray(dw::core::StringView typeName, dw::core::StringView name, PortBinding binding=PortBinding::OPTIONAL, dw::core::StringView comment=""_sv) -> PortDescriptorT< PortType, ArraySize, NameSize >
constexpr size_t portDescriptorIndex(StringView identifier)
constexpr auto describeNodeInputPorts()
constexpr auto portDescriptorType()
constexpr auto describePort(dw::core::StringView typeName, dw::core::StringView name, PortBinding binding=PortBinding::OPTIONAL, dw::core::StringView comment=""_sv) -> PortDescriptorT< PortType, 0, NameSize >
constexpr size_t portArraySize(StringView identifier)
constexpr std::size_t portDescriptorSize()
constexpr auto describePortCollection(Args &&... args) -> dw::core::Tuple< Args... >
constexpr bool isValidPortIndex(std::size_t portID)
constexpr std::size_t portSize()
constexpr PortBinding descriptorPortBinding()
constexpr dw::core::StringView portName()
constexpr auto describeNodeOutputPorts()
constexpr bool isValidPortIdentifier(StringView identifier)
constexpr dw::core::StringView descriptorPortComment()
constexpr auto portType()
constexpr size_t descriptorIndex()
static constexpr size_t arraySize
dw::core::StringView typeName
dw::core::StringView comment
dw::core::StringView name
constexpr PortDescriptorT(dw::core::StringView &&typeName_, dw::core::StringView &&name_, PortBinding binding_=PortBinding::OPTIONAL, dw::core::StringView comment_=""_sv)
static constexpr size_t nameSize