Changes to get lua table entries working using variant type

This commit is contained in:
GPayne
2021-10-01 16:44:20 -06:00
parent 450b101cd5
commit 9464530cdd
3 changed files with 177 additions and 111 deletions

View File

@@ -54,6 +54,7 @@ enum class PropertyValueType {
Table,
Nil
};
typedef std::variant<bool, float, std::string, ghoul::lua::nil_t> ProfilePropertyLua;
class SceneInitializer;
@@ -255,6 +256,60 @@ public:
void setPropertiesFromProfile(const Profile& p);
private:
/**
* Accepts string version of a property value from a profile, converts it to the
* appropriate type, and then pushes the value onto the lua state.
*
* \param L the lua state to push value to
* \param value string representation of the value with which to set property
*/
void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L,
std::string& value);
/**
* Accepts string version of a property value from a profile, and processes it
* according to the data type of the value
*
* \param L the lua state to (eventually) push to
* \param value string representation of the value with which to set property
* \param didPushToLua Bool reference that represents the lua push state at the end
* of this function call. This will be set to true if the value (e.g. table)
* has already been pushed to the lua stack
* \return The ProfilePropertyLua variant type translated from string representation
*/
ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L,
std::string& value, bool& didPushToLua);
/**
* Accepts string version of a property value from a profile, and returns the
* supported data types that can be pushed to a lua state. Currently, the full
* range of possible lua values is not supported.
*
* \param value string representation of the value with which to set property
*/
PropertyValueType getPropertyValueType(std::string& value);
/**
* Accepts string version of a property value from a profile, and adds it to a vector
* which will later be used to push as a lua table containing values of type T
*
* \param L the lua state to (eventually) push to
* \param value string representation of the value with which to set property
* \param table the std::vector container which has elements of type T for a lua table
*/
template <typename T>
void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value,
std::vector<T>& table);
/**
* Handles a lua table entry, creating a vector of the correct variable type based
* on the profile string, and pushes this vector to the lua stack.
*
* \param L the lua state to (eventually) push to
* \param value string representation of the value with which to set property
*/
void handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value);
/**
* Update dependencies.
*/
@@ -269,7 +324,7 @@ private:
bool _dirtyNodeRegistry = false;
SceneGraphNode _rootDummy;
std::unique_ptr<SceneInitializer> _initializer;
std::string _profilePropertyName;
std::vector<InterestingTime> _interestingTimes;
std::mutex _programUpdateLock;
@@ -288,49 +343,7 @@ private:
ghoul::MemoryPool<4096> _memoryPool;
};
/**
* Accepts string version of a property value from a profile, converts it to the
* appropriate type, and then pushes the value onto the lua state.
*
* \param L the lua state to push value to
* \param value string representation of the value with which to set property
*/
void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L,
const std::string& value);
/**
* Accepts string version of a property value from a profile, and processes it
* according to the data type of the value
*
* \param L the lua state to (eventually) push to
* \param value string representation of the value with which to set property
* \param pushFn the std::function provided for pushing the result, which may be
* a lambda that pushes to the lua state, or a lambda that pushes
* to a vector (the vector will eventually be pushed to a lua table)
*/
void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value,
std::function<void(auto v)>pushFn);
/**
* Accepts string version of a property value from a profile, and returns the
* supported data types that can be pushed to a lua state. Currently, the full
* range of possible lua values is not supported.
*
* \param value string representation of the value with which to set property
*/
PropertyValueType getPropertyValueType(std::string& value);
/**
* Accepts string version of a property value from a profile, and adds it to a vector
* which will later be used to push as a lua table containing values of type T
*
* \param L the lua state to (eventually) push to
* \param value string representation of the value with which to set property
* \param table the std::vector container which has elements of type T for a lua table
*/
template <typename T>
void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value,
std::vector<T>& table);
void trimSurroundingCharacters(std::string& valueString, const char c);
} // namespace openspace

View File

@@ -73,6 +73,9 @@ namespace {
}
}
#endif // TRACY_ENABLE
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...)->overloaded<Ts...>;
} // namespace
namespace openspace {
@@ -613,10 +616,14 @@ void Scene::setPropertiesFromProfile(const Profile& p) {
// Remove group name from start of regex and replace with '*'
uriOrRegex = removeGroupNameFromUri(uriOrRegex);
}
_profilePropertyName = uriOrRegex;
ghoul::lua::push(L, uriOrRegex);
ghoul::lua::push(L, 0.0);
std::string workingValue = prop.value;
trimSurroundingCharacters(workingValue, ' ');
// Later functions expect the value to be at the last position on the stack
propertyPushValueFromProfileToLuaState(L, prop.value);
propertyPushValueFromProfileToLuaState(L, workingValue);
applyRegularExpression(
L,
@@ -631,114 +638,145 @@ void Scene::setPropertiesFromProfile(const Profile& p) {
}
}
template<typename T>
void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L,
std::string& value)
void Scene::propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L,
std::string& value)
{
propertyProcessValue(
L,
value,
[&](T resultValue) {
ghoul::lua::push(L, resultValue);
}
);
bool alreadyPushedToLua = false;
ProfilePropertyLua elem = propertyProcessValue(L, value, alreadyPushedToLua);
if (!alreadyPushedToLua) {
std::visit(overloaded{
[&L](const bool& value) {
ghoul::lua::push(L, value);
},
[&L](const float& value) {
ghoul::lua::push(L, value);
},
[&L](const std::string& value) {
ghoul::lua::push(L, value);
},
[&L](const ghoul::lua::nil_t& nilValue) {
ghoul::lua::push(L, nilValue);
}
}, elem);
}
}
template<typename T>
void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value,
std::function<void(T val)>pushFn)
ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::string& value,
bool& didPushToLua)
{
ProfilePropertyLua result;
PropertyValueType pType = getPropertyValueType(value);
switch (pType) {
case PropertyValueType::Boolean:
(value == "true") ? pushFn(true) : pushFn(false);
result = (value == "true") ? true : false;
break;
case PropertyValueType::Float:
pushFn(L, std::stof(value));
result = std::stof(value);
break;
case PropertyValueType::Nil:
ghoul::lua::nil_t n;
pushFn(n);
result = n;
break;
case PropertyValueType::Table:
std::string nextValue = value;
size_t commaPos = value.find(',', commaPos);
if (commaPos != std::string::npos) {
nextValue = value.substr(1, commaPos);
}
PropertyValueType enclosedType = getPropertyValueType(nextValue);
switch (enclosedType) {
case PropertyValueType::Boolean:
std::vector<bool> valsB;
processPropertyValueTableEntries(L, value, valsB);
pushFn(valsB);
break;
trimSurroundingCharacters(value, '{');
trimSurroundingCharacters(value, '}');
handlePropertyLuaTableEntry(L, value);
didPushToLua = true;
break;
case PropertyValueType::Float:
case PropertyValueType::String:
default:
std::string newValue = value;
newValue.insert(0, "[[");
newValue.append("]]");
result = newValue;
break;
}
return result;
}
void Scene::handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value) {
std::string firstValue;
size_t commaPos = 0;
commaPos = value.find(',', commaPos);
if (commaPos != std::string::npos) {
firstValue = value.substr(0, commaPos);
}
else {
firstValue = value;
}
PropertyValueType enclosedType = getPropertyValueType(firstValue);
switch (enclosedType) {
case PropertyValueType::Boolean:
LERROR(fmt::format(
"A lua table of bool values is not supported. (processing property {})",
_profilePropertyName)
);
break;
case PropertyValueType::Float:
{
std::vector<float> valsF;
processPropertyValueTableEntries(L, value, valsF);
pushFn(valsF);
break;
case PropertyValueType::Nil:
std::vector<ghoul::lua::nil_t> valsN;
processPropertyValueTableEntries(L, value, valsN);
pushFn(valsN);
break;
case PropertyValueType::String:
std::vector<std::string> valsS;
processPropertyValueTableEntries(L, value, valsS);
pushFn(valsS);
break;
case PropertyValueType::Table:
default:
LERROR("Table-within-a-table values are not supported for profile property");
break;
ghoul::lua::push(L, valsF);
}
break;
case PropertyValueType::String:
{
std::vector<std::string> valsS;
processPropertyValueTableEntries(L, value, valsS);
ghoul::lua::push(L, valsS);
}
break;
case PropertyValueType::Table:
default:
value.insert(0, "[[");
value.append("]]");
pushFn(value);
LERROR(fmt::format(
"Table-within-a-table values are not supported for profile a "
"property (processing property {})", _profilePropertyName)
);
break;
}
}
template <typename T>
void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value,
void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value,
std::vector<T>& table)
{
size_t commaPos = 0;
size_t prevPos = 0;
std::string nextValue;
while (commaPos != std::string::npos) {
commaPos = value.find(',', commaPos);
commaPos = value.find(',', prevPos);
if (commaPos != std::string::npos) {
nextValue = value.substr(prevPos, commaPos);
nextValue = value.substr(prevPos, commaPos - prevPos);
prevPos = commaPos + 1;
}
else {
nextValue = value.substr(prevPos);
}
propertyProcessValue(L, nextValue, [&](T val){table.push_back(val);});
trimSurroundingCharacters(nextValue, ' ');
bool alreadyPushedToLua = false;
ProfilePropertyLua tableElement = propertyProcessValue(L, nextValue,
alreadyPushedToLua);
try {
table.push_back(std::get<T>(tableElement));
}
catch (std::bad_variant_access& e) {
LERROR(fmt::format(
"Error attempting to parse profile property setting for "
"{} using value = {}", _profilePropertyName, value)
);
}
}
}
PropertyValueType getPropertyValueType(std::string& value) {
//First trim spaces from front and back of string
while (value.front() == ' ') {
value.erase(0, 1);
}
while (value.back() == ' ') {
value.pop_back();
}
PropertyValueType Scene::getPropertyValueType(std::string& value) {
if (luascriptfunctions::isBoolValue(value)) {
return PropertyValueType::Boolean;
}
@@ -756,6 +794,15 @@ PropertyValueType getPropertyValueType(std::string& value) {
}
}
void trimSurroundingCharacters(std::string& valueString, const char c) {
while (valueString.front() == c) {
valueString.erase(0, 1);
}
while (valueString.back() == c) {
valueString.pop_back();
}
}
scripting::LuaLibrary Scene::luaLibrary() {
return {
"",

View File

@@ -915,8 +915,14 @@ bool isBoolValue(const std::string& s) {
*/
bool isFloatValue(const std::string& s) {
try {
float converted = std::stof(s);
return true;
float converted = std::numeric_limits<float>::min();
converted = std::stof(s);
if (converted != std::numeric_limits<float>::min()) {
return true;
}
else {
return false;
}
}
catch (...) {
return false;