[esnacc-dev] [PATCH 1/2] cxx-lib/asn-buf: Add a filedescriptor streambuf
Aaron Conole
aconole at bytheb.org
Fri Aug 26 19:32:08 UTC 2016
This commit adds a file-descriptor based streambuffer which can be used to
read/write directly to open file descriptors. Such a buffer is useful when
dealing with sockets or pipes, which do not have a standardized C++ access
framework.
Signed-off-by: Aaron Conole <aconole at bytheb.org>
---
cxx-lib/inc/asn-buf.h | 49 ++++++++++++++--------
cxx-lib/src/asn-buf.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 135 insertions(+), 22 deletions(-)
diff --git a/cxx-lib/inc/asn-buf.h b/cxx-lib/inc/asn-buf.h
index c4baeda..d316ba9 100644
--- a/cxx-lib/inc/asn-buf.h
+++ b/cxx-lib/inc/asn-buf.h
@@ -2,34 +2,25 @@
#define _ASN_BUF_H 1
-#if defined(WIN32)
#if defined(_MSC_VER)
#pragma warning(disable: 4100 4702 4710 4514 4786 4251 4018 4146 4284)
#pragma warning(push,3)
#endif
-#include <ostream>
-#include <streambuf>
#include <deque>
-#include <list>
#include <fstream>
+#include <list>
+#include <ostream>
#include <sstream>
-//#include <strstream>
+#include <streambuf>
+#include <vector>
+
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
-#else // WIN32
-
-#include <ostream>
-#include <streambuf>
-#include <deque>
-#include <list>
-#include <fstream>
+#if !defined(WIN32)
#include <utility>
-#include <sstream>
-//#include <strstream>
-
#endif // WIN32
@@ -65,13 +56,37 @@ typedef unsigned long AsnLen;
typedef std::deque<Card *> Deck;
+class SNACCDLL_API AsnFDBuf : public std::streambuf
+{
+ int fd;
+ const bool sock;
+ const size_t putsz;
+ const bool close_on_fail;
+ std::vector<char> buffer;
+
+protected:
+ virtual void extra_reset();
+ std::streambuf::int_type underflow();
+ std::streambuf::int_type overflow(std::streambuf::int_type c);
+ std::streamsize xsputn (const char* s, std::streamsize num);
+
+public:
+ explicit AsnFDBuf(int descriptor, bool socket = false, bool failure = true,
+ size_t buffersz = 256, size_t putsize = 8)
+ : fd(descriptor), sock(socket), putsz(std::max<int>(putsize,1)),
+ close_on_fail(failure), buffer(std::max<int>(buffersz,putsz) + putsz)
+ {
+ char *end = &buffer.front() + buffer.size();
+ setg(end, end, end);
+ }
+};
+
struct SNACCDLL_API AsnBufLoc
{
Deck::iterator m_card;
long m_offset;
};
-
-
+
class SNACCDLL_API AsnBuf
{
public:
diff --git a/cxx-lib/src/asn-buf.cpp b/cxx-lib/src/asn-buf.cpp
index 0441968..0d62824 100644
--- a/cxx-lib/src/asn-buf.cpp
+++ b/cxx-lib/src/asn-buf.cpp
@@ -1,11 +1,22 @@
+#include <config.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifndef WIN32
+#include <sys/socket.h>
+#include <unistd.h>
+#else
+#include "winsock2.h"
+#include "windows.h"
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+#endif
#include "asn-incl.h"
-
-#ifdef _MSC_VER
- #pragma warning(disable: 4189) // Disable local variable not referenced warning
-#endif
-
using namespace SNACC;
@@ -781,6 +792,93 @@ const char * Card::bufTypeStr()
}
return NULL;
}
+#endif
+
+std::streambuf::int_type
+AsnFDBuf::underflow()
+{
+ if (fd == -1)
+ return std::streambuf::traits_type::eof();
+
+ if (gptr() < egptr())
+ return std::streambuf::traits_type::to_int_type(*gptr());
+
+ char *base = &buffer.front();
+ char *start = base;
+
+ if (eback() == base) {
+ // Make arrangements for putback characters
+ ::memmove(base, egptr() - putsz, putsz);
+ start += putsz;
+ }
+
+ int n = 0;
+ if (sock)
+ n = recv(fd, start, buffer.size() - (start - base), 0);
+ else
+ n = ::read(fd, start, buffer.size() - (start - base));
+
+ if(n == 0 || n < 0) {
+ extra_reset();
+ return std::streambuf::traits_type::eof();
+ }
+
+ setg(base, start, start+n);
+ return std::streambuf::traits_type::to_int_type(*gptr());
+}
+
+std::streambuf::int_type
+AsnFDBuf::overflow(std::streambuf::int_type c)
+{
+ if( fd == -1 || c == std::streambuf::traits_type::eof() )
+ return std::streambuf::traits_type::eof();
+
+ char a = c;
+ int n = 0;
+ if (sock)
+ n = send(fd, &a, 1, MSG_NOSIGNAL);
+ else
+ n = ::write(fd, &a, 1);
+
+ if (n != 1) {
+ extra_reset();
+ return std::streambuf::traits_type::eof();
+ }
+ return n;
+}
+
+std::streamsize
+AsnFDBuf::xsputn(const char* s, std::streamsize num)
+{
+ if( fd == -1 )
+ return std::streambuf::traits_type::eof();
+
+ int result;
+ if (sock)
+ result = send(fd, s, num, MSG_NOSIGNAL);
+ else
+ result = ::write(fd, s, num);
+ if (result < 0) {
+ extra_reset();
+ return std::streambuf::traits_type::eof();
+ }
+ return result;
+}
+void
+AsnFDBuf::extra_reset()
+{
+ if (close_on_fail) {
+ if (!sock) {
+ close(fd);
+ } else {
+#ifndef WIN32
+ ::close(fd);
+#else
+ ::closesocket(fd);
#endif
+ }
+ fd = -1;
+ }
+}
--
2.5.5
More information about the dev
mailing list