summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/streams.h34
-rw-r--r--phpcpp.h1
-rw-r--r--src/includes.h2
-rw-r--r--src/streambuf.cpp90
-rw-r--r--src/streambuf.h80
-rw-r--r--src/streams.cpp40
6 files changed, 247 insertions, 0 deletions
diff --git a/include/streams.h b/include/streams.h
new file mode 100644
index 0000000..c4d5339
--- /dev/null
+++ b/include/streams.h
@@ -0,0 +1,34 @@
+/**
+ * Streams.h
+ *
+ * Just like the standard std::cout and std::cerr objects to output data, you
+ * can use similar stream objects for outputting data to PHP. Php::out is the
+ * C++ equivalent of the PHP echo() function, and Php::err() is the C++ stream
+ * that behaves like calling trigger_error() from PHP.
+ *
+ * Php::out << "this is example text" << std::endl;
+ * Php::err << "this is an error message" << std::endl;
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Define the out and err objects
+ */
+extern std::ostream out;
+extern std::ostream error;
+extern std::ostream notice;
+extern std::ostream warning;
+extern std::ostream deprecated;
+
+/**
+ * End namespace
+ */
+}
+
diff --git a/phpcpp.h b/phpcpp.h
index b9f10df..028636e 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -54,6 +54,7 @@
#include <phpcpp/namespace.h>
#include <phpcpp/extension.h>
#include <phpcpp/call.h>
+#include <phpcpp/streams.h>
/**
* Macro to export a function
diff --git a/src/includes.h b/src/includes.h
index cf7dff3..2f5cc1c 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -73,6 +73,7 @@
#include "../include/namespace.h"
#include "../include/extension.h"
#include "../include/call.h"
+#include "../include/streams.h"
#include "../include/init.h"
/**
@@ -96,6 +97,7 @@
#include "hashiterator.h"
#include "invaliditerator.h"
#include "traverseiterator.h"
+#include "streambuf.h"
#ifndef ZVAL_COPY_VALUE
#define ZVAL_COPY_VALUE(z, v) \
diff --git a/src/streambuf.cpp b/src/streambuf.cpp
new file mode 100644
index 0000000..d4b4680
--- /dev/null
+++ b/src/streambuf.cpp
@@ -0,0 +1,90 @@
+/**
+ * StreamBuf.cpp
+ *
+ * Implementation file for the StreamBuf class
+ *
+ * @see http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+#include "includes.h"
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Constructor
+ * @param error
+ */
+StreamBuf::StreamBuf(int error) : _error(error)
+{
+ // we reserve one byte, so that when overflow is called, we still have one
+ // byte extra in the buffer to put the overflowed byte int
+ setp(_buffer, _buffer+1024-1);
+}
+
+
+/**
+ * Method that is called when the internal buffer overflows
+ * @param c
+ * @return int
+ */
+int StreamBuf::overflow(int c)
+{
+ // end-of-file has not output, we call EOF directly, and by using the
+ // comma operator we ensure that EOF is returned
+ if (c == EOF) return sync(), EOF;
+
+ // because we lied the underlying buffer about the size of the buffer
+ // by one byte, there is no real overflow, and we can still add the byte
+ // to the end of the buffer
+ *pptr() = c;
+
+ // increment buffer size
+ pbump(1);
+
+ // and now we're going to syn the buffer
+ return sync() == -1 ? EOF : c;
+}
+
+/**
+ * Called when the internal buffer should be synchronized
+ * @return int
+ */
+int StreamBuf::sync()
+{
+ // current buffer size
+ size_t size = pptr() - pbase();
+
+ // is this the error stream or the regular output stream?
+ if (_error)
+ {
+ // write to error (the zend_error() method is a varargs function,
+ // which means that we have to include a printf() like format as first
+ // parameter. We can not specify pbase() directly, because (1) it is
+ // not null terminated and (2) it could contain % signs and allow all
+ // sorts of buffer overflows.
+ zend_error(_error, "%.*s", (int)size, pbase());
+
+ }
+ else
+ {
+ // write to zend
+ zend_write(pbase(), size);
+ }
+
+ // reset the buffer
+ pbump(-size);
+
+ // done
+ return 0;
+}
+
+/**
+ * End namespace
+ */
+}
+ \ No newline at end of file
diff --git a/src/streambuf.h b/src/streambuf.h
new file mode 100644
index 0000000..ed1506a
--- /dev/null
+++ b/src/streambuf.h
@@ -0,0 +1,80 @@
+/**
+ * StreamBuf.h
+ *
+ * PHP output stream buffer which is used by the Php::out object to
+ * have an output stream just like the regular std::ostream buffers,
+ * but that sends all output to PHP output
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Class definition
+ */
+class StreamBuf : public std::streambuf
+{
+public:
+ /**
+ * Constructor
+ * @param error the error type, or 0 for regular output
+ */
+ StreamBuf(int error);
+
+ /**
+ * No copying or moving
+ * @param that
+ */
+ StreamBuf(const StreamBuf &that) = delete;
+ StreamBuf(StreamBuf &&that) = delete;
+
+ /**
+ * Destructor
+ */
+ virtual ~StreamBuf() {}
+
+ /**
+ * No copying or moving
+ * @param that
+ */
+ StreamBuf &operator=(const StreamBuf &that) = delete;
+ StreamBuf &operator=(StreamBuf &&that) = delete;
+
+protected:
+ /**
+ * Method that is called when the internal buffer overflows
+ * @param c
+ * @return int
+ */
+ virtual int overflow(int c = EOF) override;
+
+ /**
+ * Called when the internal buffer should be synchronized
+ * @return int
+ */
+ virtual int sync() override;
+
+private:
+ /**
+ * The error type, or 0 for regular output
+ * @var int
+ */
+ int _error;
+
+ /**
+ * The internal buffer
+ * @var char[]
+ */
+ char _buffer[1024];
+};
+
+/**
+ * End namespace
+ */
+}
+
diff --git a/src/streams.cpp b/src/streams.cpp
new file mode 100644
index 0000000..ba6d916
--- /dev/null
+++ b/src/streams.cpp
@@ -0,0 +1,40 @@
+/**
+ * Streams.cpp
+ *
+ * Implementation of the streams
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+#include "includes.h"
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Some static buffers for writing data
+ * @var StreamBuf
+ */
+static StreamBuf bufOut (0);
+static StreamBuf bufError (E_ERROR);
+static StreamBuf bufWarning (E_WARNING);
+static StreamBuf bufNotice (E_NOTICE);
+static StreamBuf bufDeprecated (E_DEPRECATED);
+
+/**
+ * Create the actual steams
+ * @var std::ostream
+ */
+std::ostream out (&bufOut);
+std::ostream error (&bufError);
+std::ostream warning (&bufWarning);
+std::ostream notice (&bufNotice);
+std::ostream deprecated (&bufDeprecated);
+
+/**
+ * End namespace
+ */
+}
+