#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) { } BytesAsHex::BytesAsHex() : AbstractExtractor(NAME(BytesAsHex), DataType::TextString) { setCountWithin(1); } #include "TranslateBasic.h" void BytesAsHex::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 BytesAsHex::newDefault() const { return std::make_shared(); } BytesAsBitCombine::BytesAsBitCombine() : AbstractExtractor(NAME(BytesAsBitCombine), DataType::TextString) { } bool BytesAsBitCombine::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 BytesAsBitCombine::switchOptions() const { return _combine._switch_options; } void BytesAsBitCombine::clearOptions() { _combine._switch_options.clear(); } void BytesAsBitCombine::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 BytesAsBitCombine::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 BytesAsBitCombine::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 BytesAsBitCombine::newDefault() const { return std::make_shared(); } std::shared_ptr BytesAsInteger::newDefault() const { return std::make_shared(); } BytesAsInteger::BytesAsInteger() :AbstractExtractor(NAME(BytesAsInteger), DataType::Integer) { } bool BytesAsInteger::setCountWithin(int bytes) { bytes = std::min(8, std::max(bytes, 0)); return AbstractExtractor::setCountWithin(bytes); } void BytesAsInteger::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))); } #include BytesAsString::BytesAsString() :AbstractExtractor(NAME(BytesAsString), DataType::TextString) { _strings._conv_with = QTextCodec::codecForName("GBK"); } void BytesAsString::setStrCodec(QTextCodec* ins) { this->_strings._conv_with = ins; } QString BytesAsString::codecName() const { return this->_strings._conv_with->name(); } void BytesAsString::parse(const QByteArray& bytes, std::shared_ptr out) const { auto v = _strings._conv_with->toUnicode(bytes); out->append(v); } void BytesAsString::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 BytesAsString::saveTo(QJsonObject& obj) const { AbstractExtractor::saveTo(obj); auto codec_name = this->codecName(); STRING_SAVE(codec_name, obj); } std::shared_ptr BytesAsString::newDefault() const { return std::make_shared(); } void BytesAsFloat::parse(const QByteArray& bytes, std::shared_ptr out) const { out->append(*((float*)bytes.data())); } std::shared_ptr BytesAsFloat::newDefault() const { return std::make_shared(); } BytesAsFloat::BytesAsFloat() :AbstractExtractor(NAME(BytesAsFloat), DataType::Flt32) { this->setCountWithin(4); } std::shared_ptr BytesAsDouble::newDefault() const { return std::make_shared(); } void BytesAsDouble::parse(const QByteArray& bytes, std::shared_ptr out) const { out->append(*((double*)bytes.data())); } BytesAsDouble::BytesAsDouble() :AbstractExtractor(NAME(BytesAsDouble), DataType::Dbl64) { this->setCountWithin(8); } BytesAsUnsigned::BytesAsUnsigned() :AbstractExtractor(NAME(BytesAsUnsigned), DataType::Unsigned) { } bool BytesAsUnsigned::setCountWithin(int bytes) { auto count = std::max(1, std::min(8, bytes)); return AbstractExtractor::setCountWithin(count); } void BytesAsUnsigned::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 BytesAsUnsigned::newDefault() const { return std::make_shared(); } #include bool BytesAsList::setOffsetSpan(int value) { this->_list._bytes_offset = value; return true; } std::shared_ptr BytesAsList::elementRule() const { return this->_list._bind_unit; } bool BytesAsList::appendElementRule(std::shared_ptr u) { this->_list._bind_unit = u; return true; } std::shared_ptr BytesAsList::sizeProvider() const { return this->_list._bind_size_v; } bool BytesAsList::setSizeProvider(std::shared_ptr ins) { this->_list._bind_size_v = ins; return true; } QString BytesAsList::name() const { return NAME(BytesAsList); } DataType BytesAsList::outType() const { return DataType::LIST_COLLECTION; } int BytesAsList::offsetSpan() const { return _list._bytes_offset; } int BytesAsList::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 BytesAsList::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 BytesAsList::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 BytesAsList::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 BytesAsList::newDefault() const { return std::make_shared(); } void BytesAsList::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 BytesAsUnion::name() const { return NAME(BytesAsUnion); } DataType BytesAsUnion::outType() const { return DataType::UNION_COMBINATE; } int BytesAsUnion::offsetSpan() const { return _union.byte_offset; } int BytesAsUnion::countWithin() const { return _union.byte_count; } void BytesAsUnion::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 BytesAsUnion::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 BytesAsUnion::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 BytesAsUnion::newDefault() const { return std::make_shared(); } QList> BytesAsUnion::elementRules() const { return _union._rule_list; } bool BytesAsUnion::appendElementRule(std::shared_ptr u) { this->_union._rule_list << u; return true; } void BytesAsUnion::clearRules() { this->_union._rule_list.clear(); } bool BytesAsUnion::setCountWithin(int bytes) { this->_union.byte_count = bytes; return true; } bool BytesAsUnion::setOffsetSpan(int value) { this->_union.byte_offset = value; return true; } void BytesAsUnion::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); } } void BytesAsRuleSet::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 BytesAsRuleSet::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 BytesAsRuleSet::name() const { return NAME(BytesAsRuleSet); } DataType BytesAsRuleSet::outType() const { return DataType::SUB_RULE; } bool BytesAsRuleSet::setOffsetSpan(int bytes) { this->_bind._byte_offset = bytes; return true; } int BytesAsRuleSet::offsetSpan() const { return this->_bind._byte_offset; } int BytesAsRuleSet::countWithin() const { return this->_bind._byte_count; } void BytesAsRuleSet::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 BytesAsRuleSet::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 BytesAsRuleSet::newDefault() const { return std::make_shared(); } std::pair> BytesAsRuleSet::operator[](int index) const { return this->_bind.sub_units[index]; } void BytesAsRuleSet::replace(int index, std::pair> inst) { this->_bind.sub_units.replace(index, inst); } extract::BytesAsRuleSet& BytesAsRuleSet::append(const QString& nm, std::shared_ptr u) { this->_bind.sub_units.append(std::make_pair(nm, u)); return *this; } void BytesAsRuleSet::removeAt(int index) { this->_bind.sub_units.removeAt(index); } QList BytesAsRuleSet::fieldNames() const { QList fields_store; for (auto fpair : this->_bind.sub_units) { fields_store << fpair.first; } return fields_store;; } std::shared_ptr BytesAsRuleSet::operator[](const QString& field) const { for (auto pair : this->_bind.sub_units) { if(pair.first == field) return pair.second; } return std::shared_ptr(); } void BytesAsRuleSet::setCustomName(const QString& name) { _bind._name_store = name; } QString BytesAsRuleSet::customName() const { return _bind._name_store; } int BytesAsRuleSet::memberCount() const { return _bind.sub_units.size(); }