// 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 XPLRA_GETDATAREFTASK_H #define XPLRA_GETDATAREFTASK_H //------------------------------------------------------------------------------ #include "DataRefTask.h" #include //------------------------------------------------------------------------------ namespace xplra { //------------------------------------------------------------------------------ /** * Base class for tasks that query the value of some dataref. */ class GetDataRefTask : public DataRefTask { public: /** * Read a dataref query specification and create the appropriate * GetDataRefTask instance. * * @return the new instance, or 0 on error. In that case the given * result reference variable will be filled with the error code, * unless the stream failed, in which case it remains RESULT_OK. */ static GetDataRefTask* create(uint8_t& result, xplcommon::DataStream& stream); /** * Construct the task for the dataref with the given name. */ GetDataRefTask(const std::string& name); /** * Construct the task for the given dataref. */ GetDataRefTask(XPLMDataRef dataRef); /** * Write the value into the given stream. */ virtual void writeValue(xplcommon::DataStream& stream) = 0; }; //------------------------------------------------------------------------------ /** * Base class for dataref querying tasks that query some scalar value. * * ConcreteClass is the actual child class. It should have a function * called queryData, which wraps the corresponding function in XPLM. */ template class GetScalarDataRefTask : public GetDataRefTask { private: /** * The value retrieved. */ T value; public: /** * Construct the task for the dataref with the given name. */ GetScalarDataRefTask(const std::string& name); /** * Construct the task for the given dataref. */ GetScalarDataRefTask(XPLMDataRef dataRef); /** * Get the value */ T getValue() const; protected: /** * Perform the actual operation. */ virtual void process(); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of an integer. */ class GetIntDataRefTask : public GetScalarDataRefTask { public: /** * Query the value from XPLM */ static int queryData(XPLMDataRef dataRef); /** * Construct the task for the dataref with the given name. */ GetIntDataRefTask(const std::string& name); /** * Construct the task for the given dataref. */ GetIntDataRefTask(XPLMDataRef dataRef); /** * Write the value into the given stream. */ virtual void writeValue(xplcommon::DataStream& stream); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of a single-precision * floating point data. */ class GetFloatDataRefTask : public GetScalarDataRefTask { public: /** * Query the value from XPLM */ static float queryData(XPLMDataRef dataRef); /** * Construct the task for the dataref with the given name. */ GetFloatDataRefTask(const std::string& name); /** * Construct the task for the given dataref. */ GetFloatDataRefTask(XPLMDataRef dataRef); /** * Write the value into the given stream. */ virtual void writeValue(xplcommon::DataStream& stream); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of a double-precision * floating point data. */ class GetDoubleDataRefTask : public GetScalarDataRefTask { public: /** * Query the value from XPLM */ static double queryData(XPLMDataRef dataRef); /** * Construct the task for the dataref with the given name. */ GetDoubleDataRefTask(const std::string& name); /** * Construct the task for the given dataref. */ GetDoubleDataRefTask(XPLMDataRef dataRef); /** * Write the value into the given stream. */ virtual void writeValue(xplcommon::DataStream& stream); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * Base class for dataref querying tasks that query some array. * * ConcreteClass is the actual child class. It should have a function * called queryData, which wraps the corresponding function in XPLM. */ template class GetArrayDataRefTask : public GetDataRefTask { private: /** * The maximal number of data items returned. */ int maxCount; /** * The offset within the dataref's value to start the query from. */ int offset; /** * The data. */ T* data; /** * The actual length of the data retrieved. */ int length; protected: /** * Construct the task for the dataref with the given name. * * @param maxCount the maximal number of items to retrieve. If <0, * the function will perform an extra query to retrieve the size of * of the dataref's data, which it will store in the task, so * later on it can be reused. */ GetArrayDataRefTask(const std::string& name, int maxCount = -1, int offset = 0); /** * Construct the task for the given dataref * * @param maxCount the maximal number of items to retrieve. If <0, * the function will perform an extra query to retrieve the size * of the dataref's data, which it will store in the task, so * later on it can be reused. */ GetArrayDataRefTask(XPLMDataRef dataRef, int maxCount = -1, int offset = 0); public: /** * Destroy the object. */ virtual ~GetArrayDataRefTask(); /** * Get the data. */ const T* getData() const; /** * Get the length of the data. */ int getLength() const; protected: /** * Process the dataref by querying its value. */ virtual void process(); /** * Write the value into the given stream. */ virtual void writeValue(xplcommon::DataStream& stream); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of a float array. */ class GetFloatArrayDataRefTask : public GetArrayDataRefTask { public: /** * Get the data via XPLM */ static int queryData(XPLMDataRef dataRef, float* dest, int offset, int count); public: /** * Construct the task for the dataref with the given name. * * @param maxCount the maximal number of data items to * retrieve. If <0, the function will perform an extra query to * retrieve the size of the dataref's data, which it will store in * the task, so later on it can be reused. */ GetFloatArrayDataRefTask(const std::string& name, int maxCount = -1, int offset = 0); /** * Construct the task for the given dataref * * @param maxBytes the maximal number of data items to * retrieve. If <0, the function will perform an extra query to * retrieve the size of the dataref's data, which it will store in * the task, so later on it can be reused. */ GetFloatArrayDataRefTask(XPLMDataRef dataRef, int maxCount = -1, int offset = 0); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of an integer array. */ class GetIntArrayDataRefTask : public GetArrayDataRefTask { public: /** * Get the data via XPLM */ static int queryData(XPLMDataRef dataRef, int* dest, int offset, int count); public: /** * Construct the task for the dataref with the given name. * * @param maxCount the maximal number of data items to * retrieve. If <0, the function will perform an extra query to * retrieve the size of the dataref's data, which it will store in * the task, so later on it can be reused. */ GetIntArrayDataRefTask(const std::string& name, int maxCount = -1, int offset = 0); /** * Construct the task for the given dataref * * @param maxBytes the maximal number of data items to * retrieve. If <0, the function will perform an extra query to * retrieve the size of the dataref's data, which it will store in * the task, so later on it can be reused. */ GetIntArrayDataRefTask(XPLMDataRef dataRef, int maxCount = -1, int offset = 0); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** * A dataref task which retrieves the value of a byte array. */ class GetByteArrayDataRefTask : public GetArrayDataRefTask { public: /** * Get the data via XPLM */ static int queryData(XPLMDataRef dataRef, void* dest, int offset, int count); public: /** * Construct the task for the dataref with the given name. * * @param maxBytes the maximal number of bytes to retrieve. If <0, * the function will perform an extra query to retrieve the size * of the dataref's data, which it will store in the task, so * later on it can be reused. */ GetByteArrayDataRefTask(const std::string& name, int maxBytes = -1, int offset = 0); /** * Construct the task for the given dataref * * @param maxBytes the maximal number of bytes to retrieve. If <0, * the function will perform an extra query to retrieve the size * of the dataref's data, which it will store in the task, so * later on it can be reused. */ GetByteArrayDataRefTask(XPLMDataRef dataRef, int maxBytes = -1, int offset = 0); }; //------------------------------------------------------------------------------ // Template definitions //------------------------------------------------------------------------------ template inline GetScalarDataRefTask:: GetScalarDataRefTask(const std::string& name) : GetDataRefTask(name), value(0) { } //------------------------------------------------------------------------------ template inline GetScalarDataRefTask:: GetScalarDataRefTask(XPLMDataRef dataRef) : GetDataRefTask(dataRef), value(0) { } //------------------------------------------------------------------------------ template inline T GetScalarDataRefTask::getValue() const { return value; } //------------------------------------------------------------------------------ template void GetScalarDataRefTask::process() { value = ConcreteClass::queryData(getDataRef()); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ template inline GetArrayDataRefTask:: GetArrayDataRefTask(const std::string& name, int maxCount, int offset) : GetDataRefTask(name), maxCount(maxCount), offset(offset), data( (maxCount>0) ? new T[maxCount] : 0 ), length(-1) { } //------------------------------------------------------------------------------ template inline GetArrayDataRefTask:: GetArrayDataRefTask(XPLMDataRef dataRef, int maxCount, int offset) : GetDataRefTask(dataRef), maxCount(maxCount), offset(offset), data( (maxCount>0) ? new T[maxCount] : 0), length(-1) { } //------------------------------------------------------------------------------ template inline GetArrayDataRefTask::~GetArrayDataRefTask() { delete [] data; } //------------------------------------------------------------------------------ template inline const T* GetArrayDataRefTask::getData() const { return data; } //------------------------------------------------------------------------------ template inline int GetArrayDataRefTask::getLength() const { return length; } //------------------------------------------------------------------------------ template void GetArrayDataRefTask::process() { if (maxCount<0) { maxCount = ConcreteClass::queryData(getDataRef(), 0, 0, 0); if (maxCount>0) { maxCount -= offset; } if (maxCount>0) { data = new T[maxCount]; } else { maxCount = 0; } } // Util::debug("GetByteArrayDataRefTask::process: dataRef=%p, maxBytes=%d, data=%p, offset\n", // getDataRef(), maxBytes, data, offset); if (maxCount>0) { length = ConcreteClass::queryData(getDataRef(), data, offset, maxCount); } else { length = maxCount; } } //------------------------------------------------------------------------------ template void GetArrayDataRefTask:: writeValue(xplcommon::DataStream& stream) { stream.writeS32(length); if (length>0) { stream.write(data, length * sizeof(T)); } } //------------------------------------------------------------------------------ // Inline definitions //------------------------------------------------------------------------------ inline GetDataRefTask::GetDataRefTask(const std::string& name) : DataRefTask(name) { } //------------------------------------------------------------------------------ inline GetDataRefTask::GetDataRefTask(XPLMDataRef dataRef) : DataRefTask(dataRef) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline int GetIntDataRefTask::queryData(XPLMDataRef dataRef) { return XPLMGetDatai(dataRef); } //------------------------------------------------------------------------------ inline GetIntDataRefTask::GetIntDataRefTask(const std::string& name) : GetScalarDataRefTask(name) { } //------------------------------------------------------------------------------ inline GetIntDataRefTask::GetIntDataRefTask(XPLMDataRef dataRef) : GetScalarDataRefTask(dataRef) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline float GetFloatDataRefTask::queryData(XPLMDataRef dataRef) { return XPLMGetDataf(dataRef); } //------------------------------------------------------------------------------ inline GetFloatDataRefTask::GetFloatDataRefTask(const std::string& name) : GetScalarDataRefTask(name) { } //------------------------------------------------------------------------------ inline GetFloatDataRefTask::GetFloatDataRefTask(XPLMDataRef dataRef) : GetScalarDataRefTask(dataRef) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline double GetDoubleDataRefTask::queryData(XPLMDataRef dataRef) { return XPLMGetDatad(dataRef); } //------------------------------------------------------------------------------ inline GetDoubleDataRefTask::GetDoubleDataRefTask(const std::string& name) : GetScalarDataRefTask(name) { } //------------------------------------------------------------------------------ inline GetDoubleDataRefTask::GetDoubleDataRefTask(XPLMDataRef dataRef) : GetScalarDataRefTask(dataRef) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline int GetFloatArrayDataRefTask::queryData(XPLMDataRef dataRef, float* dest, int offset, int count) { return XPLMGetDatavf(dataRef, dest, offset, count); } //------------------------------------------------------------------------------ inline GetFloatArrayDataRefTask::GetFloatArrayDataRefTask(const std::string& name, int maxCount, int offset) : GetArrayDataRefTask(name, maxCount, offset) { } //------------------------------------------------------------------------------ inline GetFloatArrayDataRefTask::GetFloatArrayDataRefTask(XPLMDataRef dataRef, int maxCount, int offset) : GetArrayDataRefTask(dataRef, maxCount, offset) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline int GetIntArrayDataRefTask::queryData(XPLMDataRef dataRef, int* dest, int offset, int count) { return XPLMGetDatavi(dataRef, dest, offset, count); } //------------------------------------------------------------------------------ inline GetIntArrayDataRefTask::GetIntArrayDataRefTask(const std::string& name, int maxCount, int offset) : GetArrayDataRefTask(name, maxCount, offset) { } //------------------------------------------------------------------------------ inline GetIntArrayDataRefTask::GetIntArrayDataRefTask(XPLMDataRef dataRef, int maxCount, int offset) : GetArrayDataRefTask(dataRef, maxCount, offset) { } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline int GetByteArrayDataRefTask::queryData(XPLMDataRef dataRef, void* dest, int offset, int count) { return XPLMGetDatab(dataRef, dest, offset, count); } //------------------------------------------------------------------------------ inline GetByteArrayDataRefTask::GetByteArrayDataRefTask(const std::string& name, int maxBytes, int offset) : GetArrayDataRefTask(name, maxBytes, offset) { } //------------------------------------------------------------------------------ inline GetByteArrayDataRefTask::GetByteArrayDataRefTask(XPLMDataRef dataRef, int maxBytes, int offset) : GetArrayDataRefTask(dataRef, maxBytes, offset) { } //------------------------------------------------------------------------------ } /* namespace xplra */ //------------------------------------------------------------------------------ #endif // XPLRA_GETDATAREFTASK_H // Local Variables: // mode: C++ // c-basic-offset: 4 // indent-tabs-mode: nil // End: