|
- #include <algorithm> /**< std::find_if */
- #include <iomanip> /**< std::setw std::setfill */
- #include <iostream> /**< */
- #include <sstream> /**< std;:stringstream */
- #include <string> /**< std::string */
- #include <vector> /**< std::vector */
-
- #include "dbcc/helper/signal_helper.h"
-
- namespace ad {
- namespace dbcc {
- namespace helper {
-
- const std::string kDefaultIndentSpaces = " ";
-
- inline void LeftTrim(std::string& s)
- {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
- return !std::isspace(ch);
- }));
- }
-
- inline void RightTrim(std::string& s)
- {
- s.erase(std::find_if(s.rbegin(), s.rend(),
- [](int ch) {
- return !std::isspace(ch);
- })
- .base(),
- s.end());
- }
-
- inline void Trim(std::string& s)
- {
- LeftTrim(s);
- RightTrim(s);
- }
-
- inline const std::string GenerateIndent(int indent_level)
- {
- std::stringstream ss;
-
- for (int i = 0; i < indent_level; i++) {
- ss << kDefaultIndentSpaces;
- }
-
- return ss.str();
- }
-
- static inline int Bsf(int input)
- {
- int s = (int)(sizeof(input) * 8);
- for (int i = 0; i < s; i++) {
- if ((input >> i) & 1) {
- s = i;
- break;
- }
- }
- return s;
- }
-
- int SignalHelper::TypeLengthBsf() const
- {
- return Bsf(TypeLength());
- }
-
- const std::string& SignalHelper::OperationTypeName() const
- {
- static const std::string types[] = {"int8_t", "int16_t", "int32_t", "int64_t",
- "uint8_t", "uint16_t", "uint32_t", "uint64_t"};
-
- if (signal_.GetSign() == ad::dbcc::Sign::kSigned) {
- return types[Bsf(TypeLength() / 8)];
- }
-
- return types[Bsf(TypeLength() / 8) + 4];
- }
-
- const std::string& SignalHelper::TypeName() const
- {
- if (signal_.IsFloat()) {
- static const std::string kFloatTypes[] = {"float", "double"};
- if (signal_.Length() <= 32) {
- return kFloatTypes[0];
- } else {
- return kFloatTypes[1];
- }
- }
-
- return OperationTypeName();
- }
-
- const std::string& SignalHelper::ConversionTypeSuffix() const
- {
- static const std::string kSuffixes[] = {"u", "u", "u", "ull"};
-
- return kSuffixes[TypeLength() / 8];
- }
-
- const std::string& SignalHelper::TypeSuffix() const
- {
- if (signal_.IsFloat()) {
- static const std::string kFloatSuffixes[] = {"f", ""};
- if (signal_.Length() == 32) {
- return kFloatSuffixes[0];
- } else {
- return kFloatSuffixes[1];
- }
- } else {
- static const std::string kSuffixes[] = {"", "", "", "ll", "u", "u", "u", "ull"};
-
- if (signal_.GetSign() == ad::dbcc::Sign::kSigned) {
- return kSuffixes[Bsf(TypeLength() / 8)];
- } else {
- return kSuffixes[(TypeLength() / 8) + 4];
- }
- }
- }
-
- std::vector<SignalHelper::Segment> SignalHelper::Segments(bool invert_shift) const
- {
- std::vector<SignalHelper::Segment> segs;
- int index = signal_.StartBit() / 8;
- int pos = signal_.StartBit() % 8;
- int left = static_cast<int>(signal_.Length());
-
- int length = 0;
- SignalHelper::Segment seg;
-
- while (left > 0) {
- if (signal_.GetByteOrder() == ad::dbcc::ByteOrder::kMotorola) {
- if (left >= (pos + 1)) {
- length = (pos + 1);
- pos = 7;
- seg.shift = -(left - length);
- seg.mask = ((1 << length) - 1);
- } else {
- length = left;
- seg.shift = (pos - length + 1);
- seg.mask = ((1 << length) - 1);
- seg.mask <<= (pos - length + 1);
- }
- } else {
- seg.shift = (left - signal_.Length()) + pos;
-
- if (left >= (8 - pos)) {
- length = (8 - pos);
- seg.mask = ((1 << length) - 1);
- seg.mask <<= pos;
- pos = 0;
- } else {
- length = left;
- seg.mask = ((1 << length) - 1);
- seg.mask <<= pos;
- }
- }
-
- if (invert_shift) {
- if (seg.shift < 0) {
- seg.shift = -seg.shift;
- seg.direction = ShiftDirection::kLeft;
- } else {
- seg.direction = ShiftDirection::kRight;
- }
- } else {
- if (seg.shift < 0) {
- seg.shift = -seg.shift;
- seg.direction = ShiftDirection::kRight;
- } else {
- seg.direction = ShiftDirection::kLeft;
- }
- }
- seg.index = index;
- segs.push_back(seg);
-
- left -= length;
- index += 1;
- }
-
- return segs;
- }
-
- std::string SignalHelper::Unpack2Code(const std::string& name, const std::string& prefix,
- int indent_level)
- {
- std::stringstream ss;
- const std::string indent = GenerateIndent(indent_level);
- // Unpack the type information of this signal
- std::string signal_member_type = TypeName();
-
- ss << indent << OperationTypeName() << " " << name << "_temp = 0;" << std::endl;
-
- for (auto seg : Segments(true)) {
- ss << indent;
-
- if (seg.direction == ad::dbcc::helper::SignalHelper::ShiftDirection::kLeft) {
- ss << name << "_temp |= UNPACK_LEFT_SHIFT(";
- } else {
- ss << name << "_temp |= UNPACK_RIGHT_SHIFT(";
- }
-
- ss << OperationTypeName() << ", "
- << "data[" << seg.index << "], " << seg.shift << "u, " << std::setw(2)
- << std::setfill('0') << "0x" << std::hex << seg.mask << std::dec << "u);" << std::setw(0)
- << std::setfill(' ') << std::endl;
- }
-
- if (signal_.GetSign() == ad::dbcc::Sign::kSigned) {
- uint32_t mask = ((1 << (TypeLength() - signal_.Length())) - 1);
-
- if (mask != 0) {
- const std::string indent2 = GenerateIndent(indent_level + 1);
- auto cts = ConversionTypeSuffix();
-
- mask <<= signal_.Length();
-
- ss << indent << "if ((" << name << "_temp & (1" << cts << " << "
- << (signal_.Length() - 1) << ")) != 0" << cts << ")" << std::endl
- << indent << "{" << std::endl
- << indent2 << name << "_temp |= 0x" << std::hex << mask << std::dec << cts << ";"
- << std::endl
- << indent << "}" << std::endl;
- }
- }
-
- ss << indent << prefix << name << " = (" << signal_member_type << ")(" << name << "_temp";
- if (signal_.Factor() != 1) {
- ss << " * " << signal_.Factor();
- }
-
- if (signal_.Offset() != 0) {
- ss << " + (" << signal_.Offset() << ")";
- }
-
- ss << ");";
-
- return ss.str();
- }
-
- std::string SignalHelper::Pack2Code(const std::string& name, const std::string& prefix,
- int indent_level)
- {
- std::stringstream ss;
- bool need_new_line = false;
- const std::string indent = GenerateIndent(indent_level);
- ss << indent << OperationTypeName() << " " << name << "_temp = (" << OperationTypeName() << ")(";
-
- if (signal_.Factor() != 1) {
- ss << "(";
- }
-
- ss << prefix << name;
-
- if (signal_.Offset() != 0)
- {
- ss << " - (" << signal_.Offset() << ")";
- }
-
- if (signal_.Factor() != 1) {
- ss << ") / " << signal_.Factor();
- }
- ss << ");" << std::endl;
-
- for (auto seg : Segments()) {
- if (need_new_line) {
- ss << std::endl;
- }
-
- ss << indent;
-
- if (seg.direction == ad::dbcc::helper::SignalHelper::ShiftDirection::kLeft) {
- ss << "data[" << seg.index << "]"
- << " |= PACK_LEFT_SHIFT(";
- } else {
- ss << "data[" << seg.index << "]"
- << " |= PACK_RIGHT_SHIFT(";
- }
-
- ss << name << "_temp, " << seg.shift << "u, " << std::setw(2) << std::setfill('0') << "0x"
- << std::hex << seg.mask << std::dec << "u);" << std::setw(0) << std::setfill(' ');
- need_new_line = true;
- }
-
- return ss.str();
- }
-
- } // namespace helper
- } // namespace dbcc
- } // namespace ad
|