#include "extract_basic.h" #include using namespace extract; AbstractExtractor::AbstractExtractor(const QString& name, DataType data) { _abs_data.name_store = name; _abs_data.type_store = data; } bool AbstractExtractor::setOffsetSpan(int bytes) { this->_abs_data.byte_offset = bytes; return true; } bool AbstractExtractor::setCountWithin(int bytes) { this->_abs_data.byte_count = bytes; return true; } QString AbstractExtractor::name() const { return _abs_data.name_store; } DataType AbstractExtractor::outType() const { return _abs_data.type_store; } int AbstractExtractor::offsetSpan() const { return _abs_data.byte_offset; } int AbstractExtractor::countWithin() const { return this->_abs_data.byte_count; } void AbstractExtractor::loadFrom( std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_abs_data.byte_offset, obj); INT32_PEAK(_abs_data.byte_count, obj); } void AbstractExtractor::saveTo(QJsonObject& obj) const { INT32_SAVE(_abs_data.byte_offset, obj); INT32_SAVE(_abs_data.byte_count, obj); } void AbstractExtractor::registSubField(std::shared_ptr inst) { } AsHex::AsHex(): AbstractExtractor(topic(), DataType::TextString) { setCountWithin(1); } #include "TranslateBasic.h" void AsHex::parse(const QByteArray& bytes, std::shared_ptr out) const { QString result; for (auto char_v : bytes) { result += QString("%1").arg(char_v, 2, 16, QChar('0')); } out->append(result); } std::shared_ptr AsHex::newDefault() const { return std::make_shared(); } QString AsHex::topic() { return NAME(AsHex); } AsBitCombine::AsBitCombine() : AbstractExtractor(topic(), DataType::TextString) { } bool AsBitCombine::setSwitchOption(int bit_index, const QString& keyword) { if (bit_index >= 0 && bit_index <= this->countWithin() * 8) { _combine._switch_options[bit_index] = keyword; return true; } return false; } QHash AsBitCombine::switchOptions() const { return _combine._switch_options; } void AsBitCombine::clearOptions() { _combine._switch_options.clear(); } void AsBitCombine::parse(const QByteArray& bytes, std::shared_ptr out) const { auto keys = _combine._switch_options.keys(); std::sort(keys.begin(), keys.end()); QString result; for (auto idx : keys) { auto byte_idx = idx / 8; auto bit_idx = idx % 8; auto char_v = bytes.at(byte_idx); if (char_v & (0x1u << bit_idx)) result += QString("%1<%2>;").arg(_combine._switch_options[idx], "Y"); else result += QString("%1<%2>;").arg(_combine._switch_options[idx], "N"); } out->append(result); } #include void AsBitCombine::loadFrom( std::shared_ptr core, const QJsonObject& obj) { AbstractExtractor::loadFrom(core, obj); _combine._switch_options.clear(); QJsonArray arr; ARRAY_PEAK(arr, obj); for (auto index = 0; index < arr.size(); ++index) { auto switch_obj = arr.at(index); auto key = switch_obj["index"].toInt(); auto content = switch_obj["content"].toString(); _combine._switch_options[key] = content; } } void AsBitCombine::saveTo(QJsonObject& obj) const { AbstractExtractor::saveTo(obj); QJsonArray arr; for (auto key : _combine._switch_options.keys()) { QJsonObject switch_obj; switch_obj["index"] = key; switch_obj["content"] = _combine._switch_options[key]; arr.append(switch_obj); } ARRAY_SAVE(arr, obj); } std::shared_ptr AsBitCombine::newDefault() const { return std::make_shared(); } QString AsBitCombine::topic() { return NAME(AsBitCombine); } std::shared_ptr AsInteger::newDefault() const { return std::make_shared(); } AsInteger::AsInteger() :AbstractExtractor(topic(), DataType::Integer) { } bool AsInteger::setCountWithin(int bytes) { bytes = std::min(8, std::max(bytes, 0)); return AbstractExtractor::setCountWithin(bytes); } void AsInteger::parse(const QByteArray& bytes, std::shared_ptr out) const { auto last = bytes[bytes.size() - 1]; auto mark = last == 0 ? 0 : last / std::abs(last); auto xbuffer = bytes; if (mark >= 0) { xbuffer.append(8 - bytes.size(), 0); } else { xbuffer.append(8 - bytes.size(), static_cast(0xff)); } unsigned long long value = 0; for (auto vidx = xbuffer.size() - 1; vidx >= 0; vidx--) { auto vchar = xbuffer.at(vidx); value = value << 8; value += (uchar)vchar; } out->append(*((long long*)(&value))); } QString AsInteger::topic() { return NAME(AsInteger); } #include AsString::AsString() :AbstractExtractor(topic(), DataType::TextString) { _strings._conv_with = QTextCodec::codecForName("GBK"); } void AsString::setStrCodec(QTextCodec* ins) { this->_strings._conv_with = ins; } QString AsString::codecName() const { return this->_strings._conv_with->name(); } void AsString::parse(const QByteArray& bytes, std::shared_ptr out) const { auto v = _strings._conv_with->toUnicode(bytes); out->append(v); } void AsString::loadFrom(std::shared_ptr core, const QJsonObject& obj) { AbstractExtractor::loadFrom(core, obj); QString codec_name; STRING_PEAK(codec_name, obj); this->_strings._conv_with = QTextCodec::codecForName(codec_name.toLatin1()); } void AsString::saveTo(QJsonObject& obj) const { AbstractExtractor::saveTo(obj); auto codec_name = this->codecName(); STRING_SAVE(codec_name, obj); } std::shared_ptr AsString::newDefault() const { return std::make_shared(); } QString AsString::topic() { return NAME(AsString); } void AsFloat::parse(const QByteArray& bytes, std::shared_ptr out) const { out->append(*((float*)bytes.data())); } std::shared_ptr AsFloat::newDefault() const { return std::make_shared(); } AsFloat::AsFloat() :AbstractExtractor(topic(), DataType::Flt32) { this->setCountWithin(4); } QString AsFloat::topic() { return NAME(AsFloat); } std::shared_ptr AsDouble::newDefault() const { return std::make_shared(); } void AsDouble::parse(const QByteArray& bytes, std::shared_ptr out) const { out->append(*((double*)bytes.data())); } AsDouble::AsDouble() :AbstractExtractor(topic(), DataType::Dbl64) { this->setCountWithin(8); } QString AsDouble::topic() { return NAME(AsDouble); } AsUnsigned::AsUnsigned() :AbstractExtractor(topic(), DataType::Unsigned) { } bool AsUnsigned::setCountWithin(int bytes) { auto count = std::max(1, std::min(8, bytes)); return AbstractExtractor::setCountWithin(count); } void AsUnsigned::parse(const QByteArray& bytes, std::shared_ptr out) const { unsigned long long value = 0; for (auto vidx = bytes.size() - 1; vidx >= 0; vidx--) { auto vchar = bytes.at(vidx); value = value << 8; value += (uchar)vchar; } out->append(value); } std::shared_ptr AsUnsigned::newDefault() const { return std::make_shared(); } QString AsUnsigned::topic() { return NAME(AsUnsigned); } #include bool AsList::setOffsetSpan(int value) { this->_list._bytes_offset = value; return true; } std::shared_ptr AsList::elementRule() const { return this->_list._bind_unit; } bool AsList::setElementRule(std::shared_ptr u) { this->_list._bind_unit = u; return true; } std::shared_ptr AsList::sizeProvider() const { return this->_list._bind_size_v; } bool AsList::setSizeProvider(std::shared_ptr ins) { this->_list._bind_size_v = ins; return true; } QString AsList::name() const { return topic(); } DataType AsList::outType() const { return DataType::LIST_COLLECTION; } int AsList::offsetSpan() const { return _list._bytes_offset; } int AsList::countWithin() const { auto expr = this->_list._bind_size_v->expression(); if (this->_list._bind_size_v->value(expr) < 0) { return 0; } return this->_list._bind_size_v->value(expr) * this->_list._bind_unit->countWithin(); } #include "TranslateBasic.h" void AsList::loadFrom(std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_list._bytes_offset, obj); QString bind_unit_name = ""; QString bind_size_provider_name = ""; STRING_PEAK(bind_unit_name, obj); STRING_PEAK(bind_size_provider_name, obj); auto xdev = core->sizeProviderList()[bind_size_provider_name]->newDefault(); this->_list._bind_size_v = std::dynamic_pointer_cast(xdev); xdev = core->extractUnitList()[bind_unit_name]->newDefault(); this->_list._bind_unit = std::dynamic_pointer_cast(xdev); QString bind_provider_expr = ""; STRING_SAVE(bind_provider_expr, obj); this->_list._bind_size_v->setExpression(bind_provider_expr); QJsonObject unit_obj; QJsonObject size_provider_obj; OBJECT_PEAK(unit_obj, obj); OBJECT_PEAK(size_provider_obj, obj); this->_list._bind_size_v->loadFrom(core, size_provider_obj); this->_list._bind_unit->loadFrom(core, unit_obj); } #include void AsList::saveTo(QJsonObject& obj) const { INT32_SAVE(_list._bytes_offset, obj); QString bind_unit_name = ""; QJsonObject unit_obj; if (this->_list._bind_unit) { bind_unit_name = this->_list._bind_unit->name(); this->_list._bind_unit->saveTo(unit_obj); } STRING_SAVE(bind_unit_name, obj); OBJECT_SAVE(unit_obj, obj); QString bind_size_provider_name = ""; QString bind_provider_expr = ""; QJsonObject size_provider_obj; if (this->_list._bind_size_v) { bind_provider_expr = this->_list._bind_size_v->expression(); bind_size_provider_name = this->_list._bind_size_v->name(); this->_list._bind_size_v->saveTo(size_provider_obj); } STRING_SAVE(bind_size_provider_name, obj); STRING_SAVE(bind_provider_expr, obj); OBJECT_SAVE(size_provider_obj, obj); } void AsList::parse(const QByteArray& bytes, std::shared_ptr out) const { auto expr = this->_list._bind_size_v->expression(); auto size_value = this->_list._bind_size_v->value(expr); auto unit_size = this->_list._bind_unit->countWithin(); for (auto idx = 0; idx < size_value; ++idx) { auto secn = bytes.mid(unit_size * idx, unit_size); auto slice_context = std::make_shared(); slice_context->init(QString("ls<%1>").arg(idx), out); this->_list._bind_unit->parse(secn, slice_context); } } std::shared_ptr AsList::newDefault() const { return std::make_shared(); } void AsList::registSubField(std::shared_ptr inst) { inst->setField("ls", this->_list._bind_unit->outType()); auto layer = std::make_shared("ls", inst); this->_list._bind_unit->registSubField(layer); } QString AsList::topic() { return NAME(AsList); } QString AsUnion::name() const { return topic(); } DataType AsUnion::outType() const { return DataType::UNION_COMBINATE; } int AsUnion::offsetSpan() const { return _union.byte_offset; } int AsUnion::countWithin() const { return _union.byte_count; } void AsUnion::parse(const QByteArray& bytes, std::shared_ptr out) const { for (auto u : this->elementRules()) if (u->checkpass(bytes)) { auto enum_context = std::make_shared(); enum_context->init(u->name(), out); u->bindRule()->parse(bytes, enum_context); } } void AsUnion::loadFrom( std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_union.byte_count, obj); INT32_PEAK(_union.byte_offset, obj); QJsonArray array; ARRAY_PEAK(array, obj); this->_union._rule_list.clear(); for (auto index = 0; index < array.size(); ++index) { auto rule_obj = array.at(index); QString match_name; STRING_PEAK(match_name, rule_obj); QJsonObject match_obj; OBJECT_PEAK(match_obj, rule_obj); auto match = core->ruleMatchList()[match_name]; auto nmatch = match->newDefault(); nmatch->loadFrom(core, match_obj); this->_union._rule_list.append( std::dynamic_pointer_cast(nmatch)); } } void AsUnion::saveTo(QJsonObject& obj) const { INT32_SAVE(_union.byte_count, obj); INT32_SAVE(_union.byte_offset, obj); QJsonArray array; for (auto insr : this->_union._rule_list) { QJsonObject rule_obj; auto match_name = insr->name(); STRING_SAVE(match_name, rule_obj); QJsonObject match_obj; insr->saveTo(match_obj); OBJECT_SAVE(match_obj, rule_obj); array.append(rule_obj); } ARRAY_SAVE(array, obj); } std::shared_ptr AsUnion::newDefault() const { return std::make_shared(); } QList> AsUnion::elementRules() const { return _union._rule_list; } bool AsUnion::appendElementRule(std::shared_ptr u) { this->_union._rule_list << u; return true; } void AsUnion::clearRules() { this->_union._rule_list.clear(); } bool AsUnion::setCountWithin(int bytes) { this->_union.byte_count = bytes; return true; } bool AsUnion::setOffsetSpan(int value) { this->_union.byte_offset = value; return true; } void AsUnion::registSubField(std::shared_ptr inst) { for (auto rl : this->_union._rule_list) { inst->setField(rl->name(), rl->bindRule()->outType()); auto layer = std::make_shared(rl->name(), inst); rl->bindRule()->registSubField(layer); } } QString AsUnion::topic() { return NAME(AsUnion); } void AsRuleSet::registSubField(std::shared_ptr inst) { for (auto rl_key : this->fieldNames()){ auto rlinst = (*this)[rl_key]; inst->setField(rl_key, rlinst->outType()); auto layer = std::make_shared(rl_key, inst); rlinst->registSubField(layer); } } void AsRuleSet::parse(const QByteArray& bytes, std::shared_ptr out) const { auto bufx = bytes; for (auto keym : this->fieldNames()) { auto rule_context = std::make_shared(); rule_context->init(keym, out); auto rule = (*this)[keym]; bufx = bufx.mid(rule->offsetSpan()); auto count = rule->countWithin(); auto secx = bufx.mid(0, count); rule->parse(secx, rule_context); bufx = bufx.mid(count); } } QString AsRuleSet::name() const { return topic(); } DataType AsRuleSet::outType() const { return DataType::SUB_RULE; } bool AsRuleSet::setOffsetSpan(int bytes) { this->_bind._byte_offset = bytes; return true; } int AsRuleSet::offsetSpan() const { return this->_bind._byte_offset; } int AsRuleSet::countWithin() const { return this->_bind._byte_count; } void AsRuleSet::loadFrom(std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_bind._byte_count, obj); INT32_PEAK(_bind._byte_offset, obj); QJsonArray array; ARRAY_SAVE(array, obj); for (auto index = 0; index < array.size(); ++index) { auto rule_obj = array.at(index); QString match_name, key; QJsonObject match_obj; STRING_PEAK(match_name, rule_obj); STRING_PEAK(key, rule_obj); OBJECT_PEAK(match_obj, rule_obj); auto xdev = core->extractUnitList()[match_name]->newDefault(); xdev->loadFrom(core, match_obj); _bind.sub_units << std::make_pair(key, std::dynamic_pointer_cast(xdev)); } } void AsRuleSet::saveTo(QJsonObject& obj) const { INT32_SAVE(_bind._byte_count, obj); INT32_SAVE(_bind._byte_offset, obj); QJsonArray array; for (auto pairk : _bind.sub_units) { QJsonObject rule_obj, match_obj; auto key = pairk.first; auto info = pairk.second; STRING_SAVE(key, rule_obj); QString match_name = info->name(); STRING_SAVE(match_name, rule_obj); info->saveTo(match_obj); OBJECT_SAVE(match_obj, rule_obj); array.append(rule_obj); } ARRAY_SAVE(array, obj); } std::shared_ptr AsRuleSet::newDefault() const { return std::make_shared(); } std::pair> AsRuleSet::operator[](int index) const { return this->_bind.sub_units[index]; } void AsRuleSet::replace(int index, std::pair> inst) { this->_bind.sub_units.replace(index, inst); } extract::AsRuleSet& AsRuleSet::append(const QString& nm, std::shared_ptr u) { this->_bind.sub_units.append(std::make_pair(nm, u)); return *this; } void AsRuleSet::removeAt(int index) { this->_bind.sub_units.removeAt(index); } QList AsRuleSet::fieldNames() const { QList fields_store; for (auto fpair : this->_bind.sub_units) { fields_store << fpair.first; } return fields_store;; } std::shared_ptr AsRuleSet::operator[](const QString& field) const { for (auto pair : this->_bind.sub_units) { if(pair.first == field) return pair.second; } return std::shared_ptr(); } void AsRuleSet::setCustomName(const QString& name) { _bind._name_store = name; } QString AsRuleSet::customName() const { return _bind._name_store; } int AsRuleSet::memberCount() const { return _bind.sub_units.size(); } QString AsRuleSet::topic() { return NAME(AsRuleSet); }