/*****************************************************************************
 *
 * $Id$
 *
 * Copyright (C) 2009 - 2012  Richard Hacker <lerich@gmx.net>
 *                            Florian Pose <fp@igh-essen.com>
 *
 * This file is part of the PdCom library.
 *
 * The PdCom library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * The PdCom library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the PdCom Library. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#ifndef PDCOM_VARIABLE_H
#define PDCOM_VARIABLE_H

#include <inttypes.h>

#include <string>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <bitset>
#include "Time.h"
#include "Data.h"
#include "Exception.h"

namespace PdCom {

class Process;
class Subscriber;

/****************************************************************************/

/** Process variable.
 *
 * A real-time process usually provides a set of variables, i. e. signals and
 * parameters, that are represented as objects of this class. After Process
 * has connected to the real-time process, it fetches information about the
 * variables and fills its set of Variable objects. Pointers to process
 * variables can be obtained via Process::getVariableMap() or
 * Process::findVariable(). Variables are identified by a path string.
 *
 * To receive variable values, it has to be subscribed to. The subscriber is
 * then notified when a new sample arrives from the real-time process.  The
 * variable's value can only be accessed within the notify call to the
 * subscriber.  See the Subscription and Subscriber class documentation for
 * more information.
 *
 * The Variable object itself provides information about the variable, i. e.
 * - the path name, - the data type and internal structure (scalar, vector,
 * matrix, etc.), - if it is readable and/or writable, - the sample time
 * inside the real-time process.
 *
 * Data contained in a variable is essentially a row major matrix. Vectors and
 * scalars are subsets of these.
 *
 * In this class, only the public interface is relevant.
 */
class Variable: public Data {
    friend class Process;

    public:
        /** Constructor.
         *
         * A process variable can't exist without a parent process object and
         * is usually created by the process itself.
         */
        Variable(
                Process *process, /**< Parent */
                const std::string &path, /**< Path. */
                const std::string &alias, /**< Alias. */
                const Data::Type& type, /**< Data type. */
                const Data::Dimension& dim, /**< Data dimension. */
                double samplePeriod /**< Original sampling period */
                );

        /** Destructor.
         */
        virtual ~Variable();

        /** The parent process.
         */
        Process * const process;

        /** The variable's path.
         */
        const std::string path;

        /** The variable's alias name.
         *
         * Some protocols support a second name for a variable.
         */
        const std::string alias;

        /** The #samplePeriod inside the process.
         */
        const double samplePeriod;

        /** Test whether the Variable is readable.
         */
        bool isRead() const { return readable; }

        /** Test whether the Variable is writeable.
         */
        bool isWrite() const { return writeable; }

        /** Poll the variable once.
         *
         * The given subscriber will get one notify with the polled value.
         */
        void poll(
                Subscriber* s /**< Subscriber that shall receive the value. */
                );

        /** Subscribe to a Variable
         *
         * As long as the Subscriber has not called unsubscribe(), it
         * will be notified of a destruction of Variable.
         *
         * It is therefor essential that the Subscriber informs the Variable
         * if it no longer exists, e.g. by calling unsubscribe() in its
         * destructor, otherwise a runtime exception will occur upon
         * destruction of the Variable
         *
         * \param s The Subscriber() receiving the notify()
         * \param interval The subscription interval:
         *      * == 0 event method: the value is sent on value change only
         *      * > 0 stream method: the value is sent at the requested
         *              intervals.
         *
         * Note that protocols do not have to implement all of the
         * different subscription methods simultaneously, or may exclude
         * one method if another is active, e.g. event and stream methods
         * may exclude each other.
         *
         * \throw VariableException when it is impossible to subscribe this
         * variable with the giben interval.
         */
        void subscribe(Subscriber* s, double interval);

        /** Cancel a subscription
         *
         * Removes a Subscriber from all subscriptions to this variable.
         */
        void unsubscribe(Subscriber*);

        /** Get the current modification time.
         */
        const Time& getMTime() const {
            return mtime;
        }

        /** Scale vector.
         */
        struct Scale {
            /** Constructor.
             */
            Scale(
                    double gain = 1.0, /**< Gain factor. */
                    double offset = 0.0 /** Offset. */
                    ):
                gain(gain), offset(offset) {}
            double gain; /**< Gain factor. */
            double offset; /**< Offset. */
        };

        /** Write the variable's contents directly into a primary data type.
         *
         * \param dst   Destination variable pointer.
         * \param n     Number of elements to write to \c dst.
         * \param scale Scale object to use, or \a NULL.
         * \param idx   Index to use, or \a NULL.
         *
         * @{
         */
        void getValue(double* dst,   size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(float* dst,    size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(uint8_t* dst,  size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(int8_t* dst,   size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(uint16_t* dst, size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(int16_t* dst,  size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(uint32_t* dst, size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(int32_t* dst,  size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(uint64_t* dst, size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(int64_t* dst,  size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        void getValue(bool* dst,     size_t n = 1, const Scale* scale = 0,
                const Dimension* idx = 0) const;
        /** @} */

        /** Set the variable's value directly from a primary data type.
         *
         * \param src   Source value pointer.
         * \param n     Number of elements in \c src.
         * \param scale Scale object to use, or \a NULL. Inverse scaling is
         *              used.
         * \param idx   Index to use, or \a NULL.
         *
         * @{
         */
        void setValue(const double* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const float* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const uint8_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const int8_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const uint16_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const int16_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const uint32_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const int32_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const uint64_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const int64_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        void setValue(const bool* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        /** @} */

        /** Write the variable's value to a data object.
         */
        void getValue(
                Data& dst, /**< Destination. */
                const Scale* scale = 0, /**< Scale object. */
                const Dimension* idx = 0 /**< Index. */
                ) const;

        /** Set the variable's value from a data object.
         */
        void setValue(
                const Data& src, /**< Source. */
                const Scale* scale = 0, /**< Scale (used inversely). */
                const Dimension* idx = 0 /**< Index. */
                );

    protected:
        /** Set to true if value is readable
         */
        bool readable;

        /** Set to true if value is writeable
         */
        bool writeable;

        /** Notify all subscribers about a new stream value.
         *
         * \param decimation to notify
         */
        void notifySubscribers(unsigned int decimation);

        /** Notify all subscribers about a new polled value.
         */
        void notifyPoll();

        /** Add a subscription.
         *
         * Reimplement this method in the specialisation. This requests
         * the variable to be sent with the requested decimation.
         *
         * \param interval
         *      * 0 - send on change
         *      * >0 - stream
         */
        virtual unsigned int addTransmissionInterval(double interval) = 0;

        /** Poll the variable.
         *
         * Has to be reimplemented by derived classes.
         */
        virtual void pollVariable() = 0;

        /** Cancel a subscription.
         */
        virtual void rmTransmissionDecimation(
                int decimation /**< Decimation to remove. */
                ) = 0;

        /* These variables are used by the derived classes for their
         * data exchange with the Application and the clients */

        Time mtime; /**< Modification time of data. */

        /** Notification that the data value has changed.
         *
         * Reimplement this in derived classes.
         */
        virtual void valueChanged(
                const char* dataPtr, /**< Pointer to changed data. */
                size_t n /**< Number of changed elements. */
                );

        /** Force write the variable's value directly from a primary data type.
         * This is used internally to set the value without checking if the
         * variable is writeable.
         *
         * \param src   Source value pointer.
         * \param n     Number of elements in \c src.
         * \param scale Scale object to use, or \a NULL. Inverse scaling is
         *              used.
         * \param idx   Index to use, or \a NULL.
         *
         * @{
         */
        char* pushValue(const double* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const float* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const uint8_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const int8_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const uint16_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const int16_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const uint32_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const int32_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const uint64_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const int64_t* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        char* pushValue(const bool* src, size_t n = 1,
                const Scale* scale = 0, const Dimension* idx = 0);
        /** @} */

    private:
        static Time nullTime; /**< Static nulltime. A reference to
                                        this is returned in the default
                                        implementation of getValue(). */

        /* Called by Process to let the Variable inform Subscribers about
         * an impending death */
        void cancelSubscribers();

        /* The set of all subscribers.
         * This list is used when cancelSubscribers() is called */
        typedef std::map<Subscriber*,unsigned int> SubscriberMap;
        SubscriberMap subscriberMap;

        /* A map of subscription types
         * key: -1 : poll subscriptions
         *       0 : event subscriptions
         *      >0 : stream subscriptions with the key as the decimation
         */
        typedef std::set<Subscriber*> Subscribers;
        typedef std::map<int,Subscribers> DecimationSubscribers;
        DecimationSubscribers decimationSubscribers;

        void removeStreamSubscribers(Subscriber* vs);

        typedef void (*convert_t)(
                const void *src, /**< Source data. */
                void *dst, /**< Destination buffer. */
                size_t count, /**< Number of values in \a src to convert. */
                const Scale *scale /**< Scale vector(s) to use. */
                );

        /** Read conversion function matrix. */
        static const convert_t read_convert[11][11];

        /** Write conversion function matrix. */
        static const convert_t write_convert[11][11];

        /** Conversion functions without scaling. */
        static const convert_t read_convert_noscale[11][11];
        static const convert_t write_convert_noscale[11][11];

        const convert_t *read;
        const convert_t *write;
        const convert_t *read_noscale;
        const convert_t *write_noscale;

        static void boolToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void boolToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_boolToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_boolToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_boolToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_boolToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void uint8ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void sint8ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint8ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint8ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void uint16ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void sint16ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint16ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint16ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void uint32ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void sint32ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint32ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint32ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void uint64ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void uint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_uint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_uint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void sint64ToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void sint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_sint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint64ToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_sint64ToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void doubleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void doubleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void write_doubleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_doubleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void read_doubleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_doubleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void singleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void singleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void write_singleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void write_singleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

        static void read_singleToBool(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToUint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToSint8(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToUint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToSint16(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToUint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToSint32(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToUint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToSint64(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToDouble(const void *src, void* dst,
                size_t count, const Scale* scale);
        static void read_singleToSingle(const void *src, void* dst,
                size_t count, const Scale* scale);

};

} // namespace PdCom

#endif // PDCOM_VARIABLE_H

/****************************************************************************/
