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*` |
---|
15 | //typedef int CodeTable; |
---|
16 | class Codec; |
---|
17 | |
---|
18 | /** |
---|
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; |
---|
33 | virtual Column fromAscii(char ch) const = 0; |
---|
34 | virtual bool canEncode(const Column* col) const { return toAscii(col) != illegal; } |
---|
35 | virtual bool canEncode(char ch) const = 0; |
---|
36 | |
---|
37 | int countIllegalColumns(const Card* card) const; |
---|
38 | int countIllegalColumns(const Deck* deck) const; |
---|
39 | }; |
---|
40 | |
---|
41 | /** |
---|
42 | * Codec-Implementierung, der mithilfe von hardgecodeten Codetabellen |
---|
43 | * (von Douglas Jones uebernommen) eine Umwandlung char->Column und andersrum |
---|
44 | * durchfuehren kann. Letzteres geht genauso perfomant dank 4kb grosser |
---|
45 | * inverser Tabelle, die bei Objektkonstruktion angelegt wird. |
---|
46 | **/ |
---|
47 | class CharArrayCodec : public Codec { |
---|
48 | const int* table; |
---|
49 | char inverse_table[4096]; |
---|
50 | |
---|
51 | public: |
---|
52 | CharArrayCodec(const int* table, char illegal = '~');// : Codec(illegal), table(table) {} |
---|
53 | char toAscii(const Column* col) const { return inverse_table[*col]; } |
---|
54 | Column fromAscii(char ch) const { return Column(table[ch]); } |
---|
55 | |
---|
56 | bool canEncode(const Column* col) const { return inverse_table[*col] != illegal; } |
---|
57 | bool canEncode(char ch) const { return table[ch] != ERROR; } |
---|
58 | }; |
---|
59 | |
---|
60 | /** |
---|
61 | * Factory-Klasse, die alle bekannten Codecs zurueckgeben kann. Wesentliches |
---|
62 | * Merkmal ist die Faehigkeit, mit Namen (QStrings) von Codecs umgehen zu |
---|
63 | * koennen und Codecs aus Namen erstellen zu koennen. Ausserdem gibt es |
---|
64 | * Algorithmen zum Finden des bestmoeglichen Codecs zu einer Card/einem Deck, |
---|
65 | * die mit Codec:countIllegalColumns() arbeitet. |
---|
66 | **/ |
---|
67 | class CodecFactory { |
---|
68 | public: |
---|
69 | // TODO: Codec-Caching (Codec-Constructor privatisieren, dafuer hier caching |
---|
70 | // betreiben) weil einige codecs recht teuer zu erstellen sind (CharArrayCodec) |
---|
71 | static QList<QString> availableCodecs(); |
---|
72 | static const Codec* createCodec(const QString& name, char illegal_character = '~'); |
---|
73 | static const QString autoDetectCodec(const Card* card); |
---|
74 | static const QString autoDetectCodec(const Deck* deck); |
---|
75 | }; |
---|
76 | |
---|
77 | |
---|
78 | }; // Namespace |
---|
79 | #endif // CODEC_H |
---|