Files
redAcore/DataTreeCore.cpp
Charl Wentzel b823bd7ea7 Important Update: (incomplete)
- Split CConfigCore into two classes:
  - DataTreeCore.h - Tree data structure and access
  - JSONparseCore.h - JSON parsing functionality
- Renamed TConfigParam struct to TDataMember
- Renamed most of CDataTreeCore methods
2017-03-23 20:53:32 +02:00

471 lines
12 KiB
C++

/*
* DataTreeCore.cpp
*
* Created on: 5 Mar 2017
* Author: wentzelc
*/
// redA Libraries
#include "DataTreeCore.h"
// Standard C/C++ Libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
//---------------------------------------------------------------------------
CDataTree::CDataTree()
{
// Create Root member of tree
RootObject = CreateMember( NULL );
RootObject->Type = jtObject;
}
//---------------------------------------------------------------------------
CDataTree::~CDataTree()
{
// Destroy Members
DeleteAll();
DestroyMember( &RootObject );
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::CreateMember( const char * Name )
{
TDataMember * Member;
Member = (TDataMember *)calloc( 1, sizeof(TDataMember) );
if (Name && *Name)
{
Member->Name = (char *)malloc( strlen( Name )+1 );
strcpy( Member->Name, Name );
}
return Member;
}
//---------------------------------------------------------------------------
bool CDataTree::DestroyMember( TDataMember ** Member )
{
TDataMember * NextMember;
// Valdate
if (!Member || !*Member)
return false;
// Get next param in list
NextMember = (*Member)->Next;
// Destroy
if ((*Member)->Name)
free( (*Member)->Name );
if ((*Member)->Value)
free( (*Member)->Value );
while ((*Member)->FirstChild) {
DestroyMember( &((*Member)->FirstChild) );
}
free( *Member );
// Restore list integrity
*Member = NextMember;
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::GetParent( const char * ParentPath, TDataMember **Parent )
{
TDataMember * Member;
char * ParentName;
char * Pos;
// Validate
if (!Parent) {
return false;
}
// Set first Parent
*Parent = RootObject;
// Check if path provided
if (!ParentPath || !*ParentPath) {
return true;
}
// Split path
Pos = (char*)ParentPath;
while (*Pos)
{
// Set Name start
ParentName = Pos;
// Find delimeter
while (*Pos && (*Pos != '/')) {
Pos++;
}
// Zero terminate name
if (*Pos) {
*Pos = 0;
Pos++;
}
// Find next parent
Member = (*Parent)->FirstChild;
while (Member && strcasecmp( Member->Name, ParentName )) {
Member = Member->Next;
}
if (!Member) {
return false;
}
// Set Next parent
*Parent = Member;
}
return true;
}
//---------------------------------------------------------------------------
TDataMember * CDataTree::GetMember( TDataMember * Parent, const char * Name )
{
TDataMember * Member;
// Validate
if (!Parent || !Name || !*Name) {
return NULL;
}
// Get Member
Member = Parent->FirstChild;
while (Member && strcasecmp( Member->Name, Name ))
Member = Member->Next;
return Member;
}
//---------------------------------------------------------------------------
TDataMember ** CDataTree::GetMemberPtr( TDataMember * Parent, const char * Name )
{
TDataMember ** Member;
// Validate
if (!Parent || !Name || !*Name) {
return NULL;
}
// Get Member
Member = &(Parent->FirstChild);
while (Member && strcasecmp( (*Member)->Name, Name ))
Member = &((*Member)->Next);
return Member;
}
//---------------------------------------------------------------------------
bool CDataTree::Delete( const char * ParentPath, const char * Name )
{
TDataMember * Parent;
TDataMember ** Member;
// Check if exists
if (!GetParent( ParentPath, &Parent ) ||
!(Member = GetMemberPtr( Parent, Name ))) {
return false;
}
// Destroy
DestroyMember( Member );
Parent->Len--;
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::DeleteAll()
{
while (RootObject->FirstChild) {
DestroyMember( &(RootObject->FirstChild) );
}
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetMember( TDataMember * Member, EDataType Type, const char * Value, const int Len )
{
// Clear previous value
if (Member->Value != NULL) {
free( Member->Value );
}
// Set type
Member->Type = Type;
// Set new value
switch (Type) {
case jtNull:
case jtObject:
case jtArray:
Member->Len = 0;
Member->Value = NULL;
break;
case jtString:
case jtFloat:
case jtInt:
case jtBool:
Member->Len = (Len == -1)? strlen(Value) : Len;
Member->Value = (char *)malloc( sizeof(Member->Len+1) );
if (Value) {
memcpy( Member->Value, Value, Member->Len+1 );
} else {
memset( Member->Value, 0, Member->Len+1 );
}
Member->Value[Member->Len] = 0;
break;
}
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetObject( const char * ParentPath, const char * Name )
{
TDataMember * Parent;
TDataMember ** Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
SetMember( *Member, jtObject, NULL, -1 );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetStr( const char * ParentPath, const char * Name, const char * Value, const int Len )
{
TDataMember * Parent;
TDataMember ** Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
SetMember( *Member, jtString, Value, Len );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetInt( const char * ParentPath, const char * Name, const long Value )
{
TDataMember * Parent;
TDataMember ** Member;
char ValueStr[50];
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
sprintf( ValueStr, "%ld", Value );
SetMember( *Member, jtInt, ValueStr, -1 );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetFloat( const char * ParentPath, const char * Name, const double Value )
{
TDataMember * Parent;
TDataMember ** Member;
char ValueStr[50];
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!*(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
sprintf( ValueStr, "%lf", Value );
SetMember( *Member, jtFloat, ValueStr, -1 );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetBool( const char * ParentPath, const char * Name, const bool Value )
{
TDataMember * Parent;
TDataMember ** Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!*(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
SetMember( *Member, jtBool, ((Value == 0)? "0" : "1"), -1 );
return true;
}
//---------------------------------------------------------------------------
bool CDataTree::SetNull( const char * ParentPath, const char * Name )
{
TDataMember * Parent;
TDataMember ** Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return false;
}
// Create new param if it doesn't exist
if (!*(Member = GetMemberPtr( Parent, Name ))) {
*Member = CreateMember( Name );
}
SetMember( *Member, jtNull, NULL, -1 );
return true;
}
//---------------------------------------------------------------------------
const EDataType CDataTree::GetType( const char * ParentPath, const char * Name )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return jtNull;
}
// Return type
if ((Member = GetMember( Parent, Name ))) {
return Member->Type;
}
else {
return jtNull;
}
}
//---------------------------------------------------------------------------
const char * CDataTree::GetStr( const char * ParentPath, const char * Name, const char * Default )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return Default;
}
// Return value
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtString)) {
return Member->Value;
}
else {
return Default;
}
}
//---------------------------------------------------------------------------
const char * CDataTree::GetStr( const char * ParentPath, const char * Name, int &Len, const char * Default )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return Default;
}
// Return value
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtString)) {
Len = Member->Len;
return Member->Value;
}
else {
Len = strlen( Default );
return Default;
}
}
//---------------------------------------------------------------------------
const long CDataTree::GetInt( const char * ParentPath, const char * Name, long Default )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return Default;
}
// Return value
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtInt)) {
return strtol( Member->Value, NULL, 10 );
}
else {
return Default;
}
}
//---------------------------------------------------------------------------
const double CDataTree::GetFloat( const char * ParentPath, const char * Name, double Default )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return Default;
}
// Return value
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtFloat)) {
return strtod( Member->Value, NULL );
}
else {
return Default;
}
}
//---------------------------------------------------------------------------
const bool CDataTree::GetBool( const char * ParentPath, const char * Name, bool Default )
{
TDataMember * Parent;
TDataMember * Member;
// Validate
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
return Default;
}
// Return value
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtBool)) {
return ((!strcasecmp( Member->Value, "0" ))? false : true );
}
else {
return Default;
}
}
//---------------------------------------------------------------------------