aboutsummaryrefslogtreecommitdiffstats
path: root/common/rdr/BufferedOutStream.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'common/rdr/BufferedOutStream.cxx')
-rw-r--r--common/rdr/BufferedOutStream.cxx115
1 files changed, 115 insertions, 0 deletions
diff --git a/common/rdr/BufferedOutStream.cxx b/common/rdr/BufferedOutStream.cxx
new file mode 100644
index 00000000..76b0163b
--- /dev/null
+++ b/common/rdr/BufferedOutStream.cxx
@@ -0,0 +1,115 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011-2020 Pierre Ossman for Cendio AB
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <rdr/BufferedOutStream.h>
+#include <rdr/Exception.h>
+
+
+using namespace rdr;
+
+static const size_t DEFAULT_BUF_SIZE = 16384;
+
+BufferedOutStream::BufferedOutStream(size_t bufSize_)
+ : bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
+{
+ ptr = start = sentUpTo = new U8[bufSize];
+ end = start + bufSize;
+}
+
+BufferedOutStream::~BufferedOutStream()
+{
+ // FIXME: Complain about non-flushed buffer?
+ delete [] start;
+}
+
+size_t BufferedOutStream::length()
+{
+ return offset + ptr - sentUpTo;
+}
+
+size_t BufferedOutStream::bufferUsage()
+{
+ return ptr - sentUpTo;
+}
+
+void BufferedOutStream::flush()
+{
+ while (sentUpTo < ptr) {
+ size_t len;
+
+ len = bufferUsage();
+
+ if (!flushBuffer(false))
+ break;
+
+ offset += len - bufferUsage();
+ }
+
+ // Managed to flush everything?
+ if (sentUpTo == ptr)
+ ptr = sentUpTo = start;
+}
+
+size_t BufferedOutStream::overrun(size_t itemSize, size_t nItems)
+{
+ if (itemSize > bufSize)
+ throw Exception("BufferedOutStream overrun: "
+ "requested size of %lu bytes exceeds maximum of %lu bytes",
+ (long unsigned)itemSize, (long unsigned)bufSize);
+
+ // First try to get rid of the data we have
+ flush();
+
+ // Still not enough space?
+ while (itemSize > avail()) {
+ // Can we shuffle things around?
+ // (don't do this if it gains us less than 25%)
+ if (((size_t)(sentUpTo - start) > bufSize / 4) &&
+ (itemSize < bufSize - (ptr - sentUpTo))) {
+ memmove(start, sentUpTo, ptr - sentUpTo);
+ ptr = start + (ptr - sentUpTo);
+ sentUpTo = start;
+ } else {
+ size_t len;
+
+ len = bufferUsage();
+
+ // Have to get rid of more data, so allow the flush to wait...
+ flushBuffer(true);
+
+ offset += len - bufferUsage();
+
+ // Managed to flush everything?
+ if (sentUpTo == ptr)
+ ptr = sentUpTo = start;
+ }
+ }
+
+ size_t nAvail;
+ nAvail = avail() / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
+
+ return nItems;
+}