THRIFT-1348 C++ Qt bindings
Patch: Doug Rosvick and Vitali Lovich

git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1242900 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/qt/TQIODeviceTransport.cpp b/lib/cpp/src/qt/TQIODeviceTransport.cpp
new file mode 100644
index 0000000..c5b53a8
--- /dev/null
+++ b/lib/cpp/src/qt/TQIODeviceTransport.cpp
@@ -0,0 +1,155 @@
+#include "TQIODeviceTransport.h"
+
+#include <transport/TBufferTransports.h>
+
+#include <QAbstractSocket>
+
+#include <iostream>
+
+namespace apache { namespace thrift { namespace transport {
+  using boost::shared_ptr;
+
+  TQIODeviceTransport::TQIODeviceTransport(shared_ptr<QIODevice> dev)
+    : dev_(dev)
+  {
+  }
+
+  TQIODeviceTransport::~TQIODeviceTransport()
+  {
+    dev_->close();
+  }
+
+  void TQIODeviceTransport::open()
+  {
+    if (!isOpen()) {
+      throw TTransportException(TTransportException::NOT_OPEN,
+                                "open(): underlying QIODevice isn't open");
+    }
+  }
+
+  bool TQIODeviceTransport::isOpen()
+  {
+    return dev_->isOpen();
+  }
+
+  bool TQIODeviceTransport::peek()
+  {
+    return dev_->bytesAvailable() > 0;
+  }
+
+  void TQIODeviceTransport::close()
+  {
+    dev_->close();
+  }
+
+  uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) {
+    uint32_t requestLen = len;
+    while (len) {
+      uint32_t readSize;
+      try {
+        readSize = read(buf, len);
+      } catch (...) {
+        if (len != requestLen) {
+          // something read already
+          return requestLen - len;
+        }
+        // error but nothing read yet
+        throw;
+      }
+      if (readSize == 0) {
+        // dev_->waitForReadyRead(50);
+      } else {
+        buf += readSize;
+        len -= readSize;
+      }
+    }
+    return requestLen;
+  }
+
+  uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len)
+  {
+    uint32_t actualSize;
+    qint64 readSize;
+
+    if (!dev_->isOpen()) {
+      throw TTransportException(TTransportException::NOT_OPEN,
+                                "read(): underlying QIODevice is not open");
+    }
+
+    actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable());
+    readSize = dev_->read(reinterpret_cast<char *>(buf), len);
+
+    if (readSize < 0) {
+      QAbstractSocket* socket;
+      if ((socket = qobject_cast<QAbstractSocket* >(dev_.get()))) {
+        throw TTransportException(TTransportException::UNKNOWN,
+                                  "Failed to read() from QAbstractSocket",
+                                  socket->error());
+      }
+      throw TTransportException(TTransportException::UNKNOWN,
+                                "Failed to read from from QIODevice");
+    }
+
+    return (uint32_t)readSize;
+  }
+
+  void TQIODeviceTransport::write(const uint8_t* buf, uint32_t len)
+  {
+    while (len) {
+      uint32_t written = write_partial(buf, len);
+      len -= written;
+      // dev_->waitForBytesWritten(50);
+    }
+  }
+
+  uint32_t TQIODeviceTransport::write_partial(const uint8_t* buf, uint32_t len)
+  {
+    qint64 written;
+
+    if (!dev_->isOpen()) {
+      throw TTransportException(TTransportException::NOT_OPEN,
+                                "write_partial(): underlying QIODevice is not open");
+    }
+
+    written = dev_->write(reinterpret_cast<const char*>(buf), len);
+    if (written < 0) {
+      QAbstractSocket* socket;
+      if ((socket = qobject_cast<QAbstractSocket*>(dev_.get()))) {
+        throw TTransportException(TTransportException::UNKNOWN,
+                                  "write_partial(): failed to write to QAbstractSocket", socket->error());
+      }
+
+      throw TTransportException(TTransportException::UNKNOWN,
+                                "write_partial(): failed to write to underlying QIODevice");
+    }
+
+    return (uint32_t)written;
+  }
+
+  void TQIODeviceTransport::flush()
+  {
+    if (!dev_->isOpen()) {
+      throw TTransportException(TTransportException::NOT_OPEN,
+                                "flush(): underlying QIODevice is not open");
+    }
+
+    QAbstractSocket* socket;
+
+    if ((socket = qobject_cast<QAbstractSocket*>(dev_.get()))) {
+      socket->flush();
+    } else {
+      dev_->waitForBytesWritten(1);
+    }
+  }
+
+  uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len)
+  {
+    return NULL;
+  }
+
+  void TQIODeviceTransport::consume(uint32_t len)
+  {
+    throw TTransportException(TTransportException::UNKNOWN);
+  }
+}}} // apache::thrift::transport
+