hs-tango-1.0.0: c_tango/src/c_tango_dbase.cpp
/******************************************************************************
*
* File: c_tango_dbase.c
* Project: C client interface to Tango
* Description: Interface functions to access Tango properties
* Original: November 2007
* Author: jensmeyer
*
* Adapted for tango-rs by Georg Brandl, 2015.
*
******************************************************************************/
#include "c_tango.h"
ErrorStack *tango_translate_exception(Tango::DevFailed &tango_exception);
static void convert_property_reading(Tango::DbDatum &tango_prop, DbDatum *prop);
static void convert_property_writing(DbDatum *prop, Tango::DbDatum &tango_prop);
ErrorStack *tango_create_database_proxy(void **db_proxy)
{
try
{
Tango::Database *dbase = new Tango::Database();
*db_proxy = (void *)dbase;
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_delete_database_proxy(void *db_proxy)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
try
{
delete dbase;
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_device_exported(void *db_proxy, char *name_filter, DbDatum *dev_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbDatum tango_dev_list;
try
{
std::string filter = name_filter;
tango_dev_list = dbase->get_device_exported(filter);
// the result is a string array, set the data type for the conversion
dev_list->data_type = DEVVAR_STRINGARRAY;
convert_property_reading(tango_dev_list, dev_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_device_exported_for_class(void *db_proxy, char *class_name, DbDatum *dev_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbDatum tango_dev_list;
try
{
std::string name = class_name;
tango_dev_list = dbase->get_device_exported_for_class(name);
// the result is a string array, set the data type for the conversion
dev_list->data_type = DEVVAR_STRINGARRAY;
convert_property_reading(tango_dev_list, dev_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_object_list(void *db_proxy, char *name_filter, DbDatum *obj_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbDatum tango_obj_list;
try
{
std::string filter = name_filter;
tango_obj_list = dbase->get_object_list(filter);
// the result is a string array, set the data type for the conversion
obj_list->data_type = DEVVAR_STRINGARRAY;
convert_property_reading(tango_obj_list, obj_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_object_property_list(
void *db_proxy, char *obj_name, char *name_filter, DbDatum *prop_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbDatum tango_prop_list;
try
{
std::string name = obj_name;
std::string filter = name_filter;
tango_prop_list = dbase->get_object_property_list(name, filter);
// the result is a string array, set the data type for the conversion
prop_list->data_type = DEVVAR_STRINGARRAY;
convert_property_reading(tango_prop_list, prop_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_property(void *db_proxy, char *obj_name, DbData *prop_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbData tango_prop_list;
try
{
std::string name = obj_name;
// copy the property names into the Tango object
for (uint32_t i = 0; i < prop_list->length; i++)
{
tango_prop_list.push_back(Tango::DbDatum(prop_list->sequence[i].property_name));
}
// read the properties
dbase->get_property(name, tango_prop_list);
for (uint32_t i = 0; i < prop_list->length; i++)
{
// copy the property data into the C structure
convert_property_reading(tango_prop_list[i], &prop_list->sequence[i]);
}
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_put_property(void *db_proxy, char *obj_name, DbData *prop_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbData tango_prop_list;
try
{
std::string name = obj_name;
// copy the property names and data into the Tango object
tango_prop_list.resize(prop_list->length);
for (uint32_t i = 0; i < prop_list->length; i++)
{
convert_property_writing(&prop_list->sequence[i], tango_prop_list[i]);
}
// write the properties
dbase->put_property(name, tango_prop_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_delete_property(void *db_proxy, char *obj_name, DbData *prop_list)
{
Tango::Database *dbase = (Tango::Database *)db_proxy;
Tango::DbData tango_prop_list;
try
{
std::string name = obj_name;
// copy the property names into the Tango object
for (uint32_t i = 0; i < prop_list->length; i++)
{
tango_prop_list.push_back(Tango::DbDatum(prop_list->sequence[i].property_name));
}
// read the properties
dbase->delete_property(name, tango_prop_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_get_device_property(void *proxy, DbData *prop_list)
{
Tango::DeviceProxy *dev = (Tango::DeviceProxy *)proxy;
Tango::DbData tango_prop_list;
try
{
// copy the property names into the Tango object
for (uint32_t i = 0; i < prop_list->length; i++)
{
tango_prop_list.push_back(Tango::DbDatum(prop_list->sequence[i].property_name));
}
// read the properties
dev->get_property(tango_prop_list);
for (uint32_t i = 0; i < prop_list->length; i++)
{
// copy the property data into the C structure
convert_property_reading(tango_prop_list[i], &prop_list->sequence[i]);
}
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_put_device_property(void *proxy, DbData *prop_list)
{
Tango::DeviceProxy *dev = (Tango::DeviceProxy *)proxy;
Tango::DbData tango_prop_list;
try
{
// copy the property names into the Tango object
tango_prop_list.resize(prop_list->length);
for (uint32_t i = 0; i < prop_list->length; i++)
{
convert_property_writing(&prop_list->sequence[i], tango_prop_list[i]);
}
// write the properties
dev->put_property(tango_prop_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
ErrorStack *tango_delete_device_property(void *proxy, DbData *prop_list)
{
Tango::DeviceProxy *dev = (Tango::DeviceProxy *)proxy;
Tango::DbData tango_prop_list;
try
{
// copy the property names into the Tango object
for (uint32_t i = 0; i < prop_list->length; i++)
{
tango_prop_list.push_back(Tango::DbDatum(prop_list->sequence[i].property_name));
}
// read the properties
dev->delete_property(tango_prop_list);
}
catch (Tango::DevFailed &tango_exception)
{
return tango_translate_exception(tango_exception);
}
return 0;
}
void tango_free_DbDatum(DbDatum *db_datum)
{
free(db_datum->property_name); // from strdup
switch (db_datum->data_type)
{
case DEV_STRING:
free(db_datum->prop_data.string_val);
break;
case DEVVAR_SHORTARRAY:
delete[] db_datum->prop_data.short_arr.sequence;
break;
case DEVVAR_USHORTARRAY:
delete[] db_datum->prop_data.ushort_arr.sequence;
break;
case DEVVAR_LONGARRAY:
delete[] db_datum->prop_data.long_arr.sequence;
break;
case DEVVAR_ULONGARRAY:
delete[] db_datum->prop_data.ulong_arr.sequence;
break;
case DEVVAR_LONG64ARRAY:
delete[] db_datum->prop_data.long64_arr.sequence;
break;
case DEVVAR_ULONG64ARRAY:
delete[] db_datum->prop_data.ulong64_arr.sequence;
break;
case DEVVAR_FLOATARRAY:
delete[] db_datum->prop_data.float_arr.sequence;
break;
case DEVVAR_DOUBLEARRAY:
delete[] db_datum->prop_data.double_arr.sequence;
break;
case DEVVAR_STRINGARRAY:
for (uint32_t i = 0; i < db_datum->prop_data.string_arr.length; i++)
{
free(db_datum->prop_data.string_arr.sequence[i]); // from strdup
}
delete[] db_datum->prop_data.string_arr.sequence;
break;
default:
break;
}
}
void tango_free_DbData(DbData *db_data)
{
for (uint32_t i = 0; i < db_data->length; i++)
{
tango_free_DbDatum(&db_data->sequence[i]);
}
}
class HaskellCallBack : public Tango::CallBack
{
public:
HaskellCallBack(void (*callback_fn)(void *, char const *, bool)) : callback_fn{callback_fn} {}
void push_event(Tango::EventData *ed)
{
this->callback_fn(ed->device, ed->event.c_str(), ed->err);
}
private:
void (*callback_fn)(void *, char const *, bool);
};
void *tango_create_event_callback(void (*callback_fn)(void *, char const *, bool))
{
return new HaskellCallBack(callback_fn);
}
void tango_free_event_callback(void *cb) { delete static_cast<HaskellCallBack *>(cb); }
int tango_subscribe_event(
void *dev_proxy,
char const *attribute,
TangoEventType event_type,
void *event_callback,
bool stateless)
{
try
{
return static_cast<Tango::DeviceProxy *>(dev_proxy)->subscribe_event(
attribute,
static_cast<Tango::EventType>(event_type),
static_cast<HaskellCallBack *>(event_callback),
stateless);
}
catch (Tango::DevFailed const &e)
{
std::cerr << "caught exception in subscribe_event: " << e.errors[0].reason << "\n";
throw e;
}
}
void tango_unsubscribe_event(void *dev_proxy, int event_id)
{
static_cast<Tango::DeviceProxy *>(dev_proxy)->unsubscribe_event(event_id);
}
static void convert_property_reading(Tango::DbDatum &tango_prop, DbDatum *prop)
{
// allocate property name
prop->property_name = strdup(tango_prop.name.c_str());
// copy the property data into the C structure
if (!tango_prop.is_empty())
{
// set the flags
prop->is_empty = false;
prop->wrong_data_type = false;
// convert the data
switch (prop->data_type)
{
case DEV_BOOLEAN:
if (!(tango_prop >> prop->prop_data.bool_val))
prop->wrong_data_type = true;
break;
case DEV_UCHAR:
if (!(tango_prop >> prop->prop_data.char_val))
prop->wrong_data_type = true;
break;
case DEV_SHORT:
if (!(tango_prop >> prop->prop_data.short_val))
prop->wrong_data_type = true;
break;
case DEV_USHORT:
if (!(tango_prop >> prop->prop_data.ushort_val))
prop->wrong_data_type = true;
break;
case DEV_LONG:
{
Tango::DevLong long_val;
if (!(tango_prop >> long_val))
prop->wrong_data_type = true;
else
prop->prop_data.long_val = long_val;
break;
}
case DEV_ULONG:
{
Tango::DevULong ulong_val;
if (!(tango_prop >> ulong_val))
prop->wrong_data_type = true;
else
prop->prop_data.ulong_val = ulong_val;
break;
}
case DEV_LONG64:
{
Tango::DevLong64 long64_val;
if (!(tango_prop >> long64_val))
prop->wrong_data_type = true;
else
prop->prop_data.long64_val = long64_val;
break;
}
case DEV_ULONG64:
{
Tango::DevULong64 ulong64_val;
if (!(tango_prop >> ulong64_val))
prop->wrong_data_type = true;
else
prop->prop_data.ulong64_val = ulong64_val;
break;
}
case DEV_FLOAT:
if (!(tango_prop >> prop->prop_data.float_val))
prop->wrong_data_type = true;
break;
case DEV_DOUBLE:
if (!(tango_prop >> prop->prop_data.double_val))
prop->wrong_data_type = true;
break;
case DEV_STRING:
{
std::string string_val;
if (tango_prop >> string_val)
{
prop->prop_data.string_val = strdup(string_val.c_str());
}
else
{
prop->wrong_data_type = true;
}
break;
}
#define EXTRACT_ARRAY(member, type) \
{ \
std::vector<type> vect; \
uint32_t nb_data; \
if (tango_prop >> vect) \
{ \
nb_data = vect.size(); \
prop->prop_data.member.length = nb_data; \
prop->prop_data.member.sequence = new type[nb_data]; \
memcpy(prop->prop_data.member.sequence, vect.data(), sizeof(type) * nb_data); \
} \
else \
{ \
prop->wrong_data_type = true; \
} \
break; \
}
case DEVVAR_SHORTARRAY:
EXTRACT_ARRAY(short_arr, int16_t);
case DEVVAR_USHORTARRAY:
EXTRACT_ARRAY(ushort_arr, uint16_t);
case DEVVAR_LONGARRAY:
EXTRACT_ARRAY(long_arr, Tango::DevLong);
case DEVVAR_ULONGARRAY:
EXTRACT_ARRAY(ulong_arr, Tango::DevULong);
case DEVVAR_LONG64ARRAY:
EXTRACT_ARRAY(long64_arr, Tango::DevLong64);
case DEVVAR_ULONG64ARRAY:
EXTRACT_ARRAY(ulong64_arr, Tango::DevULong64);
case DEVVAR_FLOATARRAY:
EXTRACT_ARRAY(float_arr, float);
case DEVVAR_DOUBLEARRAY:
EXTRACT_ARRAY(double_arr, double);
case DEVVAR_STRINGARRAY:
{
std::vector<std::string> string_vect;
uint32_t nb_data;
if (tango_prop >> string_vect)
{
nb_data = string_vect.size();
prop->prop_data.string_arr.sequence = new char *[nb_data];
prop->prop_data.string_arr.length = nb_data;
for (uint32_t i = 0; i < nb_data; i++)
{
prop->prop_data.string_arr.sequence[i] = strdup(string_vect[i].c_str());
}
}
else
{
prop->wrong_data_type = true;
}
break;
}
default:
Tango::Except::throw_exception(
"Data type error",
"The requested data type is not implemented for property reading!",
"c_tango_dbase.c::convert_property_reading()");
break;
}
}
else
{
// no property value found, set the is_empty flag
prop->is_empty = true;
prop->wrong_data_type = false;
}
}
static void convert_property_writing(DbDatum *prop, Tango::DbDatum &tango_prop)
{
tango_prop.name = prop->property_name;
switch (prop->data_type)
{
case DEV_BOOLEAN:
tango_prop << prop->prop_data.bool_val;
break;
case DEV_UCHAR:
tango_prop << prop->prop_data.char_val;
break;
case DEV_SHORT:
tango_prop << prop->prop_data.short_val;
break;
case DEV_USHORT:
tango_prop << prop->prop_data.ushort_val;
break;
case DEV_LONG:
tango_prop << (Tango::DevLong)prop->prop_data.long_val;
break;
case DEV_ULONG:
tango_prop << (Tango::DevULong)prop->prop_data.ulong_val;
break;
case DEV_LONG64:
tango_prop << (Tango::DevLong64)prop->prop_data.long64_val;
break;
case DEV_ULONG64:
tango_prop << (Tango::DevULong64)prop->prop_data.ulong64_val;
break;
case DEV_FLOAT:
tango_prop << prop->prop_data.float_val;
break;
case DEV_DOUBLE:
tango_prop << prop->prop_data.double_val;
break;
case DEV_STRING:
case CONST_DEV_STRING:
tango_prop << prop->prop_data.string_val;
break;
#define INSERT_ARRAY(member, type) \
{ \
std::vector<type> arr(prop->prop_data.member.length); \
memcpy( \
arr.data(), \
prop->prop_data.member.sequence, \
sizeof(type) * prop->prop_data.member.length); \
tango_prop << arr; \
break; \
}
case DEVVAR_SHORTARRAY:
INSERT_ARRAY(short_arr, int16_t);
case DEVVAR_USHORTARRAY:
INSERT_ARRAY(ushort_arr, uint16_t);
case DEVVAR_LONGARRAY:
INSERT_ARRAY(long_arr, Tango::DevLong);
case DEVVAR_ULONGARRAY:
INSERT_ARRAY(ulong_arr, Tango::DevULong);
case DEVVAR_LONG64ARRAY:
INSERT_ARRAY(long64_arr, Tango::DevLong64);
case DEVVAR_ULONG64ARRAY:
INSERT_ARRAY(ulong64_arr, Tango::DevULong64);
case DEVVAR_FLOATARRAY:
INSERT_ARRAY(float_arr, float);
case DEVVAR_DOUBLEARRAY:
INSERT_ARRAY(double_arr, double);
case DEVVAR_STRINGARRAY:
{
std::vector<std::string> string_arr(prop->prop_data.string_arr.length);
for (uint32_t i = 0; i < prop->prop_data.string_arr.length; i++)
{
string_arr[i] = prop->prop_data.string_arr.sequence[i];
}
tango_prop << string_arr;
break;
}
default:
Tango::Except::throw_exception(
"Data type error",
"The requested data type is not implemented for property writing!",
"c_tango_dbase.c::convert_property_writing()");
break;
}
}