Major Update:

- DataTreeCore:
  - Merge TDataMember and CDataTree into => CDataMember
  - Each node, incl root is now CDataMember object
  - Modified function to not require BaseMember (Object is basemember)
  - Split/duplicat most functions to require, or not require child path
  - Added isNull/Object/Array/Sting() etc methods
  - Many other methods removed or restructured
- Updated DataTree usage in: JSONparseCore,
  ApplicationCore, FunctionCore, SelectableCore, WatchdogCore
This commit is contained in:
Charl Wentzel
2018-11-17 19:10:59 +02:00
parent d36bf3230b
commit f2a1ca950a
10 changed files with 472 additions and 488 deletions

View File

@@ -14,111 +14,126 @@
//---------------------------------------------------------------------------
CDataTree::CDataTree()
CDataMember::CDataMember( const char * pName, const int pLen )
{
// Create Root member of tree
RootMember = CreateMember( NULL, NULL, NULL );
RootMember->Type = jtObject;
}
//---------------------------------------------------------------------------
CDataTree::~CDataTree()
{
// Destroy Members
DeleteAll();
DestroyMember( &RootMember );
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::CreateMember( TDataMember * Parent, TDataMember * PrevChild, const char * Name, const int Len )
{
TDataMember * Member;
// Create data structure
Member = (TDataMember *)calloc( 1, sizeof(TDataMember) );
// Set name
if (Name)
{
Member->NameLen = (Len == -1)? strlen( Name ) : Len ;
Member->Name = (char *)malloc( Member->NameLen+1 );
memcpy( Member->Name, Name, Member->NameLen );
Member->Name[ Member->NameLen ] = 0;
if (Name) {
NameLen = (pLen == -1)? strlen( pName ) : pLen ;
Name = (char *)malloc( NameLen+1 );
memcpy( Name, pName, NameLen );
Name[ NameLen ] = 0;
}
// Update Parent
if (Parent) {
Member->Parent = Parent;
Type = jtNull;
Value = NULL;
Len = 0;
FirstChild = NULL;
LastChild = NULL;
Parent = NULL;
PrevPeer = NULL;
NextPeer = NULL;
}
//---------------------------------------------------------------------------
CDataMember::CDataMember( CDataMember * pParent, const char * pName, const int pLen )
{
if (pName) {
NameLen = (pLen == -1)? strlen( pName ) : pLen ;
Name = (char *)malloc( NameLen+1 );
memcpy( Name, pName, NameLen );
Name[ NameLen ] = 0;
}
Type = jtNull;
Value = NULL;
Len = 0;
FirstChild = NULL;
LastChild = NULL;
if (!pParent) {
Parent = NULL;
PrevPeer = NULL;
NextPeer = NULL;
}
else {
// Clear/reset parent if not object
Parent = pParent;
if ((Parent->Type != jtNull) && (Parent->Type != jtObject) && (Parent->Type != jtArray)) {
Parent->Clear();
}
// Insert into Parent & Peer lists
Parent->Len++;
if (!Parent->FirstChild) {
Parent->FirstChild = this;
Parent->LastChild = this;
}
else {
PrevPeer = Parent->LastChild;
Parent->LastChild->NextPeer = this;
Parent->LastChild = this;
}
}
// Set Sibling links
Member->Prev = PrevChild;
Member->Next = NULL;
return Member;
}
//---------------------------------------------------------------------------
bool CDataTree::DestroyMember( TDataMember ** Member )
CDataMember::~CDataMember()
{
TDataMember * NextMember;
// Validate
if (!Member || !*Member)
return false;
// Get next param in list
NextMember = (*Member)->Next;
// Update Parent
if ((*Member)->Parent)
(*Member)->Parent->Len--;
// Destroy
if ((*Member)->Name)
free( (*Member)->Name );
if ((*Member)->Value)
free( (*Member)->Value );
while ((*Member)->FirstChild) {
DestroyMember( &((*Member)->FirstChild) );
// Remove from parent
if (Parent)
Parent->Len--;
if (this == Parent->LastChild) {
Parent->LastChild = PrevPeer;
}
PrevPeer->NextPeer = NextPeer;
NextPeer->PrevPeer = PrevPeer;
free( *Member );
// Destroy value/children
Clear();
// Restore list integrity
*Member = NextMember;
// Destroy member
if (Name)
free( Name );
if (Value)
free( Value );
}
//---------------------------------------------------------------------------
CDataMember * CDataMember::CreateChild( const char * Name, const int Len )
{
CDataMember * Member;
Member = new CDataMember( this, Name, Len );
return Member;
}
//---------------------------------------------------------------------------
bool CDataMember::Clear()
{
if (Value) {
free( Value );
Value = NULL;
}
while (FirstChild) {
delete FirstChild;
// FirstChild = NULL;
// LastChild = NULL;
// Len = 0;
}
Type = jtNull;
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::DestroyValue( TDataMember * Member )
CDataMember * CDataMember::GetMember( const char * Path, bool Create )
{
// Validate
if (!Member)
return false;
// Destroy values
if (Member->Value) {
free( Member->Value );
Member->Value = NULL;
}
// Destroy Children
while (Member->FirstChild) {
DestroyMember( &(Member->FirstChild) );
}
return true;
}
//---------------------------------------------------------------------------
TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char * Path, bool Create, TDataMember ** Parent )
{
TDataMember * Member;
TDataMember ** Child;
TDataMember * PrevChild;
CDataMember * Member;
CDataMember ** Child;
CDataMember * PrevChild;
char * Pos;
char * EndPos;
char * Key;
@@ -129,14 +144,12 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
// Validate
if (!Path || !*Path) {
if (Parent) *Parent = NULL;
return NULL;
return this;
}
// Set init references
if (Parent) *Parent = NULL;
Child = NULL;
Member = (BaseMember)? BaseMember : RootMember;
Member = this;
// Split path
Pos = (char*)Path;
@@ -182,7 +195,7 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
Child = &(Member->FirstChild);
while (*Child) {
PrevChild = *Child;
Child = &((*Child)->Next);
Child = &((*Child)->NextPeer);
}
}
else {
@@ -197,7 +210,7 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
Count = 0;
while (*Child && (Count < Index)) {
PrevChild = *Child;
Child = &((*Child)->Next);
Child = &((*Child)->NextPeer);
Count++;
}
}
@@ -205,7 +218,7 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
// Create element if needed
if (!*Child && Create) {
if ((Index == -1) || (Index = Count + 1)) {
*Child = CreateMember( Member, PrevChild, NULL );
*Child = new CDataMember( Member, NULL );
}
}
}
@@ -242,53 +255,55 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
Child = &(Member->FirstChild);
while (*Child && (((*Child)->NameLen != KeyLen) || strncasecmp( (*Child)->Name, Key, KeyLen ))) {
PrevChild = *Child;
Child = &((*Child)->Next);
Child = &((*Child)->NextPeer);
}
if (!*Child && Create) {
*Child = CreateMember( Member, PrevChild, Key, KeyLen );
*Child = new CDataMember( this, Key, KeyLen );
}
}
// Set Parent
if (Last && Parent) {
*Parent = Member;
}
// Next level
Member = *Child;
}
return Child;
return *Child;
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::GetMember( TDataMember * BaseMember, const char * Path, bool Create )
CDataMember * CDataMember::GetFirstChild( const char * Path )
{
TDataMember ** Member;
CDataMember * Member = NULL;
// Get Child
if (!Path || !*Path) {
return ((BaseMember)? BaseMember : NULL);
} else {
Member = GetMemberPtr( BaseMember, Path, Create );
return ((Member)? *Member : NULL);
// Find member
Member = (!Path || !*Path)? this : GetMember( Path, false );
// Check if valid type
if (!Member || ((Member->Type != jtObject) && (Member->Type != jtNull))) {
return NULL;
}
return Member->FirstChild;
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::GetIndexChild( TDataMember * Parent, const int Index )
CDataMember * CDataMember::GetElement( const char * Path, const int Index )
{
TDataMember * Child;
CDataMember * Member = NULL;
CDataMember * Child = NULL;
int Count;
// Get Parent
if (!Parent)
return NULL;
// Find Member
Member = (!Path || !*Path)? this : GetMember( Path, false );
// Get Indexed child
// Check if valid type
if (!Member || ((Member->Type != jtArray) && (Member->Type != jtNull))) {
return NULL;
}
// Find element at position
Count = 0;
Child = Parent->FirstChild;
Child = Member->FirstChild;
while (Child && (Count < Index)) {
Child = Child->Next;
Child = Child->NextPeer;
Count++;
}
@@ -297,38 +312,18 @@ TDataMember * CDataTree::GetIndexChild( TDataMember * Parent, const int Index )
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::GetFirstChild( TDataMember * BaseMember, const char * Path, bool Create )
bool CDataMember::Delete( const char * Path )
{
TDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, Create ))) {
return NULL;
}
// Return child
return Member->FirstChild;
}
//---------------------------------------------------------------------------
bool CDataTree::Delete( TDataMember * BaseMember, const char * Path )
{
TDataMember * Parent;
TDataMember ** Member;
// Validate
if (!BaseMember && (!Path || !*Path)) {
return false;
}
CDataMember * Member;
if (!Path || !*Path) {
// No path - destroy value
DestroyValue( BaseMember );
Clear();
return true;
}
else if ((Member = GetMemberPtr( BaseMember, Path, false, &Parent ))) {
else if ((Member = GetMember( Path, false ))) {
// If valid path, destroy member
DestroyMember( Member );
delete Member;
return true;
}
else {
@@ -337,197 +332,185 @@ bool CDataTree::Delete( TDataMember * BaseMember, const char * Path )
}
//---------------------------------------------------------------------------
bool CDataTree::DeleteAll()
bool CDataMember::SetValue( EDataType pType, const char * pValue, int pLen )
{
// Delete all except root member
while (RootMember->FirstChild) {
DestroyMember( &(RootMember->FirstChild) );
}
return true;
}
//---------------------------------------------------------------------------
Clear();
Type = pType;
bool CDataTree::SetValuePtr( TDataMember * Member, EDataType Type, char * Value, int Len )
{
// Clear previous value
if (Member->Value != NULL || (Member->FirstChild != NULL)) {
DestroyValue( Member );
}
// Set type
Member->Type = Type;
Member->Value = Value;
Member->Len = Len;
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetValue( TDataMember * Member, EDataType Type, const char * Value, int Len )
{
char * NewValue = NULL;
if ((Type == jtString) || (Type == jtFloat) || (Type == jtInt) || (Type == jtBool))
if ((pType == jtString) || (pType == jtFloat) || (pType == jtInt) || (pType == jtBool))
{
// Validate
if (!Value) {
return false;
}
// Check Length
if (Len == -1) {
Len = strlen(Value);
}
// Create copy of value
NewValue = (char*)malloc( Len+1 );
if (Value) {
memcpy( NewValue, Value, Len );
} else {
memset( NewValue, 0, Len );
}
NewValue[Len] = 0;
SetValuePtr( Member, Type, NewValue, Len );
}
else {
// Set null value
SetValuePtr( Member, Type, NULL, 0 );
Len = (pLen == -1)? strlen(pValue) : pLen;
Value = (char*)malloc( Len+1 );
memcpy( Value, pValue, Len );
Value[Len] = 0;
}
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetObject( TDataMember * BaseMember, const char * Path )
bool CDataMember::SetChildObject( const char * Path )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Set as Object
SetValue( Member, jtObject, NULL );
Member->SetValue( jtObject, NULL );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetArray( TDataMember * BaseMember, const char * Path )
bool CDataMember::SetChildArray( const char * Path )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Set as Object
SetValue( Member, jtArray, NULL );
Member->SetValue( jtArray, NULL );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetStr( TDataMember * BaseMember, const char * Path, const char * Value, const int Len )
bool CDataMember::SetChildStr( const char * Path, const char * Value, const int Len )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Create Value
SetValue( Member, jtString, Value, Len );
if (!Value) {
Member->SetValue( jtString, "", 0 );
}
else {
Member->SetValue( jtString, Value, Len );
}
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetInt( TDataMember * BaseMember, const char * Path, const long Value, const char * Mask )
bool CDataMember::SetChildInt( const char * Path, const long Value, const char * Mask )
{
TDataMember * Member;
CDataMember * Member;
char ValueStr[20];
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Create Value
sprintf( ValueStr, ((Mask)? Mask : "%ld"), Value );
SetValue( Member, jtInt, ValueStr );
Member->SetValue( jtInt, ValueStr );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetFloat( TDataMember * BaseMember, const char * Path, const double Value, const char * Mask )
bool CDataMember::SetChildFloat( const char * Path, const double Value, const char * Mask )
{
TDataMember * Member;
CDataMember * Member;
char ValueStr[20];
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Create Value
sprintf( ValueStr, ((Mask)? Mask : "%lf"), Value );
SetValue( Member, jtFloat, ValueStr );
Member->SetValue( jtFloat, ValueStr );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetBool( TDataMember * BaseMember, const char * Path, const bool Value )
bool CDataMember::SetChildBool( const char * Path, const bool Value )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Create Value
SetValue( Member, jtBool, ((Value == 0)? "0" : "1") );
Member->SetValue( jtBool, ((Value == 0)? "0" : "1") );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetNull( TDataMember * BaseMember, const char * Path )
bool CDataMember::SetChildNull( const char * Path )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, true ))) {
if (!(Member = GetMember( Path, true ))) {
return false;
}
// Create Value
SetValue( Member, jtNull, NULL );
Member->SetValue( jtNull, NULL );
return true;
}
//---------------------------------------------------------------------------
EDataType CDataTree::GetType( TDataMember * BaseMember, const char * Path )
const char * CDataMember::GetName( const char * Path )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if (!(Member = GetMember( BaseMember, Path, false ))) {
if (!(Member = GetMember( Path, false ))) {
return NULL;
}
return Member->Name;
}
//---------------------------------------------------------------------------
EDataType CDataMember::GetType( const char * Path )
{
CDataMember * Member;
// Validate
if (!(Member = GetMember( Path, false ))) {
return jtNull;
}
return Member->Type;
}
//---------------------------------------------------------------------------
const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, const char * Default, bool Create )
const int CDataMember::GetLen( const char * Path )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, Create )) &&
if ((Member = GetMember( Path, false ))) {
return Member->Len;
}
else {
return 0;
}
}
//---------------------------------------------------------------------------
const char * CDataMember::GetChildStr( const char * Path, const char * Default, bool Create )
{
CDataMember * Member;
// Validate
if ((Member = GetMember( Path, Create )) &&
((Member->Type == jtString) || (Member->Type == jtFloat) || (Member->Type == jtInt) || (Member->Type == jtBool)) ) {
return Member->Value;
}
else if (Member && Create && (Member->Type == jtNull)) {
SetValue( Member, jtString, Default );
Member->SetValue( jtString, Default );
return Member->Value;
}
else {
@@ -536,18 +519,18 @@ const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, con
}
//---------------------------------------------------------------------------
const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, int &Len, const char * Default, bool Create )
const char * CDataMember::GetChildStr( const char * Path, int &Len, const char * Default, bool Create )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, Create )) &&
if ((Member = GetMember( Path, Create )) &&
((Member->Type == jtString) || (Member->Type == jtFloat) || (Member->Type == jtInt) || (Member->Type == jtBool)) ) {
Len = Member->Len;
return Member->Value;
}
else if (Member && Create && (Member->Type == jtNull)) {
SetValue( Member, jtString, Default );
Member->SetValue( jtString, Default );
Len = Member->Len;
return Member->Value;
}
@@ -558,34 +541,19 @@ const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, int
}
//---------------------------------------------------------------------------
const int CDataTree::GetLen( TDataMember * BaseMember, const char * Path )
const long CDataMember::GetChildInt( const char * Path, long Default, bool Create, const char * Mask )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, false )) &&
((Member->Type == jtString) || (Member->Type == jtFloat) || (Member->Type == jtInt) || (Member->Type == jtBool)) ) {
return Member->Len;
}
else {
return 0;
}
}
//---------------------------------------------------------------------------
const long CDataTree::GetInt( TDataMember * BaseMember, const char * Path, long Default, bool Create, const char * Mask )
{
TDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, Create )) &&
if ((Member = GetMember( Path, Create )) &&
((Member->Type == jtString) || (Member->Type == jtFloat) || (Member->Type == jtInt) || (Member->Type == jtBool)) ) {
return strtol( Member->Value, NULL, 10 );
}
else if (Member && Create && (Member->Type == jtNull)) {
char TempStr[20];
sprintf( TempStr, ((Mask)? Mask : "%ld"), Default );
SetValue( Member, jtInt, TempStr );
Member->SetValue( jtInt, TempStr );
return Default;
}
else {
@@ -594,19 +562,19 @@ const long CDataTree::GetInt( TDataMember * BaseMember, const char * Path, long
}
//---------------------------------------------------------------------------
const double CDataTree::GetFloat( TDataMember * BaseMember, const char * Path, double Default, bool Create, const char * Mask )
const double CDataMember::GetChildFloat( const char * Path, double Default, bool Create, const char * Mask )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, Create )) &&
if ((Member = GetMember( Path, Create )) &&
((Member->Type == jtString) || (Member->Type == jtFloat) || (Member->Type == jtInt) || (Member->Type == jtBool)) ) {
return strtod( Member->Value, NULL );
}
else if (Member && Create && (Member->Type == jtNull)) {
char TempStr[20];
sprintf( TempStr, ((Mask)? Mask : "%lf"), Default );
SetValue( Member, jtFloat, TempStr );
Member->SetValue( jtFloat, TempStr );
return Default;
}
else {
@@ -615,12 +583,12 @@ const double CDataTree::GetFloat( TDataMember * BaseMember, const char * Path,
}
//---------------------------------------------------------------------------
const bool CDataTree::GetBool( TDataMember * BaseMember, const char * Path, bool Default, bool Create )
const bool CDataMember::GetChildBool( const char * Path, bool Default, bool Create )
{
TDataMember * Member;
CDataMember * Member;
// Validate
if ((Member = GetMember( BaseMember, Path, Create ))) {
if ((Member = GetMember( Path, Create ))) {
if (Member->Type == jtString) {
return ((!*Member->Value)? false : true);
}
@@ -634,7 +602,7 @@ const bool CDataTree::GetBool( TDataMember * BaseMember, const char * Path, boo
return ((!strcasecmp( Member->Value, "0" ))? false : true );
}
else if ((Member->Type == jtNull) && Create) {
SetValue( Member, jtBool, ((Default)? "1" : "0") );
Member->SetValue( jtBool, ((Default)? "1" : "0") );
return Default;
}
else {