Nnnn add extra functionality to string converter

adding three new converters to operate over strings:
- first one supports padding text with a set of characters
- second one removes trailing zeroes from a string
- third one trims spaces from text

several files are just the usual boilerplate code.
Added some comments in the code

Diffs=
2240d091f8 Nnnn add extra functionality to string converter (#8876)

Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
bodymovin
2025-01-17 02:04:38 +00:00
parent 6280716f40
commit 647942d81b
19 changed files with 570 additions and 12 deletions

View File

@@ -1 +1 @@
5574d9e34ecfa4ba2790ff928e839fa854aa5b60
2240d091f8d55ae4ef75409109684d9ca68b2450

View File

@@ -0,0 +1,40 @@
{
"name": "DataConverterStringPad",
"key": {
"int": 530,
"string": "dataconverterstringpad"
},
"extends": "data_bind/converters/data_converter.json",
"properties": {
"length": {
"type": "uint",
"initialValue": "1",
"key": {
"int": 743,
"string": "length"
},
"description": "Applies text pad depending on the padType until it reaches the given length",
"bindable": true
},
"text": {
"type": "String",
"initialValue": "''",
"key": {
"int": 744,
"string": "text"
},
"description": "String to apply as pad.",
"bindable": true
},
"padType": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 745,
"string": "padtype"
},
"description": "Pad type, 0 is start, 1 is end",
"bindable": true
}
}
}

View File

@@ -0,0 +1,8 @@
{
"name": "DataConverterStringRemoveZeros",
"key": {
"int": 531,
"string": "dataconverterstringremovezeros"
},
"extends": "data_bind/converters/data_converter.json"
}

View File

@@ -0,0 +1,20 @@
{
"name": "DataConverterStringTrim",
"key": {
"int": 532,
"string": "dataconverterstringtrim"
},
"extends": "data_bind/converters/data_converter.json",
"properties": {
"trimType": {
"type": "uint",
"initialValue": "1",
"key": {
"int": 746,
"string": "trimtype"
},
"description": "Trim type, 0 is none, 1 is start, 2 is end, 3 is all",
"bindable": true
}
}
}

View File

@@ -0,0 +1,20 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_PAD_HPP_
#define _RIVE_DATA_CONVERTER_STRING_PAD_HPP_
#include "rive/generated/data_bind/converters/data_converter_string_pad_base.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
#include <stdio.h>
namespace rive
{
class DataConverterStringPad : public DataConverterStringPadBase
{
public:
DataValue* convert(DataValue* value, DataBind* dataBind) override;
DataType outputType() override { return DataType::string; };
private:
DataValueString m_output;
};
} // namespace rive
#endif

View File

@@ -0,0 +1,20 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_REMOVE_ZEROS_HPP_
#define _RIVE_DATA_CONVERTER_STRING_REMOVE_ZEROS_HPP_
#include "rive/generated/data_bind/converters/data_converter_string_remove_zeros_base.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
#include <stdio.h>
namespace rive
{
class DataConverterStringRemoveZeros : public DataConverterStringRemoveZerosBase
{
public:
DataValue* convert(DataValue* value, DataBind* dataBind) override;
DataType outputType() override { return DataType::string; };
private:
DataValueString m_output;
};
} // namespace rive
#endif

View File

@@ -0,0 +1,46 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_TRIM_HPP_
#define _RIVE_DATA_CONVERTER_STRING_TRIM_HPP_
#include "rive/generated/data_bind/converters/data_converter_string_trim_base.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
#include "rive/trim_type.hpp"
#include <stdio.h>
#include <algorithm>
#include <cctype>
#include <locale>
namespace rive
{
class DataConverterStringTrim : public DataConverterStringTrimBase
{
public:
DataValue* convert(DataValue* value, DataBind* dataBind) override;
DataType outputType() override { return DataType::string; };
TrimType trimValue() { return (TrimType)trimType(); }
private:
DataValueString m_output;
inline void ltrim(std::string& s)
{
s.erase(s.begin(),
std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
inline void rtrim(std::string& s)
{
s.erase(std::find_if(s.rbegin(),
s.rend(),
[](unsigned char ch) { return !std::isspace(ch); })
.base(),
s.end());
}
inline void trim(std::string& s)
{
rtrim(s);
ltrim(s);
}
};
} // namespace rive
#endif

View File

@@ -138,6 +138,9 @@
#include "rive/data_bind/converters/data_converter_operation_viewmodel.hpp"
#include "rive/data_bind/converters/data_converter_range_mapper.hpp"
#include "rive/data_bind/converters/data_converter_rounder.hpp"
#include "rive/data_bind/converters/data_converter_string_pad.hpp"
#include "rive/data_bind/converters/data_converter_string_remove_zeros.hpp"
#include "rive/data_bind/converters/data_converter_string_trim.hpp"
#include "rive/data_bind/converters/data_converter_system_degs_to_rads.hpp"
#include "rive/data_bind/converters/data_converter_system_normalizer.hpp"
#include "rive/data_bind/converters/data_converter_to_string.hpp"
@@ -549,10 +552,16 @@ public:
return new DataConverterGroupItem();
case DataConverterGroupBase::typeKey:
return new DataConverterGroup();
case DataConverterStringRemoveZerosBase::typeKey:
return new DataConverterStringRemoveZeros();
case DataConverterRounderBase::typeKey:
return new DataConverterRounder();
case DataConverterStringPadBase::typeKey:
return new DataConverterStringPad();
case DataConverterTriggerBase::typeKey:
return new DataConverterTrigger();
case DataConverterStringTrimBase::typeKey:
return new DataConverterStringTrim();
case DataConverterOperationViewModelBase::typeKey:
return new DataConverterOperationViewModel();
case DataConverterToStringBase::typeKey:
@@ -1247,6 +1256,15 @@ public:
case DataConverterRounderBase::decimalsPropertyKey:
object->as<DataConverterRounderBase>()->decimals(value);
break;
case DataConverterStringPadBase::lengthPropertyKey:
object->as<DataConverterStringPadBase>()->length(value);
break;
case DataConverterStringPadBase::padTypePropertyKey:
object->as<DataConverterStringPadBase>()->padType(value);
break;
case DataConverterStringTrimBase::trimTypePropertyKey:
object->as<DataConverterStringTrimBase>()->trimType(value);
break;
case BindablePropertyEnumBase::propertyValuePropertyKey:
object->as<BindablePropertyEnumBase>()->propertyValue(value);
break;
@@ -1397,6 +1415,9 @@ public:
case DataConverterBase::namePropertyKey:
object->as<DataConverterBase>()->name(value);
break;
case DataConverterStringPadBase::textPropertyKey:
object->as<DataConverterStringPadBase>()->text(value);
break;
case BindablePropertyStringBase::propertyValuePropertyKey:
object->as<BindablePropertyStringBase>()->propertyValue(value);
break;
@@ -2460,6 +2481,12 @@ public:
return object->as<DataConverterGroupItemBase>()->converterId();
case DataConverterRounderBase::decimalsPropertyKey:
return object->as<DataConverterRounderBase>()->decimals();
case DataConverterStringPadBase::lengthPropertyKey:
return object->as<DataConverterStringPadBase>()->length();
case DataConverterStringPadBase::padTypePropertyKey:
return object->as<DataConverterStringPadBase>()->padType();
case DataConverterStringTrimBase::trimTypePropertyKey:
return object->as<DataConverterStringTrimBase>()->trimType();
case BindablePropertyEnumBase::propertyValuePropertyKey:
return object->as<BindablePropertyEnumBase>()->propertyValue();
case NestedArtboardLeafBase::fitPropertyKey:
@@ -2570,6 +2597,8 @@ public:
return object->as<OpenUrlEventBase>()->url();
case DataConverterBase::namePropertyKey:
return object->as<DataConverterBase>()->name();
case DataConverterStringPadBase::textPropertyKey:
return object->as<DataConverterStringPadBase>()->text();
case BindablePropertyStringBase::propertyValuePropertyKey:
return object->as<BindablePropertyStringBase>()
->propertyValue();
@@ -3174,6 +3203,9 @@ public:
case DataConverterRangeMapperBase::flagsPropertyKey:
case DataConverterGroupItemBase::converterIdPropertyKey:
case DataConverterRounderBase::decimalsPropertyKey:
case DataConverterStringPadBase::lengthPropertyKey:
case DataConverterStringPadBase::padTypePropertyKey:
case DataConverterStringTrimBase::trimTypePropertyKey:
case BindablePropertyEnumBase::propertyValuePropertyKey:
case NestedArtboardLeafBase::fitPropertyKey:
case WeightBase::valuesPropertyKey:
@@ -3222,6 +3254,7 @@ public:
case TransitionValueStringComparatorBase::valuePropertyKey:
case OpenUrlEventBase::urlPropertyKey:
case DataConverterBase::namePropertyKey:
case DataConverterStringPadBase::textPropertyKey:
case BindablePropertyStringBase::propertyValuePropertyKey:
case TextValueRunBase::textPropertyKey:
case CustomPropertyStringBase::propertyValuePropertyKey:
@@ -3822,6 +3855,12 @@ public:
return object->is<DataConverterGroupItemBase>();
case DataConverterRounderBase::decimalsPropertyKey:
return object->is<DataConverterRounderBase>();
case DataConverterStringPadBase::lengthPropertyKey:
return object->is<DataConverterStringPadBase>();
case DataConverterStringPadBase::padTypePropertyKey:
return object->is<DataConverterStringPadBase>();
case DataConverterStringTrimBase::trimTypePropertyKey:
return object->is<DataConverterStringTrimBase>();
case BindablePropertyEnumBase::propertyValuePropertyKey:
return object->is<BindablePropertyEnumBase>();
case NestedArtboardLeafBase::fitPropertyKey:
@@ -3914,6 +3953,8 @@ public:
return object->is<OpenUrlEventBase>();
case DataConverterBase::namePropertyKey:
return object->is<DataConverterBase>();
case DataConverterStringPadBase::textPropertyKey:
return object->is<DataConverterStringPadBase>();
case BindablePropertyStringBase::propertyValuePropertyKey:
return object->is<BindablePropertyStringBase>();
case TextValueRunBase::textPropertyKey:

View File

@@ -0,0 +1,109 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_PAD_BASE_HPP_
#define _RIVE_DATA_CONVERTER_STRING_PAD_BASE_HPP_
#include <string>
#include "rive/core/field_types/core_string_type.hpp"
#include "rive/core/field_types/core_uint_type.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
namespace rive
{
class DataConverterStringPadBase : public DataConverter
{
protected:
typedef DataConverter Super;
public:
static const uint16_t typeKey = 530;
/// Helper to quickly determine if a core object extends another without
/// RTTI at runtime.
bool isTypeOf(uint16_t typeKey) const override
{
switch (typeKey)
{
case DataConverterStringPadBase::typeKey:
case DataConverterBase::typeKey:
return true;
default:
return false;
}
}
uint16_t coreType() const override { return typeKey; }
static const uint16_t lengthPropertyKey = 743;
static const uint16_t textPropertyKey = 744;
static const uint16_t padTypePropertyKey = 745;
protected:
uint32_t m_Length = 1;
std::string m_Text = "";
uint32_t m_PadType = 0;
public:
inline uint32_t length() const { return m_Length; }
void length(uint32_t value)
{
if (m_Length == value)
{
return;
}
m_Length = value;
lengthChanged();
}
inline const std::string& text() const { return m_Text; }
void text(std::string value)
{
if (m_Text == value)
{
return;
}
m_Text = value;
textChanged();
}
inline uint32_t padType() const { return m_PadType; }
void padType(uint32_t value)
{
if (m_PadType == value)
{
return;
}
m_PadType = value;
padTypeChanged();
}
Core* clone() const override;
void copy(const DataConverterStringPadBase& object)
{
m_Length = object.m_Length;
m_Text = object.m_Text;
m_PadType = object.m_PadType;
DataConverter::copy(object);
}
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
{
switch (propertyKey)
{
case lengthPropertyKey:
m_Length = CoreUintType::deserialize(reader);
return true;
case textPropertyKey:
m_Text = CoreStringType::deserialize(reader);
return true;
case padTypePropertyKey:
m_PadType = CoreUintType::deserialize(reader);
return true;
}
return DataConverter::deserialize(propertyKey, reader);
}
protected:
virtual void lengthChanged() {}
virtual void textChanged() {}
virtual void padTypeChanged() {}
};
} // namespace rive
#endif

View File

@@ -0,0 +1,36 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_REMOVE_ZEROS_BASE_HPP_
#define _RIVE_DATA_CONVERTER_STRING_REMOVE_ZEROS_BASE_HPP_
#include "rive/data_bind/converters/data_converter.hpp"
namespace rive
{
class DataConverterStringRemoveZerosBase : public DataConverter
{
protected:
typedef DataConverter Super;
public:
static const uint16_t typeKey = 531;
/// Helper to quickly determine if a core object extends another without
/// RTTI at runtime.
bool isTypeOf(uint16_t typeKey) const override
{
switch (typeKey)
{
case DataConverterStringRemoveZerosBase::typeKey:
case DataConverterBase::typeKey:
return true;
default:
return false;
}
}
uint16_t coreType() const override { return typeKey; }
Core* clone() const override;
protected:
};
} // namespace rive
#endif

View File

@@ -0,0 +1,71 @@
#ifndef _RIVE_DATA_CONVERTER_STRING_TRIM_BASE_HPP_
#define _RIVE_DATA_CONVERTER_STRING_TRIM_BASE_HPP_
#include "rive/core/field_types/core_uint_type.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
namespace rive
{
class DataConverterStringTrimBase : public DataConverter
{
protected:
typedef DataConverter Super;
public:
static const uint16_t typeKey = 532;
/// Helper to quickly determine if a core object extends another without
/// RTTI at runtime.
bool isTypeOf(uint16_t typeKey) const override
{
switch (typeKey)
{
case DataConverterStringTrimBase::typeKey:
case DataConverterBase::typeKey:
return true;
default:
return false;
}
}
uint16_t coreType() const override { return typeKey; }
static const uint16_t trimTypePropertyKey = 746;
protected:
uint32_t m_TrimType = 1;
public:
inline uint32_t trimType() const { return m_TrimType; }
void trimType(uint32_t value)
{
if (m_TrimType == value)
{
return;
}
m_TrimType = value;
trimTypeChanged();
}
Core* clone() const override;
void copy(const DataConverterStringTrimBase& object)
{
m_TrimType = object.m_TrimType;
DataConverter::copy(object);
}
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
{
switch (propertyKey)
{
case trimTypePropertyKey:
m_TrimType = CoreUintType::deserialize(reader);
return true;
}
return DataConverter::deserialize(propertyKey, reader);
}
protected:
virtual void trimTypeChanged() {}
};
} // namespace rive
#endif

View File

@@ -0,0 +1,13 @@
#ifndef _RIVE_TRIM_TYPE_HPP_
#define _RIVE_TRIM_TYPE_HPP_
namespace rive
{
enum class TrimType : int
{
none = 0,
start = 1,
end = 2,
all = 3,
};
}
#endif

View File

@@ -0,0 +1,44 @@
#include "rive/math/math_types.hpp"
#include "rive/data_bind/converters/data_converter_string_pad.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
using namespace rive;
DataValue* DataConverterStringPad::convert(DataValue* input, DataBind* dataBind)
{
if (input->is<DataValueString>())
{
auto inputValue = input->as<DataValueString>()->value();
auto inputLength = inputValue.size();
if (inputLength < length())
{
auto padPattern = text();
auto padLength = padPattern.size();
inputValue.reserve(length());
std::string padText{""};
int padTextSize = length() - inputLength;
padText.reserve(padTextSize);
while (inputLength < length())
{
auto maxLength =
(padTextSize > padLength) ? padLength : padTextSize;
padText.append(padPattern, 0, maxLength);
inputLength += maxLength;
}
if (padType() == 1)
{
inputValue.append(padText, 0, padTextSize);
}
else
{
inputValue.insert(0, padText, 0, padTextSize);
}
}
m_output.value(inputValue);
}
else
{
m_output.value(DataValueString::defaultValue);
}
return &m_output;
}

View File

@@ -0,0 +1,33 @@
#include "rive/math/math_types.hpp"
#include "rive/data_bind/converters/data_converter_string_remove_zeros.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
using namespace rive;
DataValue* DataConverterStringRemoveZeros::convert(DataValue* input,
DataBind* dataBind)
{
if (input->is<DataValueString>())
{
auto inputValue = input->as<DataValueString>()->value();
if (inputValue.find('.') != std::string::npos)
{
// Remove trailing zeroes
inputValue =
inputValue.substr(0, inputValue.find_last_not_of('0') + 1);
// If the decimal point is now the last character, remove that as
// well
if (inputValue.find('.') == inputValue.size() - 1)
{
inputValue = inputValue.substr(0, inputValue.size() - 1);
}
}
m_output.value(inputValue);
}
else
{
m_output.value(DataValueString::defaultValue);
}
return &m_output;
}

View File

@@ -0,0 +1,35 @@
#include "rive/math/math_types.hpp"
#include "rive/data_bind/converters/data_converter_string_trim.hpp"
#include "rive/data_bind/data_values/data_value_string.hpp"
using namespace rive;
DataValue* DataConverterStringTrim::convert(DataValue* input,
DataBind* dataBind)
{
if (input->is<DataValueString>())
{
auto inputValue = input->as<DataValueString>()->value();
switch (trimValue())
{
case TrimType::start:
ltrim(inputValue);
break;
case TrimType::end:
rtrim(inputValue);
break;
case TrimType::all:
trim(inputValue);
break;
default:
break;
}
m_output.value(inputValue);
}
else
{
m_output.value(DataValueString::defaultValue);
}
return &m_output;
}

View File

@@ -12,17 +12,6 @@ DataValue* DataConverterToString::convert(DataValue* input, DataBind* dataBind)
{
float value = input->as<DataValueNumber>()->value();
std::string str = std::to_string(value);
if (str.find('.') != std::string::npos)
{
// Remove trailing zeroes
str = str.substr(0, str.find_last_not_of('0') + 1);
// If the decimal point is now the last character, remove that as
// well
if (str.find('.') == str.size() - 1)
{
str = str.substr(0, str.size() - 1);
}
}
m_output.value(str);
}
else if (input->is<DataValueEnum>())

View File

@@ -0,0 +1,11 @@
#include "rive/generated/data_bind/converters/data_converter_string_pad_base.hpp"
#include "rive/data_bind/converters/data_converter_string_pad.hpp"
using namespace rive;
Core* DataConverterStringPadBase::clone() const
{
auto cloned = new DataConverterStringPad();
cloned->copy(*this);
return cloned;
}

View File

@@ -0,0 +1,11 @@
#include "rive/generated/data_bind/converters/data_converter_string_remove_zeros_base.hpp"
#include "rive/data_bind/converters/data_converter_string_remove_zeros.hpp"
using namespace rive;
Core* DataConverterStringRemoveZerosBase::clone() const
{
auto cloned = new DataConverterStringRemoveZeros();
cloned->copy(*this);
return cloned;
}

View File

@@ -0,0 +1,11 @@
#include "rive/generated/data_bind/converters/data_converter_string_trim_base.hpp"
#include "rive/data_bind/converters/data_converter_string_trim.hpp"
using namespace rive;
Core* DataConverterStringTrimBase::clone() const
{
auto cloned = new DataConverterStringTrim();
cloned->copy(*this);
return cloned;
}