Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow dynamic array indexing in a data address. #547

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Include/RmlUi/Core/DataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@ template <typename Object, typename AssignType>
using MemberSetterFunc = void (Object::*)(AssignType);

using DirtyVariables = SmallUnorderedSet<String>;
using DataAddress = Vector<struct DataAddressEntry>;

struct DataAddressEntry {
DataAddressEntry(String name) : name(std::move(name)), index(-1) {}
DataAddressEntry(int index) : index(index) {}
DataAddressEntry(String name_) : name(std::move(name_)), index(-1) {}
DataAddressEntry(DataAddress address_) : address(std::move(address_)), index(-1) {}
DataAddressEntry(int index_) : index(index_) {}
String name;
DataAddress address;
int index;
};
using DataAddress = Vector<DataAddressEntry>;

template <class T>
struct PointerTraits {
Expand Down
17 changes: 10 additions & 7 deletions Include/RmlUi/Core/DataVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

namespace Rml {

class DataModel;

enum class DataVariableType { Scalar, Array, Struct };

/*
Expand All @@ -56,7 +58,7 @@ class RMLUICORE_API DataVariable {
bool Get(Variant& variant);
bool Set(const Variant& variant);
int Size();
DataVariable Child(const DataAddressEntry& address);
DataVariable Child(const DataModel& model, const DataAddressEntry& address);
DataVariableType Type();

private:
Expand All @@ -79,11 +81,13 @@ class RMLUICORE_API VariableDefinition : public NonCopyMoveable {
virtual bool Set(void* ptr, const Variant& variant);

virtual int Size(void* ptr);
virtual DataVariable Child(void* ptr, const DataAddressEntry& address);
virtual DataVariable Child(const DataModel& model, void* ptr, const DataAddressEntry& address);

protected:
VariableDefinition(DataVariableType type) : type(type) {}

static int ResolveArrayIndex(const DataModel& model, const DataAddressEntry &address);

private:
DataVariableType type;
};
Expand Down Expand Up @@ -145,7 +149,7 @@ class RMLUICORE_API StructDefinition final : public VariableDefinition {
public:
StructDefinition();

DataVariable Child(void* ptr, const DataAddressEntry& address) override;
DataVariable Child(const DataModel& model, void* ptr, const DataAddressEntry& address) override;

void AddMember(const String& name, UniquePtr<VariableDefinition> member);

Expand All @@ -163,11 +167,10 @@ class ArrayDefinition final : public VariableDefinition {
int Size(void* ptr) override { return int(static_cast<Container*>(ptr)->size()); }

protected:
DataVariable Child(void* void_ptr, const DataAddressEntry& address) override
DataVariable Child(const DataModel& model, void* void_ptr, const DataAddressEntry& address) override
{
Container* ptr = static_cast<Container*>(void_ptr);
const int index = address.index;

const int index = VariableDefinition::ResolveArrayIndex(model, address);
const int container_size = int(ptr->size());
if (index < 0 || index >= container_size)
{
Expand Down Expand Up @@ -196,7 +199,7 @@ class RMLUICORE_API BasePointerDefinition : public VariableDefinition {
bool Get(void* ptr, Variant& variant) override;
bool Set(void* ptr, const Variant& variant) override;
int Size(void* ptr) override;
DataVariable Child(void* ptr, const DataAddressEntry& address) override;
DataVariable Child(const DataModel& model, void* ptr, const DataAddressEntry& address) override;

protected:
virtual void* DereferencePointer(void* ptr) = 0;
Expand Down
17 changes: 15 additions & 2 deletions Source/Core/DataExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,15 +1021,28 @@ bool DataExpression::Run(const DataExpressionInterface& expression_interface, Va
return true;
}

static void CollectAddresses(StringList& list, const DataAddress& address)
{
if (!address.empty())
list.push_back(address[0].name);

for (const DataAddressEntry& entry : address)
{
if (!entry.address.empty())
CollectAddresses(list, entry.address);
}
}

StringList DataExpression::GetVariableNameList() const
{
StringList list;
list.reserve(addresses.size());

for (const DataAddress& address : addresses)
{
if (!address.empty())
list.push_back(address[0].name);
CollectAddresses(list, address);
}

return list;
}

Expand Down
29 changes: 20 additions & 9 deletions Source/Core/DataModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace Rml {
static DataAddress ParseAddress(const String& address_str)
{
StringList list;
StringUtilities::ExpandString(list, address_str, '.');
StringUtilities::ExpandString(list, address_str, '.', '[', ']');

DataAddress address;
address.reserve(list.size() * 2);
Expand All @@ -55,15 +55,26 @@ static DataAddress ParseAddress(const String& address_str)

while (i_open != String::npos)
{
size_t i_close = item.find(']', i_open + 1);
if (i_close == String::npos)
return DataAddress();
int depth = 1;
size_t i_close = i_open;
while (depth > 0)
{
i_close = item.find_first_of("[]", i_close + 1);
if (i_close == String::npos)
return DataAddress();

int index = FromString<int>(item.substr(i_open + 1, i_close - i_open), -1);
if (index < 0)
return DataAddress();
if (item[i_close] == '[')
depth++;
else if (item[i_close] == ']')
depth--;
}

address.emplace_back(index);
std::string accessor = item.substr(i_open + 1, i_close - (i_open + 1));
int index = FromString<int>(accessor, -1);
if (index >= 0)
address.emplace_back(index);
else
address.emplace_back(ParseAddress(accessor));

i_open = item.find('[', i_close + 1);
}
Expand Down Expand Up @@ -308,7 +319,7 @@ DataVariable DataModel::GetVariable(const DataAddress& address) const

for (int i = 1; i < (int)address.size() && variable; i++)
{
variable = variable.Child(address[i]);
variable = variable.Child(*this, address[i]);
if (!variable)
return DataVariable();
}
Expand Down
34 changes: 28 additions & 6 deletions Source/Core/DataVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/

#include "../../Include/RmlUi/Core/DataVariable.h"
#include "DataModel.h"

namespace Rml {

Expand All @@ -45,9 +46,9 @@ int DataVariable::Size()
return definition->Size(ptr);
}

DataVariable DataVariable::Child(const DataAddressEntry& address)
DataVariable DataVariable::Child(const DataModel& model, const DataAddressEntry& address)
{
return definition->Child(ptr, address);
return definition->Child(model, ptr, address);
}

DataVariableType DataVariable::Type()
Expand All @@ -70,12 +71,33 @@ int VariableDefinition::Size(void* /*ptr*/)
Log::Message(Log::LT_WARNING, "Tried to get the size from a non-array data type.");
return 0;
}
DataVariable VariableDefinition::Child(void* /*ptr*/, const DataAddressEntry& /*address*/)
DataVariable VariableDefinition::Child(const DataModel& /*model*/ , void* /*ptr*/, const DataAddressEntry& /*address*/)
{
Log::Message(Log::LT_WARNING, "Tried to get the child of a scalar type.");
return DataVariable();
}

int VariableDefinition::ResolveArrayIndex(const DataModel& model, const DataAddressEntry &address)
{
if (address.index >= 0)
return address.index;

if (!address.address.empty())
{
Rml::DataVariable variable_index = model.GetVariable(address.address);
if (variable_index)
{
Rml::Variant value;
if (variable_index.Get(value))
{
return value.Get<int>(-1);
}
}
}

return -1;
}

class LiteralIntDefinition final : public VariableDefinition {
public:
LiteralIntDefinition() : VariableDefinition(DataVariableType::Scalar) {}
Expand All @@ -95,7 +117,7 @@ DataVariable MakeLiteralIntVariable(int value)

StructDefinition::StructDefinition() : VariableDefinition(DataVariableType::Struct) {}

DataVariable StructDefinition::Child(void* ptr, const DataAddressEntry& address)
DataVariable StructDefinition::Child(const DataModel& /*model*/, void *ptr, const DataAddressEntry &address)
{
const String& name = address.name;
if (name.empty())
Expand Down Expand Up @@ -169,11 +191,11 @@ int BasePointerDefinition::Size(void* ptr)
return underlying_definition->Size(DereferencePointer(ptr));
}

DataVariable BasePointerDefinition::Child(void* ptr, const DataAddressEntry& address)
DataVariable BasePointerDefinition::Child(const DataModel& model, void* ptr, const DataAddressEntry& address)
{
if (!ptr)
return DataVariable();
return underlying_definition->Child(DereferencePointer(ptr), address);
return underlying_definition->Child(model, DereferencePointer(ptr), address);
}

} // namespace Rml
11 changes: 6 additions & 5 deletions Source/Lua/LuaDataModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <RmlUi/Core/DataModelHandle.h>
#include <RmlUi/Core/DataVariable.h>
#include <RmlUi/Lua/Utilities.h>
#include "../Core/DataModel.h"

#define RMLDATAMODEL "RMLDATAMODEL"

Expand Down Expand Up @@ -133,7 +134,7 @@ class LuaTableDef : public VariableDefinition {
bool Get(void* ptr, Variant& variant) override;
bool Set(void* ptr, const Variant& variant) override;
int Size(void* ptr) override;
DataVariable Child(void* ptr, const DataAddressEntry& address) override;
DataVariable Child(const DataModel& data_model, void* ptr, const DataAddressEntry& address) override;

protected:
const struct LuaDataModel* model;
Expand All @@ -142,7 +143,7 @@ class LuaTableDef : public VariableDefinition {
class LuaScalarDef final : public LuaTableDef {
public:
LuaScalarDef(const struct LuaDataModel* model);
DataVariable Child(void* ptr, const DataAddressEntry& address) override;
DataVariable Child(const DataModel& data_model, void* ptr, const DataAddressEntry& address) override;
};

LuaTableDef::LuaTableDef(const struct LuaDataModel* model) : VariableDefinition(DataVariableType::Scalar), model(model) {}
Expand Down Expand Up @@ -206,7 +207,7 @@ int LuaTableDef::Size(void* ptr)
return size;
}

DataVariable LuaTableDef::Child(void* ptr, const DataAddressEntry& address)
DataVariable LuaTableDef::Child(const DataModel& /*data_model*/, void* ptr, const DataAddressEntry& address)
{
lua_State* L = model->dataL;
if (!L)
Expand Down Expand Up @@ -240,13 +241,13 @@ DataVariable LuaTableDef::Child(void* ptr, const DataAddressEntry& address)

LuaScalarDef::LuaScalarDef(const struct LuaDataModel* model) : LuaTableDef(model) {}

DataVariable LuaScalarDef::Child(void* ptr, const DataAddressEntry& address)
DataVariable LuaScalarDef::Child(const DataModel& data_model, void* ptr, const DataAddressEntry& address)
{
lua_State* L = model->dataL;
if (!L)
return DataVariable{};
lua_settop(L, model->top);
return LuaTableDef::Child(ptr, address);
return LuaTableDef::Child(data_model, ptr, address);
}

static void BindVariable(struct LuaDataModel* D, lua_State* L)
Expand Down
Loading