X-Git-Url: http://deadsoftware.ru/gitweb?p=odcread.git;a=blobdiff_plain;f=odcread.cc;h=d2aa025e12713d516fa5355d7d4751a03c5a1a50;hp=e790fdd36bcdc3b211d3c4d277cf9462ee6db3dd;hb=123f20a45dc791d5566433a041155d44744b9a90;hpb=c71568094a35bbda781ac2070e50a59a3b5ac9f7 diff --git a/odcread.cc b/odcread.cc index e790fdd..d2aa025 100644 --- a/odcread.cc +++ b/odcread.cc @@ -9,6 +9,13 @@ #include #include +// Character encoding conversions +#include // determine the current charset +#include // locale support +#include // charset conversions +#include // error codes +#include // string descriptions of error codes + namespace odc { class Context { public: @@ -80,14 +87,61 @@ namespace odc { virtual void foldRight() { terminateContext(); } + char *getCharSet() { + return nl_langinfo(CODESET); + } virtual void textShortPiece(const ShortPiece *piece) { - std::string text = piece->getText(); - d_context.top()->addPiece(text); + std::string str = convert((char *)piece->getBuffer(), piece->size() + 1, (char *)"ISO-8859-1", 1); + d_context.top()->addPiece(str); } virtual void textLongPiece(const LongPiece *piece) { - throw "Long Piece not handled"; - //std::string text = piece->getText(); - //d_context.top()->addPiece(text); + std::string str = convert((char *)piece->getBuffer(), piece->size() + 2, (char *)"UCS-2", 2); + d_context.top()->addPiece(str); + } + + /** + * Convert an input character buffer in the given encoding to the + * locale's encoding. + */ + std::string convert(char *in, size_t bytesIn, char *encodingIn, size_t inBytesPerChar) { + // Convert from the input encoding to the locale's encoding + iconv_t conv = iconv_open(getCharSet(), encodingIn); + + // Handle errors by throwing a readable message + if (conv == (iconv_t)-1) { + std::string str("iconv initialization error: "); + str += strerror(errno); + throw str.c_str(); + } + + // Assume at most 4 bytes per character are needed + size_t bytesOut = 4 * bytesIn / inBytesPerChar; + + // Allocate the output buffer + char *out = new char[bytesOut]; + char *outPtr = out; + + // Perform conversion + size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut); + if (rval == (size_t)-1) { + std::string str("iconv error: "); + str += strerror(errno); + throw str.c_str(); + } + + // Free the iconv state + iconv_close(conv); + + // Copy result into a std::string + std::string str(out); + delete out; + + // Convert newlines + for (std::string::iterator it = str.begin(); it < str.end(); ++it) { + if (*it == '\r') *it = '\n'; + } + + return str; } }; @@ -112,13 +166,32 @@ int main(int argc, char *argv[]) { if (argc < 2) { return 1; } + + // Set the locale according to the terminal's environment + setlocale(LC_ALL, ""); + std::ifstream in(argv[1], std::ios::in | std::ios::binary); - odc::Store* s = odc::importDocument(in); + + odc::Store* s; + try { + s = odc::importDocument(in); + } catch (int trap) { + std::cerr << "Exception in parsing file: BlackBox trap no. " << trap << std::endl; + return 2; + } catch (const char * exception) { + std::cerr << "Exception in parsing file: " << exception << std::endl; + return 2; + } // std::cout << s->toPlainText() << std::endl; // std::cout << std::endl << std::endl; - odc::MyVisitor visitor; - s->accept(visitor); + try { + odc::MyVisitor visitor; + s->accept(visitor); + } catch (const char * exception) { + std::cerr << "Exception in processing document: " << exception << std::endl; + return 3; + } // std::cout << s->toString() << std::endl; // std::cout << in.tellg() << " " << in.eof() << std::endl;