source: projects/punch-card/punch-card-editor/src/qpunchcard/format.cc @ 52

Last change on this file since 52 was 52, checked in by sven, 10 years ago

Punch Card Editor: Code reordering and class renaming, rewriting.
Now using the namespace QPunchCard everywhere.

Parted the whole application into 5 parts/directories:

  • app: The application core with MainWindow and main() function
  • qpunchcard: Everything directly binary card related (no interpretation): modeling, input/output, view. Most important classes are Card, Deck, FileFormat, Widget
  • text: Everything related to text interpretation of Cards/Card Decks. Having the abstract Codec classes and the Text::Editor, Text::EditorDock
  • deckviewer: Application components like binary card editing central widget (CardEditor) and Navigator (Model View Controller classes)
  • driver: Basis for the driver framework, must be written soon.

Deck now hides the complete Storage to implement frontend methods that
implement versioning (Undo framework). All code was cleaned up, but doesn't
compile right now (still quite some non heavy errors).

-- Sven @ workstation

File size: 5.1 KB
Line 
1#include "format.h"
2#include <QDebug>
3
4using namespace QPunchCard;
5
6QList<QString> FileFormatFactory::availableFormats() {
7        QList<QString> ret;
8        ret << "Jones Emulated Card Deck File" << "Punch Card Markup Language File";
9        return ret;
10}
11
12const FileFormat* FileFormatFactory::createFormat(const QString& name) {
13        if(name == "Jones Emulated Card Deck File")
14                return new JonesFileFormat;
15        if(name == "Punch Card Markup Language File")
16                return new PunchCardMarkupLanguageFormat;
17        else {
18                qDebug() << "FileFormatFactory: Invalid createFormat name: " << name;
19                return 0;
20        }
21}
22
23QString FileFormatFactory::autoDetectFormat(const QFile&) {
24        // spaeter per magic bytes-Erkennung machen
25        return QString("Jones Emulated Card Deck File");
26}
27
28bool JonesFileFormat::read(QFile& file, Deck& deck) const {
29        qDebug() << "Jones reading";
30
31        if(!file.isOpen()) {
32                // oeffne Datei
33                if(! file.open(QIODevice::ReadOnly))
34                        return false;
35        }
36
37        // Now we have an open file at `file`. Use
38        // QIODevice methods:
39
40        // At first, check the file prefix (magic bytes)
41        char char1, char2, char3;
42        file.getChar(&char1);
43        file.getChar(&char2);
44        file.getChar(&char3);
45        if( (char1 == 'H') && (char2 == '8') && (char3 == '0') ) {
46                //this.default_col_length = 80; // hum... nice
47        } else if ((char1 == 'H') && (char2 == '8') && (char3 == '2')) {
48                //this.default_col_length = 82;
49                return false; // hum... bad
50        } else {
51                // Fehler spezifizieren...:
52                // Input file not a card file
53                return false;
54        }
55
56        // Process card deck
57        while( file.bytesAvailable() > 0 ) {
58                //Card* cur_card = new Card();
59                Card cur_card;
60                // try to read in 120 (body) + 3 (header) bytes
61                QByteArray data = file.read(123);
62
63                if( ((data[0] & 0x08) == 0)
64                 || ((data[1] & 0x08) == 0)
65                 || ((data[2] & 0x08) == 0)) {
66                        // This card was corrupt or there were no more data.
67                        // Break it. Don't save the current card any more.
68                        break;
69                }
70
71                /* This algorithm is based on the C algorithm
72                   of Jones */
73                int x = 3;
74                for(int cur_col = 0; cur_col < 80; ) {
75                        /* read in 3 bytes */
76                        int first = data[x++];
77                        int second = data[x++];
78                        int third = data[x++];
79
80                        /* convert to 2 columns */
81                        int even_col = (first << 4) | (second >> 4);
82                        int odd_col = ((second & 0017) << 8) | third;
83
84                        /* save the columns in the card */
85                        // This is integer => Column conversion with
86                        // implicit knowledge that this followes the
87                        // Jones file format
88                        cur_card.column[cur_col++] = jones_integer_to_column(even_col);
89                        cur_card.column[cur_col++] = jones_integer_to_column(odd_col);
90                }
91
92                /* push card on the card deck*/
93                // TODO: Das muss irgendwie ggf. in das UNDO-System eingebaut
94                // werden (hier falsche Stelle -- in Deck-Class muss das eingebaut
95                // werden
96                deck.push_back(cur_card);
97        } // while ! eof
98
99        file.close();
100        return true;
101} // jones reader
102
103// jones writer
104bool JonesFileFormat::write(QFile& file, const Deck& deck) const {
105        qDebug() << "Jones writing";
106
107        if(!file.isOpen()) {
108                // oeffne Datei
109                if(! file.open(QIODevice::WriteOnly)) {
110                        qDebug() << "Failed to open file: " << file.errorString();
111                        return false;
112                }
113        }
114
115        int col_length = 80;
116
117        // Write out file prefix
118        qDebug() << "Beginning Jones writing";
119        file.putChar('H');
120        file.putChar('8');
121        file.putChar(col_length==80 ? '0' : '2');
122
123        //QVector::iterator i;
124
125        //for(i = begin(); i != end(); i++ ) {
126        for(int i=0; i < deck.count(); i++) {
127                // iterate throught the Cards
128                // erhmm... write a header...
129                file.putChar(0x80);
130                file.putChar(0x80);
131                file.putChar(0x80);
132
133                //int cur_col = 0;
134                //int max_col = i->col_length;
135
136                //while(cur_col < max_col) {
137                for(int cur_col = 0; cur_col < 80; ) {
138                        char first, second, third;
139
140                        int even = jones_column_to_integer( deck.at(i).get(cur_col++) );
141                        int odd = jones_column_to_integer( deck.at(i).get(cur_col++) );
142
143                        first = even >> 4;
144                        second = ((even & 017) << 4) | (odd >> 8);
145                        third = odd & 00377;
146
147                        file.putChar(first);
148                        file.putChar(second);
149                        file.putChar(third);
150                } // while columns
151        } // for cards
152
153        file.close();
154        qDebug() << "Jones File written.";
155        return true; // done.
156} // jones writer
157
158/**
159 * Like Douglas Jones says in his punchcard proposal:
160 *
161 *     Top                  Bottom
162 *       _ _ _ _ _ _ _ _ _ _ _ _
163 *      |_|_|_|_|_|_|_|_|_|_|_|_|
164 *     12 11 0 1 2 3 4 5 6 7 8 9
165 *      |     |                 |
166 *      |Zone |     Numeric     |
167 *
168 **/
169int JonesFileFormat::jones_column_to_integer(const Column& col) {
170        static const int Mapping[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 10, 11 };
171        // where 14 is a dummy position outside the range since column[10] is also
172        // a dummy position ;-)
173
174        int r;
175        //             das hier sollte im Idealfall gleich sein ;-)
176        for(int i = 0; i < col.size() && i < (int)sizeof(Mapping); i++)
177                r |= (col[i] << Mapping[i]);
178        return r;
179}
180
181Column JonesFileFormat::jones_integer_to_column(int data) {
182        static const int Mapping[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 10, 11 };
183        // where 14 is a dummy position outside the range since column[10] is also
184        // a dummy position ;-)
185
186        // this is just the inverse...
187        Column r;
188        for(int i = 0; i < (int)sizeof(Mapping); i++) {
189                r[i] = ( (1 << Mapping[i]) & data != 0 );
190        }
191        return r;
192}
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License