    static DBCManager dbc_manager(nullptr);
    return &dbc_manager;
  }
  
  // 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> remove int SignalModel::signalRow(const Signal *sig) const {
 </s> add int SignalModel::signalRow(const cabana::Signal *sig) const { </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   Signal sig = {.is_little_endian = little_endian, .factor = 1};
 </s> add   cabana::Signal sig = {.is_little_endian = little_endian, .factor = 1}; </s> remove void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Signal *sig) {
 </s> add void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const cabana::Signal *sig) { </s> remove 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;
};
 </s> add #include "tools/cabana/dbc.h"
    static DBCManager dbc_manager(nullptr);
    return &dbc_manager;
  }
  


















































































































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 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
 cabana: refactor Msg and Signal into dbc.cc (#27552) 
tools/cabana/dbcmanager.cc