#include "extract_basic.h" #include using namespace extract; AbstractExtractor::AbstractExtractor(const QString& typeAlias, DataType data) { _abs_data.typename_store = typeAlias; _abs_data.type_store = data; } bool AbstractExtractor::setCountWithin(int bytes) { this->_abs_data.byte_count = bytes; return true; } QString AbstractExtractor::unitType() const { return _abs_data.typename_store; } DataType AbstractExtractor::outType() const { return _abs_data.type_store; } int AbstractExtractor::countWithin() const { return this->_abs_data.byte_count; } void AbstractExtractor::loadFrom( std::shared_ptr core, const QJsonObject& obj) { STRING_PEAK(_abs_data.name_alias, obj); INT32_PEAK(_abs_data.byte_count, obj); } void AbstractExtractor::saveTo(QJsonObject& obj) const { STRING_SAVE(_abs_data.name_alias, obj); INT32_SAVE(_abs_data.byte_count, obj); } void AbstractExtractor::registSubField(std::shared_ptr inst) const {} QString AbstractExtractor::aliasName() const { return _abs_data.name_alias; } void AbstractExtractor::setAlias(const QString& name) { _abs_data.name_alias = name; } 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 void AsRuleSet::registSubField(std::shared_ptr inst) const { for (auto subrule : _bind.sub_units) { subrule->registSubField(inst); } } void AsRuleSet::parse(const QByteArray& bytes, std::shared_ptr out) const { const_cast(this)->_bind.count_within_rt = 0; auto bufx = bytes; for (auto rule : _bind.sub_units) { rule->parse(bufx, out); auto size_u = rule->countWithin(); bufx = bufx.mid(size_u); const_cast(this)->_bind.count_within_rt += size_u; } } QString AsRuleSet::unitType() const { return topic(); } DataType AsRuleSet::outType() const { return DataType::COMPLEX_RULESET; } int AsRuleSet::countWithin() const { return _bind.count_within_rt; } void AsRuleSet::loadFrom(std::shared_ptr core, const QJsonObject& obj) { STRING_PEAK(_bind.alias_name, obj); QJsonArray array; ARRAY_SAVE(array, obj); _bind.sub_units.clear(); for (auto index = 0; index < array.size(); ++index) { auto rule_obj = array.at(index); QString unit_type, field_name; STRING_PEAK(field_name, rule_obj); STRING_PEAK(unit_type, rule_obj); QJsonObject match_obj; OBJECT_PEAK(match_obj, rule_obj); auto xdev = core->extractUnitTypeMap()[unit_type]->newDefault(); xdev->loadFrom(core, match_obj); _bind.sub_units << std::dynamic_pointer_cast(xdev); } } void AsRuleSet::saveTo(QJsonObject& obj) const { STRING_SAVE(_bind.alias_name, obj); QJsonArray array; for (auto pairk : _bind.sub_units) { QJsonObject rule_obj, match_obj; auto field_name = pairk->name(); STRING_SAVE(field_name, rule_obj); auto unit_type = pairk->baseType(); STRING_SAVE(unit_type, rule_obj); pairk->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::shared_ptr AsRuleSet::operator[](int index) const { return this->_bind.sub_units[index]; } void AsRuleSet::replace(int index, std::shared_ptr inst) { this->_bind.sub_units.replace(index, inst); } extract::AsRuleSet& AsRuleSet::append(std::shared_ptr u) { this->_bind.sub_units.append(u); return *this; } void AsRuleSet::removeAt(int index) { this->_bind.sub_units.removeAt(index); } QList AsRuleSet::fieldNames() const { QList fields_store; for (auto fins : this->_bind.sub_units) { fields_store << fins->name(); } return fields_store;; } std::shared_ptr AsRuleSet::operator[](const QString& field) const { for (auto pair : this->_bind.sub_units) { if (pair->name() == field) return pair; } return std::shared_ptr(); } void AsRuleSet::setAlias(const QString& typeAlias) { _bind.alias_name = typeAlias; } QString AsRuleSet::aliasName() const { return _bind.alias_name; } int AsRuleSet::memberCount() const { return _bind.sub_units.size(); } QString AsRuleSet::topic() { return NAME(AsRuleSet); } QString SingleBasedUnit::name() const { return _inst._field_name; } bool SingleBasedUnit::setOffsetSpan(int bytes) { _inst._bytes_offset = bytes; return true; } int SingleBasedUnit::offsetSpan() const { return _inst._bytes_offset; } std::shared_ptr SingleBasedUnit::delegateInst() const { return _inst._delegate_inst; } void SingleBasedUnit::setDelegate(std::shared_ptr inst) { _inst._delegate_inst = inst; } void SingleBasedUnit::registSubField(std::shared_ptr inst) const { inst->setField(name(), _inst._delegate_inst->outType()); auto nlayer = std::make_shared(name(), inst); _inst._delegate_inst->registSubField(nlayer); } void SingleBasedUnit::parse(const QByteArray& bytes, std::shared_ptr out) const { auto context = std::make_shared(); context->init(name(), out); auto bytes_sec = bytes.mid(this->offsetSpan()); _inst._delegate_inst->parse(bytes_sec, context); } void SingleBasedUnit::loadFrom(std::shared_ptr core, const QJsonObject& obj) { QJsonObject field_obj; OBJECT_PEAK(field_obj, obj); STRING_PEAK(_inst._field_name, field_obj); INT32_PEAK(_inst._bytes_offset, field_obj); QString delegate_alias; STRING_PEAK(delegate_alias, obj); auto vcopy = core->operator[](delegate_alias)->newDefault(); _inst._delegate_inst = std::dynamic_pointer_cast(vcopy); QJsonObject data_obj; OBJECT_PEAK(data_obj, field_obj); _inst._delegate_inst->loadFrom(core, data_obj); } void SingleBasedUnit::saveTo(QJsonObject& obj) const { QJsonObject field_obj; STRING_SAVE(_inst._field_name, field_obj); INT32_SAVE(_inst._bytes_offset, field_obj); auto delegate_alias = _inst._delegate_inst->aliasName(); STRING_SAVE(delegate_alias, obj); QJsonObject data_obj; _inst._delegate_inst->saveTo(data_obj); OBJECT_SAVE(data_obj, field_obj); OBJECT_SAVE(field_obj, obj); } std::shared_ptr SingleBasedUnit::newDefault() const { return std::make_shared(); } void SingleBasedUnit::setName(const QString& name) { _inst._field_name = name; } int SingleBasedUnit::countWithin() const { return _inst._delegate_inst->countWithin() + offsetSpan(); } QString SingleBasedUnit::baseType() const { return topic(); } QString SingleBasedUnit::topic() { return NAME(SingleBasedUnit); } QString ListBasedUnit::name() const { return _list.field_name; } void ListBasedUnit::setName(const QString& name) { _list.field_name = name; } bool ListBasedUnit::setOffsetSpan(int bytes) { _list.bytes_offset = bytes; return true; } int ListBasedUnit::offsetSpan() const { return _list.bytes_offset; } std::shared_ptr ListBasedUnit::delegateInst() const { return _list.delegate_inst; } void ListBasedUnit::setDelegate(std::shared_ptr inst) { _list.delegate_inst = inst; } void ListBasedUnit::registSubField(std::shared_ptr inst) const {} int ListBasedUnit::countWithin() const { return _list.count_with_runtime; } void ListBasedUnit::parse(const QByteArray& bytes, std::shared_ptr out) const { const_cast(this)->_list.count_with_runtime = 0; _list.size_provider_inst->bindInput(out); auto expr = _list.size_provider_inst->expression(); auto count = _list.size_provider_inst->value(expr); auto buffer = bytes.mid(_list.bytes_offset); for (auto index = 0; index < count; ++index) { auto context = std::shared_ptr(); context->init(name() + QString("<%1>").arg(index), out); delegateInst()->parse(buffer, context); auto size_u = delegateInst()->countWithin(); buffer = buffer.mid(size_u); } } void ListBasedUnit::loadFrom(std::shared_ptr core, const QJsonObject& obj) { STRING_PEAK(_list.field_name, obj); INT32_PEAK(_list.bytes_offset, obj); QString provider_name, delegate_name; STRING_PEAK(provider_name, obj); STRING_PEAK(delegate_name, obj); QJsonObject provider_obj, delegate_obj; OBJECT_PEAK(provider_obj, obj); OBJECT_PEAK(delegate_obj, obj); auto ins_size = core->sizeProviderTypeMap()[provider_name]->newDefault(); ins_size->loadFrom(core, provider_obj); auto ins_delt = core->operator[](delegate_name)->newDefault(); ins_delt->loadFrom(core, delegate_obj); _list.size_provider_inst = std::dynamic_pointer_cast(ins_size); _list.delegate_inst = std::dynamic_pointer_cast(ins_delt); } void ListBasedUnit::saveTo(QJsonObject& obj) const { STRING_SAVE(_list.field_name, obj); INT32_SAVE(_list.bytes_offset, obj); auto provider_name = _list.size_provider_inst->name(); auto delegate_name = _list.delegate_inst->aliasName(); STRING_SAVE(provider_name, obj); STRING_SAVE(delegate_name, obj); QJsonObject provider_obj, delegate_obj; _list.size_provider_inst->saveTo(provider_obj); _list.delegate_inst->saveTo(delegate_obj); OBJECT_SAVE(provider_obj, obj); OBJECT_SAVE(delegate_obj, obj); } std::shared_ptr ListBasedUnit::newDefault() const { return std::make_shared(); } QString ListBasedUnit::baseType() const { return topic(); } std::shared_ptr ListBasedUnit::sizeProvider() const { return _list.size_provider_inst; } void ListBasedUnit::setSizeProvider(std::shared_ptr inst) { _list.size_provider_inst = inst; } QString ListBasedUnit::topic() { return NAME(ListBasedUnit); } void UnionBasedUnit::updateMatch(int index, std::shared_ptr rule) { auto nidx = std::min(std::max(0, index), _union.rulematch_list.size() - 1); _union.rulematch_list.replace(nidx, rule); } QList> UnionBasedUnit::matchRules() const { return _union.rulematch_list; } void UnionBasedUnit::clearRules() { _union.rulematch_list.clear(); } QString UnionBasedUnit::baseType() const { return topic(); } QString UnionBasedUnit::name() const { return _union.alias_name; } void UnionBasedUnit::setName(const QString& name) { _union.alias_name = name; } bool UnionBasedUnit::setOffsetSpan(int bytes) { _union.bytes_offset = bytes; return true; } int UnionBasedUnit::offsetSpan() const { return _union.bytes_offset; } void UnionBasedUnit::registSubField(std::shared_ptr inst) const {} int UnionBasedUnit::countWithin() const { return _union.bytes_count; } void UnionBasedUnit::parse(const QByteArray& bytes, std::shared_ptr out) const { auto buffer = bytes.mid(_union.bytes_offset); for (auto instr : _union.rulematch_list) { if (instr->checkpass(buffer)) { auto context = std::make_shared(); context->init(instr->getDelegate()->aliasName(), out); instr->getDelegate()->parse(buffer, context); if (instr->getDelegate()->countWithin() > _union.bytes_count) throw new BaseException(u8"指定规则类型长度超过最大限值"); break; } } } void UnionBasedUnit::loadFrom(std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_union.bytes_offset, obj); INT32_PEAK(_union.bytes_count, obj); STRING_PEAK(_union.alias_name, obj); QJsonArray array; ARRAY_PEAK(array, obj); _union.rulematch_list.clear(); for (auto index = 0; index < array.size(); ++index) { auto rule_obj = array.at(index); QString match_type; STRING_PEAK(match_type, rule_obj); auto ninst = core->ruleMatchTypeMap()[match_type]->newDefault(); QJsonObject content_obj; OBJECT_PEAK(content_obj, rule_obj); ninst->loadFrom(core, content_obj); _union.rulematch_list.append(std::dynamic_pointer_cast(ninst)); } } void UnionBasedUnit::saveTo(QJsonObject& obj) const { INT32_SAVE(_union.bytes_offset, obj); INT32_SAVE(_union.bytes_count, obj); STRING_SAVE(_union.alias_name, obj); QJsonArray array; for (auto instr : _union.rulematch_list) { QJsonObject rule_obj; auto match_type = instr->matchType(); STRING_SAVE(match_type, rule_obj); QJsonObject content_obj; instr->saveTo(content_obj); OBJECT_SAVE(content_obj, rule_obj); array.append(rule_obj); } ARRAY_SAVE(array, obj); } std::shared_ptr UnionBasedUnit::newDefault() const { return std::make_shared(); } void UnionBasedUnit::setCountWithin(int count) { _union.bytes_count = count; } QString UnionBasedUnit::topic() { return NAME(UnionBasedUnit); }