summaryrefslogtreecommitdiff
path: root/src/pyfstream.h
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-04-30 06:26:38 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:33 -0400
commitc8899addfd2deed3d84be2de234681db64987722 (patch)
tree07f9a5eb603ff4ec83fe18c83083575d2b7a439a /src/pyfstream.h
parentaa9cc125796711afcaa459898e95527fdae8e912 (diff)
downloadfork-ledger-c8899addfd2deed3d84be2de234681db64987722.tar.gz
fork-ledger-c8899addfd2deed3d84be2de234681db64987722.tar.bz2
fork-ledger-c8899addfd2deed3d84be2de234681db64987722.zip
Rearranged the sources a bit.
Diffstat (limited to 'src/pyfstream.h')
-rw-r--r--src/pyfstream.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/pyfstream.h b/src/pyfstream.h
new file mode 100644
index 00000000..27e5166b
--- /dev/null
+++ b/src/pyfstream.h
@@ -0,0 +1,138 @@
+#ifndef _PYFSTREAM_H
+#define _PYFSTREAM_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) {
+ char * buf = new char[num + 1];
+ std::strncpy(buf, s, num);
+ buf[num] = '\0';
+ if (PyFile_WriteString(buf, (PyObject *)fo) < 0)
+ num = 0;
+ delete[] buf;
+ 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