QBinaryTranslate/TranslateUI/extract_basic.cpp

471 lines
9.8 KiB
C++
Raw Normal View History

2025-08-01 01:47:41 +00:00
#include "extract_basic.h"
#include <QVariant>
using namespace extract;
AbstractExtractor::AbstractExtractor(const QString& name, DataType data)
2025-08-02 02:04:30 +00:00
{
_abs_data.name_store = name;
_abs_data.type_store = data;
2025-08-01 01:47:41 +00:00
}
bool AbstractExtractor::setOffsetSpan(int bytes)
{
2025-08-02 02:04:30 +00:00
this->_abs_data.byte_offset = bytes;
2025-08-01 01:47:41 +00:00
return true;
}
bool AbstractExtractor::setCountWithin(int bytes)
{
2025-08-02 02:04:30 +00:00
this->_abs_data.byte_count = bytes;
2025-08-01 01:47:41 +00:00
return true;
}
QString AbstractExtractor::name() const
{
2025-08-02 02:04:30 +00:00
return _abs_data.name_store;
2025-08-01 01:47:41 +00:00
}
DataType AbstractExtractor::outType() const
{
2025-08-02 02:04:30 +00:00
return _abs_data.type_store;
2025-08-01 01:47:41 +00:00
}
int AbstractExtractor::offsetSpan() const
{
2025-08-02 02:04:30 +00:00
return _abs_data.byte_offset;
2025-08-01 01:47:41 +00:00
}
int AbstractExtractor::countWithin() const
{
2025-08-02 02:04:30 +00:00
return this->_abs_data.byte_count;
2025-08-01 01:47:41 +00:00
}
void AbstractExtractor::loadFrom(const QJsonObject& obj)
{
2025-08-02 02:04:30 +00:00
INT32_PEAK(_abs_data.byte_offset);
INT32_PEAK(_abs_data.byte_count);
2025-08-01 01:47:41 +00:00
}
void AbstractExtractor::saveTo(QJsonObject& obj) const
{
2025-08-02 02:04:30 +00:00
INT32_SAVE(_abs_data.byte_offset);
INT32_SAVE(_abs_data.byte_count);
2025-08-01 01:47:41 +00:00
}
BytesAsHex::BytesAsHex()
: AbstractExtractor(NAME(BytesAsHex), DataType::TextString) {
2025-08-02 02:04:30 +00:00
setCountWithin(1);
2025-08-01 01:47:41 +00:00
}
QVariant BytesAsHex::parse(const QByteArray& bytes) const
{
QString result;
for (auto char_v : bytes) {
result += QString("%1").arg(char_v, 2, 16, QChar('0'));
}
return result;
}
std::shared_ptr<Serializable> BytesAsHex::newDefault() const
{
return std::make_shared<BytesAsHex>();
}
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) {
2025-08-02 02:04:30 +00:00
_combines._switch_options[bit_index] = keyword;
2025-08-01 01:47:41 +00:00
return true;
}
return false;
}
QHash<int, QString> BytesAsBitCombine::switchOptions() const
{
2025-08-02 02:04:30 +00:00
return _combines._switch_options;
2025-08-01 01:47:41 +00:00
}
void BytesAsBitCombine::clearOptions()
{
2025-08-02 02:04:30 +00:00
_combines._switch_options.clear();
2025-08-01 01:47:41 +00:00
}
QVariant BytesAsBitCombine::parse(const QByteArray& bytes) const
{
2025-08-02 02:04:30 +00:00
auto keys = _combines._switch_options.keys();
2025-08-01 01:47:41 +00:00
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))
2025-08-02 02:04:30 +00:00
result += QString("%1<%2>;").arg(_combines._switch_options[idx], "Y");
2025-08-01 01:47:41 +00:00
else
2025-08-02 02:04:30 +00:00
result += QString("%1<%2>;").arg(_combines._switch_options[idx], "N");
2025-08-01 01:47:41 +00:00
}
return result;
}
void BytesAsBitCombine::loadFrom(const QJsonObject& obj)
{
AbstractExtractor::loadFrom(obj);
QStringList value_list;
STRLIST_PEAK(value_list);
2025-08-02 02:04:30 +00:00
_combines._switch_options.clear();
2025-08-01 01:47:41 +00:00
for (auto pair : value_list) {
auto items = pair.split("=");
2025-08-02 02:04:30 +00:00
_combines._switch_options[items.first().toInt()] = items.last();
2025-08-01 01:47:41 +00:00
}
}
void BytesAsBitCombine::saveTo(QJsonObject& obj) const
{
AbstractExtractor::saveTo(obj);
QStringList value_list;
2025-08-02 02:04:30 +00:00
for (auto key : _combines._switch_options.keys()) {
auto pair_str = QString("%1=%2").arg(key)
.arg(_combines._switch_options[key]);
2025-08-01 10:55:53 +00:00
value_list << pair_str;
2025-08-01 01:47:41 +00:00
}
STRLIST_SAVE(value_list);
}
std::shared_ptr<Serializable> BytesAsBitCombine::newDefault() const
{
return std::make_shared<BytesAsBitCombine>();
}
std::shared_ptr<Serializable> BytesAsInteger::newDefault() const
{
return std::make_shared<BytesAsInteger>();
}
BytesAsInteger::BytesAsInteger()
:AbstractExtractor(NAME(BytesAsInteger), DataType::Integer) {
}
bool BytesAsInteger::setCountWithin(int bytes)
{
bytes = std::min(8, std::max(bytes, 0));
return AbstractExtractor::setCountWithin(bytes);
}
QVariant BytesAsInteger::parse(const QByteArray& bytes) 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 {
2025-08-02 02:04:30 +00:00
xbuffer.append(8 - bytes.size(), static_cast<char>(0xff));
2025-08-01 01:47:41 +00:00
}
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;
}
return *((long long*)(&value));
}
#include <QTextCodec>
BytesAsString::BytesAsString()
:AbstractExtractor(NAME(BytesAsString), DataType::TextString) {
2025-08-02 02:04:30 +00:00
_strings._conv_with = QTextCodec::codecForName("GBK");
2025-08-01 01:47:41 +00:00
}
void BytesAsString::setStrCodec(QTextCodec* ins)
{
2025-08-02 02:04:30 +00:00
this->_strings._conv_with = ins;
2025-08-01 01:47:41 +00:00
}
QString BytesAsString::codecName() const
{
2025-08-02 02:04:30 +00:00
return this->_strings._conv_with->name();
2025-08-01 01:47:41 +00:00
}
QVariant BytesAsString::parse(const QByteArray& bytes) const
{
2025-08-02 02:04:30 +00:00
return _strings._conv_with->toUnicode(bytes);
2025-08-01 01:47:41 +00:00
}
void BytesAsString::loadFrom(const QJsonObject& obj)
{
AbstractExtractor::loadFrom(obj);
QString codec_name;
STRING_PEAK(codec_name);
2025-08-02 02:04:30 +00:00
this->_strings._conv_with = QTextCodec::codecForName(codec_name.toLatin1());
2025-08-01 01:47:41 +00:00
}
void BytesAsString::saveTo(QJsonObject& obj) const
{
AbstractExtractor::saveTo(obj);
auto codec_name = this->codecName();
STRING_SAVE(codec_name);
}
std::shared_ptr<Serializable> BytesAsString::newDefault() const
{
return std::make_shared<BytesAsString>();
}
QVariant BytesAsFloat::parse(const QByteArray& bytes) const
{
return *((float*)bytes.data());
}
std::shared_ptr<Serializable> BytesAsFloat::newDefault() const
{
return std::make_shared<BytesAsFloat>();
}
BytesAsFloat::BytesAsFloat()
:AbstractExtractor(NAME(BytesAsFloat), DataType::Flt32)
{
2025-08-01 07:03:35 +00:00
this->setCountWithin(4);
2025-08-01 01:47:41 +00:00
}
std::shared_ptr<Serializable> BytesAsDouble::newDefault() const
{
return std::make_shared<BytesAsDouble>();
}
QVariant BytesAsDouble::parse(const QByteArray& bytes) const
{
return *((double*)bytes.data());
}
BytesAsDouble::BytesAsDouble()
:AbstractExtractor(NAME(BytesAsDouble), DataType::Dbl64)
{
2025-08-01 07:03:35 +00:00
this->setCountWithin(8);
2025-08-01 01:47:41 +00:00
}
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);
}
QVariant BytesAsUnsigned::parse(const QByteArray& bytes) 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;
}
return value;
}
std::shared_ptr<Serializable> BytesAsUnsigned::newDefault() const
{
return std::make_shared<BytesAsUnsigned>();
}
#include <stdexcept>
2025-08-01 23:06:42 +00:00
bool BytesAsList::setOffsetSpan(int value)
2025-08-01 01:47:41 +00:00
{
2025-08-02 02:04:30 +00:00
this->_list._bytes_offset = value;
2025-08-01 23:06:42 +00:00
return true;
}
2025-08-01 01:47:41 +00:00
2025-08-01 23:06:42 +00:00
std::shared_ptr<ExtractUnit> BytesAsList::elementRule() const
{
2025-08-02 02:04:30 +00:00
return this->_list._bind_unit;
2025-08-01 23:06:42 +00:00
}
bool BytesAsList::setElementRule(std::shared_ptr<ExtractUnit> u)
{
2025-08-02 02:04:30 +00:00
this->_list._bind_unit = u;
2025-08-01 01:47:41 +00:00
return true;
}
2025-08-02 02:04:30 +00:00
std::shared_ptr<SizeProvider> BytesAsList::sizeProvider() const
2025-08-01 01:47:41 +00:00
{
2025-08-02 02:04:30 +00:00
return this->_list._bind_size_v;
2025-08-01 01:47:41 +00:00
}
2025-08-01 23:06:42 +00:00
bool BytesAsList::setSizeProvider(std::shared_ptr<SizeProvider> ins)
2025-08-01 01:47:41 +00:00
{
2025-08-02 02:04:30 +00:00
this->_list._bind_size_v = ins;
2025-08-01 23:06:42 +00:00
return true;
}
QString BytesAsList::name() const
{
return NAME(BytesAsList);
}
DataType BytesAsList::outType() const
{
return DataType::LIST_COLLECTION;
}
int BytesAsList::offsetSpan() const
{
2025-08-02 02:04:30 +00:00
return _list._bytes_offset;
2025-08-01 23:06:42 +00:00
}
int BytesAsList::countWithin() const
{
2025-08-02 02:04:30 +00:00
auto expr = this->_list._bind_size_v->expression();
if (this->_list._bind_size_v->value(expr) < 0) {
2025-08-01 23:06:42 +00:00
return 0;
}
2025-08-02 02:04:30 +00:00
return this->_list._bind_size_v->value(expr)
* this->_list._bind_unit->countWithin();
2025-08-01 23:06:42 +00:00
}
void BytesAsList::loadFrom(const QJsonObject& obj)
{
2025-08-02 02:04:30 +00:00
INT32_PEAK(_list._bytes_offset);
2025-08-01 23:06:42 +00:00
QString bind_provider_expr = "";
STRING_SAVE(bind_provider_expr);
2025-08-02 02:04:30 +00:00
if (this->_list._bind_size_v)
this->_list._bind_size_v->setExpression(bind_provider_expr);
2025-08-01 23:06:42 +00:00
}
void BytesAsList::saveTo(QJsonObject& obj) const
{
QString bind_unit_name = "";
2025-08-02 02:04:30 +00:00
if (this->_list._bind_unit)
bind_unit_name = this->_list._bind_unit->name();
2025-08-01 23:06:42 +00:00
STRING_SAVE(bind_unit_name);
2025-08-02 02:04:30 +00:00
INT32_SAVE(_list._bytes_offset);
2025-08-01 23:06:42 +00:00
QString bind_size_provider_name = "";
QString bind_provider_expr = "";
2025-08-02 02:04:30 +00:00
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();
2025-08-01 23:06:42 +00:00
}
STRING_SAVE(bind_size_provider_name);
STRING_SAVE(bind_provider_expr);
}
QVariant BytesAsList::parse(const QByteArray& bytes) const
{
QVariantList value_list;
2025-08-02 02:04:30 +00:00
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();
2025-08-01 23:06:42 +00:00
for (auto idx = 0; idx < size_value; ++idx) {
auto secn = bytes.mid(unit_size * idx, unit_size);
2025-08-02 02:04:30 +00:00
auto value_v = this->_list._bind_unit->parse(secn);
2025-08-01 23:06:42 +00:00
value_list << value_v;
}
return value_list;
}
std::shared_ptr<Serializable> BytesAsList::newDefault() const
{
return std::make_shared<BytesAsList>();
2025-08-01 01:47:41 +00:00
}
2025-08-02 02:04:30 +00:00
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;
}
QVariant BytesAsUnion::parse(const QByteArray& bytes) const
{
for (auto u : this->elementRules())
if (u->checkpass(bytes))
return u->bindRule()->parse(bytes);
return QVariant();
}
void BytesAsUnion::loadFrom(const QJsonObject& obj)
{
throw std::logic_error("The method or operation is not implemented.");
}
void BytesAsUnion::saveTo(QJsonObject& obj) const
{
INT32_SAVE(_union.byte_count);
INT32_SAVE(_union.byte_offset);
}
std::shared_ptr<Serializable> BytesAsUnion::newDefault() const
{
return std::make_shared<BytesAsUnion>();
}
QList<std::shared_ptr<RuleMatch>> BytesAsUnion::elementRules() const
{
return _union._rule_list;
}
bool BytesAsUnion::setElementRule(std::shared_ptr<RuleMatch> 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;
}