DEADSOFTWARE

e6e174899125370fffc9d2bb0ea337e972f3dd56
[odcread.git] / main / odcread.cc
1 #include "main/module.ih"
3 namespace odc {
4 class Context {
5 public:
6 virtual void addPiece(std::string &piece) = 0;
7 virtual std::string getPlainText() const = 0;
8 };
9 class PartContext : public Context {
10 private:
11 std::string d_text;
12 public:
13 virtual void addPiece(std::string &piece) {
14 d_text += piece;
15 }
16 virtual std::string getPlainText() const {
17 return d_text;
18 }
19 };
20 class FoldContext : public Context {
21 private:
22 bool d_collapsed;
23 bool d_haveFirst; // flag that first part has been set
24 std::string d_firstPart;
25 std::string d_remainder;
26 public:
27 FoldContext(bool collapsed) : d_collapsed(collapsed), d_haveFirst(false) {}
28 virtual void addPiece(std::string &piece) {
29 if (!d_haveFirst) {
30 d_haveFirst = true;
31 d_firstPart = piece;
32 } else {
33 d_remainder += piece;
34 }
35 }
36 virtual std::string getPlainText() const {
37 if (d_collapsed) {
38 return std::string("##=>") + d_remainder + "\n" + d_firstPart +"##<=";
39 } else {
40 return std::string("##=>") + d_firstPart + "\n" + d_remainder +"##<=";
41 }
42 }
43 };
45 class MyVisitor : public Visitor {
46 private:
47 std::stack<Context*> d_context;
49 void terminateContext() {
50 Context *c = d_context.top();
51 d_context.pop();
52 if (d_context.empty()) {
53 std::cout << c->getPlainText() << std::endl;
54 } else {
55 std::string text = c->getPlainText();
56 d_context.top()->addPiece(text);
57 }
58 delete c;
59 }
61 public:
62 virtual void partStart() {
63 d_context.push(new PartContext());
64 }
65 virtual void partEnd() {
66 terminateContext();
67 }
68 virtual void foldLeft(bool collapsed) {
69 d_context.push(new FoldContext(collapsed));
70 }
71 virtual void foldRight() {
72 terminateContext();
73 }
74 char *getCharSet() {
75 return nl_langinfo(CODESET);
76 }
77 virtual void textShortPiece(const ShortPiece *piece) {
78 std::string str = convert((char *)piece->getBuffer(), piece->size() + 1, (char *)"ISO-8859-1", 1);
79 d_context.top()->addPiece(str);
80 }
81 virtual void textLongPiece(const LongPiece *piece) {
82 std::string str = convert((char *)piece->getBuffer(), piece->size() + 2, (char *)"UCS-2", 2);
83 d_context.top()->addPiece(str);
84 }
86 /**
87 * Convert an input character buffer in the given encoding to the
88 * locale's encoding.
89 */
90 std::string convert(char *in, size_t bytesIn, char *encodingIn, size_t inBytesPerChar) {
91 // Convert from the input encoding to the locale's encoding
92 iconv_t conv = iconv_open(getCharSet(), encodingIn);
94 // Handle errors by throwing a readable message
95 if (conv == (iconv_t)-1) {
96 std::string str("iconv initialization error: ");
97 str += strerror(errno);
98 throw str.c_str();
99 }
101 // Assume at most 4 bytes per character are needed
102 size_t bytesOut = 4 * bytesIn / inBytesPerChar;
104 // Allocate the output buffer
105 char *out = new char[bytesOut];
106 char *outPtr = out;
108 // Perform conversion
109 size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
110 if (rval == (size_t)-1) {
111 std::string str("iconv error: ");
112 str += strerror(errno);
113 throw str.c_str();
116 // Free the iconv state
117 iconv_close(conv);
119 // Copy result into a std::string
120 std::string str(out);
121 delete out;
123 // Convert newlines
124 for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
125 if (*it == '\r') *it = '\n';
128 return str;
130 };
132 Store* importDocument(std::istream &is) {
133 const INTEGER docTag = 0x6F4F4443;
134 const INTEGER docVersion = 0;
135 Reader r(is);
136 INTEGER tag = r.readInt();
137 if (tag == docTag) {
138 INTEGER version = r.readInt();
139 if (version != docVersion) {
140 throw 100;
142 Store *s = r.readStore();
143 return s;
145 return 0;
149 int main(int argc, char *argv[]) {
150 // Set the locale according to the terminal's environment
151 setlocale(LC_ALL, "");
154 odc::Store* s;
155 try {
156 if (argc < 2) {
157 s = odc::importDocument(std::cin);
158 } else if (argc = 2) {
159 std::ifstream in(argv[1], std::ios::in | std::ios::binary);
160 s = odc::importDocument(in);
161 } else {
162 return 1;
164 } catch (int trap) {
165 std::cerr << "Exception in parsing file: BlackBox trap no. " << trap << std::endl;
166 return 2;
167 } catch (const char * exception) {
168 std::cerr << "Exception in parsing file: " << exception << std::endl;
169 return 2;
171 // std::cout << s->toPlainText() << std::endl;
172 // std::cout << std::endl << std::endl;
174 if (s == nullptr) {
175 return 1;
178 try {
179 odc::MyVisitor visitor;
180 s->accept(visitor);
181 } catch (const char * exception) {
182 std::cerr << "Exception in processing document: " << exception << std::endl;
183 return 3;
185 // std::cout << s->toString() << std::endl;
186 // std::cout << in.tellg() << " " << in.eof() << std::endl;
188 // odc::TypePath path;
189 // odc::ContainerModel(0).getTypePath(&path);
190 // std::cout << path.toString() << std::endl;
191 return 0;