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

Last change on this file since 49 was 49, checked in by sven, 10 years ago
  • Text editing part:

Improved Column counting
80 column line bar

  • Saving with Jones Format works
File size: 4.9 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                // try to read in 120 (body) + 3 (header) bytes
60                QByteArray data = file.read(123);
61
62                if( ((data[0] & 0x08) == 0)
63                 || ((data[1] & 0x08) == 0)
64                 || ((data[2] & 0x08) == 0)) {
65                        // This card was corrupt or there were no more data.
66                        // Break it. Don't save the current card any more.
67                        break;
68                }
69
70                /* This algorithm is based on the C algorithm
71                   of Jones */
72                int x = 3;
73                for(int cur_col = 0; cur_col < 80; ) {
74                        /* read in 3 bytes */
75                        int first = data[x++];
76                        int second = data[x++];
77                        int third = data[x++];
78
79                        /* convert to 2 columns */
80                        int even_col = (first << 4) | (second >> 4);
81                        int odd_col = ((second & 0017) << 8) | third;
82
83                        /* save the columns in the card */
84                        // This is integer => Column conversion with
85                        // implicit knowledge that this followes the
86                        // Jones file format
87                        cur_card->column[cur_col++] = jones_integer_to_column(even_col);
88                        cur_card->column[cur_col++] = jones_integer_to_column(odd_col);
89                }
90
91                /* push card on the card deck*/
92                deck.push_back(cur_card);
93        } // while ! eof
94
95        file.close();
96        return true;
97} // jones reader
98
99// jones writer
100bool JonesFileFormat::write(QFile& file, const Deck& deck) const {
101        qDebug() << "Jones writing";
102
103        if(!file.isOpen()) {
104                // oeffne Datei
105                if(! file.open(QIODevice::WriteOnly)) {
106                        qDebug() << "Failed to open file: " << file.errorString();
107                        return false;
108                }
109        }
110
111        int col_length = 80;
112
113        // Write out file prefix
114        qDebug() << "Beginning Jones writing";
115        file.putChar('H');
116        file.putChar('8');
117        file.putChar(col_length==80 ? '0' : '2');
118
119        //QVector::iterator i;
120
121        //for(i = begin(); i != end(); i++ ) {
122        for(int i=0; i < deck.count(); i++) {
123                // iterate throught the Cards
124                // erhmm... write a header...
125                file.putChar(0x80);
126                file.putChar(0x80);
127                file.putChar(0x80);
128
129                //int cur_col = 0;
130                //int max_col = i->col_length;
131
132                //while(cur_col < max_col) {
133                for(int cur_col = 0; cur_col < 80; ) {
134                        char first, second, third;
135
136                        int even = jones_column_to_integer( deck[i]->get(cur_col++) );
137                        int odd = jones_column_to_integer( deck[i]->get(cur_col++) );
138
139                        first = even >> 4;
140                        second = ((even & 017) << 4) | (odd >> 8);
141                        third = odd & 00377;
142
143                        file.putChar(first);
144                        file.putChar(second);
145                        file.putChar(third);
146                } // while columns
147        } // for cards
148
149        file.close();
150        qDebug() << "Jones File written.";
151        return true; // done.
152} // jones writer
153
154/**
155 * Like Douglas Jones says in his punchcard proposal:
156 *
157 *     Top                  Bottom
158 *       _ _ _ _ _ _ _ _ _ _ _ _
159 *      |_|_|_|_|_|_|_|_|_|_|_|_|
160 *     12 11 0 1 2 3 4 5 6 7 8 9
161 *      |     |                 |
162 *      |Zone |     Numeric     |
163 *
164 **/
165int JonesFileFormat::jones_column_to_integer(const Column& col) {
166        static const int Mapping[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 10, 11 };
167        // where 14 is a dummy position outside the range since column[10] is also
168        // a dummy position ;-)
169
170        int r;
171        //             das hier sollte im Idealfall gleich sein ;-)
172        for(int i = 0; i < col.size() && i < (int)sizeof(Mapping); i++)
173                r |= (col[i] << Mapping[i]);
174        return r;
175}
176
177Column JonesFileFormat::jones_integer_to_column(int data) {
178        static const int Mapping[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 10, 11 };
179        // where 14 is a dummy position outside the range since column[10] is also
180        // a dummy position ;-)
181
182        // this is just the inverse...
183        Column r;
184        for(int i = 0; i < (int)sizeof(Mapping); i++) {
185                r[i] = ( (1 << Mapping[i]) & data != 0 );
186        }
187        return r;
188}
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