#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){} 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 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::unitType() const { return topic(); } DataType AsList::outType() const { return DataType::LIST_COLLECTION; } int AsList::countWithin() const { return _list.count_acculate; } void AsList::loadFrom(std::shared_ptr core, const QJsonObject& obj) { STRING_PEAK(_list._alias_name, obj); QString size_provider_name = ""; STRING_PEAK(size_provider_name, obj); auto xdev = core->sizeProviderList()[size_provider_name]->newDefault(); this->_list._bind_size_v = std::dynamic_pointer_cast(xdev); QString bind_unit_name = ""; STRING_PEAK(bind_unit_name, obj); xdev = core->operator[](bind_unit_name)->newDefault(); this->_list._bind_unit = std::dynamic_pointer_cast(xdev); 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); } void AsList::saveTo(QJsonObject& obj) const { STRING_SAVE(_list._alias_name, obj); QString size_provider_name = this->_list._bind_size_v->name(); STRING_SAVE(size_provider_name, obj); QString bind_unit_name = this->_list._bind_unit->name(); STRING_SAVE(bind_unit_name, obj); QJsonObject unit_obj; _list._bind_unit->saveTo(unit_obj); QJsonObject size_provider_obj; _list._bind_size_v->saveTo(size_provider_obj); OBJECT_SAVE(unit_obj, obj); OBJECT_PEAK(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 remains = bytes; const_cast(this)->_list.count_acculate = 0; for (auto idx = 0; idx < size_value; ++idx) { this->_list._bind_unit->parse(remains, out); auto unit_size = this->_list._bind_unit->countWithin(); remains = remains.mid(unit_size); const_cast(this)->_list.count_acculate += unit_size; } } std::shared_ptr AsList::newDefault() const { return std::make_shared(); } void AsList::registSubField(std::shared_ptr inst){} QString AsList::topic() { return NAME(AsList); } QString AsList::aliasName() const { return _list._alias_name; } void AsList::setAlias(const QString& name) { _list._alias_name = name; } DataType AsUnion::outType() const { return DataType::UNION_COMBINATE; } 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)) { u->bindRule()->parse(bytes, out); break; } } void AsUnion::loadFrom(std::shared_ptr core, const QJsonObject& obj) { INT32_PEAK(_union.byte_count, obj); STRING_PEAK(_union.alias_name, 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); STRING_SAVE(_union.alias_name, obj); QJsonArray array; for (auto insr : this->_union._rule_list) { QJsonObject rule_obj; auto match_name = insr->matchType(); 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; } void AsUnion::registSubField(std::shared_ptr inst) { for (auto rl : this->_union._rule_list) rl->bindRule()->registSubField(inst); } QString AsUnion::topic() { return NAME(AsUnion); } QString AsUnion::aliasName() const { return _union.alias_name; } void AsUnion::setAlias(const QString& name) { _union.alias_name = name; } QString AsUnion::unitType() const { return topic(); } void AsRuleSet::registSubField(std::shared_ptr inst) { for (auto rl_key : this->fieldNames()){ auto rlinst = this->operator[](rl_key); rlinst->registSubField(inst); } } void AsRuleSet::parse(const QByteArray& bytes, std::shared_ptr out) const { auto bufx = bytes; for (auto keym : this->fieldNames()) { auto rule = this->operator[](keym); rule->parse(bufx, out); auto size_u = rule->countWithin(); bufx = bufx.mid(size_u); } } QString AsRuleSet::unitType() const { return topic(); } DataType AsRuleSet::outType() const { return DataType::COMPLEX_RULESET; } int AsRuleSet::countWithin() const { auto count = 0; for (auto inst : _bind.sub_units) count += inst->countWithin(); return count; } void AsRuleSet::loadFrom(std::shared_ptr core, const QJsonObject& obj) { STRING_PEAK(_bind.alias_name, obj); QJsonArray array; ARRAY_SAVE(array, obj); for (auto index = 0; index < array.size(); ++index) { auto rule_obj = array.at(index); QString match_name, field_name; STRING_PEAK(field_name, rule_obj); STRING_PEAK(match_name, rule_obj); QJsonObject match_obj; OBJECT_PEAK(match_obj, rule_obj); auto xdev = core->operator[](match_name)->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); QString match_name = pairk->delegateInst()->aliasName(); STRING_SAVE(match_name, 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 ExtractDelegate::name() const { return _inst._field_name; } bool ExtractDelegate::setOffsetSpan(int bytes) { _inst._bytes_offset = bytes; return true; } int ExtractDelegate::offsetSpan() const { return _inst._bytes_offset; } std::shared_ptr ExtractDelegate::delegateInst() const { return _inst._delegate_inst; } void ExtractDelegate::setDelegate(std::shared_ptr inst) { _inst._delegate_inst = inst; } void ExtractDelegate::registSubField(std::shared_ptr inst) { inst->setField(name(), _inst._delegate_inst->outType()); auto nlayer = std::make_shared(name(), inst); _inst._delegate_inst->registSubField(nlayer); } void ExtractDelegate::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 ExtractDelegate::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 ExtractDelegate::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 ExtractDelegate::newDefault() const { return std::make_shared(); } void ExtractDelegate::setName(const QString& name) { _inst._field_name = name; } int ExtractDelegate::countWithin() const { return _inst._delegate_inst->countWithin() + offsetSpan(); }