diff options
-rw-r--r-- | emacs.py | 53 | ||||
-rw-r--r-- | pyfstream.h | 142 |
2 files changed, 142 insertions, 53 deletions
diff --git a/emacs.py b/emacs.py deleted file mode 100644 index 3398ec9c..00000000 --- a/emacs.py +++ /dev/null @@ -1,53 +0,0 @@ -import sys - -from ledger import * - -def emacs_date (seconds): - return "(%d %d %d)" % (seconds / 65536, seconds % 65536, 0) - -class EmacsFormatTransactions (TransactionHandler): - last_entry = None - output = None - - def __init__ (self): - self.last_entry = None - - if config.output_file: - self.output = open (config.output_file, "w") - else: - self.output = sys.stdout - - TransactionHandler.__init__ (self) - - def __del__ (self): - if config.output_file: - self.output.close () - - def flush (self): - self.output.write ("))\n") - self.output.flush () - - def write_entry (self, entry): - self.output.write("%s %s %s %s\n" % - (emacs_date (entry.date), - (entry.state and "t") or "nil", - (entry.code and "\"%s\"" % entry.code) or "nil", - (entry.payee and "\"%s\"" % entry.payee) or "nil")) - - def __call__ (self, xact): - if not transaction_has_xdata (xact) or \ - not transaction_xdata (xact).dflags & TRANSACTION_DISPLAYED: - if self.last_entry is None: - self.output.write("((") - self.write_entry (xact.entry) - elif xact.entry != self.last_entry: - self.output.write(")\n (") - self.write_entry (xact.entry) - else: - self.output.write("\n") - self.output.write(" (\"%s\" \"%s\"%s%s)" % - (xact.account.fullname (), xact.amount, - (xact.cost and " \"%s\"" % xact.cost) or "", - (xact.note and " \"%s\"" % xact.note) or "")) - self.last_entry = xact.entry - transaction_xdata (xact).dflags |= TRANSACTION_DISPLAYED diff --git a/pyfstream.h b/pyfstream.h new file mode 100644 index 00000000..e10b5bd5 --- /dev/null +++ b/pyfstream.h @@ -0,0 +1,142 @@ +#ifndef _PYFSTREAM_H +#define _PYFSTREAM_H + +#include <istream> +#include <ostream> +#include <streambuf> +#include <cstdio> +#include <cstring> + +#include "Python.h" + +// pyofstream +// - a stream that writes on a Python file object + +class pyoutbuf : public std::streambuf { + protected: + PyFileObject * fo; // Python file object + public: + // constructor + pyoutbuf (PyFileObject * _fo) : fo(_fo) {} + + protected: + // write one character + virtual int_type overflow (int_type c) { + if (c != EOF) { + char z[2]; + z[0] = c; + z[1] = '\0'; + if (PyFile_WriteString(z, (PyObject *)fo) < 0) { + return EOF; + } + } + return c; + } + + // write multiple characters + virtual std::streamsize xsputn (const char* s, std::streamsize num) { + if (PyFile_WriteString(s, (PyObject *)fo) < 0) + return 0; + return num; + } +}; + +class pyofstream : public std::ostream { + protected: + pyoutbuf buf; + public: + pyofstream (PyFileObject * fo) : std::ostream(0), buf(fo) { + rdbuf(&buf); + } +}; + +// pyifstream +// - a stream that reads on a file descriptor + +class pyinbuf : public std::streambuf { + protected: + PyFileObject * fo; // Python file object + protected: + /* data buffer: + * - at most, pbSize characters in putback area plus + * - at most, bufSize characters in ordinary read buffer + */ + static const int pbSize = 4; // size of putback area + static const int bufSize = 1024; // size of the data buffer + char buffer[bufSize + pbSize]; // data buffer + + public: + /* constructor + * - initialize file descriptor + * - initialize empty data buffer + * - no putback area + * => force underflow() + */ + pyinbuf (PyFileObject * _fo) : fo(_fo) { + setg (buffer+pbSize, // beginning of putback area + buffer+pbSize, // read position + buffer+pbSize); // end position + } + + protected: + // insert new characters into the buffer + virtual int_type underflow () { +#ifndef _MSC_VER + using std::memmove; +#endif + + // is read position before end of buffer? + if (gptr() < egptr()) { + return traits_type::to_int_type(*gptr()); + } + + /* process size of putback area + * - use number of characters read + * - but at most size of putback area + */ + int numPutback; + numPutback = gptr() - eback(); + if (numPutback > pbSize) { + numPutback = pbSize; + } + + /* copy up to pbSize characters previously read into + * the putback area + */ + memmove (buffer+(pbSize-numPutback), gptr()-numPutback, + numPutback); + + // read at most bufSize new characters + int num; + PyObject *line = PyFile_GetLine((PyObject *)fo, bufSize); + if (! line || ! PyString_Check(line)) { + // ERROR or EOF + return EOF; + } + + num = PyString_Size(line); + if (num == 0) + return EOF; + + memmove (buffer+pbSize, PyString_AsString(line), num); + + // reset buffer pointers + setg (buffer+(pbSize-numPutback), // beginning of putback area + buffer+pbSize, // read position + buffer+pbSize+num); // end of buffer + + // return next character + return traits_type::to_int_type(*gptr()); + } +}; + +class pyifstream : public std::istream { + protected: + pyinbuf buf; + public: + pyifstream (PyFileObject * fo) : std::istream(0), buf(fo) { + rdbuf(&buf); + } +}; + +#endif // _PYFSTREAM_H |