Index: src/client/c/hu/Makefile.am
===================================================================
--- src/client/c/hu/Makefile.am	(revision 13)
+++ src/client/c/hu/Makefile.am	(revision 13)
@@ -0,0 +1,1 @@
+SUBDIRS=varadiistvan
Index: src/client/c/hu/Makefile.am
===================================================================
--- src/client/c/hu/Makefile.am	(revision 13)
+++ 	(revision )
@@ -1,1 +1,0 @@
-SUBDIRS=varadiistvan
Index: src/client/c/hu/varadiistvan/Makefile.am
===================================================================
--- src/client/c/hu/varadiistvan/Makefile.am	(revision 13)
+++ src/client/c/hu/varadiistvan/Makefile.am	(revision 13)
@@ -0,0 +1,1 @@
+SUBDIRS=xplra
Index: src/client/c/hu/varadiistvan/Makefile.am
===================================================================
--- src/client/c/hu/varadiistvan/Makefile.am	(revision 13)
+++ 	(revision )
@@ -1,1 +1,0 @@
-SUBDIRS=xplra
Index: src/client/c/hu/varadiistvan/xplra/.copyright
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.copyright	(revision 13)
+++ src/client/c/hu/varadiistvan/xplra/.copyright	(revision 13)
@@ -0,0 +1,23 @@
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
Index: src/client/c/hu/varadiistvan/xplra/.copyright
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.copyright	(revision 13)
+++ 	(revision )
@@ -1,23 +1,0 @@
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
Index: src/client/c/hu/varadiistvan/xplra/.namespace
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.namespace	(revision 13)
+++ src/client/c/hu/varadiistvan/xplra/.namespace	(revision 13)
@@ -0,0 +1,3 @@
+hu
+varadiistvan
+xplra
Index: src/client/c/hu/varadiistvan/xplra/.namespace
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.namespace	(revision 13)
+++ 	(revision )
@@ -1,3 +1,0 @@
-hu
-varadiistvan
-xplra
Index: src/client/c/hu/varadiistvan/xplra/.srcmessage
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.srcmessage	(revision 13)
+++ src/client/c/hu/varadiistvan/xplra/.srcmessage	(revision 13)
@@ -0,0 +1,1 @@
+// This file is part of XPLRA, a remote-access plugin for X-Plane
Index: src/client/c/hu/varadiistvan/xplra/.srcmessage
===================================================================
--- src/client/c/hu/varadiistvan/xplra/.srcmessage	(revision 13)
+++ 	(revision )
@@ -1,1 +1,0 @@
-// This file is part of XPLRA, a remote-access plugin for X-Plane
Index: src/client/c/hu/varadiistvan/xplra/Exception.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Exception.cc	(revision 40)
+++ src/client/c/hu/varadiistvan/xplra/Exception.cc	(revision 40)
@@ -0,0 +1,114 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "Exception.h"
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::Exception;
+using hu::varadiistvan::xplra::IOException;
+using hu::varadiistvan::xplra::ProtocolException;
+
+//------------------------------------------------------------------------------
+
+const char* Exception::what() const throw()
+{
+    return message.c_str();
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+IOException::IOException(errorCode_t errorCode) throw() :
+    errorCode(errorCode)
+{
+    char buf[256];
+    snprintf(buf, sizeof(buf), "xplra::IOException: error code=%lu",
+             errorCode);
+    message = buf;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+ProtocolException::ProtocolException(errorCode_t errorCode, bool hasParameter,
+                                     long parameter) throw() :
+    errorCode(errorCode),
+    hasParameter(parameter),
+    parameter(parameter)
+{
+    switch (errorCode) {
+      case INVALID_COMMAND:
+        message = "xplra::ProtocolException: invalid command";
+        break;
+      case UNKNOWN_DATAREF:
+        message = "xplra::ProtocolException: unknown dataref";
+        if (hasParameter) {
+            char buf[32];
+            snprintf(buf, sizeof(buf), " (# %ld)", parameter);
+            message += buf;
+        }
+        break;
+      case INVALID_TYPE:
+        message = "xplra::ProtocolException: invalid type";
+        break;
+      case INVALID_LENGTH:
+        message = "xplra::ProtocolException: invalid length";
+        break;
+      case INVALID_OFFSET:
+        message = "xplra::ProtocolException: invalid offset";
+        break;
+      case INVALID_COUNT:
+        message = "xplra::ProtocolException: invalid count";
+        break;
+      case INVALID_ID:
+        message = "xplra::ProtocolException: invalid ID";
+        break;
+      case INVALID_DURATION:
+        message = "xplra::ProtocolException: invalid duration";
+        break;
+      case OTHER:
+        message = "xplra::ProtocolException: other error";
+        break;
+      default:
+        message = "xplra::ProtocolException: unknown error";
+        break;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/Exception.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Exception.cc	(revision 40)
+++ 	(revision )
@@ -1,114 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "Exception.h"
-
-#include <cstdio>
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::Exception;
-using hu::varadiistvan::xplra::IOException;
-using hu::varadiistvan::xplra::ProtocolException;
-
-//------------------------------------------------------------------------------
-
-const char* Exception::what() const throw()
-{
-    return message.c_str();
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-IOException::IOException(errorCode_t errorCode) throw() :
-    errorCode(errorCode)
-{
-    char buf[256];
-    snprintf(buf, sizeof(buf), "xplra::IOException: error code=%lu",
-             errorCode);
-    message = buf;
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-ProtocolException::ProtocolException(errorCode_t errorCode, bool hasParameter,
-                                     long parameter) throw() :
-    errorCode(errorCode),
-    hasParameter(parameter),
-    parameter(parameter)
-{
-    switch (errorCode) {
-      case INVALID_COMMAND:
-        message = "xplra::ProtocolException: invalid command";
-        break;
-      case UNKNOWN_DATAREF:
-        message = "xplra::ProtocolException: unknown dataref";
-        if (hasParameter) {
-            char buf[32];
-            snprintf(buf, sizeof(buf), " (# %ld)", parameter);
-            message += buf;
-        }
-        break;
-      case INVALID_TYPE:
-        message = "xplra::ProtocolException: invalid type";
-        break;
-      case INVALID_LENGTH:
-        message = "xplra::ProtocolException: invalid length";
-        break;
-      case INVALID_OFFSET:
-        message = "xplra::ProtocolException: invalid offset";
-        break;
-      case INVALID_COUNT:
-        message = "xplra::ProtocolException: invalid count";
-        break;
-      case INVALID_ID:
-        message = "xplra::ProtocolException: invalid ID";
-        break;
-      case INVALID_DURATION:
-        message = "xplra::ProtocolException: invalid duration";
-        break;
-      case OTHER:
-        message = "xplra::ProtocolException: other error";
-        break;
-      default:
-        message = "xplra::ProtocolException: unknown error";
-        break;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/Exception.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Exception.h	(revision 40)
+++ src/client/c/hu/varadiistvan/xplra/Exception.h	(revision 40)
@@ -0,0 +1,312 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#ifndef HU_VARADIISTVAN_XPLRA_EXCEPTION_H
+#define HU_VARADIISTVAN_XPLRA_EXCEPTION_H
+//------------------------------------------------------------------------------
+
+#include <exception>
+
+#include <string>
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace xplra {
+
+//------------------------------------------------------------------------------
+
+/**
+ * Base class for exceptions that can be thrown by the client.
+ */
+class Exception : public std::exception
+{
+protected:
+    /**
+     * The string representation of the error message.
+     */
+    std::string message;
+
+public:
+    /**
+     * Construct the exception with the given message.
+     */
+    Exception(const char* message) throw();
+
+protected:
+    /**
+     * Default constructor for children.
+     */
+    Exception() throw();
+
+public:
+    /**
+     * Destroy the exception
+     */
+    virtual ~Exception() throw();
+
+public:
+    /**
+     * Get a message.
+     */
+    virtual const char* what() const throw();
+};
+
+//------------------------------------------------------------------------------
+
+/**
+ * An I/O exception.
+ */
+class IOException : public Exception
+{
+public:
+    /**
+     * Type for the error code.
+     */
+    typedef unsigned long errorCode_t;
+
+private:
+    /**
+     * The error code.
+     */
+    errorCode_t errorCode;
+
+public:
+    /**
+     * Construct the exception.
+     */
+    IOException(errorCode_t errorCode) throw();
+
+
+    /**
+     * Get the error code.
+     */
+    errorCode_t getErrorCode() const throw();
+};
+
+//------------------------------------------------------------------------------
+
+/**
+ * An exception arising from the invalid use of the protocol, e.g. an
+ * invalid dataref.
+ */
+class ProtocolException : public Exception
+{
+public:
+    /**
+     * Type for the error codes.
+     */
+    typedef enum {
+        /// Invalid command issued
+        INVALID_COMMAND = 1,
+
+        /// Unknown dataref
+        UNKNOWN_DATAREF = 2,
+
+        /// Invalid type
+        INVALID_TYPE = 3,
+
+        /// Invalid length
+        INVALID_LENGTH = 4,
+
+        /// Invalid offset
+        INVALID_OFFSET = 5,
+
+        /// Invalid count
+        INVALID_COUNT = 6,
+
+        /// Invalid ID
+        INVALID_ID = 7,
+
+        /// Invalid duration
+        INVALID_DURATION = 8,
+
+        /// Other error
+        OTHER = 255
+    } errorCode_t;
+
+private:
+    /**
+     * The error code.
+     */
+    errorCode_t errorCode;
+
+    /**
+     * Indicate if the parameter is valid.
+     */
+    bool hasParameter;
+
+    /**
+     * Parameter of the error.
+     */
+    long parameter;
+
+public:
+    /**
+     * Construct the exception.
+     */
+    ProtocolException(errorCode_t errorCode,
+                      bool hasParameter = false, long parameter = 0) throw();
+
+    /**
+     * Get the error code.
+     */
+    errorCode_t getErrorCode() const throw();
+
+    /**
+     * Get the value of the parameter and whether it is valid or not.
+     */
+    bool getParameter(long& param) const throw();
+};
+
+//------------------------------------------------------------------------------
+
+/**
+ * Exception to signify the fact the we are not connected to the
+ * simulator.
+ */
+class NotConnectedException : public Exception
+{
+public:
+    /**
+     * Construct the exception
+     */
+    NotConnectedException() throw();
+};
+
+//------------------------------------------------------------------------------
+
+/**
+ * Exception thrown when we want to get or set a dataref in a
+ * MultiBuffer into or from a value of the wrong type.
+ */
+class TypeMismatchException : public Exception
+{
+public:
+    /**
+     * Construct the exception
+     */
+    TypeMismatchException() throw();
+};
+
+//------------------------------------------------------------------------------
+
+/**
+ * Exception thrown when we want to get or set a dataref with an
+ * invalid ID.
+ */
+class InvalidIDException : public Exception
+{
+public:
+    /**
+     * Construct the exception
+     */
+    InvalidIDException() throw();
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline Exception::Exception(const char* message) throw() :
+    message(message)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline Exception::Exception() throw()
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline Exception::~Exception() throw()
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline IOException::errorCode_t IOException::getErrorCode() const throw()
+{
+    return errorCode;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline ProtocolException::errorCode_t
+ProtocolException::getErrorCode() const throw()
+{
+    return errorCode;
+}
+
+//------------------------------------------------------------------------------
+
+inline bool ProtocolException::getParameter(long& param) const throw()
+{
+    if (hasParameter) param = parameter;
+    return hasParameter;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline NotConnectedException::NotConnectedException() throw() :
+    Exception("xplra::NotConnectedException: not connected to the simulator")
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline TypeMismatchException::TypeMismatchException() throw() :
+    Exception("xplra::TypeMismatchException")
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline InvalidIDException::InvalidIDException() throw() :
+    Exception("xplra::InvalidIDException")
+{
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+#endif // HU_VARADIISTVAN_XPLRA_EXCEPTION_H
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/Exception.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Exception.h	(revision 40)
+++ 	(revision )
@@ -1,312 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-#ifndef HU_VARADIISTVAN_XPLRA_EXCEPTION_H
-#define HU_VARADIISTVAN_XPLRA_EXCEPTION_H
-//------------------------------------------------------------------------------
-
-#include <exception>
-
-#include <string>
-
-//------------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace xplra {
-
-//------------------------------------------------------------------------------
-
-/**
- * Base class for exceptions that can be thrown by the client.
- */
-class Exception : public std::exception
-{
-protected:
-    /**
-     * The string representation of the error message.
-     */
-    std::string message;
-
-public:
-    /**
-     * Construct the exception with the given message.
-     */
-    Exception(const char* message) throw();
-
-protected:
-    /**
-     * Default constructor for children.
-     */
-    Exception() throw();
-
-public:
-    /**
-     * Destroy the exception
-     */
-    virtual ~Exception() throw();
-
-public:
-    /**
-     * Get a message.
-     */
-    virtual const char* what() const throw();
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * An I/O exception.
- */
-class IOException : public Exception
-{
-public:
-    /**
-     * Type for the error code.
-     */
-    typedef unsigned long errorCode_t;
-
-private:
-    /**
-     * The error code.
-     */
-    errorCode_t errorCode;
-
-public:
-    /**
-     * Construct the exception.
-     */
-    IOException(errorCode_t errorCode) throw();
-
-
-    /**
-     * Get the error code.
-     */
-    errorCode_t getErrorCode() const throw();
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * An exception arising from the invalid use of the protocol, e.g. an
- * invalid dataref.
- */
-class ProtocolException : public Exception
-{
-public:
-    /**
-     * Type for the error codes.
-     */
-    typedef enum {
-        /// Invalid command issued
-        INVALID_COMMAND = 1,
-
-        /// Unknown dataref
-        UNKNOWN_DATAREF = 2,
-
-        /// Invalid type
-        INVALID_TYPE = 3,
-
-        /// Invalid length
-        INVALID_LENGTH = 4,
-
-        /// Invalid offset
-        INVALID_OFFSET = 5,
-
-        /// Invalid count
-        INVALID_COUNT = 6,
-
-        /// Invalid ID
-        INVALID_ID = 7,
-
-        /// Invalid duration
-        INVALID_DURATION = 8,
-
-        /// Other error
-        OTHER = 255
-    } errorCode_t;
-
-private:
-    /**
-     * The error code.
-     */
-    errorCode_t errorCode;
-
-    /**
-     * Indicate if the parameter is valid.
-     */
-    bool hasParameter;
-
-    /**
-     * Parameter of the error.
-     */
-    long parameter;
-
-public:
-    /**
-     * Construct the exception.
-     */
-    ProtocolException(errorCode_t errorCode,
-                      bool hasParameter = false, long parameter = 0) throw();
-
-    /**
-     * Get the error code.
-     */
-    errorCode_t getErrorCode() const throw();
-
-    /**
-     * Get the value of the parameter and whether it is valid or not.
-     */
-    bool getParameter(long& param) const throw();
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * Exception to signify the fact the we are not connected to the
- * simulator.
- */
-class NotConnectedException : public Exception
-{
-public:
-    /**
-     * Construct the exception
-     */
-    NotConnectedException() throw();
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * Exception thrown when we want to get or set a dataref in a
- * MultiBuffer into or from a value of the wrong type.
- */
-class TypeMismatchException : public Exception
-{
-public:
-    /**
-     * Construct the exception
-     */
-    TypeMismatchException() throw();
-};
-
-//------------------------------------------------------------------------------
-
-/**
- * Exception thrown when we want to get or set a dataref with an
- * invalid ID.
- */
-class InvalidIDException : public Exception
-{
-public:
-    /**
-     * Construct the exception
-     */
-    InvalidIDException() throw();
-};
-
-//------------------------------------------------------------------------------
-// Inline definitions
-//------------------------------------------------------------------------------
-
-inline Exception::Exception(const char* message) throw() :
-    message(message)
-{
-}
-
-//------------------------------------------------------------------------------
-
-inline Exception::Exception() throw()
-{
-}
-
-//------------------------------------------------------------------------------
-
-inline Exception::~Exception() throw()
-{
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline IOException::errorCode_t IOException::getErrorCode() const throw()
-{
-    return errorCode;
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline ProtocolException::errorCode_t
-ProtocolException::getErrorCode() const throw()
-{
-    return errorCode;
-}
-
-//------------------------------------------------------------------------------
-
-inline bool ProtocolException::getParameter(long& param) const throw()
-{
-    if (hasParameter) param = parameter;
-    return hasParameter;
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline NotConnectedException::NotConnectedException() throw() :
-    Exception("xplra::NotConnectedException: not connected to the simulator")
-{
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline TypeMismatchException::TypeMismatchException() throw() :
-    Exception("xplra::TypeMismatchException")
-{
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline InvalidIDException::InvalidIDException() throw() :
-    Exception("xplra::InvalidIDException")
-{
-}
-
-//------------------------------------------------------------------------------
-
-} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-#endif // HU_VARADIISTVAN_XPLRA_EXCEPTION_H
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/Makefile.am
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Makefile.am	(revision 21)
+++ src/client/c/hu/varadiistvan/xplra/Makefile.am	(revision 21)
@@ -0,0 +1,26 @@
+AM_CXXFLAGS=$(VSCPL_CFLAGS) -I$(top_srcdir)/src/plugin/src
+
+lib_LTLIBRARIES=libxplra.la
+
+libxplra_la_SOURCES=\
+        Exception.cc    \
+        XPlane.cc       \
+        MultiBuffer.cc  \
+        MultiGetter.cc  \
+        MultiSetter.cc  \
+        xplra.cc
+
+libxplra_la_LIBADD=$(VSCPL_LIBS)
+
+if TARGET_API_WIN32
+libxplra_la_LDFLAGS=-no-undefined
+endif
+
+include_xplradir=$(includedir)/hu/varadiistvan/xplra
+include_xplra_HEADERS=\
+        Exception.h     \
+        XPlane.h        \
+        MultiBuffer.h   \
+        MultiGetter.h   \
+        MultiSetter.h   \
+        xplra.h
Index: src/client/c/hu/varadiistvan/xplra/Makefile.am
===================================================================
--- src/client/c/hu/varadiistvan/xplra/Makefile.am	(revision 21)
+++ 	(revision )
@@ -1,26 +1,0 @@
-AM_CXXFLAGS=$(VSCPL_CFLAGS) -I$(top_srcdir)/src/plugin/src
-
-lib_LTLIBRARIES=libxplra.la
-
-libxplra_la_SOURCES=\
-        Exception.cc    \
-        XPlane.cc       \
-        MultiBuffer.cc  \
-        MultiGetter.cc  \
-        MultiSetter.cc  \
-        xplra.cc
-
-libxplra_la_LIBADD=$(VSCPL_LIBS)
-
-if TARGET_API_WIN32
-libxplra_la_LDFLAGS=-no-undefined
-endif
-
-include_xplradir=$(includedir)/hu/varadiistvan/xplra
-include_xplra_HEADERS=\
-        Exception.h     \
-        XPlane.h        \
-        MultiBuffer.h   \
-        MultiGetter.h   \
-        MultiSetter.h   \
-        xplra.h
Index: src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc	(revision 66)
+++ src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc	(revision 66)
@@ -0,0 +1,650 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "MultiBuffer.h"
+
+#include "XPlane.h"
+
+#include <xplra/Protocol.h>
+
+#include <hu/varadiistvan/scpl/io/DataStream.h>
+
+#include <cstring>
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::MultiBuffer;
+
+using xplra::Protocol;
+
+using std::vector;
+using std::string;
+using std::min;
+
+//------------------------------------------------------------------------------
+
+inline MultiBuffer::DataRef::DataRef(const string& name, uint8_t type,
+                                     const DataRef* previous,
+                                     size_t length, size_t offset) throw() :
+    name(name),
+    type(type),
+    length(length),
+    offset(offset),
+    dataOffset(0)
+{
+    if (previous!=0) {
+        size_t alignment = getAlignment();
+        dataOffset = previous->dataOffset + previous->getSize();
+        dataOffset += alignment - 1;
+        dataOffset &= ~(alignment-1);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+inline size_t MultiBuffer::DataRef::getSize() const throw()
+{
+    switch (type) {
+      case Protocol::TYPE_INT:
+        return sizeof(int32_t);
+      case Protocol::TYPE_FLOAT:
+        return sizeof(float);
+      case Protocol::TYPE_DOUBLE:
+        return sizeof(double);
+      case Protocol::TYPE_FLOAT_ARRAY:
+        return sizeof(float) * length;
+      case Protocol::TYPE_INT_ARRAY:
+        return sizeof(int32_t) * length;
+      case Protocol::TYPE_BYTE_ARRAY:
+        return sizeof(uint8_t) * length;
+      default:
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+inline size_t MultiBuffer::DataRef::getAlignment() const throw()
+{
+    switch (type) {
+      case Protocol::TYPE_INT:
+      case Protocol::TYPE_INT_ARRAY:
+        return sizeof(int32_t);
+      case Protocol::TYPE_FLOAT:
+      case Protocol::TYPE_FLOAT_ARRAY:
+        return sizeof(float);
+      case Protocol::TYPE_DOUBLE:
+        return sizeof(double);
+      case Protocol::TYPE_BYTE_ARRAY:
+      default:
+        return sizeof(uint8_t);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+bool MultiBuffer::DataRef::isArray() const throw()
+{
+    return
+        type==Protocol::TYPE_FLOAT_ARRAY ||
+        type==Protocol::TYPE_INT_ARRAY ||
+        type==Protocol::TYPE_BYTE_ARRAY;
+}
+
+//------------------------------------------------------------------------------
+
+inline size_t
+MultiBuffer::DataRef::getCopyLength(size_t userLength, size_t userOffset)
+    const throw()
+{
+    size_t maxLength =
+        (userOffset>length) ? 0 : (length - userOffset);
+    return (userLength==0) ? maxLength : min(userLength, maxLength);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+inline void MultiBuffer::unfinalize() throw()
+{
+    delete data; data = 0;
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::forgetRegistration() throw()
+{
+    registeredID = -1;
+}
+
+//------------------------------------------------------------------------------
+
+inline const MultiBuffer::DataRef* MultiBuffer::getLastDataRef() const throw()
+{
+    return dataRefs.empty() ? 0 : &(dataRefs.back());
+}
+
+//------------------------------------------------------------------------------
+
+inline const MultiBuffer::DataRef& MultiBuffer::getDataRef(size_t id, uint8_t type) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    if (id>=dataRefs.size()) throw InvalidIDException();
+    const DataRef& dataRef = dataRefs[id];
+    if (dataRef.type!=type) throw TypeMismatchException();
+    return dataRef;
+}
+
+//------------------------------------------------------------------------------
+
+inline void* MultiBuffer::getData(size_t id, uint8_t type)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, type);
+    finalize();
+    return data + dataRef.dataOffset;
+}
+
+//------------------------------------------------------------------------------
+
+inline const void* MultiBuffer::getData(size_t id, uint8_t type) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, type);
+    finalize();
+    return data + dataRef.dataOffset;
+}
+
+//------------------------------------------------------------------------------
+
+template <typename T, uint8_t type> size_t
+inline MultiBuffer::setArray(size_t id, const T* value,
+                             size_t length, size_t offset)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, type);
+    finalize();
+
+    size_t toCopy = dataRef.getCopyLength(length, offset);
+
+    if (toCopy>0) {
+        memcpy( data + dataRef.dataOffset + offset * sizeof(T),
+                value, toCopy * sizeof(T) );
+    }
+
+    return toCopy;
+}
+
+//------------------------------------------------------------------------------
+
+template <typename T, uint8_t type>
+inline size_t MultiBuffer::getArray(size_t id, T* value,
+                                    size_t length, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, type);
+    finalize();
+
+    size_t toCopy = dataRef.getCopyLength(length, offset);
+
+    if (toCopy>0) {
+        memcpy( value, data + dataRef.dataOffset + offset * sizeof(T),
+                toCopy * sizeof(T) );
+    }
+
+    return toCopy;
+}
+
+//------------------------------------------------------------------------------
+
+template <typename T, uint8_t type>
+inline const T* MultiBuffer::getArray(size_t id, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, type);
+    finalize();
+    return (offset<dataRef.length) ?
+        reinterpret_cast<const T*>(data + dataRef.dataOffset +
+                                   offset * sizeof(T)) : 0;
+}
+
+//------------------------------------------------------------------------------
+
+MultiBuffer::MultiBuffer(XPlane& xplane, uint8_t registerCommand,
+                         uint8_t unregisterCommand) throw() :
+    data(0),
+    xplane(xplane),
+    registerCommand(registerCommand),
+    unregisterCommand(unregisterCommand),
+    registeredID(-1)
+{
+}
+
+//------------------------------------------------------------------------------
+
+MultiBuffer::~MultiBuffer() throw()
+{
+    unregisterSafelyFromXPlane();
+    delete[] data;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addInt(const std::string& name) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_INT, getLastDataRef()));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addFloat(const std::string& name) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT, getLastDataRef()));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addDouble(const std::string& name) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_DOUBLE, getLastDataRef()));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addFloatArray(const std::string& name, size_t length,
+                                  size_t offset) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT_ARRAY,
+                               getLastDataRef(), length, offset));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addIntArray(const std::string& name, size_t length,
+                                size_t offset) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_INT_ARRAY,
+                               getLastDataRef(), length, offset));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::addByteArray(const std::string& name, size_t length,
+                                 size_t offset) throw()
+{
+    unfinalize();
+    dataRefs.push_back(DataRef(name, Protocol::TYPE_BYTE_ARRAY,
+                               getLastDataRef(), length, offset));
+    return dataRefs.size() - 1;
+}
+
+//------------------------------------------------------------------------------
+
+bool MultiBuffer::finalize() const
+{
+    if (data==0 && !dataRefs.empty()) {
+        const DataRef* lastDataRef = getLastDataRef();
+        size_t dataSize = lastDataRef->dataOffset + lastDataRef->getSize();
+        data = new unsigned char[dataSize];
+        memset(data, 0, dataSize);
+        return true;
+    } else {
+        return data!=0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::registerInXPlane() throw(Exception)
+{
+    if (finalize() && registeredID<0) {
+        xplane.checkStream();
+
+        writeSpec(registerCommand);
+
+        uint32_t id = xplane.stream->readU32();
+        xplane.checkStream();
+
+        registeredID = static_cast<int>(id);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::unregisterFromXPlane() throw(Exception)
+{
+    if (registeredID>=0) {
+        xplane.stream->writeU8(unregisterCommand);
+        xplane.stream->writeU32(static_cast<uint32_t>(registeredID));
+        xplane.stream->flush();
+        xplane.checkResult();
+        registeredID = -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+bool MultiBuffer::unregisterSafelyFromXPlane() throw()
+{
+    try {
+        unregisterFromXPlane();
+        return true;
+    } catch(...) {
+        registeredID = -1;
+        return false;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::execute() throw(Exception)
+{
+    if (data==0 && registeredID>=0) {
+        unregisterFromXPlane();
+        registerInXPlane();
+    } else {
+        finalize();
+    }
+
+    if (registeredID>=0) {
+        doExecute();
+    } else {
+        doExecuteUnregistered();
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::setInt(size_t id, int value)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
+}
+
+//------------------------------------------------------------------------------
+
+int MultiBuffer::getInt(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
+}
+
+//------------------------------------------------------------------------------
+
+const int32_t& MultiBuffer::getIntRef(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
+}
+
+//------------------------------------------------------------------------------
+
+int32_t& MultiBuffer::getIntRef(size_t id)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::setFloat(size_t id, float value)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
+}
+
+//------------------------------------------------------------------------------
+
+float MultiBuffer::getFloat(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
+}
+
+//------------------------------------------------------------------------------
+
+const float& MultiBuffer::getFloatRef(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
+}
+
+//------------------------------------------------------------------------------
+
+float& MultiBuffer::getFloatRef(size_t id)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::setDouble(size_t id, double value)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
+}
+
+//------------------------------------------------------------------------------
+
+double MultiBuffer::getDouble(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
+}
+
+//------------------------------------------------------------------------------
+
+const double& MultiBuffer::getDoubleRef(size_t id) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
+}
+
+//------------------------------------------------------------------------------
+
+double& MultiBuffer::getDoubleRef(size_t id)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::setFloatArray(size_t id, const float* value,
+                                  size_t length, size_t offset)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::getFloatArray(size_t id, float* value,
+                                  size_t length, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
+                                size_t length, size_t offset)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
+                                size_t length, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
+                                size_t length, size_t offset)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
+                                size_t length, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
+}
+
+//------------------------------------------------------------------------------
+
+const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
+}
+
+//------------------------------------------------------------------------------
+
+size_t MultiBuffer::setString(size_t id, const string& value,
+                              size_t offset)
+    throw(InvalidIDException, TypeMismatchException)
+{
+    return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
+                        value.length(), offset);
+}
+
+//------------------------------------------------------------------------------
+
+string MultiBuffer::getString(size_t id, size_t offset) const
+    throw(InvalidIDException, TypeMismatchException)
+{
+    const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
+    finalize();
+
+    size_t toCopy = dataRef.getCopyLength(0, offset);
+    const uint8_t* str = data + dataRef.dataOffset + offset;
+
+    size_t length = 0;
+    if (toCopy!=0) {
+        while(length<toCopy && str[length]!=0) ++length;
+    }
+
+    return string(reinterpret_cast<const char*>(str), length);
+}
+
+//------------------------------------------------------------------------------
+
+const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
+        throw(InvalidIDException, TypeMismatchException)
+{
+    return reinterpret_cast<const char*>(getByteArray(id, offset));
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::writeSpec(uint8_t command) const throw(Exception)
+{
+    xplane.stream->writeU8(command);
+    xplane.stream->writeU32(dataRefs.size());
+
+    for(vector<DataRef>::const_iterator i = dataRefs.begin();
+        i!=dataRefs.end(); ++i)
+    {
+        const DataRef& dataRef = *i;
+        xplane.stream->writeString(dataRef.name);
+        xplane.stream->writeU8(dataRef.type);
+        if (dataRef.isArray()) {
+            xplane.stream->writeS32(dataRef.length);
+            xplane.stream->writeS32(dataRef.offset);
+        }
+    }
+
+    xplane.stream->flush();
+    xplane.checkResult(true);
+}
+
+//------------------------------------------------------------------------------
+
+void MultiBuffer::reregisterInXPlane() throw(Exception)
+{
+    if (registeredID>=0) {
+        int origRegisteredID = registeredID;
+        try {
+            registeredID = -1;
+            registerInXPlane();
+        } catch(...) {
+            registeredID = origRegisteredID;
+            throw;
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc	(revision 57)
+++ 	(revision )
@@ -1,650 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "MultiBuffer.h"
-
-#include "XPlane.h"
-
-#include <xplra/Protocol.h>
-
-#include <hu/varadiistvan/scpl/io/DataStream.h>
-
-#include <cstring>
-#include <cstdio>
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::MultiBuffer;
-
-using xplra::Protocol;
-
-using std::vector;
-using std::string;
-using std::min;
-
-//------------------------------------------------------------------------------
-
-inline MultiBuffer::DataRef::DataRef(const string& name, uint8_t type,
-                                     const DataRef* previous,
-                                     size_t length, size_t offset) throw() :
-    name(name),
-    type(type),
-    length(length),
-    offset(offset),
-    dataOffset(0)
-{
-    if (previous!=0) {
-        size_t alignment = getAlignment();
-        dataOffset = previous->dataOffset + previous->getSize();
-        dataOffset += alignment - 1;
-        dataOffset &= ~(alignment-1);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-inline size_t MultiBuffer::DataRef::getSize() const throw()
-{
-    switch (type) {
-      case Protocol::TYPE_INT:
-        return sizeof(int32_t);
-      case Protocol::TYPE_FLOAT:
-        return sizeof(float);
-      case Protocol::TYPE_DOUBLE:
-        return sizeof(double);
-      case Protocol::TYPE_FLOAT_ARRAY:
-        return sizeof(float) * length;
-      case Protocol::TYPE_INT_ARRAY:
-        return sizeof(int32_t) * length;
-      case Protocol::TYPE_BYTE_ARRAY:
-        return sizeof(uint8_t) * length;
-      default:
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-inline size_t MultiBuffer::DataRef::getAlignment() const throw()
-{
-    switch (type) {
-      case Protocol::TYPE_INT:
-      case Protocol::TYPE_INT_ARRAY:
-        return sizeof(int32_t);
-      case Protocol::TYPE_FLOAT:
-      case Protocol::TYPE_FLOAT_ARRAY:
-        return sizeof(float);
-      case Protocol::TYPE_DOUBLE:
-        return sizeof(double);
-      case Protocol::TYPE_BYTE_ARRAY:
-      default:
-        return sizeof(uint8_t);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-bool MultiBuffer::DataRef::isArray() const throw()
-{
-    return
-        type==Protocol::TYPE_FLOAT_ARRAY ||
-        type==Protocol::TYPE_INT_ARRAY ||
-        type==Protocol::TYPE_BYTE_ARRAY;
-}
-
-//------------------------------------------------------------------------------
-
-inline size_t
-MultiBuffer::DataRef::getCopyLength(size_t userLength, size_t userOffset)
-    const throw()
-{
-    size_t maxLength =
-        (userOffset>length) ? 0 : (length - userOffset);
-    return (userLength==0) ? maxLength : min(userLength, maxLength);
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-inline void MultiBuffer::unfinalize() throw()
-{
-    delete data; data = 0;
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::forgetRegistration() throw()
-{
-    registeredID = -1;
-}
-
-//------------------------------------------------------------------------------
-
-inline const MultiBuffer::DataRef* MultiBuffer::getLastDataRef() const throw()
-{
-    return dataRefs.empty() ? 0 : &(dataRefs.back());
-}
-
-//------------------------------------------------------------------------------
-
-inline const MultiBuffer::DataRef& MultiBuffer::getDataRef(size_t id, uint8_t type) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    if (id>=dataRefs.size()) throw InvalidIDException();
-    const DataRef& dataRef = dataRefs[id];
-    if (dataRef.type!=type) throw TypeMismatchException();
-    return dataRef;
-}
-
-//------------------------------------------------------------------------------
-
-inline void* MultiBuffer::getData(size_t id, uint8_t type)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, type);
-    finalize();
-    return data + dataRef.dataOffset;
-}
-
-//------------------------------------------------------------------------------
-
-inline const void* MultiBuffer::getData(size_t id, uint8_t type) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, type);
-    finalize();
-    return data + dataRef.dataOffset;
-}
-
-//------------------------------------------------------------------------------
-
-template <typename T, uint8_t type> size_t
-inline MultiBuffer::setArray(size_t id, const T* value,
-                             size_t length, size_t offset)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, type);
-    finalize();
-
-    size_t toCopy = dataRef.getCopyLength(length, offset);
-
-    if (toCopy>0) {
-        memcpy( data + dataRef.dataOffset + offset * sizeof(T),
-                value, toCopy * sizeof(T) );
-    }
-
-    return toCopy;
-}
-
-//------------------------------------------------------------------------------
-
-template <typename T, uint8_t type>
-inline size_t MultiBuffer::getArray(size_t id, T* value,
-                                    size_t length, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, type);
-    finalize();
-
-    size_t toCopy = dataRef.getCopyLength(length, offset);
-
-    if (toCopy>0) {
-        memcpy( value, data + dataRef.dataOffset + offset * sizeof(T),
-                toCopy * sizeof(T) );
-    }
-
-    return toCopy;
-}
-
-//------------------------------------------------------------------------------
-
-template <typename T, uint8_t type>
-inline const T* MultiBuffer::getArray(size_t id, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, type);
-    finalize();
-    return (offset<dataRef.length) ?
-        reinterpret_cast<const T*>(data + dataRef.dataOffset +
-                                   offset * sizeof(T)) : 0;
-}
-
-//------------------------------------------------------------------------------
-
-MultiBuffer::MultiBuffer(XPlane& xplane, uint8_t registerCommand,
-                         uint8_t unregisterCommand) throw() :
-    data(0),
-    xplane(xplane),
-    registerCommand(registerCommand),
-    unregisterCommand(unregisterCommand),
-    registeredID(-1)
-{
-}
-
-//------------------------------------------------------------------------------
-
-MultiBuffer::~MultiBuffer() throw()
-{
-    unregisterSafelyFromXPlane();
-    delete[] data;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addInt(const string& name) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_INT, getLastDataRef()));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addFloat(const string& name) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT, getLastDataRef()));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addDouble(const string& name) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_DOUBLE, getLastDataRef()));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addFloatArray(const string& name, size_t length,
-                                  size_t offset) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT_ARRAY,
-                               getLastDataRef(), length, offset));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addIntArray(const string& name, size_t length,
-                                size_t offset) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_INT_ARRAY,
-                               getLastDataRef(), length, offset));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::addByteArray(const string& name, size_t length,
-                                 size_t offset) throw()
-{
-    unfinalize();
-    dataRefs.push_back(DataRef(name, Protocol::TYPE_BYTE_ARRAY,
-                               getLastDataRef(), length, offset));
-    return dataRefs.size() - 1;
-}
-
-//------------------------------------------------------------------------------
-
-bool MultiBuffer::finalize() const
-{
-    if (data==0 && !dataRefs.empty()) {
-        const DataRef* lastDataRef = getLastDataRef();
-        size_t dataSize = lastDataRef->dataOffset + lastDataRef->getSize();
-        data = new unsigned char[dataSize];
-        memset(data, 0, dataSize);
-        return true;
-    } else {
-        return data!=0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::registerInXPlane() throw(Exception)
-{
-    if (finalize() && registeredID<0) {
-        xplane.checkStream();
-
-        writeSpec(registerCommand);
-
-        uint32_t id = xplane.stream->readU32();
-        xplane.checkStream();
-
-        registeredID = static_cast<int>(id);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::unregisterFromXPlane() throw(Exception)
-{
-    if (registeredID>=0) {
-        xplane.stream->writeU8(unregisterCommand);
-        xplane.stream->writeU32(static_cast<uint32_t>(registeredID));
-        xplane.stream->flush();
-        xplane.checkResult();
-        registeredID = -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-bool MultiBuffer::unregisterSafelyFromXPlane() throw()
-{
-    try {
-        unregisterFromXPlane();
-        return true;
-    } catch(...) {
-        registeredID = -1;
-        return false;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::execute() throw(Exception)
-{
-    if (data==0 && registeredID>=0) {
-        unregisterFromXPlane();
-        registerInXPlane();
-    } else {
-        finalize();
-    }
-
-    if (registeredID>=0) {
-        doExecute();
-    } else {
-        doExecuteUnregistered();
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::setInt(size_t id, int value)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
-}
-
-//------------------------------------------------------------------------------
-
-int MultiBuffer::getInt(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
-}
-
-//------------------------------------------------------------------------------
-
-const int32_t& MultiBuffer::getIntRef(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
-}
-
-//------------------------------------------------------------------------------
-
-int32_t& MultiBuffer::getIntRef(size_t id)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::setFloat(size_t id, float value)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
-}
-
-//------------------------------------------------------------------------------
-
-float MultiBuffer::getFloat(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
-}
-
-//------------------------------------------------------------------------------
-
-const float& MultiBuffer::getFloatRef(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
-}
-
-//------------------------------------------------------------------------------
-
-float& MultiBuffer::getFloatRef(size_t id)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::setDouble(size_t id, double value)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
-}
-
-//------------------------------------------------------------------------------
-
-double MultiBuffer::getDouble(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
-}
-
-//------------------------------------------------------------------------------
-
-const double& MultiBuffer::getDoubleRef(size_t id) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
-}
-
-//------------------------------------------------------------------------------
-
-double& MultiBuffer::getDoubleRef(size_t id)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::setFloatArray(size_t id, const float* value,
-                                  size_t length, size_t offset)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::getFloatArray(size_t id, float* value,
-                                  size_t length, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
-                                size_t length, size_t offset)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
-                                size_t length, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
-                                size_t length, size_t offset)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
-                                size_t length, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
-}
-
-//------------------------------------------------------------------------------
-
-const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
-}
-
-//------------------------------------------------------------------------------
-
-size_t MultiBuffer::setString(size_t id, const string& value,
-                              size_t offset)
-    throw(InvalidIDException, TypeMismatchException)
-{
-    return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
-                        value.length(), offset);
-}
-
-//------------------------------------------------------------------------------
-
-string MultiBuffer::getString(size_t id, size_t offset) const
-    throw(InvalidIDException, TypeMismatchException)
-{
-    const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
-    finalize();
-
-    size_t toCopy = dataRef.getCopyLength(0, offset);
-    const uint8_t* str = data + dataRef.dataOffset + offset;
-
-    size_t length = 0;
-    if (toCopy!=0) {
-        while(length<toCopy && str[length]!=0) ++length;
-    }
-
-    return string(reinterpret_cast<const char*>(str), length);
-}
-
-//------------------------------------------------------------------------------
-
-const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
-        throw(InvalidIDException, TypeMismatchException)
-{
-    return reinterpret_cast<const char*>(getByteArray(id, offset));
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::writeSpec(uint8_t command) const throw(Exception)
-{
-    xplane.stream->writeU8(command);
-    xplane.stream->writeU32(dataRefs.size());
-
-    for(vector<DataRef>::const_iterator i = dataRefs.begin();
-        i!=dataRefs.end(); ++i)
-    {
-        const DataRef& dataRef = *i;
-        xplane.stream->writeString(dataRef.name);
-        xplane.stream->writeU8(dataRef.type);
-        if (dataRef.isArray()) {
-            xplane.stream->writeS32(dataRef.length);
-            xplane.stream->writeS32(dataRef.offset);
-        }
-    }
-
-    xplane.stream->flush();
-    xplane.checkResult(true);
-}
-
-//------------------------------------------------------------------------------
-
-void MultiBuffer::reregisterInXPlane() throw(Exception)
-{
-    if (registeredID>=0) {
-        int origRegisteredID = registeredID;
-        try {
-            registeredID = -1;
-            registerInXPlane();
-        } catch(...) {
-            registeredID = origRegisteredID;
-            throw;
-        }
-    }
-}
-
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiBuffer.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiBuffer.h	(revision 66)
+++ src/client/c/hu/varadiistvan/xplra/MultiBuffer.h	(revision 66)
@@ -0,0 +1,606 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#ifndef HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
+#define HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
+//------------------------------------------------------------------------------
+
+#include "Exception.h"
+
+#include <string>
+#include <vector>
+
+#include <inttypes.h>
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace xplra {
+
+//------------------------------------------------------------------------------
+
+class XPlane;
+
+//------------------------------------------------------------------------------
+
+/**
+ * Base class for the multi-get and multi-set handlers. It contains
+ * the meta-data of the datarefs as well as a buffer for storing the
+ * data.
+ */
+class MultiBuffer
+{
+protected:
+    /**
+     * Information about a dataref.
+     */
+    class DataRef
+    {
+    public:
+        /**
+         * The name.
+         */
+        std::string name;
+
+        /**
+         * The type (the protocol constant).
+         */
+        uint8_t type;
+
+        /**
+         * The length in case of array types.
+         */
+        size_t length;
+
+        /**
+         * The offset in case of array types.
+         */
+        size_t offset;
+
+        /**
+         * The offset within the data buffer.
+         */
+        size_t dataOffset;
+
+        /**
+         * Construct the dataref with the given data.
+         */
+        DataRef(const std::string& name, uint8_t type,
+                const DataRef* previous = 0,
+                size_t length = 0, size_t offset = 0) throw();
+
+        /**
+         * Get the size of the data represented by this object.
+         */
+        size_t getSize() const throw();
+
+        /**
+         * Get the alignment requirement of the data represented by
+         * this dataref.
+         */
+        size_t getAlignment() const throw();
+
+        /**
+         * Determine if the dataref is an array.
+         */
+        bool isArray() const throw();
+
+        /**
+         * Get the length of the data the can be copied for the given
+         * user parameters.
+         */
+        size_t getCopyLength(size_t userLength, size_t userOffset) const throw();
+    };
+
+    /**
+     * The datarefs.
+     */
+    std::vector<DataRef> dataRefs;
+
+    /**
+     * The data buffer.
+     */
+    mutable unsigned char* data;
+
+    /**
+     * The XPlane object this buffer belongs to.
+     */
+    XPlane& xplane;
+
+    /**
+     * The command to use for registering the buffer.
+     */
+    uint8_t registerCommand;
+
+    /**
+     * The command to unregister the buffer.
+     */
+    uint8_t unregisterCommand;
+
+    /**
+     * The ID with which this buffer is registered in the plugin. If
+     * negative, the buffer is not registerd yet.
+     */
+    int registeredID;
+
+protected:
+    /**
+     * Construct an empty buffer for the given XPlane instance.
+     */
+    MultiBuffer(XPlane& xplane, uint8_t registerCommand,
+                uint8_t unregisterCommand) throw();
+
+    /**
+     * Destroy the buffer. If it is registered, an attempt will be
+     * made to unregister it.
+     */
+    virtual ~MultiBuffer() throw();
+
+public:
+    /**
+     * Get the X-Plane object this buffer belongs to.
+     */
+    XPlane& getXPlane() const throw();
+
+    /**
+     * Add an integer dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addInt(const std::string& name) throw();
+
+    /**
+     * Add a float dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addFloat(const std::string& name) throw();
+
+    /**
+     * Add a double dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addDouble(const std::string& name) throw();
+
+    /**
+     * Add a float array dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addFloatArray(const std::string& name, size_t length,
+                         size_t offset = 0) throw();
+
+    /**
+     * Add an integer array dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addIntArray(const std::string& name, size_t length,
+                       size_t offset = 0) throw();
+
+    /**
+     * Add a byte array dataref.
+     *
+     * @return the ID of the dataref, that can be used later to set or
+     * get the value.
+     */
+    size_t addByteArray(const std::string& name, size_t length,
+                        size_t offset = 0) throw();
+
+    /**
+     * Finalize the buffer, if not finalized yet.
+     *
+     * @return if there is any data in it
+     */
+    bool finalize() const;
+
+    /**
+     * Register this buffer in X-Plane the for either getting or
+     * setting, depending on the actual subclass. It will be finalized
+     * too.
+     */
+    void registerInXPlane() throw(Exception);
+
+    /**
+     * Unregister this buffer from X-Plane.
+     */
+    void unregisterFromXPlane() throw(Exception);
+
+    /**
+     * Unregister this buffer from X-Plane safely, i.e. without
+     * throwing any exceptions. If unregistration fails, the
+     * registered ID will be cleared anyway.
+     *
+     * @return whether unregistration succeeded.
+     */
+    bool unregisterSafelyFromXPlane() throw();
+
+    /**
+     * Execute the buffer by either reading or writing it. If the
+     * buffer is not finalized, it will be finalized. If it is not
+     * finalized, but registered, the registration will be cleared,
+     * and it will be re-registered after finalizing.
+     */
+    void execute() throw(Exception);
+
+    /**
+     * Set the value of an integer dataref with the given ID.
+     */
+    void setInt(size_t id, int value)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of an integer dataref with the given ID.
+     */
+    int getInt(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the integer dataref with the given ID
+     */
+    const int32_t& getIntRef(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the integer dataref with the given ID
+     */
+    int32_t& getIntRef(size_t id)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Set the value of a float dataref with the given ID.
+     */
+    void setFloat(size_t id, float value)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of a float dataref with the given ID.
+     */
+    float getFloat(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the float dataref with the given ID
+     */
+    const float& getFloatRef(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the integer dataref with the given ID
+     */
+    float& getFloatRef(size_t id)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Set the value of a double dataref with the given ID.
+     */
+    void setDouble(size_t id, double value)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of a double dataref with the given ID.
+     */
+    double getDouble(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the double dataref with the given ID
+     */
+    const double& getDoubleRef(size_t id) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a reference to the double dataref with the given ID
+     */
+    double& getDoubleRef(size_t id)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Set the value of the float array dataref with the given ID.
+     *
+     * @param id the ID of the float array dataref
+     * @param value the source buffer
+     * @param length the amount of data, i.e. you can set only a part
+     * of the data in the buffer. If 0, it is assumed to be the length
+     * of the data in the buffer minus the offset (see below).
+     *
+     * @param offset the offset within the buffer to set the data from
+     *
+     * @return the number of data items set
+     */
+    size_t setFloatArray(size_t id, const float* value,
+                         size_t length = 0, size_t offset = 0)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of the float array dataref with the given ID
+     *
+     * @param id the ID of the float array dataref
+     * @param value the destination buffer
+     * @param length the size of the buffer. If 0, it is assumed to be
+     * the length of the data in the buffer minus the offset (see
+     * below).
+     *
+     * @param offset the offset within the buffer to get the data from
+     *
+     * @return the number of data items retrieved.
+     */
+    size_t getFloatArray(size_t id, float* value,
+                         size_t length = 0, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the array of floating point values as a directly readable
+     * buffer.
+     *
+     * @param id the ID of the float array dataref
+     * @param offset the offset within the buffer. If it is not less
+     * than the length of the buffer, 0 is returned.
+     */
+    const float* getFloatArray(size_t id, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Set the value of the integer array dataref with the given ID.
+     *
+     * @param id the ID of the integer array dataref
+     * @param value the source buffer
+     * @param length the amount of data, i.e. you can set only a part
+     * of the data in the buffer. If 0, it is assumed to be the length
+     * of the data in the buffer minus the offset (see below).
+     *
+     * @param offset the offset within the buffer to set the data from
+     *
+     * @return the number of data items set
+     */
+    size_t setIntArray(size_t id, const int32_t* value,
+                       size_t length = 0, size_t offset = 0)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of the integer array dataref with the given ID
+     *
+     * @param id the ID of the integer array dataref
+     * @param value the destination buffer
+     * @param length the size of the buffer. If 0, it is assumed to be
+     * the length of the data in the buffer minus the offset (see
+     * below).
+     *
+     * @param offset the offset within the buffer to get the data from
+     *
+     * @return the number of data items retrieved.
+     */
+    size_t getIntArray(size_t id, int32_t* value,
+                       size_t length = 0, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the array of integer values as a directly readable buffer.
+     *
+     * @param id the ID of the float array dataref
+     * @param offset the offset within the buffer. If it is not less
+     * than the length of the buffer, 0 is returned.
+     */
+    const int32_t* getIntArray(size_t id, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+
+    /**
+     * Set the value of the byte array dataref with the given ID.
+     *
+     * @param id the ID of the byte array dataref
+     * @param value the source buffer
+     * @param length the amount of data, i.e. you can set only a part
+     * of the data in the buffer. If 0, it is assumed to be the length
+     * of the data in the buffer minus the offset (see below).
+     *
+     * @param offset the offset within the buffer to set the data from
+     *
+     * @return the number of data items set
+     */
+    size_t setByteArray(size_t id, const uint8_t* value,
+                        size_t length = 0, size_t offset = 0)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of the byte array dataref with the given ID
+     *
+     * @param id the ID of the byte array dataref
+     * @param value the destination buffer
+     * @param length the size of the buffer. If 0, it is assumed to be
+     * the length of the data in the buffer minus the offset (see
+     * below).
+     *
+     * @param offset the offset within the buffer to get the data from
+     *
+     * @return the number of data items retrieved.
+     */
+    size_t getByteArray(size_t id, uint8_t* value,
+                        size_t length = 0, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the array of byte values as a directly readable buffer.
+     *
+     * @param id the ID of the byte array dataref
+     * @param offset the offset within the buffer. If it is not less
+     * than the length of the buffer, 0 is returned.
+     */
+    const uint8_t* getByteArray(size_t id, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+
+    /**
+     * Set the value of the byte array dataref with the given ID
+     * from the given string. If the string contains less characters
+     * than the array's length, the rest will be filled with 0s.
+     *
+     * @return the number of bytes set
+     */
+    size_t setString(size_t id, const std::string& value,
+                     size_t offset = 0)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the value of the byte array dataref with the given ID as
+     * a string.
+     */
+    std::string getString(size_t id, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get a string pointer to the value of the byte array dataref
+     * with the given ID.
+     */
+    const char* getStringPtr(size_t id, size_t offset = 0) const
+        throw(InvalidIDException, TypeMismatchException);
+
+protected:
+    /**
+     * Perform the main part of the execution if the buffer is
+     * registered.
+     */
+    virtual void doExecute() throw(Exception) = 0;
+
+    /**
+     * Perform the main part of the execution if the buffer is
+     * not registered.
+     */
+    virtual void doExecuteUnregistered() throw(Exception) = 0;
+
+    /**
+     * Write the data specification with the given command. It also
+     * checks the result
+     */
+    void writeSpec(uint8_t command) const throw(Exception);
+
+    /**
+     * Re-register the buffer in X-Plane, if it has been registered
+     * earlier.
+     *
+     * it has not been registered, nothing is done. Otherwise the
+     * buffer gets registered, and the old ID is forgotten. This
+     * function is meant to be used by the XPlane object when it
+     * creates a new connection. If the registration fails, the
+     * original ID is restored, so that this function could be called
+     * again
+     */
+    void reregisterInXPlane() throw(Exception);
+
+private:
+    /**
+     * Unfinalize the buffer, if it is finalized.
+     */
+    void unfinalize() throw();
+
+    /**
+     * Forget the registration of this buffer. This is called from the
+     * destructor of the XPlane object, since that closes the
+     * connection anyway, so there is no need to unregister the
+     * multi-buffers.
+     */
+    void forgetRegistration() throw();
+
+    /**
+     * Get the last dataref, or 0 if there are not datarefs yet.
+     */
+    const DataRef* getLastDataRef() const throw();
+
+    /**
+     * Get the dataref with the given ID if it is of the given
+     * type. Otherwise throw an exception.
+     */
+    const DataRef& getDataRef(size_t id, uint8_t type) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the data area belonging to the given dataref it is of the
+     * given type. If the buffer is not finalized yet, it will be.
+     */
+    void* getData(size_t id, uint8_t type)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Get the data area belonging to the given dataref it is of the
+     * given type. If the buffer is not finalized yet, it will be.
+     */
+    const void* getData(size_t id, uint8_t type) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Template function for setting an array of a certain type.
+     */
+    template <typename T, uint8_t type> size_t
+    setArray(size_t id, const T* value, size_t length, size_t offset)
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Template function for getting the elements of an array of a
+     * certain type.
+     */
+    template <typename T, uint8_t type> size_t
+    getArray(size_t id, T* value, size_t length, size_t offset) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    /**
+     * Template function for getting the elements of an array of a
+     * certain type.
+     */
+    template <typename T, uint8_t type> const T*
+    getArray(size_t id, size_t offset) const
+        throw(InvalidIDException, TypeMismatchException);
+
+    friend class XPlane;
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline XPlane& MultiBuffer::getXPlane() const throw()
+{
+    return xplane;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+#endif // HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiBuffer.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiBuffer.h	(revision 57)
+++ 	(revision )
@@ -1,591 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-#ifndef HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
-#define HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
-//------------------------------------------------------------------------------
-
-#include "Exception.h"
-
-#include <string>
-#include <vector>
-
-#include <inttypes.h>
-
-//------------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace xplra {
-
-//------------------------------------------------------------------------------
-
-class XPlane;
-
-//------------------------------------------------------------------------------
-
-/**
- * Base class for the multi-get and multi-set handlers. It contains
- * the meta-data of the datarefs as well as a buffer for storing the
- * data.
- */
-class MultiBuffer
-{
-protected:
-    /**
-     * Information about a dataref.
-     */
-    class DataRef
-    {
-    public:
-        /**
-         * The name.
-         */
-        std::string name;
-
-        /**
-         * The type (the protocol constant).
-         */
-        uint8_t type;
-
-        /**
-         * The length in case of array types.
-         */
-        size_t length;
-
-        /**
-         * The offset in case of array types.
-         */
-        size_t offset;
-
-        /**
-         * The offset within the data buffer.
-         */
-        size_t dataOffset;
-
-        /**
-         * Construct the dataref with the given data.
-         */
-        DataRef(const std::string& name, uint8_t type,
-                const DataRef* previous = 0,
-                size_t length = 0, size_t offset = 0) throw();
-
-        /**
-         * Get the size of the data represented by this object.
-         */
-        size_t getSize() const throw();
-
-        /**
-         * Get the alignment requirement of the data represented by
-         * this dataref.
-         */
-        size_t getAlignment() const throw();
-
-        /**
-         * Determine if the dataref is an array.
-         */
-        bool isArray() const throw();
-
-        /**
-         * Get the length of the data the can be copied for the given
-         * user parameters.
-         */
-        size_t getCopyLength(size_t userLength, size_t userOffset) const throw();
-    };
-
-    /**
-     * The datarefs.
-     */
-    std::vector<DataRef> dataRefs;
-
-    /**
-     * The data buffer.
-     */
-    mutable unsigned char* data;
-
-    /**
-     * The XPlane object this buffer belongs to.
-     */
-    XPlane& xplane;
-
-    /**
-     * The command to use for registering the buffer.
-     */
-    uint8_t registerCommand;
-
-    /**
-     * The command to unregister the buffer.
-     */
-    uint8_t unregisterCommand;
-
-    /**
-     * The ID with which this buffer is registered in the plugin. If
-     * negative, the buffer is not registerd yet.
-     */
-    int registeredID;
-
-protected:
-    /**
-     * Construct an empty buffer for the given XPlane instance.
-     */
-    MultiBuffer(XPlane& xplane, uint8_t registerCommand,
-                uint8_t unregisterCommand) throw();
-
-    /**
-     * Destroy the buffer. If it is registered, an attempt will be
-     * made to unregister it.
-     */
-    virtual ~MultiBuffer() throw();
-
-public:
-    /**
-     * Get the X-Plane object this buffer belongs to.
-     */
-    XPlane& getXPlane() const throw();
-
-    /**
-     * Add an integer dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addInt(const std::string& name) throw();
-
-    /**
-     * Add a float dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addFloat(const std::string& name) throw();
-
-    /**
-     * Add a double dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addDouble(const std::string& name) throw();
-
-    /**
-     * Add a float array dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addFloatArray(const std::string& name, size_t length,
-                         size_t offset = 0) throw();
-
-    /**
-     * Add an integer array dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addIntArray(const std::string& name, size_t length,
-                       size_t offset = 0) throw();
-
-    /**
-     * Add a byte array dataref.
-     *
-     * @return the ID of the dataref, that can be used later to set or
-     * get the value.
-     */
-    size_t addByteArray(const std::string& name, size_t length,
-                        size_t offset = 0) throw();
-
-    /**
-     * Finalize the buffer, if not finalized yet.
-     *
-     * @return if there is any data in it
-     */
-    bool finalize() const;
-
-    /**
-     * Register this buffer in X-Plane the for either getting or
-     * setting, depending on the actual subclass. It will be finalized
-     * too.
-     */
-    void registerInXPlane() throw(Exception);
-
-    /**
-     * Unregister this buffer from X-Plane.
-     */
-    void unregisterFromXPlane() throw(Exception);
-
-    /**
-     * Unregister this buffer from X-Plane safely, i.e. without
-     * throwing any exceptions. If unregistration fails, the
-     * registered ID will be cleared anyway.
-     *
-     * @return whether unregistration succeeded.
-     */
-    bool unregisterSafelyFromXPlane() throw();
-
-    /**
-     * Execute the buffer by either reading or writing it. If the
-     * buffer is not finalized, it will be finalized. If it is not
-     * finalized, but registered, the registration will be cleared,
-     * and it will be re-registered after finalizing.
-     */
-    void execute() throw(Exception);
-
-    /**
-     * Set the value of an integer dataref with the given ID.
-     */
-    void setInt(size_t id, int value)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of an integer dataref with the given ID.
-     */
-    int getInt(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the integer dataref with the given ID
-     */
-    const int32_t& getIntRef(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the integer dataref with the given ID
-     */
-    int32_t& getIntRef(size_t id)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Set the value of a float dataref with the given ID.
-     */
-    void setFloat(size_t id, float value)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of a float dataref with the given ID.
-     */
-    float getFloat(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the float dataref with the given ID
-     */
-    const float& getFloatRef(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the integer dataref with the given ID
-     */
-    float& getFloatRef(size_t id)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Set the value of a double dataref with the given ID.
-     */
-    void setDouble(size_t id, double value)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of a double dataref with the given ID.
-     */
-    double getDouble(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the double dataref with the given ID
-     */
-    const double& getDoubleRef(size_t id) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a reference to the double dataref with the given ID
-     */
-    double& getDoubleRef(size_t id)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Set the value of the float array dataref with the given ID.
-     *
-     * @param length the amount of data, i.e. you can set only a part
-     * of the data in the buffer. If 0, it is assumed to be the length
-     * of the data in the buffer minus the offset (see below).
-     *
-     * @param offset the offset within the buffer to set the data from
-     *
-     * @return the number of data items set
-     */
-    size_t setFloatArray(size_t id, const float* value,
-                         size_t length = 0, size_t offset = 0)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of the float array dataref with the given ID
-     *
-     * @param length the size of the buffer. If 0, it is assumed to be
-     * the length of the data in the buffer minus the offset (see
-     * below).
-     *
-     * @param offset the offset within the buffer to get the data from
-     *
-     * @return the number of data items retrieved.
-     */
-    size_t getFloatArray(size_t id, float* value,
-                         size_t length = 0, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the array of floating point values as a directly readable
-     * buffer.
-     *
-     * @param offset the offset within the buffer. If it is not less
-     * than the length of the buffer, 0 is returned.
-     */
-    const float* getFloatArray(size_t id, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Set the value of the integer array dataref with the given ID.
-     *
-     * @param length the amount of data, i.e. you can set only a part
-     * of the data in the buffer. If 0, it is assumed to be the length
-     * of the data in the buffer minus the offset (see below).
-     *
-     * @param offset the offset within the buffer to set the data from
-     *
-     * @return the number of data items set
-     */
-    size_t setIntArray(size_t id, const int32_t* value,
-                       size_t length = 0, size_t offset = 0)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of the integer array dataref with the given ID
-     *
-     * @param length the size of the buffer. If 0, it is assumed to be
-     * the length of the data in the buffer minus the offset (see
-     * below).
-     *
-     * @param offset the offset within the buffer to get the data from
-     *
-     * @return the number of data items retrieved.
-     */
-    size_t getIntArray(size_t id, int32_t* value,
-                       size_t length = 0, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the array of integer values as a directly readable buffer.
-     *
-     * @param offset the offset within the buffer. If it is not less
-     * than the length of the buffer, 0 is returned.
-     */
-    const int32_t* getIntArray(size_t id, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-
-    /**
-     * Set the value of the byte array dataref with the given ID.
-     *
-     * @param length the amount of data, i.e. you can set only a part
-     * of the data in the buffer. If 0, it is assumed to be the length
-     * of the data in the buffer minus the offset (see below).
-     *
-     * @param offset the offset within the buffer to set the data from
-     *
-     * @return the number of data items set
-     */
-    size_t setByteArray(size_t id, const uint8_t* value,
-                        size_t length = 0, size_t offset = 0)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of the byte array dataref with the given ID
-     *
-     * @param length the size of the buffer. If 0, it is assumed to be
-     * the length of the data in the buffer minus the offset (see
-     * below).
-     *
-     * @param offset the offset within the buffer to get the data from
-     *
-     * @return the number of data items retrieved.
-     */
-    size_t getByteArray(size_t id, uint8_t* value,
-                       size_t length = 0, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the array of byte values as a directly readable buffer.
-     *
-     * @param offset the offset within the buffer. If it is not less
-     * than the length of the buffer, 0 is returned.
-     */
-    const uint8_t* getByteArray(size_t id, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-
-    /**
-     * Set the value of the byte array dataref with the given ID
-     * from the given string. If the string contains less characters
-     * than the array's length, the rest will be filled with 0s.
-     *
-     * @return the number of bytes set
-     */
-    size_t setString(size_t id, const std::string& value,
-                     size_t offset = 0)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the value of the byte array dataref with the given ID as
-     * a string.
-     */
-    std::string getString(size_t id, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get a string pointer to the value of the byte array dataref
-     * with the given ID.
-     */
-    const char* getStringPtr(size_t id, size_t offset = 0) const
-        throw(InvalidIDException, TypeMismatchException);
-
-protected:
-    /**
-     * Perform the main part of the execution if the buffer is
-     * registered.
-     */
-    virtual void doExecute() throw(Exception) = 0;
-
-    /**
-     * Perform the main part of the execution if the buffer is
-     * not registered.
-     */
-    virtual void doExecuteUnregistered() throw(Exception) = 0;
-
-    /**
-     * Write the data specification with the given command. It also
-     * checks the result
-     */
-    void writeSpec(uint8_t command) const throw(Exception);
-
-    /**
-     * Re-register the buffer in X-Plane, if it has been registered
-     * earlier.
-     *
-     * it has not been registered, nothing is done. Otherwise the
-     * buffer gets registered, and the old ID is forgotten. This
-     * function is meant to be used by the XPlane object when it
-     * creates a new connection. If the registration fails, the
-     * original ID is restored, so that this function could be called
-     * again
-     */
-    void reregisterInXPlane() throw(Exception);
-
-private:
-    /**
-     * Unfinalize the buffer, if it is finalized.
-     */
-    void unfinalize() throw();
-
-    /**
-     * Forget the registration of this buffer. This is called from the
-     * destructor of the XPlane object, since that closes the
-     * connection anyway, so there is no need to unregister the
-     * multi-buffers.
-     */
-    void forgetRegistration() throw();
-
-    /**
-     * Get the last dataref, or 0 if there are not datarefs yet.
-     */
-    const DataRef* getLastDataRef() const throw();
-
-    /**
-     * Get the dataref with the given ID if it is of the given
-     * type. Otherwise throw an exception.
-     */
-    const DataRef& getDataRef(size_t id, uint8_t type) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the data area belonging to the given dataref it is of the
-     * given type. If the buffer is not finalized yet, it will be.
-     */
-    void* getData(size_t id, uint8_t type)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Get the data area belonging to the given dataref it is of the
-     * given type. If the buffer is not finalized yet, it will be.
-     */
-    const void* getData(size_t id, uint8_t type) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Template function for setting an array of a certain type.
-     */
-    template <typename T, uint8_t type> size_t
-    setArray(size_t id, const T* value, size_t length, size_t offset)
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Template function for getting the elements of an array of a
-     * certain type.
-     */
-    template <typename T, uint8_t type> size_t
-    getArray(size_t id, T* value, size_t length, size_t offset) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    /**
-     * Template function for getting the elements of an array of a
-     * certain type.
-     */
-    template <typename T, uint8_t type> const T*
-    getArray(size_t id, size_t offset) const
-        throw(InvalidIDException, TypeMismatchException);
-
-    friend class XPlane;
-};
-
-//------------------------------------------------------------------------------
-// Inline definitions
-//------------------------------------------------------------------------------
-
-inline XPlane& MultiBuffer::getXPlane() const throw()
-{
-    return xplane;
-}
-
-//------------------------------------------------------------------------------
-
-} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-#endif // HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiGetter.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiGetter.cc	(revision 40)
+++ src/client/c/hu/varadiistvan/xplra/MultiGetter.cc	(revision 40)
@@ -0,0 +1,133 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "MultiGetter.h"
+
+#include "XPlane.h"
+
+#include <xplra/Protocol.h>
+
+#include <hu/varadiistvan/scpl/io/DataStream.h>
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::MultiGetter;
+
+using xplra::Protocol;
+
+using std::vector;
+using std::min;
+
+//------------------------------------------------------------------------------
+
+MultiGetter::MultiGetter(XPlane& xplane) throw() :
+    MultiBuffer(xplane, Protocol::COMMAND_REGISTER_GET_MULTI,
+                Protocol::COMMAND_UNREGISTER_GET_MULTI)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline void MultiGetter::read(const DataRef& dataRef) throw(Exception)
+{
+    switch (dataRef.type) {
+      case Protocol::TYPE_INT:
+        *reinterpret_cast<int32_t*>(data + dataRef.dataOffset) =
+            xplane.stream->readS32();
+        break;
+      case Protocol::TYPE_FLOAT:
+        *reinterpret_cast<float*>(data + dataRef.dataOffset) =
+            xplane.stream->readFloat();
+        break;
+      case Protocol::TYPE_DOUBLE:
+        *reinterpret_cast<double*>(data + dataRef.dataOffset) =
+            xplane.stream->readDouble();
+        break;
+      case Protocol::TYPE_FLOAT_ARRAY:
+      case Protocol::TYPE_INT_ARRAY:
+      case Protocol::TYPE_BYTE_ARRAY:
+      {
+          size_t length = xplane.stream->readS32();
+          xplane.checkStream();
+          length = min(length, dataRef.length);
+          size_t elementSize =
+              (dataRef.type==Protocol::TYPE_FLOAT_ARRAY) ? sizeof(float) :
+              ((dataRef.type==Protocol::TYPE_INT_ARRAY) ?
+               sizeof(int32_t) : sizeof(uint8_t));
+          xplane.stream->read(data + dataRef.dataOffset, length * elementSize);
+      }
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiGetter::doExecute() throw(Exception)
+{
+    xplane.checkStream();
+    xplane.stream->writeU8(Protocol::COMMAND_EXECUTE_GET_MULTI);
+    xplane.stream->writeU32(registeredID);
+    xplane.stream->flush();
+    xplane.checkResult(true);
+
+    readValues();
+}
+
+
+//------------------------------------------------------------------------------
+
+void MultiGetter::doExecuteUnregistered() throw(Exception)
+{
+    writeSpec(Protocol::COMMAND_GET_MULTI);
+
+    readValues();
+}
+
+//------------------------------------------------------------------------------
+
+void MultiGetter::readValues() throw(Exception)
+{
+    for(vector<DataRef>::const_iterator i = dataRefs.begin();
+        i!=dataRefs.end(); ++i)
+    {
+        xplane.checkStream();
+        const DataRef& dataRef = *i;
+        read(dataRef);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiGetter.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiGetter.cc	(revision 40)
+++ 	(revision )
@@ -1,133 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "MultiGetter.h"
-
-#include "XPlane.h"
-
-#include <xplra/Protocol.h>
-
-#include <hu/varadiistvan/scpl/io/DataStream.h>
-
-#include <cstdio>
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::MultiGetter;
-
-using xplra::Protocol;
-
-using std::vector;
-using std::min;
-
-//------------------------------------------------------------------------------
-
-MultiGetter::MultiGetter(XPlane& xplane) throw() :
-    MultiBuffer(xplane, Protocol::COMMAND_REGISTER_GET_MULTI,
-                Protocol::COMMAND_UNREGISTER_GET_MULTI)
-{
-}
-
-//------------------------------------------------------------------------------
-
-inline void MultiGetter::read(const DataRef& dataRef) throw(Exception)
-{
-    switch (dataRef.type) {
-      case Protocol::TYPE_INT:
-        *reinterpret_cast<int32_t*>(data + dataRef.dataOffset) =
-            xplane.stream->readS32();
-        break;
-      case Protocol::TYPE_FLOAT:
-        *reinterpret_cast<float*>(data + dataRef.dataOffset) =
-            xplane.stream->readFloat();
-        break;
-      case Protocol::TYPE_DOUBLE:
-        *reinterpret_cast<double*>(data + dataRef.dataOffset) =
-            xplane.stream->readDouble();
-        break;
-      case Protocol::TYPE_FLOAT_ARRAY:
-      case Protocol::TYPE_INT_ARRAY:
-      case Protocol::TYPE_BYTE_ARRAY:
-      {
-          size_t length = xplane.stream->readS32();
-          xplane.checkStream();
-          length = min(length, dataRef.length);
-          size_t elementSize =
-              (dataRef.type==Protocol::TYPE_FLOAT_ARRAY) ? sizeof(float) :
-              ((dataRef.type==Protocol::TYPE_INT_ARRAY) ?
-               sizeof(int32_t) : sizeof(uint8_t));
-          xplane.stream->read(data + dataRef.dataOffset, length * elementSize);
-      }
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiGetter::doExecute() throw(Exception)
-{
-    xplane.checkStream();
-    xplane.stream->writeU8(Protocol::COMMAND_EXECUTE_GET_MULTI);
-    xplane.stream->writeU32(registeredID);
-    xplane.stream->flush();
-    xplane.checkResult(true);
-
-    readValues();
-}
-
-
-//------------------------------------------------------------------------------
-
-void MultiGetter::doExecuteUnregistered() throw(Exception)
-{
-    writeSpec(Protocol::COMMAND_GET_MULTI);
-
-    readValues();
-}
-
-//------------------------------------------------------------------------------
-
-void MultiGetter::readValues() throw(Exception)
-{
-    for(vector<DataRef>::const_iterator i = dataRefs.begin();
-        i!=dataRefs.end(); ++i)
-    {
-        xplane.checkStream();
-        const DataRef& dataRef = *i;
-        read(dataRef);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiGetter.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiGetter.h	(revision 33)
+++ src/client/c/hu/varadiistvan/xplra/MultiGetter.h	(revision 33)
@@ -0,0 +1,89 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#ifndef HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
+#define HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
+//------------------------------------------------------------------------------
+
+#include "MultiBuffer.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace xplra {
+
+//------------------------------------------------------------------------------
+
+/**
+ * A multi-dataref buffer used to query those data.
+ */
+class MultiGetter : public MultiBuffer
+{
+private:
+    /**
+     * Construct the object for the given XPlane instance.
+     */
+    MultiGetter(XPlane& xplane) throw();
+
+protected:
+    /**
+     * @see MultiBuffer::doExecute
+     */
+    virtual void doExecute() throw(Exception);
+
+    /**
+     * @see MultiBuffer::doExecuteUnregistered
+     */
+    virtual void doExecuteUnregistered() throw(Exception);
+
+private:
+    /**
+     * Read the value of the given dataref from the stream into the
+     * buffer.
+     */
+    void read(const DataRef& dataRef) throw(Exception);
+
+    /**
+     * Read all the values.
+     */
+    void readValues() throw(Exception);
+
+    friend class XPlane;
+};
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+#endif // HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiGetter.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiGetter.h	(revision 33)
+++ 	(revision )
@@ -1,89 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-#ifndef HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
-#define HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
-//------------------------------------------------------------------------------
-
-#include "MultiBuffer.h"
-
-//------------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace xplra {
-
-//------------------------------------------------------------------------------
-
-/**
- * A multi-dataref buffer used to query those data.
- */
-class MultiGetter : public MultiBuffer
-{
-private:
-    /**
-     * Construct the object for the given XPlane instance.
-     */
-    MultiGetter(XPlane& xplane) throw();
-
-protected:
-    /**
-     * @see MultiBuffer::doExecute
-     */
-    virtual void doExecute() throw(Exception);
-
-    /**
-     * @see MultiBuffer::doExecuteUnregistered
-     */
-    virtual void doExecuteUnregistered() throw(Exception);
-
-private:
-    /**
-     * Read the value of the given dataref from the stream into the
-     * buffer.
-     */
-    void read(const DataRef& dataRef) throw(Exception);
-
-    /**
-     * Read all the values.
-     */
-    void readValues() throw(Exception);
-
-    friend class XPlane;
-};
-
-//------------------------------------------------------------------------------
-
-} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-#endif // HU_VARADIISTVAN_XPLRA_MULTIGETTER_H
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiSetter.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiSetter.cc	(revision 40)
+++ src/client/c/hu/varadiistvan/xplra/MultiSetter.cc	(revision 40)
@@ -0,0 +1,132 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "MultiSetter.h"
+
+#include "XPlane.h"
+
+#include <xplra/Protocol.h>
+
+#include <hu/varadiistvan/scpl/io/DataStream.h>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::MultiSetter;
+
+using xplra::Protocol;
+
+using std::vector;
+using std::min;
+
+//------------------------------------------------------------------------------
+
+MultiSetter::MultiSetter(XPlane& xplane) throw() :
+    MultiBuffer(xplane, Protocol::COMMAND_REGISTER_SET_MULTI,
+                Protocol::COMMAND_UNREGISTER_SET_MULTI)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline void MultiSetter::write(const DataRef& dataRef) const throw(Exception)
+{
+    switch (dataRef.type) {
+      case Protocol::TYPE_INT:
+        xplane.stream->writeS32(*reinterpret_cast<const int32_t*>
+                                (data + dataRef.dataOffset));
+        break;
+      case Protocol::TYPE_FLOAT:
+        xplane.stream->writeFloat(*reinterpret_cast<const float*>
+                                (data + dataRef.dataOffset));
+        break;
+      case Protocol::TYPE_DOUBLE:
+        xplane.stream->writeDouble(*reinterpret_cast<const double*>
+                                   (data + dataRef.dataOffset));
+        break;
+      case Protocol::TYPE_FLOAT_ARRAY:
+      case Protocol::TYPE_INT_ARRAY:
+      case Protocol::TYPE_BYTE_ARRAY:
+      {
+          size_t elementSize =
+              (dataRef.type==Protocol::TYPE_FLOAT_ARRAY) ? sizeof(float) :
+              ((dataRef.type==Protocol::TYPE_INT_ARRAY) ?
+               sizeof(int32_t) : sizeof(uint8_t));
+          xplane.stream->write(data + dataRef.dataOffset,
+                               dataRef.length * elementSize);
+      }
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void MultiSetter::doExecute() throw(Exception)
+{
+    xplane.checkStream();
+    xplane.stream->writeU8(Protocol::COMMAND_EXECUTE_SET_MULTI);
+    xplane.stream->writeU32(registeredID);
+    for(vector<DataRef>::const_iterator i = dataRefs.begin();
+        i!=dataRefs.end(); ++i)
+    {
+        const DataRef& dataRef = *i;
+        write(dataRef);
+    }
+    xplane.stream->flush();
+    xplane.checkResult(true);
+}
+
+//------------------------------------------------------------------------------
+
+void MultiSetter::doExecuteUnregistered() throw(Exception)
+{
+    xplane.stream->writeU8(Protocol::COMMAND_SET_MULTI);
+    xplane.stream->writeU32(dataRefs.size());
+    for(vector<DataRef>::const_iterator i = dataRefs.begin();
+        i!=dataRefs.end(); ++i)
+    {
+        const DataRef& dataRef = *i;
+        xplane.stream->writeString(dataRef.name);
+        xplane.stream->writeU8(dataRef.type);
+        if (dataRef.isArray()) {
+            xplane.stream->writeS32(dataRef.length);
+            xplane.stream->writeS32(dataRef.offset);
+        }
+        write(dataRef);
+    }
+    xplane.stream->flush();
+    xplane.checkResult(true);
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiSetter.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiSetter.cc	(revision 40)
+++ 	(revision )
@@ -1,132 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "MultiSetter.h"
-
-#include "XPlane.h"
-
-#include <xplra/Protocol.h>
-
-#include <hu/varadiistvan/scpl/io/DataStream.h>
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::MultiSetter;
-
-using xplra::Protocol;
-
-using std::vector;
-using std::min;
-
-//------------------------------------------------------------------------------
-
-MultiSetter::MultiSetter(XPlane& xplane) throw() :
-    MultiBuffer(xplane, Protocol::COMMAND_REGISTER_SET_MULTI,
-                Protocol::COMMAND_UNREGISTER_SET_MULTI)
-{
-}
-
-//------------------------------------------------------------------------------
-
-inline void MultiSetter::write(const DataRef& dataRef) const throw(Exception)
-{
-    switch (dataRef.type) {
-      case Protocol::TYPE_INT:
-        xplane.stream->writeS32(*reinterpret_cast<const int32_t*>
-                                (data + dataRef.dataOffset));
-        break;
-      case Protocol::TYPE_FLOAT:
-        xplane.stream->writeFloat(*reinterpret_cast<const float*>
-                                (data + dataRef.dataOffset));
-        break;
-      case Protocol::TYPE_DOUBLE:
-        xplane.stream->writeDouble(*reinterpret_cast<const double*>
-                                   (data + dataRef.dataOffset));
-        break;
-      case Protocol::TYPE_FLOAT_ARRAY:
-      case Protocol::TYPE_INT_ARRAY:
-      case Protocol::TYPE_BYTE_ARRAY:
-      {
-          size_t elementSize =
-              (dataRef.type==Protocol::TYPE_FLOAT_ARRAY) ? sizeof(float) :
-              ((dataRef.type==Protocol::TYPE_INT_ARRAY) ?
-               sizeof(int32_t) : sizeof(uint8_t));
-          xplane.stream->write(data + dataRef.dataOffset,
-                               dataRef.length * elementSize);
-      }
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void MultiSetter::doExecute() throw(Exception)
-{
-    xplane.checkStream();
-    xplane.stream->writeU8(Protocol::COMMAND_EXECUTE_SET_MULTI);
-    xplane.stream->writeU32(registeredID);
-    for(vector<DataRef>::const_iterator i = dataRefs.begin();
-        i!=dataRefs.end(); ++i)
-    {
-        const DataRef& dataRef = *i;
-        write(dataRef);
-    }
-    xplane.stream->flush();
-    xplane.checkResult(true);
-}
-
-//------------------------------------------------------------------------------
-
-void MultiSetter::doExecuteUnregistered() throw(Exception)
-{
-    xplane.stream->writeU8(Protocol::COMMAND_SET_MULTI);
-    xplane.stream->writeU32(dataRefs.size());
-    for(vector<DataRef>::const_iterator i = dataRefs.begin();
-        i!=dataRefs.end(); ++i)
-    {
-        const DataRef& dataRef = *i;
-        xplane.stream->writeString(dataRef.name);
-        xplane.stream->writeU8(dataRef.type);
-        if (dataRef.isArray()) {
-            xplane.stream->writeS32(dataRef.length);
-            xplane.stream->writeS32(dataRef.offset);
-        }
-        write(dataRef);
-    }
-    xplane.stream->flush();
-    xplane.checkResult(true);
-}
-
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiSetter.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiSetter.h	(revision 26)
+++ src/client/c/hu/varadiistvan/xplra/MultiSetter.h	(revision 26)
@@ -0,0 +1,84 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#ifndef HU_VARADIISTVAN_XPLRA_MULTISETTER_H
+#define HU_VARADIISTVAN_XPLRA_MULTISETTER_H
+//------------------------------------------------------------------------------
+
+#include "MultiBuffer.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace xplra {
+
+//------------------------------------------------------------------------------
+
+/**
+ * A multi-dataref buffer used to set those data.
+ */
+class MultiSetter : public MultiBuffer
+{
+private:
+    /**
+     * Construct the object for the given XPlane instance.
+     */
+    MultiSetter(XPlane& xplane) throw();
+
+protected:
+    /**
+     * @see MultiBuffer::doExecute
+     */
+    virtual void doExecute() throw(Exception);
+
+    /**
+     * @see MultiBuffer::doExecuteUnregistered
+     */
+    virtual void doExecuteUnregistered() throw(Exception);
+
+private:
+    /**
+     * Write the value of the given dataref from the buffer into the
+     * stream.
+     */
+    void write(const DataRef& dataRef) const throw(Exception);
+
+    friend class XPlane;
+};
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+#endif // HU_VARADIISTVAN_XPLRA_MULTISETTER_H
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/MultiSetter.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/MultiSetter.h	(revision 26)
+++ 	(revision )
@@ -1,84 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-#ifndef HU_VARADIISTVAN_XPLRA_MULTISETTER_H
-#define HU_VARADIISTVAN_XPLRA_MULTISETTER_H
-//------------------------------------------------------------------------------
-
-#include "MultiBuffer.h"
-
-//------------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace xplra {
-
-//------------------------------------------------------------------------------
-
-/**
- * A multi-dataref buffer used to set those data.
- */
-class MultiSetter : public MultiBuffer
-{
-private:
-    /**
-     * Construct the object for the given XPlane instance.
-     */
-    MultiSetter(XPlane& xplane) throw();
-
-protected:
-    /**
-     * @see MultiBuffer::doExecute
-     */
-    virtual void doExecute() throw(Exception);
-
-    /**
-     * @see MultiBuffer::doExecuteUnregistered
-     */
-    virtual void doExecuteUnregistered() throw(Exception);
-
-private:
-    /**
-     * Write the value of the given dataref from the buffer into the
-     * stream.
-     */
-    void write(const DataRef& dataRef) const throw(Exception);
-
-    friend class XPlane;
-};
-
-//------------------------------------------------------------------------------
-
-} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-#endif // HU_VARADIISTVAN_XPLRA_MULTISETTER_H
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/XPlane.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/XPlane.cc	(revision 57)
+++ src/client/c/hu/varadiistvan/xplra/XPlane.cc	(revision 57)
@@ -0,0 +1,557 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "XPlane.h"
+
+#include "MultiGetter.h"
+#include "MultiSetter.h"
+
+#include <hu/varadiistvan/scpl/io/LocalClientSocket.h>
+#include <hu/varadiistvan/scpl/io/DataStream.h>
+
+#include <xplra/Protocol.h>
+
+#include <memory>
+
+#ifndef _WIN32
+#include <signal.h>
+#endif
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::XPlane;
+using hu::varadiistvan::xplra::MultiGetter;
+using hu::varadiistvan::xplra::MultiSetter;
+
+using hu::varadiistvan::scpl::io::LocalClientSocket;
+using hu::varadiistvan::scpl::io::LocalConnector;
+using hu::varadiistvan::scpl::io::DataStream;
+
+using xplra::Protocol;
+
+using std::auto_ptr;
+using std::string;
+using std::min;
+
+//------------------------------------------------------------------------------
+
+void XPlane::checkStream() throw(NotConnectedException, IOException)
+{
+    if (stream==0) {
+        throw NotConnectedException();
+    } else if (stream->failed()) {
+        throw IOException(stream->getErrorCode());
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::checkResult(uint8_t result, bool hasParameter, long parameter)
+    throw(ProtocolException)
+{
+    switch(result) {
+      case Protocol::RESULT_OK:
+        return;
+      case Protocol::RESULT_INVALID_COMMAND:
+        throw ProtocolException(ProtocolException::INVALID_COMMAND,
+                                hasParameter, parameter);
+      case Protocol::RESULT_UNKNOWN_DATAREF:
+        throw ProtocolException(ProtocolException::UNKNOWN_DATAREF,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_TYPE:
+        throw ProtocolException(ProtocolException::INVALID_TYPE,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_LENGTH:
+        throw ProtocolException(ProtocolException::INVALID_LENGTH,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_OFFSET:
+        throw ProtocolException(ProtocolException::INVALID_OFFSET,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_COUNT:
+        throw ProtocolException(ProtocolException::INVALID_COUNT,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_ID:
+        throw ProtocolException(ProtocolException::INVALID_ID,
+                                hasParameter, parameter);
+      case Protocol::RESULT_INVALID_DURATION:
+        throw ProtocolException(ProtocolException::INVALID_DURATION,
+                                hasParameter, parameter);
+      case Protocol::RESULT_OTHER_ERROR:
+      default:
+        throw ProtocolException(ProtocolException::OTHER,
+                                hasParameter, parameter);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::checkResult(bool multi) throw(ProtocolException, IOException)
+{
+    uint8_t result = stream->readU8();
+    bool hasParameter = false;
+    long parameter = 0;
+    if (multi) {
+        if (result==Protocol::RESULT_UNKNOWN_DATAREF) {
+            parameter = stream->readU32();
+            hasParameter = true;
+        }
+    }
+    checkStream();
+    checkResult(result, hasParameter, parameter);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+XPlane::~XPlane() throw()
+{
+    disconnect();
+    for(multiBuffers_t::iterator i = multiBuffers.begin();
+        i!=multiBuffers.end(); ++i)
+    {
+        MultiBuffer* buffer = *i;
+        buffer->forgetRegistration();
+        delete buffer;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::connect() throw(IOException)
+{
+    if (socket!=0) return;
+
+    auto_ptr<LocalClientSocket> clientSocket(new LocalClientSocket("xplra",
+                                                                   &waiter));
+    LocalConnector& connector = clientSocket->getConnector();
+
+    while (!connector.connect()) {
+        if (connector.failed()) {
+            throw IOException(connector.getErrorCode());
+        }
+        waiter.wait();
+        if (waiter.failed()) {
+            throw IOException(waiter.getErrorCode());
+        }
+    }
+
+#ifndef _WIN32
+    signal(SIGPIPE, SIG_IGN);
+#endif
+
+    socket = clientSocket.release();
+    stream = new DataStream(*socket);
+
+    for(multiBuffers_t::iterator i = multiBuffers.begin();
+        i!=multiBuffers.end(); ++i)
+    {
+        MultiBuffer* buffer = *i;
+        buffer->reregisterInXPlane();
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::disconnect() throw()
+{
+    if (socket==0) return;
+
+    delete stream; stream = 0;
+    delete socket; socket = 0;
+}
+
+//------------------------------------------------------------------------------
+
+MultiGetter& XPlane::createMultiGetter() throw()
+{
+    MultiGetter* getter = new MultiGetter(*this);
+    multiBuffers.insert(getter);
+    return *getter;
+}
+
+//------------------------------------------------------------------------------
+
+MultiSetter& XPlane::createMultiSetter() throw()
+{
+    MultiSetter* setter = new MultiSetter(*this);
+    multiBuffers.insert(setter);
+    return *setter;
+}
+
+//------------------------------------------------------------------------------
+
+bool XPlane::destroyMultiBuffer(MultiBuffer& buffer) throw(Exception)
+{
+    multiBuffers_t::iterator i = multiBuffers.find(&buffer);
+    if (i==multiBuffers.end()) return false;
+
+    multiBuffers.erase(i);
+    delete &buffer;
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::getVersions(int& xplaneVersion, int& xplmVersion, int& xplraVersion)
+    throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_GET_VERSIONS);
+    stream->flush();
+    checkResult();
+
+    xplaneVersion = stream->readS32();
+    xplmVersion = stream->readS32();
+    xplraVersion = stream->readS32();
+
+    checkStream();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::reloadPlugins() throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_RELOAD_PLUGINS);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::getScalar(const char* name, uint8_t type) throw(Exception)
+{
+    checkStream();
+
+    stream->writeU8(Protocol::COMMAND_GET_SINGLE);
+    stream->writeString(name, strlen(name));
+    stream->writeU8(type);
+    if (!stream->flush()) checkStream();
+
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+int XPlane::getInt(const char* name) throw(Exception)
+{
+    getScalar(name, Protocol::TYPE_INT);
+
+    int value = stream->readS32();
+    checkStream();
+    return value;
+}
+
+//------------------------------------------------------------------------------
+
+float XPlane::getFloat(const char* name) throw(Exception)
+{
+    getScalar(name, Protocol::TYPE_FLOAT);
+
+    float value = stream->readFloat();
+    checkStream();
+    return value;
+}
+
+//------------------------------------------------------------------------------
+
+double XPlane::getDouble(const char* name) throw(Exception)
+{
+    getScalar(name, Protocol::TYPE_DOUBLE);
+
+    double value = stream->readDouble();
+    checkStream();
+    return value;
+}
+
+//------------------------------------------------------------------------------
+
+size_t XPlane::getArray(const char* name, uint8_t type,
+                        ssize_t length, size_t offset) throw(Exception)
+{
+    checkStream();
+
+    stream->writeU8(Protocol::COMMAND_GET_SINGLE);
+    stream->writeString(name, strlen(name));
+    stream->writeU8(type);
+    stream->writeS32(static_cast<int32_t>(length));
+    stream->writeS32(static_cast<int32_t>(offset));
+    if (!stream->flush()) checkStream();
+
+    uint8_t result = stream->readU8();
+    length = stream->readS32();
+    checkStream();
+    checkResult(result);
+
+    return length;
+}
+
+//------------------------------------------------------------------------------
+
+size_t XPlane::getFloatArray(const char* name, float* dest,
+                             size_t length, size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_FLOAT_ARRAY, length, offset);
+
+    if (!stream->read(dest, length*sizeof(float))) checkStream();
+
+    return length;
+}
+
+//------------------------------------------------------------------------------
+
+float* XPlane::getFloatArray(const char* name, size_t& length,
+                             size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_FLOAT_ARRAY, -1, offset);
+
+    auto_ptr<float> data(new float[length]);
+    if (!stream->read(data.get(), length*sizeof(float))) checkStream();
+    return data.release();
+}
+
+//------------------------------------------------------------------------------
+
+size_t XPlane::getIntArray(const char* name, int32_t* dest,
+                           size_t length, size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_INT_ARRAY, length, offset);
+
+    if (!stream->read(dest, length*sizeof(int32_t))) checkStream();
+
+    return length;
+}
+
+//------------------------------------------------------------------------------
+
+int32_t* XPlane::getIntArray(const char* name, size_t& length,
+                             size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_INT_ARRAY, -1, offset);
+
+    auto_ptr<int32_t> data(new int32_t[length]);
+    if (!stream->read(data.get(), length*sizeof(int32_t))) checkStream();
+    return data.release();
+}
+
+//------------------------------------------------------------------------------
+
+size_t XPlane::getByteArray(const char* name, uint8_t* dest,
+                            size_t length, size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_BYTE_ARRAY, length, offset);
+
+    if (!stream->read(dest, length*sizeof(uint8_t))) checkStream();
+
+    return length;
+}
+
+//------------------------------------------------------------------------------
+
+uint8_t* XPlane::getByteArray(const char* name, size_t& length,
+                              size_t offset) throw(Exception)
+{
+    length = getArray(name, Protocol::TYPE_BYTE_ARRAY, -1, offset);
+
+    auto_ptr<uint8_t> data(new uint8_t[length]);
+    if (!stream->read(data.get(), length*sizeof(uint8_t))) checkStream();
+    return data.release();
+}
+
+//------------------------------------------------------------------------------
+
+string XPlane::getString(const char* name, size_t offset) throw(Exception)
+{
+    size_t length = 0;
+    auto_ptr<uint8_t> data(getByteArray(name, length, offset));
+    return string(reinterpret_cast<char*>(data.get()));
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setScalar(const char* name, uint8_t type) throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_SET_SINGLE);
+    stream->writeString(name, strlen(name));
+    stream->writeU8(type);
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setInt(const char* name, int value) throw(Exception)
+{
+    setScalar(name, Protocol::TYPE_INT);
+    stream->writeS32(value);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setFloat(const char* name, float value) throw(Exception)
+{
+    setScalar(name, Protocol::TYPE_FLOAT);
+    stream->writeFloat(value);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setDouble(const char* name, double value) throw(Exception)
+{
+    setScalar(name, Protocol::TYPE_DOUBLE);
+    stream->writeDouble(value);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setArray(const char* name, uint8_t type, size_t length,
+                      size_t offset) throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_SET_SINGLE);
+    stream->writeString(name, strlen(name));
+    stream->writeU8(type);
+    stream->writeS32(static_cast<int32_t>(length));
+    stream->writeS32(static_cast<int32_t>(offset));
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setFloatArray(const char* name, const float* values, size_t length,
+                           size_t offset) throw(Exception)
+{
+    setArray(name, Protocol::TYPE_FLOAT_ARRAY, length, offset);
+    stream->write(values, length*sizeof(*values));
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setIntArray(const char* name, const int32_t* values, size_t length,
+                         size_t offset) throw(Exception)
+{
+    setArray(name, Protocol::TYPE_INT_ARRAY, length, offset);
+    stream->write(values, length*sizeof(*values));
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setByteArray(const char* name, const uint8_t* values, size_t length,
+                          size_t offset) throw(Exception)
+{
+    setArray(name, Protocol::TYPE_BYTE_ARRAY, length, offset);
+    stream->write(values, length*sizeof(*values));
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::setString(const char* name, const char* value, size_t length,
+                       size_t offset) throw(Exception)
+{
+    size_t valueLength = strlen(value);
+    if ((valueLength+1)>=length) {
+        setByteArray(name, reinterpret_cast<const uint8_t*>(value),
+                     length, offset);
+    } else {
+        auto_ptr<uint8_t> buffer(new uint8_t[length]);
+        memcpy(buffer.get(), value, valueLength);
+        memset(buffer.get() + valueLength, 0, length - valueLength);
+        setByteArray(name, buffer.get(), length, offset);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::showMessage(const char* message, float duration) throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_SHOW_MESSAGE);
+    stream->writeString(message);
+    stream->writeFloat(duration);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::registerHotkeys(const uint16_t* codes, size_t length)
+    throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_REGISTER_HOTKEYS);
+    stream->writeU32(length);
+    stream->write(codes, sizeof(uint16_t)*length);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::queryHotkeys(uint8_t* states, size_t length) throw(Exception)
+{
+    stream->writeU8(Protocol::COMMAND_QUERY_HOTKEYS);
+    stream->flush();
+    checkResult();
+
+    size_t count = stream->readU32();
+    checkStream();
+    stream->read(states, min(length, count));
+    if (length<count) {
+        while(length<count) {
+            stream->readU8();
+            ++length;
+        }
+    } else if (length>count) {
+        memset(states + count, 0, length - count);
+    }
+    checkStream();
+}
+
+//------------------------------------------------------------------------------
+
+void XPlane::unregisterHotkeys()
+{
+    stream->writeU8(Protocol::COMMAND_UNREGISTER_HOTKEYS);
+    stream->flush();
+    checkResult();
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/XPlane.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/XPlane.cc	(revision 57)
+++ 	(revision )
@@ -1,557 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "XPlane.h"
-
-#include "MultiGetter.h"
-#include "MultiSetter.h"
-
-#include <hu/varadiistvan/scpl/io/LocalClientSocket.h>
-#include <hu/varadiistvan/scpl/io/DataStream.h>
-
-#include <xplra/Protocol.h>
-
-#include <memory>
-
-#ifndef _WIN32
-#include <signal.h>
-#endif
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::XPlane;
-using hu::varadiistvan::xplra::MultiGetter;
-using hu::varadiistvan::xplra::MultiSetter;
-
-using hu::varadiistvan::scpl::io::LocalClientSocket;
-using hu::varadiistvan::scpl::io::LocalConnector;
-using hu::varadiistvan::scpl::io::DataStream;
-
-using xplra::Protocol;
-
-using std::auto_ptr;
-using std::string;
-using std::min;
-
-//------------------------------------------------------------------------------
-
-void XPlane::checkStream() throw(NotConnectedException, IOException)
-{
-    if (stream==0) {
-        throw NotConnectedException();
-    } else if (stream->failed()) {
-        throw IOException(stream->getErrorCode());
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::checkResult(uint8_t result, bool hasParameter, long parameter)
-    throw(ProtocolException)
-{
-    switch(result) {
-      case Protocol::RESULT_OK:
-        return;
-      case Protocol::RESULT_INVALID_COMMAND:
-        throw ProtocolException(ProtocolException::INVALID_COMMAND,
-                                hasParameter, parameter);
-      case Protocol::RESULT_UNKNOWN_DATAREF:
-        throw ProtocolException(ProtocolException::UNKNOWN_DATAREF,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_TYPE:
-        throw ProtocolException(ProtocolException::INVALID_TYPE,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_LENGTH:
-        throw ProtocolException(ProtocolException::INVALID_LENGTH,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_OFFSET:
-        throw ProtocolException(ProtocolException::INVALID_OFFSET,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_COUNT:
-        throw ProtocolException(ProtocolException::INVALID_COUNT,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_ID:
-        throw ProtocolException(ProtocolException::INVALID_ID,
-                                hasParameter, parameter);
-      case Protocol::RESULT_INVALID_DURATION:
-        throw ProtocolException(ProtocolException::INVALID_DURATION,
-                                hasParameter, parameter);
-      case Protocol::RESULT_OTHER_ERROR:
-      default:
-        throw ProtocolException(ProtocolException::OTHER,
-                                hasParameter, parameter);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::checkResult(bool multi) throw(ProtocolException, IOException)
-{
-    uint8_t result = stream->readU8();
-    bool hasParameter = false;
-    long parameter = 0;
-    if (multi) {
-        if (result==Protocol::RESULT_UNKNOWN_DATAREF) {
-            parameter = stream->readU32();
-            hasParameter = true;
-        }
-    }
-    checkStream();
-    checkResult(result, hasParameter, parameter);
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-XPlane::~XPlane() throw()
-{
-    disconnect();
-    for(multiBuffers_t::iterator i = multiBuffers.begin();
-        i!=multiBuffers.end(); ++i)
-    {
-        MultiBuffer* buffer = *i;
-        buffer->forgetRegistration();
-        delete buffer;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::connect() throw(IOException)
-{
-    if (socket!=0) return;
-
-    auto_ptr<LocalClientSocket> clientSocket(new LocalClientSocket("xplra",
-                                                                   &waiter));
-    LocalConnector& connector = clientSocket->getConnector();
-
-    while (!connector.connect()) {
-        if (connector.failed()) {
-            throw IOException(connector.getErrorCode());
-        }
-        waiter.wait();
-        if (waiter.failed()) {
-            throw IOException(waiter.getErrorCode());
-        }
-    }
-
-#ifndef _WIN32
-    signal(SIGPIPE, SIG_IGN);
-#endif
-
-    socket = clientSocket.release();
-    stream = new DataStream(*socket);
-
-    for(multiBuffers_t::iterator i = multiBuffers.begin();
-        i!=multiBuffers.end(); ++i)
-    {
-        MultiBuffer* buffer = *i;
-        buffer->reregisterInXPlane();
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::disconnect() throw()
-{
-    if (socket==0) return;
-
-    delete stream; stream = 0;
-    delete socket; socket = 0;
-}
-
-//------------------------------------------------------------------------------
-
-MultiGetter& XPlane::createMultiGetter() throw()
-{
-    MultiGetter* getter = new MultiGetter(*this);
-    multiBuffers.insert(getter);
-    return *getter;
-}
-
-//------------------------------------------------------------------------------
-
-MultiSetter& XPlane::createMultiSetter() throw()
-{
-    MultiSetter* setter = new MultiSetter(*this);
-    multiBuffers.insert(setter);
-    return *setter;
-}
-
-//------------------------------------------------------------------------------
-
-bool XPlane::destroyMultiBuffer(MultiBuffer& buffer) throw(Exception)
-{
-    multiBuffers_t::iterator i = multiBuffers.find(&buffer);
-    if (i==multiBuffers.end()) return false;
-
-    multiBuffers.erase(i);
-    delete &buffer;
-
-    return true;
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::getVersions(int& xplaneVersion, int& xplmVersion, int& xplraVersion)
-    throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_GET_VERSIONS);
-    stream->flush();
-    checkResult();
-
-    xplaneVersion = stream->readS32();
-    xplmVersion = stream->readS32();
-    xplraVersion = stream->readS32();
-
-    checkStream();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::reloadPlugins() throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_RELOAD_PLUGINS);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::getScalar(const char* name, uint8_t type) throw(Exception)
-{
-    checkStream();
-
-    stream->writeU8(Protocol::COMMAND_GET_SINGLE);
-    stream->writeString(name, strlen(name));
-    stream->writeU8(type);
-    if (!stream->flush()) checkStream();
-
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-int XPlane::getInt(const char* name) throw(Exception)
-{
-    getScalar(name, Protocol::TYPE_INT);
-
-    int value = stream->readS32();
-    checkStream();
-    return value;
-}
-
-//------------------------------------------------------------------------------
-
-float XPlane::getFloat(const char* name) throw(Exception)
-{
-    getScalar(name, Protocol::TYPE_FLOAT);
-
-    float value = stream->readFloat();
-    checkStream();
-    return value;
-}
-
-//------------------------------------------------------------------------------
-
-double XPlane::getDouble(const char* name) throw(Exception)
-{
-    getScalar(name, Protocol::TYPE_DOUBLE);
-
-    double value = stream->readDouble();
-    checkStream();
-    return value;
-}
-
-//------------------------------------------------------------------------------
-
-size_t XPlane::getArray(const char* name, uint8_t type,
-                        ssize_t length, size_t offset) throw(Exception)
-{
-    checkStream();
-
-    stream->writeU8(Protocol::COMMAND_GET_SINGLE);
-    stream->writeString(name, strlen(name));
-    stream->writeU8(type);
-    stream->writeS32(static_cast<int32_t>(length));
-    stream->writeS32(static_cast<int32_t>(offset));
-    if (!stream->flush()) checkStream();
-
-    uint8_t result = stream->readU8();
-    length = stream->readS32();
-    checkStream();
-    checkResult(result);
-
-    return length;
-}
-
-//------------------------------------------------------------------------------
-
-size_t XPlane::getFloatArray(const char* name, float* dest,
-                             size_t length, size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_FLOAT_ARRAY, length, offset);
-
-    if (!stream->read(dest, length*sizeof(float))) checkStream();
-
-    return length;
-}
-
-//------------------------------------------------------------------------------
-
-float* XPlane::getFloatArray(const char* name, size_t& length,
-                             size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_FLOAT_ARRAY, -1, offset);
-
-    auto_ptr<float> data(new float[length]);
-    if (!stream->read(data.get(), length*sizeof(float))) checkStream();
-    return data.release();
-}
-
-//------------------------------------------------------------------------------
-
-size_t XPlane::getIntArray(const char* name, int32_t* dest,
-                           size_t length, size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_INT_ARRAY, length, offset);
-
-    if (!stream->read(dest, length*sizeof(int32_t))) checkStream();
-
-    return length;
-}
-
-//------------------------------------------------------------------------------
-
-int32_t* XPlane::getIntArray(const char* name, size_t& length,
-                             size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_INT_ARRAY, -1, offset);
-
-    auto_ptr<int32_t> data(new int32_t[length]);
-    if (!stream->read(data.get(), length*sizeof(int32_t))) checkStream();
-    return data.release();
-}
-
-//------------------------------------------------------------------------------
-
-size_t XPlane::getByteArray(const char* name, uint8_t* dest,
-                            size_t length, size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_BYTE_ARRAY, length, offset);
-
-    if (!stream->read(dest, length*sizeof(uint8_t))) checkStream();
-
-    return length;
-}
-
-//------------------------------------------------------------------------------
-
-uint8_t* XPlane::getByteArray(const char* name, size_t& length,
-                              size_t offset) throw(Exception)
-{
-    length = getArray(name, Protocol::TYPE_BYTE_ARRAY, -1, offset);
-
-    auto_ptr<uint8_t> data(new uint8_t[length]);
-    if (!stream->read(data.get(), length*sizeof(uint8_t))) checkStream();
-    return data.release();
-}
-
-//------------------------------------------------------------------------------
-
-string XPlane::getString(const char* name, size_t offset) throw(Exception)
-{
-    size_t length = 0;
-    auto_ptr<uint8_t> data(getByteArray(name, length, offset));
-    return string(reinterpret_cast<char*>(data.get()));
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setScalar(const char* name, uint8_t type) throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_SET_SINGLE);
-    stream->writeString(name, strlen(name));
-    stream->writeU8(type);
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setInt(const char* name, int value) throw(Exception)
-{
-    setScalar(name, Protocol::TYPE_INT);
-    stream->writeS32(value);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setFloat(const char* name, float value) throw(Exception)
-{
-    setScalar(name, Protocol::TYPE_FLOAT);
-    stream->writeFloat(value);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setDouble(const char* name, double value) throw(Exception)
-{
-    setScalar(name, Protocol::TYPE_DOUBLE);
-    stream->writeDouble(value);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setArray(const char* name, uint8_t type, size_t length,
-                      size_t offset) throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_SET_SINGLE);
-    stream->writeString(name, strlen(name));
-    stream->writeU8(type);
-    stream->writeS32(static_cast<int32_t>(length));
-    stream->writeS32(static_cast<int32_t>(offset));
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setFloatArray(const char* name, const float* values, size_t length,
-                           size_t offset) throw(Exception)
-{
-    setArray(name, Protocol::TYPE_FLOAT_ARRAY, length, offset);
-    stream->write(values, length*sizeof(*values));
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setIntArray(const char* name, const int32_t* values, size_t length,
-                         size_t offset) throw(Exception)
-{
-    setArray(name, Protocol::TYPE_INT_ARRAY, length, offset);
-    stream->write(values, length*sizeof(*values));
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setByteArray(const char* name, const uint8_t* values, size_t length,
-                          size_t offset) throw(Exception)
-{
-    setArray(name, Protocol::TYPE_BYTE_ARRAY, length, offset);
-    stream->write(values, length*sizeof(*values));
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::setString(const char* name, const char* value, size_t length,
-                       size_t offset) throw(Exception)
-{
-    size_t valueLength = strlen(value);
-    if ((valueLength+1)>=length) {
-        setByteArray(name, reinterpret_cast<const uint8_t*>(value),
-                     length, offset);
-    } else {
-        auto_ptr<uint8_t> buffer(new uint8_t[length]);
-        memcpy(buffer.get(), value, valueLength);
-        memset(buffer.get() + valueLength, 0, length - valueLength);
-        setByteArray(name, buffer.get(), length, offset);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::showMessage(const char* message, float duration) throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_SHOW_MESSAGE);
-    stream->writeString(message);
-    stream->writeFloat(duration);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::registerHotkeys(const uint16_t* codes, size_t length)
-    throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_REGISTER_HOTKEYS);
-    stream->writeU32(length);
-    stream->write(codes, sizeof(uint16_t)*length);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::queryHotkeys(uint8_t* states, size_t length) throw(Exception)
-{
-    stream->writeU8(Protocol::COMMAND_QUERY_HOTKEYS);
-    stream->flush();
-    checkResult();
-
-    size_t count = stream->readU32();
-    checkStream();
-    stream->read(states, min(length, count));
-    if (length<count) {
-        while(length<count) {
-            stream->readU8();
-            ++length;
-        }
-    } else if (length>count) {
-        memset(states + count, 0, length - count);
-    }
-    checkStream();
-}
-
-//------------------------------------------------------------------------------
-
-void XPlane::unregisterHotkeys()
-{
-    stream->writeU8(Protocol::COMMAND_UNREGISTER_HOTKEYS);
-    stream->flush();
-    checkResult();
-}
-
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/XPlane.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/XPlane.h	(revision 66)
+++ src/client/c/hu/varadiistvan/xplra/XPlane.h	(revision 66)
@@ -0,0 +1,393 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#ifndef HU_VARADIISTVAN_XPLRA_XPLANE_H
+#define HU_VARADIISTVAN_XPLRA_XPLANE_H
+//-----------------------------------------------------------------------------
+
+#include "Exception.h"
+
+#include <hu/varadiistvan/scpl/io/Waiter.h>
+
+#include <set>
+
+#include <inttypes.h>
+
+//-----------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+class LocalClientSocket;
+class DataStream;
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace xplra {
+
+//------------------------------------------------------------------------------
+
+class MultiBuffer;
+class MultiGetter;
+class MultiSetter;
+
+//------------------------------------------------------------------------------
+
+/**
+ * The main class to access X-Plane.
+ *
+ * The calls are synchronous and not thread-safe.
+ */
+class XPlane
+{
+private:
+    /**
+     * Type for the set of multi-dataref buffers.
+     */
+    typedef std::set<MultiBuffer*> multiBuffers_t;
+
+    /**
+     * The waiter to use.
+     */
+    scpl::io::Waiter waiter;
+
+    /**
+     * The local client socket over which we are communicating with X-Plane.
+     */
+    scpl::io::LocalClientSocket* socket;
+
+    /**
+     * The data stream to handle the data conversions.
+     */
+    scpl::io::DataStream* stream;
+
+    /**
+     * The buffers created by this object.
+     */
+    multiBuffers_t multiBuffers;
+
+public:
+    /**
+     * Construct the object. It will not be connected to the simulator
+     * yet.
+     */
+    XPlane() throw();
+
+    /**
+     * Destroy the object. If connected, the connection will be
+     * closed. It destroys all existing buffers, so their references
+     * become invalid.
+     */
+    ~XPlane() throw();
+
+    /**
+     * Connect to the simulator.
+     */
+    void connect() throw(IOException);
+
+    /**
+     * Check if we are connected to the simulator.
+     */
+    bool isConnected() const throw();
+
+    /**
+     * Disconnect from the simulator.
+     */
+    void disconnect() throw();
+
+    /**
+     * Create a new getter of multiple datarefs and return a reference
+     * to it.
+     */
+    MultiGetter& createMultiGetter() throw();
+
+    /**
+     * Create a new setter of multiple datarefs and return a reference
+     * to it.
+     */
+    MultiSetter& createMultiSetter() throw();
+
+    /**
+     * Destroy the given getter or setter of multiple datarefs. As the
+     * buffer is unregistered, if it has been registered previously,
+     * and  unregistration may fail, this function might throw an
+     * exception.
+     *
+     * @return if the buffer was found and could be destroyed
+     */
+    bool destroyMultiBuffer(MultiBuffer& buffer) throw(Exception);
+
+    /**
+     * Get the versions of X-Plane, XPLM and the XPLRA plugin.
+     */
+    void getVersions(int& xplaneVersion, int& xplmVersion, int& xplraVersion) throw(Exception);
+
+    /**
+     * Reload the plugins loaded in X-Plane. After this the connection
+     * fails.
+     */
+    void reloadPlugins() throw(Exception);
+
+    /**
+     * Get the integer value of the dataref with the given name.
+     */
+    int getInt(const char* name) throw(Exception);
+
+    /**
+     * Get a float value.
+     */
+    float getFloat(const char* name) throw(Exception);
+
+    /**
+     * Get a double value.
+     */
+    double getDouble(const char* name) throw(Exception);
+
+    /**
+     * Get a possibly partial array of floats.
+     *
+     * @param name the name of the dataref
+     * @param dest the destination buffer
+     * @param length the length of the destination buffer
+     * @param offset the offset from which to get the array
+     *
+     * @return the number of values acquired actually
+     */
+    size_t getFloatArray(const char* name, float* dest,
+                         size_t length, size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a possibly partial array of floats. The result array will
+     * be created with a length needed to hold the returned value.
+     *
+     * @param name the name of the dataref
+     * @param length will contain the number of floats read
+     * @param offset the offset from which to get the array
+     */
+    float* getFloatArray(const char* name, size_t& length,
+                         size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a possibly partial array of integers.
+     *
+     * @param name the name of the dataref
+     * @param dest the destination buffer
+     * @param length the length of the destination buffer
+     * @param offset the offset from which to get the array
+     *
+     * @return the number of values acquired actually
+     */
+    size_t getIntArray(const char* name, int32_t* dest,
+                       size_t length, size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a possibly partial array of integers. The result array will
+     * be created with a length needed to hold the returned value.
+     *
+     * @param name the name of the dataref
+     * @param length will contain the number of integers read
+     * @param offset the offset from which to get the array
+     */
+    int32_t* getIntArray(const char* name, size_t& length,
+                         size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a possibly partial array of bytes.
+     *
+     * @param name the name of the dataref
+     * @param dest the destination buffer
+     * @param length the length of the destination buffer
+     * @param offset the offset from which to get the array
+     *
+     * @return the number of values acquired actually
+     */
+    size_t getByteArray(const char* name, uint8_t* dest,
+                        size_t length, size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a possibly partial array of bytes. The result array will
+     * be created with a length needed to hold the returned value.
+     *
+     * @param name the name of the dataref
+     * @param length will contain the number of bytes read on return
+     * @param offset the offset from which to get the array
+     */
+    uint8_t* getByteArray(const char* name, size_t& length,
+                          size_t offset = 0) throw(Exception);
+
+    /**
+     * Get a string. A string is a byte array.
+     */
+    std::string getString(const char* name, size_t offset = 0) throw(Exception);
+
+    /**
+     * Set the given dataref to the given integer value.
+     */
+    void setInt(const char* name, int value) throw(Exception);
+
+    /**
+     * Set the given dataref to the given float value.
+     */
+    void setFloat(const char* name, float value) throw(Exception);
+
+    /**
+     * Set the given dataref to the given double value.
+     */
+    void setDouble(const char* name, double value) throw(Exception);
+
+    /**
+     * Set the given float array to values in the given buffer.
+     */
+    void setFloatArray(const char* name, const float* values, size_t length,
+                       size_t offset = 0) throw(Exception);
+
+    /**
+     * Set the given integer array to values in the given buffer.
+     */
+    void setIntArray(const char* name, const int32_t* values, size_t length,
+                     size_t offset = 0) throw(Exception);
+
+    /**
+     * Set the given byte array to values in the given buffer.
+     */
+    void setByteArray(const char* name, const uint8_t* values, size_t length,
+                      size_t offset = 0) throw(Exception);
+
+    /**
+     * Set the given string to the given value. Since strings are byte
+     * arrays, and the bytes after the string should be zeroed, the
+     * length must be given. The string will be converted to a byte
+     * array of the given length, padded with 0s.
+     */
+    void setString(const char* name, const char* value, size_t length,
+                   size_t offset = 0) throw(Exception);
+
+    /**
+     * Show a textual message for a certain duration.
+     */
+    void showMessage(const char* message, float duration) throw(Exception);
+
+    /**
+     * Register the given hotkey codes for listening. If there is an
+     * existing set of hotkeys registered, those will be overwritten.
+     */
+    void registerHotkeys(const uint16_t* codes, size_t length) throw(Exception);
+
+    /**
+     * Query the registered hotkeys whether they were pressed.
+     */
+    void queryHotkeys(uint8_t* states, size_t length) throw(Exception);
+
+    /**
+     * Unregister the hotkeys.
+     */
+    void unregisterHotkeys();
+
+private:
+    /**
+     * Check if we have a stream and if it has not failed.
+     */
+    void checkStream() throw(NotConnectedException, IOException);
+
+    /**
+     * Check the given protocol result. If it signifies an error,
+     * throw a ProtocolException with the correct error code.
+     */
+    void checkResult(uint8_t result, bool hasParameter = false,
+                     long parameter = 0) throw(ProtocolException);
+
+    /**
+     * Read and check the result.  If it signifies an error,
+     * throw a ProtocolException with the correct error code. If there
+     * is some problem with the stream, an IOException is thrown.
+     */
+    void checkResult(bool multi = false) throw(ProtocolException, IOException);
+
+    /**
+     * Issue the command to get a single, scalar value. The result is
+     * also checked, but the value should be read by the caller.
+     */
+    void getScalar(const char* name, uint8_t type) throw(Exception);
+
+    /**
+     * Issue the command to get an array of values of the given
+     * type. It checks the result and retrieves the number of value
+     * items available.
+     *
+     * @return the number of value items available
+     */
+    size_t getArray(const char* name, uint8_t type,
+                    ssize_t length, size_t offset) throw(Exception);
+
+
+    /**
+     * Issue the command to set a scalar value of the given type.
+     */
+    void setScalar(const char* name, uint8_t type) throw(Exception);
+
+    /**
+     * Issue the command to set an array value of the given type.
+     */
+    void setArray(const char* name, uint8_t type, size_t length,
+                  size_t offset) throw(Exception);
+
+    friend class MultiBuffer;
+    friend class MultiGetter;
+    friend class MultiSetter;
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline XPlane::XPlane() throw() :
+    socket(0),
+    stream(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline bool XPlane::isConnected() const throw()
+{
+    return socket!=0;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+#endif // HU_VARADIISTVAN_XPLRA_XPLANE_H
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/XPlane.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/XPlane.h	(revision 54)
+++ 	(revision )
@@ -1,381 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-#ifndef HU_VARADIISTVAN_XPLRA_XPLANE_H
-#define HU_VARADIISTVAN_XPLRA_XPLANE_H
-//-----------------------------------------------------------------------------
-
-#include "Exception.h"
-
-#include <hu/varadiistvan/scpl/io/Waiter.h>
-
-#include <set>
-
-#include <inttypes.h>
-
-//-----------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace scpl { namespace io {
-
-class LocalClientSocket;
-class DataStream;
-
-} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-
-namespace hu { namespace varadiistvan { namespace xplra {
-
-//------------------------------------------------------------------------------
-
-class MultiBuffer;
-class MultiGetter;
-class MultiSetter;
-
-//------------------------------------------------------------------------------
-
-/**
- * The main class to access X-Plane.
- *
- * The calls are synchronous and not thread-safe.
- */
-class XPlane
-{
-private:
-    /**
-     * Type for the set of multi-dataref buffers.
-     */
-    typedef std::set<MultiBuffer*> multiBuffers_t;
-
-    /**
-     * The waiter to use.
-     */
-    scpl::io::Waiter waiter;
-
-    /**
-     * The local client socket over which we are communicating with X-Plane.
-     */
-    scpl::io::LocalClientSocket* socket;
-
-    /**
-     * The data stream to handle the data conversions.
-     */
-    scpl::io::DataStream* stream;
-
-    /**
-     * The buffers created by this object.
-     */
-    multiBuffers_t multiBuffers;
-
-public:
-    /**
-     * Construct the object. It will not be connected to the simulator
-     * yet.
-     */
-    XPlane() throw();
-
-    /**
-     * Destroy the object. If connected, the connection will be
-     * closed. It destroys all existing buffers, so their references
-     * become invalid.
-     */
-    ~XPlane() throw();
-
-    /**
-     * Connect to the simulator.
-     */
-    void connect() throw(IOException);
-
-    /**
-     * Check if we are connected to the simulator.
-     */
-    bool isConnected() const throw();
-
-    /**
-     * Disconnect from the simulator.
-     */
-    void disconnect() throw();
-
-    /**
-     * Create a new getter of multiple datarefs and return a reference
-     * to it.
-     */
-    MultiGetter& createMultiGetter() throw();
-
-    /**
-     * Create a new setter of multiple datarefs and return a reference
-     * to it.
-     */
-    MultiSetter& createMultiSetter() throw();
-
-    /**
-     * Destroy the given getter or setter of multiple datarefs. As the
-     * buffer is unregistered, if it has been registered previously,
-     * and  unregistration may fail, this function might throw an
-     * exception.
-     *
-     * @return if the buffer was found and could be destroyed
-     */
-    bool destroyMultiBuffer(MultiBuffer& buffer) throw(Exception);
-
-    /**
-     * Get the versions of X-Plane, XPLM and the XPLRA plugin.
-     */
-    void getVersions(int& xplaneVersion, int& xplmVersion, int& xplraVersion) throw(Exception);
-
-    /**
-     * Reload the plugins loaded in X-Plane. After this the connection
-     * fails.
-     */
-    void reloadPlugins() throw(Exception);
-
-    /**
-     * Get the integer value of the dataref with the given name.
-     */
-    int getInt(const char* name) throw(Exception);
-
-    /**
-     * Get a float value.
-     */
-    float getFloat(const char* name) throw(Exception);
-
-    /**
-     * Get a double value.
-     */
-    double getDouble(const char* name) throw(Exception);
-
-    /**
-     * Get a possibly partial array of floats.
-     *
-     * @param length the length of the destination buffer
-     * @param offset the offset from which to get the array
-     *
-     * @return the number of values acquired actually
-     */
-    size_t getFloatArray(const char* name, float* dest,
-                         size_t length, size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a possibly partial array of floats. The result array will
-     * be created with a length needed to hold the returned value.
-     *
-     * @param offset the offset from which to get the array
-     */
-    float* getFloatArray(const char* name, size_t& length,
-                         size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a possibly partial array of integers.
-     *
-     * @param length the length of the destination buffer
-     * @param offset the offset from which to get the array
-     *
-     * @return the number of values acquired actually
-     */
-    size_t getIntArray(const char* name, int32_t* dest,
-                       size_t length, size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a possibly partial array of integers. The result array will
-     * be created with a length needed to hold the returned value.
-     *
-     * @param offset the offset from which to get the array
-     */
-    int32_t* getIntArray(const char* name, size_t& length,
-                         size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a possibly partial array of bytes.
-     *
-     * @param length the length of the destination buffer
-     * @param offset the offset from which to get the array
-     *
-     * @return the number of values acquired actually
-     */
-    size_t getByteArray(const char* name, uint8_t* dest,
-                        size_t length, size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a possibly partial array of bytes. The result array will
-     * be created with a length needed to hold the returned value.
-     *
-     * @param offset the offset from which to get the array
-     */
-    uint8_t* getByteArray(const char* name, size_t& lengyh,
-                          size_t offset = 0) throw(Exception);
-
-    /**
-     * Get a string. A string is a byte array.
-     */
-    std::string getString(const char* name, size_t offset = 0) throw(Exception);
-
-    /**
-     * Set the given dataref to the given integer value.
-     */
-    void setInt(const char* name, int value) throw(Exception);
-
-    /**
-     * Set the given dataref to the given float value.
-     */
-    void setFloat(const char* name, float value) throw(Exception);
-
-    /**
-     * Set the given dataref to the given double value.
-     */
-    void setDouble(const char* name, double value) throw(Exception);
-
-    /**
-     * Set the given float array to values in the given buffer.
-     */
-    void setFloatArray(const char* name, const float* values, size_t length,
-                       size_t offset = 0) throw(Exception);
-
-    /**
-     * Set the given integer array to values in the given buffer.
-     */
-    void setIntArray(const char* name, const int32_t* values, size_t length,
-                     size_t offset = 0) throw(Exception);
-
-    /**
-     * Set the given byte array to values in the given buffer.
-     */
-    void setByteArray(const char* name, const uint8_t* values, size_t length,
-                      size_t offset = 0) throw(Exception);
-
-    /**
-     * Set the given string to the given value. Since strings are byte
-     * arrays, and the bytes after the string should be zeroed, the
-     * length must be given. The string will be converted to a byte
-     * array of the given length, padded with 0s.
-     */
-    void setString(const char* name, const char* value, size_t length,
-                   size_t offset = 0) throw(Exception);
-
-    /**
-     * Show a textual message for a certain duration.
-     */
-    void showMessage(const char* message, float duration) throw(Exception);
-
-    /**
-     * Register the given hotkey codes for listening. If there is an
-     * existing set of hotkeys registered, those will be overwritten.
-     */
-    void registerHotkeys(const uint16_t* codes, size_t length) throw(Exception);
-
-    /**
-     * Query the registered hotkeys whether they were pressed.
-     */
-    void queryHotkeys(uint8_t* states, size_t length) throw(Exception);
-
-    /**
-     * Unregister the hotkeys.
-     */
-    void unregisterHotkeys();
-
-private:
-    /**
-     * Check if we have a stream and if it has not failed.
-     */
-    void checkStream() throw(NotConnectedException, IOException);
-
-    /**
-     * Check the given protocol result. If it signifies an error,
-     * throw a ProtocolException with the correct error code.
-     */
-    void checkResult(uint8_t result, bool hasParameter = false,
-                     long parameter = 0) throw(ProtocolException);
-
-    /**
-     * Read and check the result.  If it signifies an error,
-     * throw a ProtocolException with the correct error code. If there
-     * is some problem with the stream, an IOException is thrown.
-     */
-    void checkResult(bool multi = false) throw(ProtocolException, IOException);
-
-    /**
-     * Issue the command to get a single, scalar value. The result is
-     * also checked, but the value should be read by the caller.
-     */
-    void getScalar(const char* name, uint8_t type) throw(Exception);
-
-    /**
-     * Issue the command to get an array of values of the given
-     * type. It checks the result and retrieves the number of value
-     * items available.
-     *
-     * @return the number of value items available
-     */
-    size_t getArray(const char* name, uint8_t type,
-                    ssize_t length, size_t offset) throw(Exception);
-
-
-    /**
-     * Issue the command to set a scalar value of the given type.
-     */
-    void setScalar(const char* name, uint8_t type) throw(Exception);
-
-    /**
-     * Issue the command to set an array value of the given type.
-     */
-    void setArray(const char* name, uint8_t type, size_t length,
-                  size_t offset) throw(Exception);
-
-    friend class MultiBuffer;
-    friend class MultiGetter;
-    friend class MultiSetter;
-};
-
-//------------------------------------------------------------------------------
-// Inline definitions
-//------------------------------------------------------------------------------
-
-inline XPlane::XPlane() throw() :
-    socket(0),
-    stream(0)
-{
-}
-
-//------------------------------------------------------------------------------
-
-inline bool XPlane::isConnected() const throw()
-{
-    return socket!=0;
-}
-
-//------------------------------------------------------------------------------
-
-} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
-
-//------------------------------------------------------------------------------
-#endif // HU_VARADIISTVAN_XPLRA_XPLANE_H
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/xplra.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.cc	(revision 58)
+++ src/client/c/hu/varadiistvan/xplra/xplra.cc	(revision 58)
@@ -0,0 +1,1389 @@
+// Copyright (c) 2013 by István Váradi
+
+// This file is part of XPLRA, a remote-access plugin for X-Plane
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "xplra.h"
+
+#include "XPlane.h"
+#include "MultiGetter.h"
+#include "MultiSetter.h"
+#include "Exception.h"
+
+#include <vector>
+#include <memory>
+
+#include <cstdio>
+#include <cassert>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::xplra::XPlane;
+using hu::varadiistvan::xplra::MultiBuffer;
+using hu::varadiistvan::xplra::MultiGetter;
+using hu::varadiistvan::xplra::MultiSetter;
+using hu::varadiistvan::xplra::Exception;
+using hu::varadiistvan::xplra::IOException;
+using hu::varadiistvan::xplra::ProtocolException;
+using hu::varadiistvan::xplra::NotConnectedException;
+using hu::varadiistvan::xplra::TypeMismatchException;
+using hu::varadiistvan::xplra::InvalidIDException;
+
+using std::exception;
+using std::string;
+using std::vector;
+using std::set;
+using std::auto_ptr;
+
+//------------------------------------------------------------------------------
+
+namespace {
+
+//------------------------------------------------------------------------------
+
+/**
+ * Template for handling slots.
+ */
+template <class Value>
+struct Slot
+{
+private:
+    /**
+     * The slots.
+     */
+    static std::vector< Slot<Value> > slots;
+
+    /**
+     * The index of the first free slot.
+     */
+    static int firstFree;
+
+public:
+    /**
+     * Add a new value.
+     *
+     * @return the ID of the new value
+     */
+    static int addValue(Value value) throw();
+
+    /**
+     * Get the value with the given ID.
+     */
+    static Value getValue(int valueID) throw();
+
+    /**
+     * Clear the value with the given ID.
+     */
+    static void clearValue(int valueID) throw();
+
+private:
+    /**
+     * Indicate if the slot contains a valid value or not.
+     */
+    bool valid;
+
+    union {
+        // The value, if the slot contains a value
+        Value value;
+
+        // The index of the next free slot
+        int nextFreeIndex;
+    };
+
+    /**
+     * Construct a slot with the given value
+     */
+    Slot(Value value) throw();
+
+    /**
+     * Set the value and return the former next free index. It
+     * should be called for a slot with no value.
+     */
+    int setValue(Value value) throw();
+
+    /**
+     * Get the value if this slot contains a value. Otherwise 0 is
+     * returned (converted to value).
+     */
+    Value getValue() const throw();
+
+    /**
+     * Clear the value and set the given next free index.
+     */
+    void clear(int nextFreeIndex) throw();
+};
+
+//------------------------------------------------------------------------------
+
+template <class Value> vector< Slot<Value> > Slot<Value>::slots;
+
+//------------------------------------------------------------------------------
+
+template <class Value> int Slot<Value>::firstFree = -1;
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline Slot<Value>::Slot(Value value) throw() :
+    valid(true)
+{
+    this->value = value;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline int Slot<Value>::setValue(Value value) throw()
+{
+    assert(!valid);
+    int nextFreeIndex = this->nextFreeIndex;
+    this->value = value;
+    valid = true;
+    return nextFreeIndex;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline Value Slot<Value>::getValue() const throw()
+{
+    return valid ? value : static_cast<Value>(0);
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+inline void Slot<Value>::clear(int nextFreeIndex) throw()
+{
+    assert(valid);
+    valid = false;
+    this->nextFreeIndex = nextFreeIndex;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+int Slot<Value>::addValue(Value value) throw()
+{
+    int id = firstFree;
+    if (id<0) {
+        id = slots.size();
+        slots.push_back(Slot<Value>(value));
+    } else {
+        Slot& slot = slots[id];
+        firstFree = slot.setValue(value);
+    }
+
+    return id;
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+Value Slot<Value>::getValue(int valueID) throw()
+{
+    size_t index = static_cast<size_t>(valueID);
+    return (index<slots.size()) ?
+        slots[index].getValue() : static_cast<Value>(0);
+}
+
+//------------------------------------------------------------------------------
+
+template <class Value>
+void Slot<Value>::clearValue(int valueID) throw()
+{
+    size_t index = static_cast<size_t>(valueID);
+    if (index<slots.size()) {
+        slots[index].clear(firstFree);
+        firstFree = index;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+typedef Slot<MultiBuffer*> MultiBufferSlot;
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+/**
+ * Information about a connection.
+ */
+class Connection : public XPlane
+{
+private:
+    /**
+     * Type for the set of multi-dataref buffers belonging to this connection.
+     */
+    typedef std::set<int> multiBufferIDs_t;
+
+public:
+    /**
+     * Get the connection for the given multi-dataref buffer.
+     */
+    static Connection& get(const MultiBuffer& buffer) throw();
+
+private:
+    /**
+     * The last error code.
+     */
+    int lastErrorCode;
+
+    /**
+     * The last error subcode.
+     */
+    unsigned long lastErrorSubCode;
+
+    /**
+     * The string of the last error
+     */
+    std::string lastErrorString;
+
+    /**
+     * The set of multi-dataref buffers belonging to this connection.
+     */
+    multiBufferIDs_t multiBufferIDs;
+
+public:
+    /**
+     * Construct the connection
+     */
+    Connection() throw();
+
+    /**
+     * Destroy the connection.
+     */
+    ~Connection() throw();
+
+    /**
+     * Handle the currently pending exception.
+     */
+    void handleException() throw();
+
+    /**
+     * Get the last error code.
+     */
+    int getLastError(unsigned long* lastErrorSubCode) const throw();
+
+    /**
+     * Get the string representation of the last error code.
+     */
+    const char* getLastErrorString() const throw();
+
+    /**
+     * Clear the last error code.
+     */
+    void clearLastError() throw();
+
+    /**
+     * Create a multi-dataref getter object and register it in a slot.
+     *
+     * @return the ID of the new getter.
+     */
+    int createMultiGetter() throw();
+
+    /**
+     * Create a multi-dataref setter object and register it in a slot.
+     *
+     * @return the ID of the new setter.
+     */
+    int createMultiSetter() throw();
+
+    /**
+     * Destroy the multi-dataref buffer with the given ID.
+     *
+     * @param bufferID the ID of the buffer. It should be a valid ID,
+     * that belongs to this connection.
+     *
+     * @return whether the buffer was found and could be destroyed.
+     */
+    bool destroyMultiBuffer(int bufferID) throw(Exception);
+};
+
+//------------------------------------------------------------------------------
+
+inline Connection& Connection::get(const MultiBuffer& buffer) throw()
+{
+    return static_cast<Connection&>(buffer.getXPlane());
+}
+
+//------------------------------------------------------------------------------
+
+inline Connection::Connection() throw() :
+    lastErrorCode(0),
+    lastErrorSubCode(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+Connection::~Connection() throw()
+{
+    for(multiBufferIDs_t::iterator i = multiBufferIDs.begin();
+        i!=multiBufferIDs.end(); ++i)
+    {
+        MultiBufferSlot::clearValue(*i);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void Connection::handleException() throw()
+{
+    try {
+        throw;
+    } catch(const IOException& e) {
+        lastErrorCode = ERROR_IO;
+        lastErrorSubCode = e.getErrorCode();
+        lastErrorString = e.what();
+    } catch(const ProtocolException& e) {
+        lastErrorCode = ERROR_PROTOCOL;
+        lastErrorSubCode = static_cast<unsigned long>(e.getErrorCode());
+        lastErrorString = e.what();
+    } catch(const NotConnectedException& e) {
+        lastErrorCode = ERROR_NOT_CONNECTED;
+        lastErrorSubCode = 0;
+        lastErrorString = e.what();
+    } catch(const TypeMismatchException& e) {
+        lastErrorCode = ERROR_TYPE_MISMATCH;
+        lastErrorSubCode = 0;
+        lastErrorString = e.what();
+    } catch(const InvalidIDException& e) {
+        lastErrorCode = ERROR_INVALID_ID;
+        lastErrorSubCode = 0;
+        lastErrorString = e.what();
+    } catch(const exception& e) {
+        lastErrorCode = ERROR_OTHER;
+        lastErrorSubCode = 0;
+        lastErrorString = e.what();
+    } catch(...) {
+        lastErrorCode = ERROR_OTHER;
+        lastErrorSubCode = 0;
+        lastErrorString = "<Exception of an unknown type>";
+    }
+}
+
+//------------------------------------------------------------------------------
+
+inline int Connection::getLastError(unsigned long* lastErrorSubCode)
+    const throw()
+{
+    if (lastErrorSubCode!=0) *lastErrorSubCode = this->lastErrorSubCode;
+    return lastErrorCode;
+}
+
+//------------------------------------------------------------------------------
+
+inline const char* Connection::getLastErrorString() const throw()
+{
+    return (lastErrorCode==ERROR_NONE) ? 0 : lastErrorString.c_str();
+}
+
+//------------------------------------------------------------------------------
+
+inline void Connection::clearLastError() throw()
+{
+    lastErrorCode = ERROR_NONE;
+    lastErrorSubCode = 0;
+    lastErrorString.clear();
+}
+
+//------------------------------------------------------------------------------
+
+inline int Connection::createMultiGetter() throw()
+{
+    MultiGetter& getter = XPlane::createMultiGetter();
+    return MultiBufferSlot::addValue(&getter);
+}
+
+//------------------------------------------------------------------------------
+
+inline int Connection::createMultiSetter() throw()
+{
+    MultiSetter& setter = XPlane::createMultiSetter();
+    return MultiBufferSlot::addValue(&setter);
+}
+
+//------------------------------------------------------------------------------
+
+bool Connection::destroyMultiBuffer(int bufferID) throw(Exception)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return false;
+
+    if (XPlane::destroyMultiBuffer(*buffer)) {
+        multiBufferIDs.erase(bufferID);
+        MultiBufferSlot::clearValue(bufferID);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+/**
+ * Slot for connections.
+ */
+typedef Slot<Connection*> ConnectionSlot;
+
+//------------------------------------------------------------------------------
+
+} /* anonymous namespace */
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_get_last_error(int connectionID, unsigned long* subCode)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? -1 : connection->getLastError(subCode);
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" const char* xplra_get_last_error_string(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? 0 : connection->getLastErrorString();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" void xplra_clear_last_error(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection!=0) connection->clearLastError();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_connect()
+{
+    try {
+        auto_ptr<Connection> connection(new Connection());
+        connection->connect();
+        return ConnectionSlot::addValue(connection.release());
+    } catch(...) {
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"int xplra_get_versions(int connectionID,
+                                 int* xplaneVersion, int* xplmVersion,
+                                 int* xplraVersion)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        connection->getVersions(*xplaneVersion, *xplmVersion, *xplraVersion);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_reload_plugins(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        connection->reloadPlugins();
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_get_int(int* value, int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        *value = connection->getInt(name);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_get_float(float* value, int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        *value = connection->getFloat(name);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_get_double(double* value,
+                                int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        *value = connection->getDouble(name);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" ssize_t xplra_get_float_array(float* dest, size_t length, size_t offset,
+                                         int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        return connection->getFloatArray(name, dest, length, offset);
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" float* xplra_get_float_array_new(size_t* length, size_t offset,
+                                            int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        return connection->getFloatArray(name, *length, offset);
+    } catch (...) {
+        connection->handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" ssize_t xplra_get_int_array(int32_t* dest, size_t length, size_t offset,
+                                       int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        return connection->getIntArray(name, dest, length, offset);
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int32_t* xplra_get_int_array_new(size_t* length, size_t offset,
+                                            int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        return connection->getIntArray(name, *length, offset);
+    } catch (...) {
+        connection->handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" ssize_t xplra_get_byte_array(void* dest, size_t length, size_t offset,
+                                        int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+    try {
+        return connection->getByteArray(name, reinterpret_cast<uint8_t*>(dest),
+                                        length, offset);
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" uint8_t* xplra_get_byte_array_new(size_t* length, size_t offset,
+                                             int connectionID, const char* name)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        return connection->getByteArray(name, *length, offset);
+    } catch (...) {
+        connection->handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_set_int(int connectionID, const char* name, int value)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setInt(name, value);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_set_float(int connectionID, const char* name, float value)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setFloat(name, value);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_set_double(int connectionID, const char* name,
+                                double value)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setDouble(name, value);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_set_float_array(int connectionID, const char* name,
+                                     const float* values,
+                                     size_t length, size_t offset)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setFloatArray(name, values, length, offset);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_set_int_array(int connectionID, const char* name,
+                                   const int32_t* values,
+                                   size_t length, size_t offset)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setIntArray(name, values, length, offset);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_set_byte_array(int connectionID, const char* name,
+                                    const void* values,
+                                    size_t length, size_t offset)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setByteArray(name, reinterpret_cast<const uint8_t*>(values),
+                                 length, offset);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_set_string(int connectionID, const char* name,
+                                const char* value,
+                                size_t length, size_t offset)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return 0;
+    try {
+        connection->setString(name, value, length, offset);
+        return 0;
+    } catch (...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_multi_create_getter(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? -1 : connection->createMultiGetter();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_multi_create_setter(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    return (connection==0) ? -1 : connection->createMultiSetter();
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" size_t xplra_multi_add_int(int bufferID, const char* name)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addInt(name);
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" size_t xplra_multi_add_float(int bufferID, const char* name)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addFloat(name);
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" size_t xplra_multi_add_double(int bufferID, const char* name)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addDouble(name);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" size_t xplra_multi_add_float_array(int bufferID, const char* name,
+                                              size_t length, size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ?
+        INVALID_DATAREF_ID : buffer->addFloatArray(name, length, offset);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" size_t xplra_multi_add_int_array(int bufferID, const char* name,
+                                            size_t length, size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ?
+        INVALID_DATAREF_ID : buffer->addIntArray(name, length, offset);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" size_t xplra_multi_add_byte_array(int bufferID, const char* name,
+                                             size_t length, size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ?
+        INVALID_DATAREF_ID : buffer->addByteArray(name, length, offset);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_finalize(int bufferID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ? -1 : (buffer->finalize() ? 1 : 0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_register(int bufferID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->registerInXPlane();
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_unregister(int bufferID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->unregisterFromXPlane();
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_unregister_safely(int bufferID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    return (buffer==0) ? -1 : (buffer->unregisterSafelyFromXPlane() ? 1 : 0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_execute(int bufferID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->execute();
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_multi_set_int(int bufferID, size_t datarefID, int value)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->setInt(datarefID, value);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_multi_get_int(int* dest, int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        *dest = buffer->getInt(datarefID);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const int32_t* xplra_multi_get_int_const_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getIntRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+int32_t* xplra_multi_get_int_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getIntRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"
+int xplra_multi_set_float(int bufferID, size_t datarefID, float value)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->setFloat(datarefID, value);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+int xplra_multi_get_float(float* dest, int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        *dest = buffer->getFloat(datarefID);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const float* xplra_multi_get_float_const_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getFloatRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+float* xplra_multi_get_float_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getFloatRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"
+int xplra_multi_set_double(int bufferID, size_t datarefID, double value)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        buffer->setDouble(datarefID, value);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+int xplra_multi_get_double(double* dest, int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        *dest = buffer->getDouble(datarefID);
+        return 0;
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const double* xplra_multi_get_double_const_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getDoubleRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+double* xplra_multi_get_double_ptr(int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return &(buffer->getDoubleRef(datarefID));
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"
+ssize_t xplra_multi_set_float_array(int bufferID, size_t datarefID,
+                                    const float* value, size_t length,
+                                    size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->setFloatArray(datarefID, value, length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+ssize_t xplra_multi_get_float_array(float* value,
+                                    size_t length, size_t offset,
+                                    int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->getFloatArray(datarefID, value, length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const float* xplra_multi_get_float_array_ptr(int bufferID, size_t datarefID,
+                                             size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return buffer->getFloatArray(datarefID, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"
+ssize_t xplra_multi_set_int_array(int bufferID, size_t datarefID,
+                                  const int32_t* value, size_t length,
+                                  size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->setIntArray(datarefID, value, length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+ssize_t xplra_multi_get_int_array(int32_t* value,
+                                  size_t length, size_t offset,
+                                  int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->getIntArray(datarefID, value, length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const int32_t* xplra_multi_get_int_array_ptr(int bufferID, size_t datarefID,
+                                             size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return buffer->getIntArray(datarefID, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C"
+ssize_t xplra_multi_set_byte_array(int bufferID, size_t datarefID,
+                                   const void* value, size_t length,
+                                   size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->setByteArray(datarefID,
+                                    reinterpret_cast<const uint8_t*>(value),
+                                    length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+ssize_t xplra_multi_get_byte_array(void* value,
+                                   size_t length, size_t offset,
+                                   int bufferID, size_t datarefID)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->getByteArray(datarefID,
+                                    reinterpret_cast<uint8_t*>(value),
+                                    length, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const uint8_t* xplra_multi_get_byte_array_ptr(int bufferID, size_t datarefID,
+                                              size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return buffer->getByteArray(datarefID, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" ssize_t xplra_multi_set_string(int bufferID, size_t datarefID,
+                                          const char* value, size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return -1;
+    try {
+        return buffer->setString(datarefID, value, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C"
+const char* xplra_multi_get_string_ptr(int bufferID, size_t datarefID,
+                                       size_t offset)
+{
+    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
+    if (buffer==0) return 0;
+    try {
+        return buffer->getStringPtr(datarefID, offset);
+    } catch (...) {
+        Connection::get(*buffer).handleException();
+        return 0;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_multi_destroy_buffer(int connectionID, int bufferID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        return connection->destroyMultiBuffer(bufferID) ? 0 : -1;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_show_message(int connectionID,
+                                  const char* message, float duration)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        connection->showMessage(message, duration);
+        return 0;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_register_hotkeys(int connectionID,
+                                      const uint16_t* codes, size_t length)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        connection->registerHotkeys(codes, length);
+        return 0;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_query_hotkeys(int connectionID,
+                                   uint8_t* states, size_t length)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        connection->queryHotkeys(states, length);
+        return 0;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+
+extern "C" int xplra_unregister_hotkeys(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    try {
+        connection->unregisterHotkeys();
+        return 0;
+    } catch(...) {
+        connection->handleException();
+        return -1;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+extern "C" int xplra_disconnect(int connectionID)
+{
+    Connection* connection = ConnectionSlot::getValue(connectionID);
+    if (connection==0) return -1;
+
+    ConnectionSlot::clearValue(connectionID);
+    connection->disconnect();
+    delete connection;
+
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/client/c/hu/varadiistvan/xplra/xplra.cc
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.cc	(revision 58)
+++ 	(revision )
@@ -1,1389 +1,0 @@
-// Copyright (c) 2013 by István Váradi
-
-// This file is part of XPLRA, a remote-access plugin for X-Plane
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The views and conclusions contained in the software and documentation are those
-// of the authors and should not be interpreted as representing official policies,
-// either expressed or implied, of the FreeBSD Project.
-
-//------------------------------------------------------------------------------
-
-#include "xplra.h"
-
-#include "XPlane.h"
-#include "MultiGetter.h"
-#include "MultiSetter.h"
-#include "Exception.h"
-
-#include <vector>
-#include <memory>
-
-#include <cstdio>
-#include <cassert>
-
-//------------------------------------------------------------------------------
-
-using hu::varadiistvan::xplra::XPlane;
-using hu::varadiistvan::xplra::MultiBuffer;
-using hu::varadiistvan::xplra::MultiGetter;
-using hu::varadiistvan::xplra::MultiSetter;
-using hu::varadiistvan::xplra::Exception;
-using hu::varadiistvan::xplra::IOException;
-using hu::varadiistvan::xplra::ProtocolException;
-using hu::varadiistvan::xplra::NotConnectedException;
-using hu::varadiistvan::xplra::TypeMismatchException;
-using hu::varadiistvan::xplra::InvalidIDException;
-
-using std::exception;
-using std::string;
-using std::vector;
-using std::set;
-using std::auto_ptr;
-
-//------------------------------------------------------------------------------
-
-namespace {
-
-//------------------------------------------------------------------------------
-
-/**
- * Template for handling slots.
- */
-template <class Value>
-struct Slot
-{
-private:
-    /**
-     * The slots.
-     */
-    static std::vector< Slot<Value> > slots;
-
-    /**
-     * The index of the first free slot.
-     */
-    static int firstFree;
-
-public:
-    /**
-     * Add a new value.
-     *
-     * @return the ID of the new value
-     */
-    static int addValue(Value value) throw();
-
-    /**
-     * Get the value with the given ID.
-     */
-    static Value getValue(int valueID) throw();
-
-    /**
-     * Clear the value with the given ID.
-     */
-    static void clearValue(int valueID) throw();
-
-private:
-    /**
-     * Indicate if the slot contains a valid value or not.
-     */
-    bool valid;
-
-    union {
-        // The value, if the slot contains a value
-        Value value;
-
-        // The index of the next free slot
-        int nextFreeIndex;
-    };
-
-    /**
-     * Construct a slot with the given value
-     */
-    Slot(Value value) throw();
-
-    /**
-     * Set the value and return the former next free index. It
-     * should be called for a slot with no value.
-     */
-    int setValue(Value value) throw();
-
-    /**
-     * Get the value if this slot contains a value. Otherwise 0 is
-     * returned (converted to value).
-     */
-    Value getValue() const throw();
-
-    /**
-     * Clear the value and set the given next free index.
-     */
-    void clear(int nextFreeIndex) throw();
-};
-
-//------------------------------------------------------------------------------
-
-template <class Value> vector< Slot<Value> > Slot<Value>::slots;
-
-//------------------------------------------------------------------------------
-
-template <class Value> int Slot<Value>::firstFree = -1;
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline Slot<Value>::Slot(Value value) throw() :
-    valid(true)
-{
-    this->value = value;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline int Slot<Value>::setValue(Value value) throw()
-{
-    assert(!valid);
-    int nextFreeIndex = this->nextFreeIndex;
-    this->value = value;
-    valid = true;
-    return nextFreeIndex;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline Value Slot<Value>::getValue() const throw()
-{
-    return valid ? value : static_cast<Value>(0);
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-inline void Slot<Value>::clear(int nextFreeIndex) throw()
-{
-    assert(valid);
-    valid = false;
-    this->nextFreeIndex = nextFreeIndex;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-int Slot<Value>::addValue(Value value) throw()
-{
-    int id = firstFree;
-    if (id<0) {
-        id = slots.size();
-        slots.push_back(Slot<Value>(value));
-    } else {
-        Slot& slot = slots[id];
-        firstFree = slot.setValue(value);
-    }
-
-    return id;
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-Value Slot<Value>::getValue(int valueID) throw()
-{
-    size_t index = static_cast<size_t>(valueID);
-    return (index<slots.size()) ?
-        slots[index].getValue() : static_cast<Value>(0);
-}
-
-//------------------------------------------------------------------------------
-
-template <class Value>
-void Slot<Value>::clearValue(int valueID) throw()
-{
-    size_t index = static_cast<size_t>(valueID);
-    if (index<slots.size()) {
-        slots[index].clear(firstFree);
-        firstFree = index;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-typedef Slot<MultiBuffer*> MultiBufferSlot;
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-/**
- * Information about a connection.
- */
-class Connection : public XPlane
-{
-private:
-    /**
-     * Type for the set of multi-dataref buffers belonging to this connection.
-     */
-    typedef std::set<int> multiBufferIDs_t;
-
-public:
-    /**
-     * Get the connection for the given multi-dataref buffer.
-     */
-    static Connection& get(const MultiBuffer& buffer) throw();
-
-private:
-    /**
-     * The last error code.
-     */
-    int lastErrorCode;
-
-    /**
-     * The last error subcode.
-     */
-    unsigned long lastErrorSubCode;
-
-    /**
-     * The string of the last error
-     */
-    std::string lastErrorString;
-
-    /**
-     * The set of multi-dataref buffers belonging to this connection.
-     */
-    multiBufferIDs_t multiBufferIDs;
-
-public:
-    /**
-     * Construct the connection
-     */
-    Connection() throw();
-
-    /**
-     * Destroy the connection.
-     */
-    ~Connection() throw();
-
-    /**
-     * Handle the currently pending exception.
-     */
-    void handleException() throw();
-
-    /**
-     * Get the last error code.
-     */
-    int getLastError(unsigned long* lastErrorSubCode) const throw();
-
-    /**
-     * Get the string representation of the last error code.
-     */
-    const char* getLastErrorString() const throw();
-
-    /**
-     * Clear the last error code.
-     */
-    void clearLastError() throw();
-
-    /**
-     * Create a multi-dataref getter object and register it in a slot.
-     *
-     * @return the ID of the new getter.
-     */
-    int createMultiGetter() throw();
-
-    /**
-     * Create a multi-dataref setter object and register it in a slot.
-     *
-     * @return the ID of the new setter.
-     */
-    int createMultiSetter() throw();
-
-    /**
-     * Destroy the multi-dataref buffer with the given ID.
-     *
-     * @param bufferID the ID of the buffer. It should be a valid ID,
-     * that belongs to this connection.
-     *
-     * @return whether the buffer was found and could be destroyed.
-     */
-    bool destroyMultiBuffer(int bufferID) throw(Exception);
-};
-
-//------------------------------------------------------------------------------
-
-inline Connection& Connection::get(const MultiBuffer& buffer) throw()
-{
-    return static_cast<Connection&>(buffer.getXPlane());
-}
-
-//------------------------------------------------------------------------------
-
-inline Connection::Connection() throw() :
-    lastErrorCode(0),
-    lastErrorSubCode(0)
-{
-}
-
-//------------------------------------------------------------------------------
-
-Connection::~Connection() throw()
-{
-    for(multiBufferIDs_t::iterator i = multiBufferIDs.begin();
-        i!=multiBufferIDs.end(); ++i)
-    {
-        MultiBufferSlot::clearValue(*i);
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void Connection::handleException() throw()
-{
-    try {
-        throw;
-    } catch(const IOException& e) {
-        lastErrorCode = ERROR_IO;
-        lastErrorSubCode = e.getErrorCode();
-        lastErrorString = e.what();
-    } catch(const ProtocolException& e) {
-        lastErrorCode = ERROR_PROTOCOL;
-        lastErrorSubCode = static_cast<unsigned long>(e.getErrorCode());
-        lastErrorString = e.what();
-    } catch(const NotConnectedException& e) {
-        lastErrorCode = ERROR_NOT_CONNECTED;
-        lastErrorSubCode = 0;
-        lastErrorString = e.what();
-    } catch(const TypeMismatchException& e) {
-        lastErrorCode = ERROR_TYPE_MISMATCH;
-        lastErrorSubCode = 0;
-        lastErrorString = e.what();
-    } catch(const InvalidIDException& e) {
-        lastErrorCode = ERROR_INVALID_ID;
-        lastErrorSubCode = 0;
-        lastErrorString = e.what();
-    } catch(const exception& e) {
-        lastErrorCode = ERROR_OTHER;
-        lastErrorSubCode = 0;
-        lastErrorString = e.what();
-    } catch(...) {
-        lastErrorCode = ERROR_OTHER;
-        lastErrorSubCode = 0;
-        lastErrorString = "<Exception of an unknown type>";
-    }
-}
-
-//------------------------------------------------------------------------------
-
-inline int Connection::getLastError(unsigned long* lastErrorSubCode)
-    const throw()
-{
-    if (lastErrorSubCode!=0) *lastErrorSubCode = this->lastErrorSubCode;
-    return lastErrorCode;
-}
-
-//------------------------------------------------------------------------------
-
-inline const char* Connection::getLastErrorString() const throw()
-{
-    return (lastErrorCode==ERROR_NONE) ? 0 : lastErrorString.c_str();
-}
-
-//------------------------------------------------------------------------------
-
-inline void Connection::clearLastError() throw()
-{
-    lastErrorCode = ERROR_NONE;
-    lastErrorSubCode = 0;
-    lastErrorString.clear();
-}
-
-//------------------------------------------------------------------------------
-
-inline int Connection::createMultiGetter() throw()
-{
-    MultiGetter& getter = XPlane::createMultiGetter();
-    return MultiBufferSlot::addValue(&getter);
-}
-
-//------------------------------------------------------------------------------
-
-inline int Connection::createMultiSetter() throw()
-{
-    MultiSetter& setter = XPlane::createMultiSetter();
-    return MultiBufferSlot::addValue(&setter);
-}
-
-//------------------------------------------------------------------------------
-
-bool Connection::destroyMultiBuffer(int bufferID) throw(Exception)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return false;
-
-    if (XPlane::destroyMultiBuffer(*buffer)) {
-        multiBufferIDs.erase(bufferID);
-        MultiBufferSlot::clearValue(bufferID);
-        return true;
-    } else {
-        return false;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-/**
- * Slot for connections.
- */
-typedef Slot<Connection*> ConnectionSlot;
-
-//------------------------------------------------------------------------------
-
-} /* anonymous namespace */
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_get_last_error(int connectionID, unsigned long* subCode)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    return (connection==0) ? -1 : connection->getLastError(subCode);
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" const char* xplra_get_last_error_string(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    return (connection==0) ? 0 : connection->getLastErrorString();
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" void xplra_clear_last_error(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection!=0) connection->clearLastError();
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_connect()
-{
-    try {
-        auto_ptr<Connection> connection(new Connection());
-        connection->connect();
-        return ConnectionSlot::addValue(connection.release());
-    } catch(...) {
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"int xplra_get_versions(int connectionID,
-                                 int* xplaneVersion, int* xplmVersion,
-                                 int* xplraVersion)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        connection->getVersions(*xplaneVersion, *xplmVersion, *xplraVersion);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_reload_plugins(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        connection->reloadPlugins();
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_get_int(int* value, int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        *value = connection->getInt(name);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_get_float(float* value, int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        *value = connection->getFloat(name);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_get_double(double* value,
-                                int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        *value = connection->getDouble(name);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" ssize_t xplra_get_float_array(float* dest, size_t length, size_t offset,
-                                         int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        return connection->getFloatArray(name, dest, length, offset);
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" float* xplra_get_float_array_new(size_t* length, size_t offset,
-                                            int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        return connection->getFloatArray(name, *length, offset);
-    } catch (...) {
-        connection->handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" ssize_t xplra_get_int_array(int32_t* dest, size_t length, size_t offset,
-                                       int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        return connection->getIntArray(name, dest, length, offset);
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int32_t* xplra_get_int_array_new(size_t* length, size_t offset,
-                                            int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        return connection->getIntArray(name, *length, offset);
-    } catch (...) {
-        connection->handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" ssize_t xplra_get_byte_array(void* dest, size_t length, size_t offset,
-                                        int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-    try {
-        return connection->getByteArray(name, reinterpret_cast<uint8_t*>(dest),
-                                        length, offset);
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" uint8_t* xplra_get_byte_array_new(size_t* length, size_t offset,
-                                             int connectionID, const char* name)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        return connection->getByteArray(name, *length, offset);
-    } catch (...) {
-        connection->handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_set_int(int connectionID, const char* name, int value)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setInt(name, value);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_set_float(int connectionID, const char* name, float value)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setFloat(name, value);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_set_double(int connectionID, const char* name,
-                                double value)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setDouble(name, value);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_set_float_array(int connectionID, const char* name,
-                                     const float* values,
-                                     size_t length, size_t offset)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setFloatArray(name, values, length, offset);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_set_int_array(int connectionID, const char* name,
-                                   const int32_t* values,
-                                   size_t length, size_t offset)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setIntArray(name, values, length, offset);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_set_byte_array(int connectionID, const char* name,
-                                    const void* values,
-                                    size_t length, size_t offset)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setByteArray(name, reinterpret_cast<const uint8_t*>(values),
-                                 length, offset);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_set_string(int connectionID, const char* name,
-                                const char* value,
-                                size_t length, size_t offset)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return 0;
-    try {
-        connection->setString(name, value, length, offset);
-        return 0;
-    } catch (...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_multi_create_getter(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    return (connection==0) ? -1 : connection->createMultiGetter();
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_multi_create_setter(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    return (connection==0) ? -1 : connection->createMultiSetter();
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" size_t xplra_multi_add_int(int bufferID, const char* name)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addInt(name);
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" size_t xplra_multi_add_float(int bufferID, const char* name)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addFloat(name);
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" size_t xplra_multi_add_double(int bufferID, const char* name)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ? INVALID_DATAREF_ID : buffer->addDouble(name);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" size_t xplra_multi_add_float_array(int bufferID, const char* name,
-                                              size_t length, size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ?
-        INVALID_DATAREF_ID : buffer->addFloatArray(name, length, offset);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" size_t xplra_multi_add_int_array(int bufferID, const char* name,
-                                            size_t length, size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ?
-        INVALID_DATAREF_ID : buffer->addIntArray(name, length, offset);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" size_t xplra_multi_add_byte_array(int bufferID, const char* name,
-                                             size_t length, size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ?
-        INVALID_DATAREF_ID : buffer->addByteArray(name, length, offset);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_finalize(int bufferID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ? -1 : (buffer->finalize() ? 1 : 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_register(int bufferID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->registerInXPlane();
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_unregister(int bufferID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->unregisterFromXPlane();
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_unregister_safely(int bufferID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    return (buffer==0) ? -1 : (buffer->unregisterSafelyFromXPlane() ? 1 : 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_execute(int bufferID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->execute();
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_multi_set_int(int bufferID, size_t datarefID, int value)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->setInt(datarefID, value);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_multi_get_int(int* dest, int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        *dest = buffer->getInt(datarefID);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const int32_t* xplra_multi_get_int_const_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getIntRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-int32_t* xplra_multi_get_int_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getIntRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"
-int xplra_multi_set_float(int bufferID, size_t datarefID, float value)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->setFloat(datarefID, value);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-int xplra_multi_get_float(float* dest, int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        *dest = buffer->getFloat(datarefID);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const float* xplra_multi_get_float_const_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getFloatRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-float* xplra_multi_get_float_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getFloatRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"
-int xplra_multi_set_double(int bufferID, size_t datarefID, double value)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        buffer->setDouble(datarefID, value);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-int xplra_multi_get_double(double* dest, int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        *dest = buffer->getDouble(datarefID);
-        return 0;
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const double* xplra_multi_get_double_const_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getDoubleRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-double* xplra_multi_get_double_ptr(int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return &(buffer->getDoubleRef(datarefID));
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"
-ssize_t xplra_multi_set_float_array(int bufferID, size_t datarefID,
-                                    const float* value, size_t length,
-                                    size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->setFloatArray(datarefID, value, length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-ssize_t xplra_multi_get_float_array(float* value,
-                                    size_t length, size_t offset,
-                                    int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->getFloatArray(datarefID, value, length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const float* xplra_multi_get_float_array_ptr(int bufferID, size_t datarefID,
-                                             size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return buffer->getFloatArray(datarefID, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"
-ssize_t xplra_multi_set_int_array(int bufferID, size_t datarefID,
-                                  const int32_t* value, size_t length,
-                                  size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->setIntArray(datarefID, value, length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-ssize_t xplra_multi_get_int_array(int32_t* value,
-                                  size_t length, size_t offset,
-                                  int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->getIntArray(datarefID, value, length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const int32_t* xplra_multi_get_int_array_ptr(int bufferID, size_t datarefID,
-                                             size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return buffer->getIntArray(datarefID, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C"
-ssize_t xplra_multi_set_byte_array(int bufferID, size_t datarefID,
-                                   const void* value, size_t length,
-                                   size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->setByteArray(datarefID,
-                                    reinterpret_cast<const uint8_t*>(value),
-                                    length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-ssize_t xplra_multi_get_byte_array(void* value,
-                                   size_t length, size_t offset,
-                                   int bufferID, size_t datarefID)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->getByteArray(datarefID,
-                                    reinterpret_cast<uint8_t*>(value),
-                                    length, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const uint8_t* xplra_multi_get_byte_array_ptr(int bufferID, size_t datarefID,
-                                              size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return buffer->getByteArray(datarefID, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" ssize_t xplra_multi_set_string(int bufferID, size_t datarefID,
-                                          const char* value, size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return -1;
-    try {
-        return buffer->setString(datarefID, value, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C"
-const char* xplra_multi_get_string_ptr(int bufferID, size_t datarefID,
-                                       size_t offset)
-{
-    MultiBuffer* buffer = MultiBufferSlot::getValue(bufferID);
-    if (buffer==0) return 0;
-    try {
-        return buffer->getStringPtr(datarefID, offset);
-    } catch (...) {
-        Connection::get(*buffer).handleException();
-        return 0;
-    }
-}
-
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_multi_destroy_buffer(int connectionID, int bufferID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    try {
-        return connection->destroyMultiBuffer(bufferID) ? 0 : -1;
-    } catch(...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_show_message(int connectionID,
-                                  const char* message, float duration)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    try {
-        connection->showMessage(message, duration);
-        return 0;
-    } catch(...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_register_hotkeys(int connectionID,
-                                      const uint16_t* codes, size_t length)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    try {
-        connection->registerHotkeys(codes, length);
-        return 0;
-    } catch(...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_query_hotkeys(int connectionID,
-                                   uint8_t* states, size_t length)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    try {
-        connection->queryHotkeys(states, length);
-        return 0;
-    } catch(...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-/*----------------------------------------------------------------------------*/
-
-extern "C" int xplra_unregister_hotkeys(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    try {
-        connection->unregisterHotkeys();
-        return 0;
-    } catch(...) {
-        connection->handleException();
-        return -1;
-    }
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-extern "C" int xplra_disconnect(int connectionID)
-{
-    Connection* connection = ConnectionSlot::getValue(connectionID);
-    if (connection==0) return -1;
-
-    ConnectionSlot::clearValue(connectionID);
-    connection->disconnect();
-    delete connection;
-
-    return 0;
-}
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 4
-// indent-tabs-mode: nil
-// End:
Index: src/client/c/hu/varadiistvan/xplra/xplra.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.h	(revision 58)
+++ src/client/c/hu/varadiistvan/xplra/xplra.h	(revision 58)
@@ -0,0 +1,808 @@
+/* Copyright (c) 2013 by István Váradi
+ *
+ * This file is part of XPLRA, a remote-access plugin for X-Plane
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of the FreeBSD Project.
+ */
+
+#ifndef HU_VARADIISTVAN_XPLRA_XPLRA_H
+#define HU_VARADIISTVAN_XPLRA_XPLRA_H
+/*----------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+/*----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------*/
+
+/** No error occured */
+#define ERROR_NONE 0
+
+/**
+ * An I/O error has occured. The subcode is the errno value on Linux, or the
+ * Windows error code.
+ */
+#define ERROR_IO 1
+
+/**
+ * A protocol error has occured. The subcode is one of the
+ * ERROR_PROTOCOL_XXX values.
+ */
+#define ERROR_PROTOCOL 2
+
+/** Invalid command was passed to the plugin */
+#define ERROR_PROTOCOL_INVALID_COMMAND = 1
+
+/** An unknown dataref was specified */
+#define ERROR_PROTOCOL_UNKNOWN_DATAREF = 2
+
+/** An invalid type was specified */
+#define ERROR_PROTOCOL_INVALID_TYPE = 3
+
+/** An invalid length was specified */
+#define ERROR_PROTOCOL_INVALID_LENGTH = 4
+
+/** An invalid offset was specified */
+#define ERROR_PROTOCOL_INVALID_OFFSET = 5
+
+/** An invalid count was specified */
+#define ERROR_PROTOCOL_INVALID_COUNT = 6
+
+/** An invalid ID was specified */
+#define ERROR_PROTOCOL_INVALID_ID = 7
+
+/** An invalid duration was specified */
+#define ERROR_PROTOCOL_INVALID_DURATION = 8
+
+/** Other protocol error  */
+#define ERROR_PROTOCOL_OTHER = 255
+
+/** A function requiring a connection is called without a connection */
+#define ERROR_NOT_CONNECTED 3
+
+/** A type-specific function was called for a dataref of a different type */
+#define ERROR_TYPE_MISMATCH 4
+
+/** An invalid ID was passed to a function */
+#define ERROR_INVALID_ID 5
+
+/** Some other error */
+#define ERROR_OTHER 255
+
+/*----------------------------------------------------------------------------*/
+
+/** Hotkey modifier: Shift */
+#define HOTKEY_MODIFIER_SHIFT 0x01
+
+/** Hotkey modifier: Control */
+#define HOTKEY_MODIFIER_CONTROL 0x02
+
+/*----------------------------------------------------------------------------*/
+
+#define INVALID_DATAREF_ID ((size_t)-1)
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the last error code with the subcode.
+ *
+ * @return the last error code, or -1 if the given connection ID is invalid.
+ */
+int xplra_get_last_error(int connectionID, unsigned long* subCode);
+
+/**
+ * Get a string representation of the last error.
+ *
+ * @return the string representation of the last error, or 0 if there
+ * was no last error, or the connection ID is invalid.
+ */
+const char* xplra_get_last_error_string(int connectionID);
+
+/**
+ * Clear the last error.
+ */
+void xplra_clear_last_error(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Connect to the simulator.
+ *
+ * @return an ID for the created connection, or -1 on error.
+ */
+int xplra_connect();
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the versions of X-Plane, the XPLM library and XPLRA
+ */
+int xplra_get_versions(int connectionID,
+                       int* xplaneVersion, int* xplmVersion,
+                       int* xplraVersion);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Reload the plugins in X-Plane. After this the connection fails.
+ */
+int xplra_reload_plugins(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+/* Single dataref support                                                     */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an integer value from the simulator.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_get_int(int* value, int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a float value from the simulator.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_get_float(float* value, int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a double value from the simulator.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_get_double(double* value, int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of floats into a buffer.
+ *
+ * @param dest the array into which to get the data
+ * @param length the length of the destination buffer
+ * @param offset the offset from which to query the array
+ *
+ * @return the actual number of elements returned in case of success,
+ * -1 on error
+ */
+ssize_t xplra_get_float_array(float* dest, size_t length, size_t offset,
+                              int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of floats into a newly allocated buffer.
+ *
+ * @param length pointer to a variable containing the length to
+ * query. On return it will be set to the actual length, which can be
+ * less than or equal to the input value.
+ * @param offset the offset from which to query the array
+ *
+ * @return the new array on success, 0 on error
+ */
+float* xplra_get_float_array_new(size_t* length, size_t offset,
+                                 int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of integers into a buffer.
+ *
+ * @param dest the array into which to get the data
+ * @param length the length of the destination buffer
+ * @param offset the offset from which to query the array
+ *
+ * @return the actual number of elements returned in case of success,
+ * -1 on error
+ */
+ssize_t xplra_get_int_array(int32_t* dest, size_t length, size_t offset,
+                            int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of integers into a newly allocated buffer.
+ *
+ * @param length pointer to a variable containing the length to
+ * query. On return it will be set to the actual length, which can be
+ * less than or equal to the input value.
+ * @param offset the offset from which to query the array
+ *
+ * @return the new array on success, 0 on error
+ */
+int32_t* xplra_get_int_array_new(size_t* length, size_t offset,
+                                 int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of bytes into a buffer.
+ *
+ * @param dest the array into which to get the data
+ * @param length the length of the destination buffer
+ * @param offset the offset from which to query the array
+ *
+ * @return the actual number of elements returned in case of success,
+ * -1 on error
+ */
+ssize_t xplra_get_byte_array(void* dest, size_t length, size_t offset,
+                             int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get an array of bytes into a newly allocated buffer.
+ *
+ * @param length pointer to a variable containing the length to
+ * query. On return it will be set to the actual length, which can be
+ * less than or equal to the input value.
+ * @param offset the offset from which to query the array
+ *
+ * @return the new array on success, 0 on error
+ */
+uint8_t* xplra_get_byte_array_new(size_t* length, size_t offset,
+                                  int connectionID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the integer dataref with the given name to the given value.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_int(int connectionID, const char* name, int value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the float dataref with the given name to the given value.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_float(int connectionID, const char* name, float value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the double dataref with the given name to the given value.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_double(int connectionID, const char* name, double value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the array of float values with the given name from the given
+ * buffer.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_float_array(int connectionID, const char* name,
+                          const float* values, size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the array of integer values with the given name from the given
+ * buffer.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_int_array(int connectionID, const char* name,
+                        const int32_t* values, size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the array of byte values with the given name from the given
+ * buffer.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_byte_array(int connectionID, const char* name,
+                         const void* values, size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the array of byte values with the given name from the given
+ * string. The string will be padded with 0 if it has a length less
+ * than the given length.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_set_string(int connectionID, const char* name,
+                     const char* value, size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+/* Multi-dataref support                                                      */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Create a multi-dataref getter for the given connection.
+ *
+ * @return the ID of the new getter, or -1 on error
+ */
+int xplra_multi_create_getter(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Create a multi-dataref setter for the given connection.
+ *
+ * @return the ID of the new setter, or -1 on error
+ */
+int xplra_multi_create_setter(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add an integer dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_int(int bufferID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add a float dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_float(int bufferID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add a double dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_double(int bufferID, const char* name);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add a float array dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_float_array(int bufferID, const char* name,
+                                   size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add an integer array dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_int_array(int bufferID, const char* name,
+                                 size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Add a byte array dataref to a multi-dataref buffer.
+ *
+ * @return the ID of the dataref that can be used later. If the buffer
+ * ID is invalid, INVALID_DATAREF_ID is returned.
+ */
+size_t xplra_multi_add_byte_array(int bufferID, const char* name,
+                                  size_t length, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Finalize the given buffer, if not finalized yet.
+ *
+ * @return -1 on error (if the buffer ID is invalid), 0 if there is no
+ * data in the buffer, 1 if there is data in it.
+ */
+int xplra_multi_finalize(int bufferID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Register the buffer with the given ID in X-Plane. If needed, it
+ * will be finalized too.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_multi_register(int bufferID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Unregister the buffer with the given ID from X-Plane.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_multi_unregister(int bufferID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Unregister the buffer with the given ID from X-Plane safely,
+ * i.e. the registration ID will be cleared anyway to support re-registration.
+ *
+ * @return -1 if the buffer ID is invalid, 0 if the unregistration
+ * call failed, 1 if it was successful.
+ */
+int xplra_multi_unregister_safely(int bufferID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Execute the buffer with the given ID. If the buffer is not
+ * finalized, it will be finalized. If it is not finalized, but
+ * registered, the registration will be cleared, and it will be
+ * re-registered after finalizing.
+ *
+ * @return 0 on success, -1 on error
+ */
+int xplra_multi_execute(int bufferID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the value of an integer dataref with the given ID.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_set_int(int bufferID, size_t datarefID, int value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the value of an integer dataref with the given ID.
+ *
+ * @param dest pointer to the variable that will receive the value
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_get_int(int* dest, int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a const pointer to the integer dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+const int32_t* xplra_multi_get_int_const_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the integer dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+int32_t* xplra_multi_get_int_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the value of a float dataref with the given ID.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_set_float(int bufferID, size_t datarefID, float value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the value of a float dataref with the given ID.
+ *
+ * @param dest pointer to the variable that will receive the value
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_get_float(float* dest, int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a const pointer to the float dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+const float* xplra_multi_get_float_const_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the float dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+float* xplra_multi_get_float_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the value of a double dataref with the given ID.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_set_double(int bufferID, size_t datarefID, double value);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the value of a double dataref with the given ID.
+ *
+ * @param dest pointer to the variable that will receive the value
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_get_double(double* dest, int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a const pointer to the double dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+const double* xplra_multi_get_double_const_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the double dataref with the given ID
+ *
+ * @return the pointer or success, 0 on error.
+ */
+double* xplra_multi_get_double_ptr(int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the contents of the float array dataref with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to set the data from
+ *
+ * @return the number of data items set, or -1 on error.
+ */
+ssize_t xplra_multi_set_float_array(int bufferID, size_t datarefID,
+                                    const float* value, size_t length,
+                                    size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the contents of the float array with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to get the data from
+ *
+ * @return the number of data items retrieved, or -1 on error.
+ */
+ssize_t xplra_multi_get_float_array(float* value,
+                                    size_t length, size_t offset,
+                                    int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the float array with the given ID.
+ *
+ * @param offset the offset within the buffer.
+ *
+ * @return the pointer on success, 0 on error.
+ */
+const float* xplra_multi_get_float_array_ptr(int bufferID, size_t datarefID,
+                                             size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the contents of the integer array dataref with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to set the data from
+ *
+ * @return the number of data items set, or -1 on error.
+ */
+ssize_t xplra_multi_set_int_array(int bufferID, size_t datarefID,
+                                  const int32_t* value, size_t length,
+                                  size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the contents of the integer array with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to get the data from
+ *
+ * @return the number of data items retrieved, or -1 on error.
+ */
+ssize_t xplra_multi_get_int_array(int32_t* value,
+                                  size_t length, size_t offset,
+                                  int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the integer array with the given ID.
+ *
+ * @param offset the offset within the buffer.
+ *
+ * @return the pointer on success, 0 on error.
+ */
+const int32_t* xplra_multi_get_int_array_ptr(int bufferID, size_t datarefID,
+                                             size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the contents of the byte array dataref with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to set the data from
+ *
+ * @return the number of data items set, or -1 on error.
+ */
+ssize_t xplra_multi_set_byte_array(int bufferID, size_t datarefID,
+                                   const void* value, size_t length,
+                                   size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get the contents of the byte array with the given ID.
+ *
+ * @param length the amount of data. If 0, it is assumed to be the
+ * length of the data in the buffer minus the offset.
+ * @param offset the offset within the buffer to get the data from
+ *
+ * @return the number of data items retrieved, or -1 on error.
+ */
+ssize_t xplra_multi_get_byte_array(void* value,
+                                   size_t length, size_t offset,
+                                   int bufferID, size_t datarefID);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer to the byte array with the given ID.
+ *
+ * @param offset the offset within the buffer.
+ *
+ * @return the pointer on success, 0 on error.
+ */
+const uint8_t* xplra_multi_get_byte_array_ptr(int bufferID, size_t datarefID,
+                                              size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Set the value of the byte array with the given ID from the given
+ * string. If the string is shorter than the array, the rest will be
+ * filled with 0s.
+ *
+ * @return the number of bytes set, or -1 on error
+ */
+ssize_t xplra_multi_set_string(int bufferID, size_t datarefID,
+                               const char* value, size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Get a pointer as a string pointer to the byte array with the given
+ * ID.
+ *
+ * @return the pointer on success, 0 on error.
+ */
+const char* xplra_multi_get_string_ptr(int bufferID, size_t datarefID,
+                                       size_t offset);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Destroy a multi-dataref buffer for the given connection.
+ *
+ * @param connectionID the ID of the connection for which the buffer
+ * has been created.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_multi_destroy_buffer(int connectionID, int bufferID);
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Show a message in the simulator window for the given duration.
+ */
+int xplra_show_message(int connectionID, const char* message, float duration);
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Register the given hotkey codes for listening. If there is an
+ * existing set of hotkeys registered, those will be overwritten.
+ */
+int xplra_register_hotkeys(int connectionID,
+                           const uint16_t* codes, size_t length);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Query the registered hotkeys whether they were pressed.
+ */
+int xplra_query_hotkeys(int connectionID, uint8_t* states, size_t length);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Unregister the hotkeys.
+ */
+int xplra_unregister_hotkeys(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Destroy the connection with the given ID.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int xplra_disconnect(int connectionID);
+
+/*----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+/*----------------------------------------------------------------------------*/
+#endif // HU_VARADIISTVAN_XPLRA_XPLRA_H
Index: src/client/c/hu/varadiistvan/xplra/xplra.h
===================================================================
--- src/client/c/hu/varadiistvan/xplra/xplra.h	(revision 58)
+++ 	(revision )
@@ -1,808 +1,0 @@
-/* Copyright (c) 2013 by István Váradi
- *
- * This file is part of XPLRA, a remote-access plugin for X-Plane
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies,
- * either expressed or implied, of the FreeBSD Project.
- */
-
-#ifndef HU_VARADIISTVAN_XPLRA_XPLRA_H
-#define HU_VARADIISTVAN_XPLRA_XPLRA_H
-/*----------------------------------------------------------------------------*/
-
-#include <stdlib.h>
-#include <inttypes.h>
-
-/*----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-/** No error occured */
-#define ERROR_NONE 0
-
-/**
- * An I/O error has occured. The subcode is the errno value on Linux, or the
- * Windows error code.
- */
-#define ERROR_IO 1
-
-/**
- * A protocol error has occured. The subcode is one of the
- * ERROR_PROTOCOL_XXX values.
- */
-#define ERROR_PROTOCOL 2
-
-/** Invalid command was passed to the plugin */
-#define ERROR_PROTOCOL_INVALID_COMMAND = 1
-
-/** An unknown dataref was specified */
-#define ERROR_PROTOCOL_UNKNOWN_DATAREF = 2
-
-/** An invalid type was specified */
-#define ERROR_PROTOCOL_INVALID_TYPE = 3
-
-/** An invalid length was specified */
-#define ERROR_PROTOCOL_INVALID_LENGTH = 4
-
-/** An invalid offset was specified */
-#define ERROR_PROTOCOL_INVALID_OFFSET = 5
-
-/** An invalid count was specified */
-#define ERROR_PROTOCOL_INVALID_COUNT = 6
-
-/** An invalid ID was specified */
-#define ERROR_PROTOCOL_INVALID_ID = 7
-
-/** An invalid duration was specified */
-#define ERROR_PROTOCOL_INVALID_DURATION = 8
-
-/** Other protocol error  */
-#define ERROR_PROTOCOL_OTHER = 255
-
-/** A function requiring a connection is called without a connection */
-#define ERROR_NOT_CONNECTED 3
-
-/** A type-specific function was called for a dataref of a different type */
-#define ERROR_TYPE_MISMATCH 4
-
-/** An invalid ID was passed to a function */
-#define ERROR_INVALID_ID 5
-
-/** Some other error */
-#define ERROR_OTHER 255
-
-/*----------------------------------------------------------------------------*/
-
-/** Hotkey modifier: Shift */
-#define HOTKEY_MODIFIER_SHIFT 0x01
-
-/** Hotkey modifier: Control */
-#define HOTKEY_MODIFIER_CONTROL 0x02
-
-/*----------------------------------------------------------------------------*/
-
-#define INVALID_DATAREF_ID ((size_t)-1)
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the last error code with the subcode.
- *
- * @return the last error code, or -1 if the given connection ID is invalid.
- */
-int xplra_get_last_error(int connectionID, unsigned long* subCode);
-
-/**
- * Get a string representation of the last error.
- *
- * @return the string representation of the last error, or 0 if there
- * was no last error, or the connection ID is invalid.
- */
-const char* xplra_get_last_error_string(int connectionID);
-
-/**
- * Clear the last error.
- */
-void xplra_clear_last_error(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Connect to the simulator.
- *
- * @return an ID for the created connection, or -1 on error.
- */
-int xplra_connect();
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the versions of X-Plane, the XPLM library and XPLRA
- */
-int xplra_get_versions(int connectionID,
-                       int* xplaneVersion, int* xplmVersion,
-                       int* xplraVersion);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Reload the plugins in X-Plane. After this the connection fails.
- */
-int xplra_reload_plugins(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-/* Single dataref support                                                     */
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an integer value from the simulator.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_get_int(int* value, int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a float value from the simulator.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_get_float(float* value, int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a double value from the simulator.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_get_double(double* value, int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of floats into a buffer.
- *
- * @param dest the array into which to get the data
- * @param length the length of the destination buffer
- * @param offset the offset from which to query the array
- *
- * @return the actual number of elements returned in case of success,
- * -1 on error
- */
-ssize_t xplra_get_float_array(float* dest, size_t length, size_t offset,
-                              int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of floats into a newly allocated buffer.
- *
- * @param length pointer to a variable containing the length to
- * query. On return it will be set to the actual length, which can be
- * less than or equal to the input value.
- * @param offset the offset from which to query the array
- *
- * @return the new array on success, 0 on error
- */
-float* xplra_get_float_array_new(size_t* length, size_t offset,
-                                 int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of integers into a buffer.
- *
- * @param dest the array into which to get the data
- * @param length the length of the destination buffer
- * @param offset the offset from which to query the array
- *
- * @return the actual number of elements returned in case of success,
- * -1 on error
- */
-ssize_t xplra_get_int_array(int32_t* dest, size_t length, size_t offset,
-                            int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of integers into a newly allocated buffer.
- *
- * @param length pointer to a variable containing the length to
- * query. On return it will be set to the actual length, which can be
- * less than or equal to the input value.
- * @param offset the offset from which to query the array
- *
- * @return the new array on success, 0 on error
- */
-int32_t* xplra_get_int_array_new(size_t* length, size_t offset,
-                                 int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of bytes into a buffer.
- *
- * @param dest the array into which to get the data
- * @param length the length of the destination buffer
- * @param offset the offset from which to query the array
- *
- * @return the actual number of elements returned in case of success,
- * -1 on error
- */
-ssize_t xplra_get_byte_array(void* dest, size_t length, size_t offset,
-                             int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get an array of bytes into a newly allocated buffer.
- *
- * @param length pointer to a variable containing the length to
- * query. On return it will be set to the actual length, which can be
- * less than or equal to the input value.
- * @param offset the offset from which to query the array
- *
- * @return the new array on success, 0 on error
- */
-uint8_t* xplra_get_byte_array_new(size_t* length, size_t offset,
-                                  int connectionID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the integer dataref with the given name to the given value.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_int(int connectionID, const char* name, int value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the float dataref with the given name to the given value.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_float(int connectionID, const char* name, float value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the double dataref with the given name to the given value.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_double(int connectionID, const char* name, double value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the array of float values with the given name from the given
- * buffer.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_float_array(int connectionID, const char* name,
-                          const float* values, size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the array of integer values with the given name from the given
- * buffer.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_int_array(int connectionID, const char* name,
-                        const int32_t* values, size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the array of byte values with the given name from the given
- * buffer.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_byte_array(int connectionID, const char* name,
-                         const void* values, size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the array of byte values with the given name from the given
- * string. The string will be padded with 0 if it has a length less
- * than the given length.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_set_string(int connectionID, const char* name,
-                     const char* value, size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-/* Multi-dataref support                                                      */
-/*----------------------------------------------------------------------------*/
-
-/**
- * Create a multi-dataref getter for the given connection.
- *
- * @return the ID of the new getter, or -1 on error
- */
-int xplra_multi_create_getter(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Create a multi-dataref setter for the given connection.
- *
- * @return the ID of the new setter, or -1 on error
- */
-int xplra_multi_create_setter(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add an integer dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_int(int bufferID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add a float dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_float(int bufferID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add a double dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_double(int bufferID, const char* name);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add a float array dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_float_array(int bufferID, const char* name,
-                                   size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add an integer array dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_int_array(int bufferID, const char* name,
-                                 size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Add a byte array dataref to a multi-dataref buffer.
- *
- * @return the ID of the dataref that can be used later. If the buffer
- * ID is invalid, INVALID_DATAREF_ID is returned.
- */
-size_t xplra_multi_add_byte_array(int bufferID, const char* name,
-                                  size_t length, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Finalize the given buffer, if not finalized yet.
- *
- * @return -1 on error (if the buffer ID is invalid), 0 if there is no
- * data in the buffer, 1 if there is data in it.
- */
-int xplra_multi_finalize(int bufferID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Register the buffer with the given ID in X-Plane. If needed, it
- * will be finalized too.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_multi_register(int bufferID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Unregister the buffer with the given ID from X-Plane.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_multi_unregister(int bufferID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Unregister the buffer with the given ID from X-Plane safely,
- * i.e. the registration ID will be cleared anyway to support re-registration.
- *
- * @return -1 if the buffer ID is invalid, 0 if the unregistration
- * call failed, 1 if it was successful.
- */
-int xplra_multi_unregister_safely(int bufferID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Execute the buffer with the given ID. If the buffer is not
- * finalized, it will be finalized. If it is not finalized, but
- * registered, the registration will be cleared, and it will be
- * re-registered after finalizing.
- *
- * @return 0 on success, -1 on error
- */
-int xplra_multi_execute(int bufferID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the value of an integer dataref with the given ID.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_set_int(int bufferID, size_t datarefID, int value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the value of an integer dataref with the given ID.
- *
- * @param dest pointer to the variable that will receive the value
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_get_int(int* dest, int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a const pointer to the integer dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-const int32_t* xplra_multi_get_int_const_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the integer dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-int32_t* xplra_multi_get_int_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the value of a float dataref with the given ID.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_set_float(int bufferID, size_t datarefID, float value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the value of a float dataref with the given ID.
- *
- * @param dest pointer to the variable that will receive the value
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_get_float(float* dest, int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a const pointer to the float dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-const float* xplra_multi_get_float_const_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the float dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-float* xplra_multi_get_float_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the value of a double dataref with the given ID.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_set_double(int bufferID, size_t datarefID, double value);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the value of a double dataref with the given ID.
- *
- * @param dest pointer to the variable that will receive the value
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_get_double(double* dest, int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a const pointer to the double dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-const double* xplra_multi_get_double_const_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the double dataref with the given ID
- *
- * @return the pointer or success, 0 on error.
- */
-double* xplra_multi_get_double_ptr(int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the contents of the float array dataref with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to set the data from
- *
- * @return the number of data items set, or -1 on error.
- */
-ssize_t xplra_multi_set_float_array(int bufferID, size_t datarefID,
-                                    const float* value, size_t length,
-                                    size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the contents of the float array with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to get the data from
- *
- * @return the number of data items retrieved, or -1 on error.
- */
-ssize_t xplra_multi_get_float_array(float* value,
-                                    size_t length, size_t offset,
-                                    int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the float array with the given ID.
- *
- * @param offset the offset within the buffer.
- *
- * @return the pointer on success, 0 on error.
- */
-const float* xplra_multi_get_float_array_ptr(int bufferID, size_t datarefID,
-                                             size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the contents of the integer array dataref with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to set the data from
- *
- * @return the number of data items set, or -1 on error.
- */
-ssize_t xplra_multi_set_int_array(int bufferID, size_t datarefID,
-                                  const int32_t* value, size_t length,
-                                  size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the contents of the integer array with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to get the data from
- *
- * @return the number of data items retrieved, or -1 on error.
- */
-ssize_t xplra_multi_get_int_array(int32_t* value,
-                                  size_t length, size_t offset,
-                                  int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the integer array with the given ID.
- *
- * @param offset the offset within the buffer.
- *
- * @return the pointer on success, 0 on error.
- */
-const int32_t* xplra_multi_get_int_array_ptr(int bufferID, size_t datarefID,
-                                             size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the contents of the byte array dataref with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to set the data from
- *
- * @return the number of data items set, or -1 on error.
- */
-ssize_t xplra_multi_set_byte_array(int bufferID, size_t datarefID,
-                                   const void* value, size_t length,
-                                   size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get the contents of the byte array with the given ID.
- *
- * @param length the amount of data. If 0, it is assumed to be the
- * length of the data in the buffer minus the offset.
- * @param offset the offset within the buffer to get the data from
- *
- * @return the number of data items retrieved, or -1 on error.
- */
-ssize_t xplra_multi_get_byte_array(void* value,
-                                   size_t length, size_t offset,
-                                   int bufferID, size_t datarefID);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer to the byte array with the given ID.
- *
- * @param offset the offset within the buffer.
- *
- * @return the pointer on success, 0 on error.
- */
-const uint8_t* xplra_multi_get_byte_array_ptr(int bufferID, size_t datarefID,
-                                              size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Set the value of the byte array with the given ID from the given
- * string. If the string is shorter than the array, the rest will be
- * filled with 0s.
- *
- * @return the number of bytes set, or -1 on error
- */
-ssize_t xplra_multi_set_string(int bufferID, size_t datarefID,
-                               const char* value, size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Get a pointer as a string pointer to the byte array with the given
- * ID.
- *
- * @return the pointer on success, 0 on error.
- */
-const char* xplra_multi_get_string_ptr(int bufferID, size_t datarefID,
-                                       size_t offset);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Destroy a multi-dataref buffer for the given connection.
- *
- * @param connectionID the ID of the connection for which the buffer
- * has been created.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_multi_destroy_buffer(int connectionID, int bufferID);
-
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-
-/**
- * Show a message in the simulator window for the given duration.
- */
-int xplra_show_message(int connectionID, const char* message, float duration);
-
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-
-/**
- * Register the given hotkey codes for listening. If there is an
- * existing set of hotkeys registered, those will be overwritten.
- */
-int xplra_register_hotkeys(int connectionID,
-                           const uint16_t* codes, size_t length);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Query the registered hotkeys whether they were pressed.
- */
-int xplra_query_hotkeys(int connectionID, uint8_t* states, size_t length);
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Unregister the hotkeys.
- */
-int xplra_unregister_hotkeys(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-
-/**
- * Destroy the connection with the given ID.
- *
- * @return 0 on success, -1 on error.
- */
-int xplra_disconnect(int connectionID);
-
-/*----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-/*----------------------------------------------------------------------------*/
-#endif // HU_VARADIISTVAN_XPLRA_XPLRA_H
