QBinaryTranslate/TranslateUI/extract_basic.cpp

816 lines
18 KiB
C++
Raw Blame History

#include "extract_basic.h"
#include <QVariant>
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<TranslateBasic> 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<ScopeFieldsSetter> 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<DataContext> 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<Serializable> AsHex::newDefault() const
{
return std::make_shared<AsHex>();
}
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<int, QString> AsBitCombine::switchOptions() const
{
return _combine._switch_options;
}
void AsBitCombine::clearOptions()
{
_combine._switch_options.clear();
}
void AsBitCombine::parse(const QByteArray& bytes, std::shared_ptr<DataContext> 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 <QJsonArray>
void AsBitCombine::loadFrom(
std::shared_ptr<TranslateBasic> 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<Serializable> AsBitCombine::newDefault() const
{
return std::make_shared<AsBitCombine>();
}
QString AsBitCombine::topic()
{
return NAME(AsBitCombine);
}
std::shared_ptr<Serializable> AsInteger::newDefault() const
{
return std::make_shared<AsInteger>();
}
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<DataContext> 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<char>(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 <QTextCodec>
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<DataContext> out) const
{
auto v = _strings._conv_with->toUnicode(bytes);
out->append(v);
}
void AsString::loadFrom(std::shared_ptr<TranslateBasic> 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<Serializable> AsString::newDefault() const
{
return std::make_shared<AsString>();
}
QString AsString::topic()
{
return NAME(AsString);
}
void AsFloat::parse(const QByteArray& bytes, std::shared_ptr<DataContext> out) const
{
out->append(*((float*)bytes.data()));
}
std::shared_ptr<Serializable> AsFloat::newDefault() const
{
return std::make_shared<AsFloat>();
}
AsFloat::AsFloat()
:AbstractExtractor(topic(), DataType::Flt32)
{
this->setCountWithin(4);
}
QString AsFloat::topic()
{
return NAME(AsFloat);
}
std::shared_ptr<Serializable> AsDouble::newDefault() const
{
return std::make_shared<AsDouble>();
}
void AsDouble::parse(const QByteArray& bytes, std::shared_ptr<DataContext> 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<DataContext> 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<Serializable> AsUnsigned::newDefault() const
{
return std::make_shared<AsUnsigned>();
}
QString AsUnsigned::topic()
{
return NAME(AsUnsigned);
}
#include <stdexcept>
void AsRuleSet::registSubField(std::shared_ptr<ScopeFieldsSetter> inst) const
{
for (auto subrule : _bind.sub_units) {
subrule->registSubField(inst);
}
}
void AsRuleSet::parse(const QByteArray& bytes, std::shared_ptr<DataContext> out) const
{
const_cast<AsRuleSet*>(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<AsRuleSet*>(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<TranslateBasic> 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<ExtractUnit>(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<Serializable> AsRuleSet::newDefault() const
{
return std::make_shared<AsRuleSet>();
}
std::shared_ptr<ExtractUnit> AsRuleSet::operator[](int index) const
{
return this->_bind.sub_units[index];
}
void AsRuleSet::replace(int index, std::shared_ptr<ExtractUnit> inst)
{
this->_bind.sub_units.replace(index, inst);
}
extract::AsRuleSet& AsRuleSet::append(std::shared_ptr<ExtractUnit> u)
{
this->_bind.sub_units.append(u);
return *this;
}
void AsRuleSet::removeAt(int index)
{
this->_bind.sub_units.removeAt(index);
}
QList<QString> AsRuleSet::fieldNames() const
{
QList<QString> fields_store;
for (auto fins : this->_bind.sub_units) {
fields_store << fins->name();
}
return fields_store;;
}
std::shared_ptr<ExtractUnit> AsRuleSet::operator[](const QString& field) const
{
for (auto pair : this->_bind.sub_units) {
if (pair->name() == field)
return pair;
}
return std::shared_ptr<ExtractUnit>();
}
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<ExtractDelegate> SingleBasedUnit::delegateInst() const
{
return _inst._delegate_inst;
}
void SingleBasedUnit::setDelegate(std::shared_ptr<ExtractDelegate> inst)
{
_inst._delegate_inst = inst;
}
void SingleBasedUnit::registSubField(std::shared_ptr<ScopeFieldsSetter> inst) const
{
inst->setField(name(), _inst._delegate_inst->outType());
auto nlayer = std::make_shared<FieldManagerLayer>(name(), inst);
_inst._delegate_inst->registSubField(nlayer);
}
void SingleBasedUnit::parse(const QByteArray& bytes, std::shared_ptr<DataContext> out) const
{
auto context = std::make_shared<ValueAccessContext>();
context->init(name(), out);
auto bytes_sec = bytes.mid(this->offsetSpan());
_inst._delegate_inst->parse(bytes_sec, context);
}
void SingleBasedUnit::loadFrom(std::shared_ptr<TranslateBasic> 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<ExtractDelegate>(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<Serializable> SingleBasedUnit::newDefault() const
{
return std::make_shared<SingleBasedUnit>();
}
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<ExtractDelegate> ListBasedUnit::delegateInst() const
{
return _list.delegate_inst;
}
void ListBasedUnit::setDelegate(std::shared_ptr<ExtractDelegate> inst)
{
_list.delegate_inst = inst;
}
void ListBasedUnit::registSubField(std::shared_ptr<ScopeFieldsSetter> inst) const {}
int ListBasedUnit::countWithin() const
{
return _list.count_with_runtime;
}
void ListBasedUnit::parse(const QByteArray& bytes, std::shared_ptr<DataContext> out) const
{
const_cast<ListBasedUnit*>(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<ValueAccessContext>();
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<TranslateBasic> 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<SizeProvider>(ins_size);
_list.delegate_inst = std::dynamic_pointer_cast<ExtractDelegate>(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<Serializable> ListBasedUnit::newDefault() const
{
return std::make_shared<ListBasedUnit>();
}
QString ListBasedUnit::baseType() const
{
return topic();
}
std::shared_ptr<SizeProvider> ListBasedUnit::sizeProvider() const
{
return _list.size_provider_inst;
}
void ListBasedUnit::setSizeProvider(std::shared_ptr<SizeProvider> inst)
{
_list.size_provider_inst = inst;
}
QString ListBasedUnit::topic()
{
return NAME(ListBasedUnit);
}
void UnionBasedUnit::updateMatch(int index, std::shared_ptr<RuleMatch> rule)
{
auto nidx = std::min(std::max(0, index), _union.rulematch_list.size() - 1);
_union.rulematch_list.replace(nidx, rule);
}
QList<std::shared_ptr<RuleMatch>> 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<ScopeFieldsSetter> inst) const {}
int UnionBasedUnit::countWithin() const
{
return _union.bytes_count;
}
void UnionBasedUnit::parse(const QByteArray& bytes, std::shared_ptr<DataContext> out) const
{
auto buffer = bytes.mid(_union.bytes_offset);
for (auto instr : _union.rulematch_list) {
if (instr->checkpass(buffer)) {
auto context = std::make_shared<ValueAccessContext>();
context->init(instr->getDelegate()->aliasName(), out);
instr->getDelegate()->parse(buffer, context);
if (instr->getDelegate()->countWithin() > _union.bytes_count)
throw new BaseException(u8"ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><EFBFBD>ȳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ");
break;
}
}
}
void UnionBasedUnit::loadFrom(std::shared_ptr<TranslateBasic> 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<RuleMatch>(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<Serializable> UnionBasedUnit::newDefault() const
{
return std::make_shared<UnionBasedUnit>();
}
void UnionBasedUnit::setCountWithin(int count)
{
_union.bytes_count = count;
}
QString UnionBasedUnit::topic()
{
return NAME(UnionBasedUnit);
}