  #include <QMetaType>
  #include <QObject>
  #include <QString>
  
  struct MessageId {
    uint8_t source;
    uint32_t address;
  
    QString toString() const {
      return QString("%1:%2").arg(source).arg(address, 1, 16);
    }
  
    bool operator==(const MessageId &other) const {
      return source == other.source && address == other.address;
    }
  
    bool operator!=(const MessageId &other) const {
      return !(*this == other);
    }
  
    bool operator<(const MessageId &other) const {
      return std::pair{source, address} < std::pair{other.source, other.address};
    }
  
    bool operator>(const MessageId &other) const {
      return std::pair{source, address} > std::pair{other.source, other.address};
    }
  };
  
  uint qHash(const MessageId &item);
  Q_DECLARE_METATYPE(MessageId);
  
  namespace dbcmanager {
  
  typedef QList<std::pair<QString, QString>> ValueDescription;
  
  struct Signal {
    QString name;
    int start_bit, msb, lsb, size;
    bool is_signed;
    double factor, offset;
    bool is_little_endian;
    QString min, max, unit;
    QString comment;
    ValueDescription val_desc;
  };
  
  struct Msg {
    QString name;
    uint32_t size;
  
    std::vector<const Signal*> getSignals() const;
    const Signal *sig(const QString &sig_name) const {
      auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; });
      return it != sigs.end() ? &(*it) : nullptr;
    }
  
  private:
    QList<Signal> sigs;
    friend class DBCManager;
  };
  
  class DBCManager : public QObject {
    Q_OBJECT
  
  public:
 
</s> remove   if (auto m = const_cast<Msg *>(msg(id))) {
 </s> add   if (auto m = const_cast<cabana::Msg *>(msg(id))) { </s> remove const QString UNTITLED = "untitled";

// TODO: Add helper function in dbc.h
double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig);
bool operator==(const Signal &l, const Signal &r);
inline bool operator!=(const Signal &l, const Signal &r) { return !(l == r); }
int bigEndianStartBitsIndex(int start_bit);
int bigEndianBitIndex(int index);
void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size);
std::pair<int, int> getSignalRange(const Signal *s);
 </s> add  </s> remove // Msg

std::vector<const Signal*> Msg::getSignals() const {
  std::vector<const Signal*> ret;
  ret.reserve(sigs.size());
  for (auto &sig : sigs) ret.push_back(&sig);
  std::sort(ret.begin(), ret.end(), [](auto l, auto r) { return l->start_bit < r->start_bit; });
  return ret;
}

// helper functions

static QVector<int> BIG_ENDIAN_START_BITS = []() {
  QVector<int> ret;
  for (int i = 0; i < 64; i++)
    for (int j = 7; j >= 0; j--)
      ret.push_back(j + i * 8);
  return ret;
}();

int bigEndianStartBitsIndex(int start_bit) { return BIG_ENDIAN_START_BITS[start_bit]; }
int bigEndianBitIndex(int index) { return BIG_ENDIAN_START_BITS.indexOf(index); }

double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) {
  int64_t val = 0;

  int i = sig.msb / 8;
  int bits = sig.size;
  while (i >= 0 && i < data_size && bits > 0) {
    int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8;
    int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1;
    int size = msb - lsb + 1;

    uint64_t d = (data[i] >> (lsb - (i * 8))) & ((1ULL << size) - 1);
    val |= d << (bits - size);

    bits -= size;
    i = sig.is_little_endian ? i - 1 : i + 1;
  }
  if (sig.is_signed) {
    val -= ((val >> (sig.size - 1)) & 0x1) ? (1ULL << sig.size) : 0;
  }
  return val * sig.factor + sig.offset;
}

void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size) {
  s.start_bit = s.is_little_endian ? start_bit : bigEndianBitIndex(start_bit);
  s.size = size;
  if (s.is_little_endian) {
    s.lsb = s.start_bit;
    s.msb = s.start_bit + s.size - 1;
  } else {
    s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1);
    s.msb = s.start_bit;
  }
}

std::pair<int, int> getSignalRange(const Signal *s) {
  int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit);
  int to = from + s->size - 1;
  return {from, to};
}

bool operator==(const Signal &l, const Signal &r) {
  return l.name == r.name && l.size == r.size &&
         l.start_bit == r.start_bit &&
         l.msb == r.msb && l.lsb == r.lsb &&
         l.is_signed == r.is_signed && l.is_little_endian == r.is_little_endian &&
         l.factor == r.factor && l.offset == r.offset &&
         l.min == r.min && l.max == r.max && l.comment == r.comment && l.unit == r.unit && l.val_desc == r.val_desc;
}

}  // namespace dbcmanager

#include "opendbc/can/common_dbc.h"
std::vector<std::string> dbcmanager::DBCManager::allDBCNames() { return get_dbc_names(); }

bool dbcmanager::DBCManager::open(const QString &name, const QString &content, QString *error) {
  try {
    std::istringstream stream(content.toStdString());
    auto dbc = const_cast<DBC *>(dbc_parse_from_stream(name.toStdString(), stream));
    msgs.clear();
    for (auto &msg : dbc->msgs) {
      auto &m = msgs[msg.address];
      m.name = msg.name.c_str();
      m.size = msg.size;
      for (auto &s : msg.sigs) {
        m.sigs.push_back({});
        auto &sig = m.sigs.last();
        sig.name = s.name.c_str();
        sig.start_bit = s.start_bit;
        sig.msb = s.msb;
        sig.lsb = s.lsb;
        sig.size = s.size;
        sig.is_signed = s.is_signed;
        sig.factor = s.factor;
        sig.offset = s.offset;
        sig.is_little_endian = s.is_little_endian;
      }
    }
    parseExtraInfo(content);
    name_ = name;
    emit DBCFileChanged();
    delete dbc;
  } catch (std::exception &e) {
    if (error) *error = e.what();
    return false;
  }
  return true;
}

uint qHash(const MessageId &item) {
  return qHash(item.source) ^ qHash(item.address);
}
 </s> add  </s> remove   inline const std::map<uint32_t, Msg> &messages() const { return msgs; }
  inline const Msg *msg(const MessageId &id) const { return msg(id.address); }
  inline const Msg *msg(uint32_t address) const {
 </s> add   inline const std::map<uint32_t, cabana::Msg> &messages() const { return msgs; }
  inline const cabana::Msg *msg(const MessageId &id) const { return msg(id.address); }
  inline const cabana::Msg *msg(uint32_t address) const { </s> remove   static std::vector<std::string> allDBCNames();
 </s> add 
#include "tools/cabana/dbc.h"
  #include <QMetaType>
  #include <QObject>
  #include <QString>
  
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
#include "tools/cabana/dbc.h"
  
  class DBCManager : public QObject {
    Q_OBJECT
  
  public:
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 cabana: refactor Msg and Signal into dbc.cc (#27552) 
tools/cabana/dbcmanager.h