Changeset 23:e3beb05af132 in xplra


Ignore:
Timestamp:
02/06/13 18:50:36 (11 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Implemented some functions of the C interface and a simple test program exercising those

Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • src/client/c/hu/varadiistvan/xplra/xplra.cc

    r14 r23  
    3434#include "Exception.h"
    3535
     36#include <vector>
     37#include <memory>
     38
    3639#include <cstdio>
     40#include <cassert>
    3741
    3842//------------------------------------------------------------------------------
     
    4044using hu::varadiistvan::xplra::XPlane;
    4145using hu::varadiistvan::xplra::Exception;
     46using hu::varadiistvan::xplra::IOException;
     47using hu::varadiistvan::xplra::ProtocolException;
     48using hu::varadiistvan::xplra::NotConnectedException;
     49using hu::varadiistvan::xplra::TypeMismatchException;
     50using hu::varadiistvan::xplra::InvalidIDException;
     51
     52using std::exception;
     53using std::string;
     54using std::vector;
     55using std::auto_ptr;
     56
     57//------------------------------------------------------------------------------
     58
     59namespace {
     60
     61//------------------------------------------------------------------------------
     62
     63/**
     64 * Information about a connection.
     65 */
     66class Connection : public XPlane
     67{
     68private:
     69    /**
     70     * The last error code.
     71     */
     72    int lastErrorCode;
     73
     74    /**
     75     * The last error subcode.
     76     */
     77    unsigned long lastErrorSubCode;
     78
     79    /**
     80     * The string of the last error
     81     */
     82    std::string lastErrorString;
     83
     84public:
     85    /**
     86     * Construct the connection
     87     */
     88    Connection() throw();
     89
     90    /**
     91     * Handle the currently pending exception.
     92     */
     93    void handleException() throw();
     94
     95    /**
     96     * Get the last error code.
     97     */
     98    int getLastError(unsigned long* lastErrorSubCode) const throw();
     99
     100    /**
     101     * Get the string representation of the last error code.
     102     */
     103    const char* getLastErrorString() const throw();
     104
     105    /**
     106     * Clear the last error code.
     107     */
     108    void clearLastError() throw();
     109};
     110
     111//------------------------------------------------------------------------------
     112
     113inline Connection::Connection() throw() :
     114    lastErrorCode(0),
     115    lastErrorSubCode(0)
     116{
     117}
     118
     119//------------------------------------------------------------------------------
     120
     121void Connection::handleException() throw()
     122{
     123    try {
     124        throw;
     125    } catch(const IOException& e) {
     126        lastErrorCode = ERROR_IO;
     127        lastErrorSubCode = e.getErrorCode();
     128        lastErrorString = e.what();
     129    } catch(const ProtocolException& e) {
     130        lastErrorCode = ERROR_PROTOCOL;
     131        lastErrorSubCode = static_cast<unsigned long>(e.getErrorCode());
     132        lastErrorString = e.what();
     133    } catch(const NotConnectedException& e) {
     134        lastErrorCode = ERROR_NOT_CONNECTED;
     135        lastErrorSubCode = 0;
     136        lastErrorString = e.what();
     137    } catch(const TypeMismatchException& e) {
     138        lastErrorCode = ERROR_TYPE_MISMATCH;
     139        lastErrorSubCode = 0;
     140        lastErrorString = e.what();
     141    } catch(const InvalidIDException& e) {
     142        lastErrorCode = ERROR_INVALID_ID;
     143        lastErrorSubCode = 0;
     144        lastErrorString = e.what();
     145    } catch(const exception& e) {
     146        lastErrorCode = ERROR_OTHER;
     147        lastErrorSubCode = 0;
     148        lastErrorString = e.what();
     149    } catch(...) {
     150        lastErrorCode = ERROR_OTHER;
     151        lastErrorSubCode = 0;
     152        lastErrorString = "<Exception of an unknown type>";
     153    }
     154}
     155
     156//------------------------------------------------------------------------------
     157
     158inline int Connection::getLastError(unsigned long* lastErrorSubCode)
     159    const throw()
     160{
     161    if (lastErrorSubCode!=0) *lastErrorSubCode = this->lastErrorSubCode;
     162    return lastErrorCode;
     163}
     164
     165//------------------------------------------------------------------------------
     166
     167inline const char* Connection::getLastErrorString() const throw()
     168{
     169    return (lastErrorCode==ERROR_NONE) ? 0 : lastErrorString.c_str();
     170}
     171
     172//------------------------------------------------------------------------------
     173
     174inline void Connection::clearLastError() throw()
     175{
     176    lastErrorCode = ERROR_NONE;
     177    lastErrorSubCode = 0;
     178    lastErrorString.clear();
     179}
     180
     181//------------------------------------------------------------------------------
     182//------------------------------------------------------------------------------
     183
     184/**
     185 * Information about a connection slot in the vector of connections.
     186 */
     187struct Slot
     188{
     189private:
     190    /**
     191     * The slots.
     192     */
     193    static std::vector<Slot> slots;
     194
     195    /**
     196     * The index of the first free slot.
     197     */
     198    static int firstFree;
     199
     200public:
     201    /**
     202     * Add a new connection.
     203     */
     204    static int addConnection(Connection* connection) throw();
     205
     206    /**
     207     * Get the connection with the given ID.
     208     */
     209    static Connection* getConnection(int connectionID) throw();
     210
     211    /**
     212     * Clear the connection with the given ID.
     213     */
     214    static void clearConnection(int connectionID) throw();
     215
     216    // Indicate if the slot contains a valid connection or not
     217    bool valid;
     218
     219    union {
     220        // The connection, if it is a valid connection
     221        Connection* connection;
     222
     223        // The index of the next free slot
     224        int nextFreeIndex;
     225    };
     226
     227    /**
     228     * Construct a slot with the given connection
     229     */
     230    Slot(Connection* connection) throw();
     231
     232    /**
     233     * Set the connection and return the former next free index. It
     234     * should be called for a slot with no connection.
     235     */
     236    int setConnection(Connection* connection) throw();
     237
     238    /**
     239     * Get the connection if this slot contains a connection.
     240     */
     241    Connection* getConnection() const throw();
     242
     243    /**
     244     * Clear the connection and set the given next free index.
     245     */
     246    void clear(int nextFreeIndex) throw();
     247};
     248
     249//------------------------------------------------------------------------------
     250
     251vector<Slot> Slot::slots;
     252
     253//------------------------------------------------------------------------------
     254
     255int Slot::firstFree = -1;
     256
     257//------------------------------------------------------------------------------
     258
     259inline Slot::Slot(Connection* connection) throw() :
     260    valid(true)
     261{
     262    this->connection = connection;
     263}
     264
     265//------------------------------------------------------------------------------
     266
     267inline int Slot::setConnection(Connection* connection) throw()
     268{
     269    assert(!valid);
     270    int nextFreeIndex = this->nextFreeIndex;
     271    this->connection = connection;
     272    valid = true;
     273    return nextFreeIndex;
     274}
     275
     276//------------------------------------------------------------------------------
     277
     278inline Connection* Slot::getConnection() const throw()
     279{
     280    return valid ? connection : 0;
     281}
     282
     283//------------------------------------------------------------------------------
     284
     285inline void Slot::clear(int nextFreeIndex) throw()
     286{
     287    assert(valid);
     288    valid = false;
     289    this->nextFreeIndex = nextFreeIndex;
     290}
     291
     292//------------------------------------------------------------------------------
     293
     294int Slot::addConnection(Connection* connection) throw()
     295{
     296    int id = firstFree;
     297    if (id<0) {
     298        id = slots.size();
     299        slots.push_back(Slot(connection));
     300    } else {
     301        Slot& slot = slots[id];
     302        firstFree = slot.setConnection(connection);
     303    }
     304
     305    return id;
     306}
     307
     308//------------------------------------------------------------------------------
     309
     310Connection* Slot::getConnection(int connectionID) throw()
     311{
     312    size_t index = static_cast<size_t>(connectionID);
     313    return (index<slots.size()) ? slots[index].getConnection() : 0;
     314}
     315
     316//------------------------------------------------------------------------------
     317
     318void Slot::clearConnection(int connectionID) throw()
     319{
     320    size_t index = static_cast<size_t>(connectionID);
     321    if (index<slots.size()) {
     322        slots[index].clear(firstFree);
     323        firstFree = index;
     324    }
     325}
     326
     327//------------------------------------------------------------------------------
     328
     329} /* anonymous namespace */
     330
     331//------------------------------------------------------------------------------
     332
     333extern "C" int xplra_get_last_error(int connectionID, unsigned long* subCode)
     334{
     335    Connection* connection = Slot::getConnection(connectionID);
     336    return (connection==0) ? -1 : connection->getLastError(subCode);
     337}
     338
     339//------------------------------------------------------------------------------
     340
     341extern "C" const char* xplra_get_last_error_string(int connectionID)
     342{
     343    Connection* connection = Slot::getConnection(connectionID);
     344    return (connection==0) ? 0 : connection->getLastErrorString();
     345}
     346
     347//------------------------------------------------------------------------------
     348
     349extern "C" void xplra_clear_last_error(int connectionID)
     350{
     351    Connection* connection = Slot::getConnection(connectionID);
     352    if (connection!=0) connection->clearLastError();
     353}
    42354
    43355//------------------------------------------------------------------------------
     
    46358{
    47359    try {
    48         XPlane xplane;
     360        auto_ptr<Connection> connection(new Connection());
     361        connection->connect();
     362        return Slot::addConnection(connection.release());
     363    } catch(...) {
     364        return -1;
     365    }
     366}
     367
     368//------------------------------------------------------------------------------
     369
     370extern "C" int xplra_get_int(int* value, int connectionID, const char* name)
     371{
     372    Connection* connection = Slot::getConnection(connectionID);
     373    if (connection==0) return -1;
     374    try {
     375        *value = connection->getInt(name);
    49376        return 0;
    50     } catch(const Exception& e) {
    51         printf("xplra_connect failed: %s\n", e.what());
     377    } catch (...) {
     378        connection->handleException();
    52379        return -1;
    53380    }
     381}
     382
     383//------------------------------------------------------------------------------
     384
     385extern "C" int xplra_get_float(float* value, int connectionID, const char* name)
     386{
     387    Connection* connection = Slot::getConnection(connectionID);
     388    if (connection==0) return -1;
     389    try {
     390        *value = connection->getFloat(name);
     391        return 0;
     392    } catch (...) {
     393        connection->handleException();
     394        return -1;
     395    }
     396}
     397
     398//------------------------------------------------------------------------------
     399
     400extern "C" int xplra_get_double(double* value,
     401                                int connectionID, const char* name)
     402{
     403    Connection* connection = Slot::getConnection(connectionID);
     404    if (connection==0) return -1;
     405    try {
     406        *value = connection->getDouble(name);
     407        return 0;
     408    } catch (...) {
     409        connection->handleException();
     410        return -1;
     411    }
     412}
     413
     414//------------------------------------------------------------------------------
     415
     416extern "C" int xplra_disconnect(int connectionID)
     417{
     418    Connection* connection = Slot::getConnection(connectionID);
     419    if (connection==0) return -1;
     420
     421    Slot::clearConnection(connectionID);
     422    connection->disconnect();
     423    delete connection;
     424
     425    return 0;
    54426}
    55427
  • src/client/c/hu/varadiistvan/xplra/xplra.h

    r14 r23  
    3838/*----------------------------------------------------------------------------*/
    3939
     40/** No error occured */
     41#define ERROR_NONE 0
     42
     43/**
     44 * An I/O error has occured. The subcode is the errno value on Linux, or the
     45 * Windows error code.
     46 */
     47#define ERROR_IO 1
     48
     49/**
     50 * A protocol error has occured. The subcode is one of the
     51 * ERROR_PROTOCOL_XXX values.
     52 */
     53#define ERROR_PROTOCOL 2
     54
     55/** Invalid command was passed to the plugin */
     56#define ERROR_PROTOCOL_INVALID_COMMAND = 1
     57
     58/** An unknown dataref was specified */
     59#define ERROR_PROTOCOL_UNKNOWN_DATAREF = 2
     60
     61/** An invalid type was specified */
     62#define ERROR_PROTOCOL_INVALID_TYPE = 3
     63
     64/** An invalid length was specified */
     65#define ERROR_PROTOCOL_INVALID_LENGTH = 4
     66
     67/** An invalid offset was specified */
     68#define ERROR_PROTOCOL_INVALID_OFFSET = 5
     69
     70/** An invalid count was specified */
     71#define ERROR_PROTOCOL_INVALID_COUNT = 6
     72
     73/** An invalid ID was specified */
     74#define ERROR_PROTOCOL_INVALID_ID = 7
     75
     76/** Other protocol error  */
     77#define ERROR_PROTOCOL_OTHER = 8
     78
     79/** A function requiring a connection is called without a connection */
     80#define ERROR_NOT_CONNECTED 3
     81
     82/** A type-specific function was called for a dataref of a different type */
     83#define ERROR_TYPE_MISMATCH 4
     84
     85/** An invalid ID was passed to a function */
     86#define ERROR_INVALID_ID 5
     87
     88/** Some other error */
     89#define ERROR_OTHER 255
     90
     91/*----------------------------------------------------------------------------*/
     92
     93/**
     94 * Get the last error code with the subcode.
     95 *
     96 * @return the last error code, or -1 if the given connection ID is invalid.
     97 */
     98int xplra_get_last_error(int connectionID, unsigned long* subCode);
     99
     100/**
     101 * Get a string representation of the last error.
     102 *
     103 * @return the string representation of the last error, or 0 if there
     104 * was no last error, or the connection ID is invalid.
     105 */
     106const char* xplra_get_last_error_string(int connectionID);
     107
     108/**
     109 * Clear the last error.
     110 */
     111void xplra_clear_last_error(int connectionID);
     112
     113/*----------------------------------------------------------------------------*/
     114
     115/**
     116 * Connect to the simulator.
     117 *
     118 * @return an ID for the created connection, or -1 on error.
     119 */
    40120int xplra_connect();
     121
     122/*----------------------------------------------------------------------------*/
     123
     124/**
     125 * Get an integer value from the simulator.
     126 *
     127 * @return 0 on success, -1 on error
     128 */
     129int xplra_get_int(int* value, int connectionID, const char* name);
     130
     131/*----------------------------------------------------------------------------*/
     132
     133/**
     134 * Get a float value from the simulator.
     135 *
     136 * @return 0 on success, -1 on error
     137 */
     138int xplra_get_float(float* value, int connectionID, const char* name);
     139
     140/*----------------------------------------------------------------------------*/
     141
     142/**
     143 * Get a double value from the simulator.
     144 *
     145 * @return 0 on success, -1 on error
     146 */
     147int xplra_get_double(double* value, int connectionID, const char* name);
     148
     149/*----------------------------------------------------------------------------*/
     150
     151/**
     152 * Destroy the connection with the given ID.
     153 *
     154 * @return 0 on success, -1 on error.
     155 */
     156int xplra_disconnect(int connectionID);
    41157
    42158/*----------------------------------------------------------------------------*/
  • test/Makefile.am

    r21 r23  
    66endif
    77
    8 noinst_PROGRAMS=ctest basictest multigettest multisettest
     8noinst_PROGRAMS=ctest basictest basicctest multigettest multisettest
    99
    1010ctest_SOURCES=ctest.c
     
    1515basictest_SOURCES=basictest.cc
    1616
     17basicctest_SOURCES=basicctest.c
     18if TARGET_API_WIN32
     19basicctest_LDFLAGS=-lstdc++
     20endif
     21
    1722multigettest_SOURCES=multigettest.cc
    1823
Note: See TracChangeset for help on using the changeset viewer.