5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #ifndef _EEPROMIMPORTEXPORT_H_
22 #define _EEPROMIMPORTEXPORT_H_
24 #include "customdebug.h"
29 DataField(DataField
* parent
, const char * name
=""):
39 virtual const QString
& getName()
44 virtual unsigned int size() = 0;
45 virtual void ExportBits(QBitArray
& output
) = 0;
46 virtual void ImportBits(const QBitArray
& input
) = 0;
48 QBitArray
bytesToBits(QByteArray bytes
)
50 QBitArray
bits(bytes
.count()*8);
51 // Convert from QByteArray to QBitArray
52 for (int i
=0; i
<bytes
.count(); ++i
)
53 for (int b
=0; b
<8; ++b
)
54 bits
.setBit(i
*8+b
, bytes
.at(i
)&(1<<b
));
58 QByteArray
bitsToBytes(QBitArray bits
, int offset
=0)
61 bytes
.resize((offset
+bits
.count()+7)/8);
63 // Convert from QBitArray to QByteArray
64 for (int b
=0; b
<bits
.count(); ++b
)
65 bytes
[(b
+offset
)/8] = ( bytes
.at((b
+offset
)/8) | ((bits
[b
]?1:0)<<((b
+offset
)%8)));
69 int Export(QByteArray
& output
)
73 output
= bitsToBytes(result
);
77 int Import(const QByteArray
& input
)
79 QBitArray bits
= bytesToBits(input
);
80 if ((unsigned int)bits
.size() < size()) {
81 qDebug() << QString("Error importing %1: size to small %2/%3").arg(getName()).arg(input
.size()).arg(size());
88 virtual int Dump(int level
=0, int offset
=0)
92 QByteArray bytes
= bitsToBytes(bits
);
93 int result
= (offset
+bits
.count()) % 8;
94 for (int i
=0; i
<level
; i
++) printf(" ");
95 if (bits
.count() % 8 == 0)
96 printf("%s (%dbytes) ", getName().toLatin1().constData(), bytes
.count());
98 printf("%s (%dbits) ", getName().toLatin1().constData(), bits
.count());
99 for (int i
=0; i
<bytes
.count(); i
++) {
100 unsigned char c
= bytes
[i
];
101 if ((i
==0 && offset
) || (i
==bytes
.count()-1 && result
!=0))
102 printf("(%02x) ", c
);
106 printf("\n"); fflush(stdout
);
111 virtual void setError(const QString
& error
)
114 parent
->setError(error
);
117 qWarning() << qPrintable(error
);
125 class ProxyField
: public DataField
{
127 explicit ProxyField(DataField
* parent
):
128 DataField(parent
, "Proxy")
132 virtual DataField
* getField() = 0;
136 template<class container
, int N
>
137 class BaseUnsignedField
: public DataField
{
139 BaseUnsignedField(DataField
* parent
, container
& field
):
140 DataField(parent
, "Unsigned"),
143 max(std::numeric_limits
<container
>::max())
147 BaseUnsignedField(DataField
* parent
, container
& field
, const char * name
):
148 DataField(parent
, name
),
151 max(std::numeric_limits
<container
>::max())
155 BaseUnsignedField(DataField
* parent
, container
& field
, container min
, container max
, const char * name
="Unsigned"):
156 DataField(parent
, name
),
163 virtual void ExportBits(QBitArray
& output
)
165 container value
= field
;
166 if (value
> max
) value
= max
;
167 if (value
< min
) value
= min
;
170 for (int i
=0; i
<N
; i
++) {
171 if (value
& ((container
)1<<i
)) {
177 virtual void ImportBits(const QBitArray
& input
)
180 for (int i
=0; i
<N
; i
++) {
182 field
|= ((container
)1<<i
);
184 qCDebug(eepromImport
) << QString("\timported %1<%2>: 0x%3(%4)").arg(name
).arg(N
).arg(field
, 0, 16).arg(field
);
187 virtual unsigned int size()
202 class UnsignedField
: public BaseUnsignedField
<unsigned int, N
>
205 UnsignedField(DataField
* parent
, unsigned int & field
):
206 BaseUnsignedField
<unsigned int, N
>(parent
, field
)
210 UnsignedField(DataField
* parent
, unsigned int & field
, const char *name
):
211 BaseUnsignedField
<unsigned int, N
>(parent
, field
, name
)
215 UnsignedField(DataField
* parent
, unsigned int & field
, unsigned int min
, unsigned int max
, const char *name
="Unsigned"):
216 BaseUnsignedField
<unsigned int, N
>(parent
, field
, min
, max
, name
)
222 class BoolField
: public DataField
{
224 explicit BoolField(DataField
* parent
, bool & field
):
225 DataField(parent
, "Bool"),
230 virtual void ExportBits(QBitArray
& output
)
238 virtual void ImportBits(const QBitArray
& input
)
240 field
= input
[0] ? true : false;
241 qCDebug(eepromImport
) << QString("\timported %1<%2>: 0x%3(%4)").arg(name
).arg(N
).arg(field
, 0, 16).arg(field
);
244 virtual unsigned int size()
257 class SignedField
: public DataField
{
259 SignedField(DataField
* parent
, int & field
):
260 DataField(parent
, "Signed"),
267 SignedField(DataField
* parent
, int & field
, const char *name
):
268 DataField(parent
, name
),
275 SignedField(DataField
* parent
, int & field
, int min
, int max
, const char *name
="Signed"):
276 DataField(parent
, name
),
283 virtual void ExportBits(QBitArray
& output
)
286 if (value
> max
) value
= max
;
287 if (value
< min
) value
= min
;
290 for (int i
=0; i
<N
; i
++) {
291 if (((unsigned int)value
) & (1<<i
))
296 virtual void ImportBits(const QBitArray
& input
)
298 unsigned int value
= 0;
299 for (int i
=0; i
<N
; i
++) {
305 for (unsigned int i
=N
; i
<8*sizeof(int); i
++) {
311 qCDebug(eepromImport
) << QString("\timported %1<%2>: 0x%3(%4)").arg(name
).arg(N
).arg(field
, 0, 16).arg(field
);
314 virtual unsigned int size()
326 class SpareBitsField
: public UnsignedField
<N
> {
328 SpareBitsField(DataField
* parent
):
329 UnsignedField
<N
>(parent
, spare
, 0, 0, "Spare"),
338 class CharField
: public DataField
{
340 CharField(DataField
* parent
, char * field
, bool truncate
=true, const char * name
="Char"):
341 DataField(parent
, name
),
347 virtual void ExportBits(QBitArray
& output
)
351 int len
= truncate
? strlen(field
) : N
;
352 for (int i
=0; i
<N
; i
++) {
353 int idx
= (i
>=len
? 0 : field
[i
]);
354 for (int j
=0; j
<8; j
++, b
++) {
361 virtual void ImportBits(const QBitArray
& input
)
364 for (int i
=0; i
<N
; i
++) {
366 for (int j
=0; j
<8; j
++) {
372 qCDebug(eepromImport
) << QString("\timported %1<%2>: '%3'").arg(name
).arg(N
).arg(field
);
375 virtual unsigned int size()
385 int8_t char2idx(char c
);
386 char idx2char(int8_t idx
);
389 class ZCharField
: public DataField
{
391 ZCharField(DataField
* parent
, char * field
, const char * name
= "ZChar"):
392 DataField(parent
, name
),
397 virtual void ExportBits(QBitArray
& output
)
401 int len
= strlen(field
);
402 for (int i
=0; i
<N
; i
++) {
403 int idx
= i
>=len
? 0 : char2idx(field
[i
]);
404 for (int j
=0; j
<8; j
++, b
++) {
411 virtual void ImportBits(const QBitArray
& input
)
414 for (int i
=0; i
<N
; i
++) {
416 for (int j
=0; j
<8; j
++) {
420 field
[i
] = idx2char(idx
);
424 for (int i
=N
-1; i
>=0; i
--) {
430 qCDebug(eepromImport
) << QString("\timported %1<%2>: '%3'").arg(name
).arg(N
).arg(field
);
433 virtual unsigned int size()
442 class StructField
: public DataField
{
444 StructField(DataField
* parent
, const char * name
="Struct"):
445 DataField(parent
, name
)
450 foreach(DataField
* field
, fields
) {
455 inline void Append(DataField
* field
) {
456 //qCDebug(eepromImport) << QString("StructField(%1) appending field: %2").arg(name).arg(field->getName());
457 fields
.append(field
);
460 virtual void ExportBits(QBitArray
& output
)
463 output
.resize(size());
464 foreach(DataField
*field
, fields
) {
466 field
->ExportBits(bits
);
467 for (int i
=0; i
<bits
.size(); i
++)
468 output
[offset
++] = bits
[i
];
472 virtual void ImportBits(const QBitArray
& input
)
474 qCDebug(eepromImport
) << QString("\timporting %1[%2]:").arg(name
).arg(fields
.size());
476 foreach(DataField
*field
, fields
) {
477 unsigned int size
= field
->size();
478 QBitArray
bits(size
);
479 for (unsigned int i
=0; i
<size
; i
++) {
480 bits
[i
] = input
[offset
++];
482 field
->ImportBits(bits
);
486 virtual unsigned int size()
488 unsigned int result
= 0;
489 foreach(DataField
*field
, fields
) {
490 result
+= field
->size();
495 virtual int Dump(int level
=0, int offset
=0)
497 for (int i
=0; i
<level
; i
++) printf(" ");
498 printf("%s (%d bytes)\n", getName().toLatin1().constData(), size()/8);
499 foreach(DataField
*field
, fields
) {
500 offset
= field
->Dump(level
+1, offset
);
506 QList
<DataField
*> fields
;
509 class TransformedField
: public DataField
{
511 TransformedField(DataField
* parent
, DataField
& field
):
517 virtual ~TransformedField()
521 virtual void ExportBits(QBitArray
& output
)
524 field
.ExportBits(output
);
527 virtual void ImportBits(const QBitArray
& input
)
529 qCDebug(eepromImport
) << QString("\timporting TransformedField %1:").arg(field
.getName());
530 field
.ImportBits(input
);
535 virtual const QString
& getName()
537 return field
.getName();
540 virtual unsigned int size()
545 virtual void beforeExport() = 0;
547 virtual void afterImport() = 0;
549 virtual int Dump(int level
=0, int offset
=0)
552 return field
.Dump(level
, offset
);
559 class ConversionTable
{
562 bool exportValue(const int before
, int &after
)
566 for (std::list
<ConversionTuple
>::iterator it
=exportTable
.begin(); it
!=exportTable
.end(); it
++) {
567 ConversionTuple
& tuple
= *it
;
568 if (before
== tuple
.a
) {
577 bool importValue(const int before
, int &after
)
581 for (std::list
<ConversionTuple
>::iterator it
=importTable
.begin(); it
!=importTable
.end(); it
++) {
582 ConversionTuple
& tuple
= *it
;
583 if (before
== tuple
.b
) {
594 class ConversionTuple
{
596 ConversionTuple(const int a
, const int b
):
606 void addConversion(const int a
, const int b
)
608 ConversionTuple
conversion(a
, b
);
609 importTable
.push_back(conversion
);
610 exportTable
.push_back(conversion
);
613 void addImportConversion(const int a
, const int b
)
615 importTable
.push_back(ConversionTuple(a
, b
));
618 void addExportConversion(const int a
, const int b
)
620 exportTable
.push_back(ConversionTuple(a
, b
));
623 std::list
<ConversionTuple
> importTable
;
624 std::list
<ConversionTuple
> exportTable
;
628 class ConversionField
: public TransformedField
{
630 ConversionField(DataField
* parent
, int & field
, ConversionTable
*table
, const char *name
, const QString
& error
= ""):
631 TransformedField(parent
, internalField
),
632 internalField(this, _field
, name
),
646 ConversionField(DataField
* parent
, unsigned int & field
, ConversionTable
*table
, const char *name
, const QString
& error
= ""):
647 TransformedField(parent
, internalField
),
648 internalField(this, (unsigned int &)_field
, name
),
662 ConversionField(DataField
* parent
, int & field
, int (*exportFunc
)(int), int (*importFunc
)(int)):
663 TransformedField(parent
, internalField
),
664 internalField(this, _field
),
672 exportFunc(exportFunc
),
673 importFunc(importFunc
),
678 ConversionField(DataField
* parent
, int & field
, int shift
, int scale
=0, int min
=INT_MIN
, int max
=INT_MAX
, const char *name
= "Signed shifted"):
679 TransformedField(parent
, internalField
),
680 internalField(this, _field
, name
),
694 ConversionField(DataField
* parent
, unsigned int & field
, int shift
, int scale
=0):
695 TransformedField(parent
, internalField
),
696 internalField(this, (unsigned int &)_field
),
710 virtual void beforeExport()
719 if (!table
->exportValue(_field
, _field
)) {
720 setError(error
.isEmpty() ? QObject::tr("Conversion error on field %1").arg(name
) : error
);
727 _field
= min
+ shift
;
728 else if (_field
> max
)
729 _field
= max
+ shift
;
735 _field
= exportFunc(_field
);
739 virtual void afterImport()
744 if (table
->importValue(field
, field
))
753 field
= importFunc(field
);
759 qCDebug(eepromImport
) << QString("\timported ConversionField<%1>:").arg(internalField
.getName()) << QString(" before: %1, after: %2").arg(_field
).arg(field
);
766 ConversionTable
* table
;
771 int (*exportFunc
)(int);
772 int (*importFunc
)(int);
776 #endif // _EEPROMIMPORTEXPORT_H_