DEADSOFTWARE

Finally found out how 16 bit chars are encoded
[odcread.git] / odcread.cc
1 #include <iostream>
2 #include <fstream>
3 #include <string>
4 #include <stack>
6 #include <oberon.h>
7 #include <reader.h>
8 #include <store.h>
9 #include <textmodel.h>
10 #include <visitor.h>
12 // Character encoding conversions
13 #include <langinfo.h> // determine the current charset
14 #include <locale.h> // locale support
15 #include <iconv.h> // charset conversions
16 #include <errno.h> // error codes
17 #include <string.h> // string descriptions of error codes
19 namespace odc {
20 class Context {
21 public:
22 virtual void addPiece(std::string &piece) = 0;
23 virtual std::string getPlainText() const = 0;
24 };
25 class PartContext : public Context {
26 private:
27 std::string d_text;
28 public:
29 virtual void addPiece(std::string &piece) {
30 d_text += piece;
31 }
32 virtual std::string getPlainText() const {
33 return d_text;
34 }
35 };
36 class FoldContext : public Context {
37 private:
38 bool d_collapsed;
39 bool d_haveFirst; // flag that first part has been set
40 std::string d_firstPart;
41 std::string d_remainder;
42 public:
43 FoldContext(bool collapsed) : d_collapsed(collapsed), d_haveFirst(false) {}
44 virtual void addPiece(std::string &piece) {
45 if (!d_haveFirst) {
46 d_haveFirst = true;
47 d_firstPart = piece;
48 } else {
49 d_remainder += piece;
50 }
51 }
52 virtual std::string getPlainText() const {
53 if (d_collapsed) {
54 return std::string("##=>") + d_remainder + "\n" + d_firstPart +"##<=";
55 } else {
56 return std::string("##=>") + d_firstPart + "\n" + d_remainder +"##<=";
57 }
58 }
59 };
61 class MyVisitor : public Visitor {
62 private:
63 std::stack<Context*> d_context;
65 void terminateContext() {
66 Context *c = d_context.top();
67 d_context.pop();
68 if (d_context.empty()) {
69 std::cout << c->getPlainText() << std::endl;
70 } else {
71 std::string text = c->getPlainText();
72 d_context.top()->addPiece(text);
73 }
74 delete c;
75 }
77 public:
78 virtual void partStart() {
79 d_context.push(new PartContext());
80 }
81 virtual void partEnd() {
82 terminateContext();
83 }
84 virtual void foldLeft(bool collapsed) {
85 d_context.push(new FoldContext(collapsed));
86 }
87 virtual void foldRight() {
88 terminateContext();
89 }
90 char *getCharSet() {
91 return nl_langinfo(CODESET);
92 }
93 virtual void textShortPiece(const ShortPiece *piece) {
94 iconv_t conv = iconv_open(getCharSet(), "ISO-8859-1");
95 if (conv == (iconv_t)-1) {
96 std::string str("iconv initialization error: ");
97 str += strerror(errno);
98 throw str.c_str();
99 }
100 size_t bytesIn = piece->size() + 1;
101 SHORTCHAR *in = piece->getBuffer();
102 size_t bytesOut = bytesIn; // FIXME probably not safe.
103 char *out = new char[bytesIn];
104 char *outPtr = out;
105 size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
106 if (rval == (size_t)-1) {
107 std::string str("iconv error: ");
108 str += strerror(errno);
109 throw str.c_str();
111 iconv_close(conv);
112 std::string str(out);
113 for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
114 if (*it == '\r') *it = '\n';
116 d_context.top()->addPiece(str);
118 virtual void textLongPiece(const LongPiece *piece) {
119 /*
120 char *out = (char*)piece->getBuffer();
121 std::string str(out);
122 d_context.top()->addPiece(str);
123 */
124 //d_convLong = iconv_open(setlocale(LC_CTYPE, 0), "UCS-2");
125 iconv_t conv = iconv_open(getCharSet(), "UCS-2");
126 if (conv == (iconv_t)-1) {
127 std::string str("iconv initialization error: ");
128 str += strerror(errno);
129 throw str.c_str();
131 size_t bytesIn = piece->size() + 2;
132 char *in = (char*)piece->getBuffer();
133 size_t bytesOut = bytesIn; // FIXME probably not safe.
134 char *out = new char[bytesIn];
135 char *outPtr = out;
136 size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
137 if (rval == (size_t)-1) {
138 std::string str("iconv error: ");
139 str += strerror(errno);
140 throw str.c_str();
142 iconv_close(conv);
143 std::string str(out);
144 for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
145 if (*it == '\r') *it = '\n';
147 d_context.top()->addPiece(str);
149 };
151 Store* importDocument(std::istream &is) {
152 const INTEGER docTag = 0x6F4F4443;
153 const INTEGER docVersion = 0;
154 Reader r(is);
155 INTEGER tag = r.readInt();
156 if (tag == docTag) {
157 INTEGER version = r.readInt();
158 if (version != docVersion) {
159 throw 100;
161 Store *s = r.readStore();
162 return s;
164 return 0;
168 int main(int argc, char *argv[]) {
169 if (argc < 2) {
170 return 1;
173 // Set the locale according to the terminal's environment
174 setlocale(LC_ALL, "");
176 std::ifstream in(argv[1], std::ios::in | std::ios::binary);
178 odc::Store* s;
179 try {
180 s = odc::importDocument(in);
181 } catch (int trap) {
182 std::cerr << "Exception in parsing file: BlackBox trap no. " << trap << std::endl;
183 return 2;
184 } catch (const char * exception) {
185 std::cerr << "Exception in parsing file: " << exception << std::endl;
186 return 2;
188 // std::cout << s->toPlainText() << std::endl;
189 // std::cout << std::endl << std::endl;
191 try {
192 odc::MyVisitor visitor;
193 s->accept(visitor);
194 } catch (const char * exception) {
195 std::cerr << "Exception in processing document: " << exception << std::endl;
196 return 3;
198 // std::cout << s->toString() << std::endl;
199 // std::cout << in.tellg() << " " << in.eof() << std::endl;
201 // odc::TypePath path;
202 // odc::ContainerModel(0).getTypePath(&path);
203 // std::cout << path.toString() << std::endl;
204 return 0;