DEADSOFTWARE

Fix 16-bit string handling -- still don't know the encoding
[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 <locale.h>
14 #include <iconv.h>
15 #include <errno.h>
16 #include <string.h>
18 namespace odc {
19 class Context {
20 public:
21 virtual void addPiece(std::string &piece) = 0;
22 virtual std::string getPlainText() const = 0;
23 };
24 class PartContext : public Context {
25 private:
26 std::string d_text;
27 public:
28 virtual void addPiece(std::string &piece) {
29 d_text += piece;
30 }
31 virtual std::string getPlainText() const {
32 return d_text;
33 }
34 };
35 class FoldContext : public Context {
36 private:
37 bool d_collapsed;
38 bool d_haveFirst; // flag that first part has been set
39 std::string d_firstPart;
40 std::string d_remainder;
41 public:
42 FoldContext(bool collapsed) : d_collapsed(collapsed), d_haveFirst(false) {}
43 virtual void addPiece(std::string &piece) {
44 if (!d_haveFirst) {
45 d_haveFirst = true;
46 d_firstPart = piece;
47 } else {
48 d_remainder += piece;
49 }
50 }
51 virtual std::string getPlainText() const {
52 if (d_collapsed) {
53 return std::string("##=>") + d_remainder + "\n" + d_firstPart +"##<=";
54 } else {
55 return std::string("##=>") + d_firstPart + "\n" + d_remainder +"##<=";
56 }
57 }
58 };
60 class MyVisitor : public Visitor {
61 private:
62 std::stack<Context*> d_context;
64 void terminateContext() {
65 Context *c = d_context.top();
66 d_context.pop();
67 if (d_context.empty()) {
68 std::cout << c->getPlainText() << std::endl;
69 } else {
70 std::string text = c->getPlainText();
71 d_context.top()->addPiece(text);
72 }
73 delete c;
74 }
76 public:
77 virtual void partStart() {
78 d_context.push(new PartContext());
79 }
80 virtual void partEnd() {
81 terminateContext();
82 }
83 virtual void foldLeft(bool collapsed) {
84 d_context.push(new FoldContext(collapsed));
85 }
86 virtual void foldRight() {
87 terminateContext();
88 }
89 char *getCharSet() {
90 return "UTF-8"; // FIXME setlocale(LC_CTYPE, 0) + processing
91 }
92 virtual void textShortPiece(const ShortPiece *piece) {
93 iconv_t conv = iconv_open("UTF-8", "ISO-8859-1");
94 if (conv == (iconv_t)-1) {
95 std::string str("iconv initialization error: ");
96 str += strerror(errno);
97 throw str.c_str();
98 }
99 size_t bytesIn = piece->size() + 1;
100 SHORTCHAR *in = piece->getBuffer();
101 size_t bytesOut = bytesIn; // FIXME probably not safe.
102 char *out = new char[bytesIn];
103 char *outPtr = out;
104 size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
105 if (rval == (size_t)-1) {
106 std::string str("iconv error: ");
107 str += strerror(errno);
108 throw str.c_str();
110 iconv_close(conv);
111 std::string str(out);
112 for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
113 if (*it == '\r') *it = '\n';
115 d_context.top()->addPiece(str);
117 virtual void textLongPiece(const LongPiece *piece) {
118 /*
119 char *out = (char*)piece->getBuffer();
120 std::string str(out);
121 d_context.top()->addPiece(str);
122 */
123 //d_convLong = iconv_open(setlocale(LC_CTYPE, 0), "UCS-2");
124 iconv_t conv = iconv_open("UTF-8", "UCS-2");
125 if (conv == (iconv_t)-1) {
126 std::string str("iconv initialization error: ");
127 str += strerror(errno);
128 throw str.c_str();
130 size_t bytesIn = piece->size() + 2;
131 char *in = (char*)piece->getBuffer();
132 size_t bytesOut = bytesIn; // FIXME probably not safe.
133 char *out = new char[bytesIn];
134 char *outPtr = out;
135 size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
136 if (rval == (size_t)-1) {
137 std::string str("iconv error: ");
138 str += strerror(errno);
139 throw str.c_str();
141 iconv_close(conv);
142 std::string str(out);
143 for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
144 if (*it == '\r') *it = '\n';
146 d_context.top()->addPiece(str);
148 };
150 Store* importDocument(std::istream &is) {
151 const INTEGER docTag = 0x6F4F4443;
152 const INTEGER docVersion = 0;
153 Reader r(is);
154 INTEGER tag = r.readInt();
155 if (tag == docTag) {
156 INTEGER version = r.readInt();
157 if (version != docVersion) {
158 throw 100;
160 Store *s = r.readStore();
161 return s;
163 return 0;
167 int main(int argc, char *argv[]) {
168 if (argc < 2) {
169 return 1;
172 // Set the locale according to the terminal's environment
173 setlocale(LC_ALL, "");
175 std::ifstream in(argv[1], std::ios::in | std::ios::binary);
177 odc::Store* s;
178 try {
179 s = odc::importDocument(in);
180 } catch (int trap) {
181 std::cerr << "Exception in parsing file: BlackBox trap no. " << trap << std::endl;
182 return 2;
183 } catch (const char * exception) {
184 std::cerr << "Exception in parsing file: " << exception << std::endl;
185 return 2;
187 // std::cout << s->toPlainText() << std::endl;
188 // std::cout << std::endl << std::endl;
190 try {
191 odc::MyVisitor visitor;
192 s->accept(visitor);
193 } catch (const char * exception) {
194 std::cerr << "Exception in processing document: " << exception << std::endl;
195 return 3;
197 // std::cout << s->toString() << std::endl;
198 // std::cout << in.tellg() << " " << in.eof() << std::endl;
200 // odc::TypePath path;
201 // odc::ContainerModel(0).getTypePath(&path);
202 // std::cout << path.toString() << std::endl;
203 return 0;