[44] | 1 | #ifndef CODEC_H |
---|
| 2 | #define CODEC_H |
---|
| 3 | |
---|
| 4 | #include <QString> |
---|
| 5 | #include <QList> |
---|
| 6 | |
---|
| 7 | #define ERROR -5 |
---|
| 8 | #include "card.h" |
---|
| 9 | // #include "cardcodes.h" |
---|
| 10 | |
---|
| 11 | namespace QPunchCard { |
---|
| 12 | |
---|
| 13 | // this is just to typify these `int Foo[]` arrays in method calls. |
---|
| 14 | // Thus `int Foo[]` is just the type `CodeTable*` |
---|
[47] | 15 | //typedef int CodeTable; |
---|
[44] | 16 | class Codec; |
---|
| 17 | |
---|
| 18 | /** |
---|
[47] | 19 | * Abstracte Codec-Klasse. Implementierungen muessen toAscii/fromAscii |
---|
| 20 | * implementieren und sollten canEncode() implementieren. Fuer Namenszuordnung |
---|
| 21 | * und fortgeschrittene Erstellung ist CodecFactory zustaendig. |
---|
| 22 | **/ |
---|
| 23 | class Codec { |
---|
| 24 | public: |
---|
| 25 | // soll const sein, weil Codec unveraenderbar *immer* das gleiche |
---|
| 26 | // Ergebnis liefern soll, nach Erzeugung. Das ist auch noetig fuer |
---|
| 27 | // CharArrayCodec. |
---|
| 28 | const char illegal; |
---|
| 29 | /// @param illegal_character Zeichen fuer nicht existente Zahlen |
---|
| 30 | Codec(char illegal_character = '~') : illegal(illegal_character) { } |
---|
| 31 | virtual ~Codec() {} |
---|
| 32 | virtual char toAscii(const Column* col) const = 0; |
---|
[48] | 33 | virtual QString toAscii(const Card* target_card) const; |
---|
[47] | 34 | virtual Column fromAscii(char ch) const = 0; |
---|
[48] | 35 | void fromAscii(const QString& string, Card* target_card) const; |
---|
| 36 | |
---|
[47] | 37 | virtual bool canEncode(const Column* col) const { return toAscii(col) != illegal; } |
---|
[48] | 38 | virtual bool canEncode(char /*char*/ ) const = 0; |
---|
| 39 | bool canEncode(const QString& string) const; |
---|
[47] | 40 | |
---|
| 41 | int countIllegalColumns(const Card* card) const; |
---|
| 42 | int countIllegalColumns(const Deck* deck) const; |
---|
| 43 | }; |
---|
| 44 | |
---|
| 45 | /** |
---|
| 46 | * Codec-Implementierung, der mithilfe von hardgecodeten Codetabellen |
---|
[44] | 47 | * (von Douglas Jones uebernommen) eine Umwandlung char->Column und andersrum |
---|
| 48 | * durchfuehren kann. Letzteres geht genauso perfomant dank 4kb grosser |
---|
| 49 | * inverser Tabelle, die bei Objektkonstruktion angelegt wird. |
---|
| 50 | **/ |
---|
[47] | 51 | class CharArrayCodec : public Codec { |
---|
| 52 | const int* table; |
---|
[44] | 53 | char inverse_table[4096]; |
---|
| 54 | |
---|
| 55 | public: |
---|
[47] | 56 | CharArrayCodec(const int* table, char illegal = '~');// : Codec(illegal), table(table) {} |
---|
| 57 | char toAscii(const Column* col) const { return inverse_table[*col]; } |
---|
[49] | 58 | Column fromAscii(char ch) const { return Column(canEncode(ch) ? table[ch]: 0); } |
---|
[44] | 59 | |
---|
[47] | 60 | bool canEncode(const Column* col) const { return inverse_table[*col] != illegal; } |
---|
[49] | 61 | bool canEncode(char ch) const { |
---|
| 62 | bool r = (table[ch] != ERROR); |
---|
| 63 | if(ch < ' ' || ch > 'z') r = false; |
---|
| 64 | //qDebug("CharArrayCodec: %c is a %s character", ch, r ? "valid" : "invalid"); |
---|
| 65 | return r; } |
---|
[47] | 66 | }; |
---|
[44] | 67 | |
---|
[47] | 68 | /** |
---|
| 69 | * Factory-Klasse, die alle bekannten Codecs zurueckgeben kann. Wesentliches |
---|
| 70 | * Merkmal ist die Faehigkeit, mit Namen (QStrings) von Codecs umgehen zu |
---|
| 71 | * koennen und Codecs aus Namen erstellen zu koennen. Ausserdem gibt es |
---|
| 72 | * Algorithmen zum Finden des bestmoeglichen Codecs zu einer Card/einem Deck, |
---|
| 73 | * die mit Codec:countIllegalColumns() arbeitet. |
---|
| 74 | **/ |
---|
| 75 | class CodecFactory { |
---|
| 76 | public: |
---|
| 77 | // TODO: Codec-Caching (Codec-Constructor privatisieren, dafuer hier caching |
---|
| 78 | // betreiben) weil einige codecs recht teuer zu erstellen sind (CharArrayCodec) |
---|
| 79 | static QList<QString> availableCodecs(); |
---|
| 80 | static const Codec* createCodec(const QString& name, char illegal_character = '~'); |
---|
| 81 | static const QString autoDetectCodec(const Card* card); |
---|
| 82 | static const QString autoDetectCodec(const Deck* deck); |
---|
[44] | 83 | }; |
---|
| 84 | |
---|
[47] | 85 | |
---|
[44] | 86 | }; // Namespace |
---|
| 87 | #endif // CODEC_H |
---|