Skip to content
Snippets Groups Projects
Commit 4d7eb7d6 authored by Daniel Hornung's avatar Daniel Hornung
Browse files

WIP ENH: Value conversion between CaosDB and Octave.

parent e3087e9b
No related branches found
No related tags found
1 merge request!3Full functionality of libcaosdb
......@@ -335,8 +335,7 @@ void assignEntityDataFromMx(ce::Entity &entity, const mxArray *array, mwSize ind
entity.SetDescription(mxGetStdString(mxGetField(array, index, "description")));
entity.SetDataType(dataTypeFromMx(mxGetField(array, index, "datatype")));
entity.SetUnit(mxGetStdString(mxGetField(array, index, "unit")));
// TODO
entity.SetValue(mxScalarToString(mxGetField(array, index, "value")));
entity.SetValue(valueFromMx(mxGetField(array, index, "value")));
// TODO Remove existing parents and properties.
for (auto parent : parentsFromMx(mxGetField(array, index, "parents"))) {
entity.AppendParent(parent);
......@@ -418,8 +417,7 @@ auto propertiesFromMx(const mxArray *propertiesArray) -> std::vector<ce::Propert
mxStringToEnum<ce::Importance>(mxGetField(propertiesArray, i, "importance")));
properties[i].SetDataType(dataTypeFromMx(mxGetField(propertiesArray, i, "datatype")));
properties[i].SetUnit(mxGetStdString(mxGetField(propertiesArray, i, "unit")));
// TODO
properties[i].SetValue(mxScalarToString(mxGetField(propertiesArray, i, "value")));
properties[i].SetValue(valueFromMx(mxGetField(propertiesArray, i, "value")));
}
return properties;
}
......@@ -449,9 +447,9 @@ auto valueFromMx(const mxArray *array) -> caosdb::entity::Value {
using ce::Value;
auto result = Value();
size_t numel;
if (mxIsSparse(array)) { // Null value.
if (mxIsSparse(array)) { // Null value
return result;
} else if (mxIsCell(array)) { // list value
} else if (mxIsCell(array)) { // list value (in cell array)
if (mxIsEmpty(array)) {
// Empty list
return Value(std::vector<int>());
......@@ -487,11 +485,25 @@ auto valueFromMx(const mxArray *array) -> caosdb::entity::Value {
}
result = Value(content);
} else {
throw std::logic_error(string("Unexpected array type (Class ID ") +
throw std::logic_error(string("Unexpected array type for list value (Class ID ") +
boost::lexical_cast<std::string>((mxGetClassID(array))) + ")");
}
} else { // scalar value (no cell array)
if (mxIsChar(array)) { // string cell array
result = Value(mxGetStdString(array));
} else if (mxIsLogical(array)) { // bool
auto data = *static_cast<bool *>(mxGetData(array));
result = Value(data);
} else if (mxIsInt64(array)) { // int
auto data = *static_cast<INT64_T *>(mxGetData(array));
result = Value(data);
} else if (mxIsDouble(array)) { // double
auto data = *static_cast<double *>(mxGetData(array));
result = Value(data);
} else {
throw std::logic_error(string("Unexpected type for scalar value (Class ID ") +
boost::lexical_cast<std::string>((mxGetClassID(array))) + ")");
}
} else { // scalar value
;
}
return result;
......
......@@ -33,7 +33,9 @@
* - isReference: logical, true if reference datatype
* - isList: logical, true if list datatype
* - unit
* - value: Array representing the value.
* - value: Array representing the value. Normal arrays represent scalar values (1xN char
* arrays for strings, scalar arrays for other atomic value), and arrays inside a 1x1
* cell array represent list values.
* - parents: Struct array with the following fields:
* - id
* - name
......
......@@ -40,64 +40,13 @@ namespace ce = caosdb::entity;
// Helper functions //
///////////////////////////////////////////////////////////////////////////////
// Helper implementation ...
template <typename T> void test_value_impl(const mxArray *mxValue, const T &value) {
EXPECT_EQ(mxGetNumberOfElements(mxValue), 1);
if (value != value) { // equality test does not make sense for NaN
EXPECT_NE(*((T *)mxGetData(mxValue)), *((T *)mxGetData(mxValue)));
} else {
EXPECT_EQ(*((T *)mxGetData(mxValue)), value);
}
}
// ... and specializations.
template <> // string
void test_value_impl(const mxArray *mxValue, const string &value) {
EXPECT_EQ(mxGetNumberOfElements(mxValue), value.size());
EXPECT_EQ(mxGetStdString(mxValue), value);
}
/**
* Can be instantiated for e.g. Entity and Property.
*
* This expects T to be either "scalar" types, or std::string.
*/
template <typename EntType, typename T>
void test_type_value(const string &datatype, const std::vector<T> &values,
const std::vector<string> &validStrings,
const std::vector<string> &invalidStrings,
const std::vector<string> &expectedErrors) {
EXPECT_EQ(values.size(), validStrings.size());
EXPECT_EQ(invalidStrings.size(), expectedErrors.size());
auto valueEntity = EntType();
valueEntity.SetDataType(datatype);
// Test an empty string
valueEntity.SetValue("");
auto mxValue = mxScalarFromStringValue(valueEntity);
EXPECT_TRUE(mxIsEmpty(mxValue));
// Test the valid strings
for (size_t i = 0; i < values.size(); ++i) {
auto value = values[i];
auto valueString = validStrings[i];
// std::cout << "---- " << value << " ----" << std::endl;
valueEntity.SetValue(valueString);
auto mxValue = mxScalarFromStringValue(valueEntity);
test_value_impl<T>(mxValue, value);
}
// Test the invalid strings
for (size_t i = 0; i < invalidStrings.size(); ++i) {
auto invalidString = invalidStrings[i];
auto expectedError = expectedErrors[i];
try {
valueEntity.SetValue(invalidString);
auto mxValue = mxScalarFromStringValue(valueEntity);
ADD_FAILURE() << "Expected error for value '" << invalidString << "'.";
} catch (std::exception const &err) {
EXPECT_EQ(err.what(), expectedError);
} catch (...) {
ADD_FAILURE() << "Expected std::exception for value '" << invalidString << "'.";
}
// Test conversion from native to mx and back
template <typename T> void test_value_native(const std::vector<T> &value_contents) {
for (auto c : value_contents) {
auto v = ce::Value(c);
auto mx_v = mxFromValue(v);
auto vv = valueFromMx(mx_v);
EXPECT_EQ(v, vv);
}
}
......@@ -142,51 +91,22 @@ template <> auto toStr(double value) -> std::string {
*/
TEST(caosdb_conversion, value_String) {
auto value_contents = std::vector<string>{"", "23", "foo", "CaosDB", "\n\n\n\a\n</>"};
for (auto c : value_contents) {
auto v = ce::Value(c);
auto mx_v = mxFromValue(v);
auto vv = valueFromMx(mx_v);
EXPECT_EQ(v, vv);
}
test_value_native(value_contents);
}
TEST(caosdb_conversion, value_Bool) {
auto value_contents = std::vector<bool>{true, false};
for (auto c : value_contents) {
auto v = ce::Value(c);
auto e = ce::Entity();
e.SetRole(ce::Role::PROPERTY);
e.SetValue(v);
// EXPECT_EQ(e.GetValue().AsBool(), v);
}
test_value_native(value_contents);
}
TEST(caosdb_conversion, value_Integer) {
auto value_contents = generateValues<long>();
for (auto c : value_contents) {
auto v = ce::Value(c);
auto e = ce::Entity();
e.SetRole(ce::Role::PROPERTY);
e.SetValue(v);
// EXPECT_EQ(e.GetValue().AsInteger(), v);
}
test_value_native(value_contents);
}
TEST(caosdb_conversion, value_Double) {
auto value_contents = generateValues<double>();
for (auto c : value_contents) {
auto v = ce::Value(c);
auto e = ce::Entity();
e.SetRole(ce::Role::PROPERTY);
e.SetValue(v);
// EXPECT_EQ(e.GetValue().AsDouble(), v);
}
test_value_native(value_contents);
}
/*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment