Major Update:
- Bug fix: BufferCore - set correct auto buffer size
- Change Get/Set methods to use BaseReference and full path instead of
ParentPath and MemberName
- Add Create param to all Get methods (create if not found)
- Implement arrays & parsing of arrays
- Set CJSONparse as friend class to DataTree (access protected methods)
- Print JSON to screen
This commit is contained in:
@@ -794,7 +794,7 @@ int CShiftBuffer::ReadFromFD( int Handle, int MaxRead )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read file descriptor into buffer
|
// Read file descriptor into buffer
|
||||||
DataRemain = (MaxRead > BufSize-BufLen)? BufSize-BufLen : MaxRead;
|
DataRemain = ((MaxRead < 0) || (MaxRead > BufSize-BufLen))? BufSize-BufLen : MaxRead;
|
||||||
while (DataRemain)
|
while (DataRemain)
|
||||||
{
|
{
|
||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
|
|||||||
472
DataTreeCore.cpp
472
DataTreeCore.cpp
@@ -20,8 +20,8 @@
|
|||||||
CDataTree::CDataTree()
|
CDataTree::CDataTree()
|
||||||
{
|
{
|
||||||
// Create Root member of tree
|
// Create Root member of tree
|
||||||
RootObject = CreateMember( NULL );
|
RootMember = CreateMember( NULL );
|
||||||
RootObject->Type = jtObject;
|
RootMember->Type = jtObject;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ CDataTree::~CDataTree()
|
|||||||
{
|
{
|
||||||
// Destroy Members
|
// Destroy Members
|
||||||
DeleteAll();
|
DeleteAll();
|
||||||
DestroyMember( &RootObject );
|
DestroyMember( &RootMember );
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -47,6 +47,28 @@ TDataMember * CDataTree::CreateMember( const char * Name )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CDataTree::AddMember( TDataMember * Parent, TDataMember * Member )
|
||||||
|
{
|
||||||
|
TDataMember ** Child;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!Parent || !Member) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get end of list
|
||||||
|
Child = &(Parent->FirstChild);
|
||||||
|
while (*Child) {
|
||||||
|
Child = &((*Child)->Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add member
|
||||||
|
*Child = Member;
|
||||||
|
Parent->Len++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::DestroyMember( TDataMember ** Member )
|
bool CDataTree::DestroyMember( TDataMember ** Member )
|
||||||
{
|
{
|
||||||
TDataMember * NextMember;
|
TDataMember * NextMember;
|
||||||
@@ -76,101 +98,168 @@ bool CDataTree::DestroyMember( TDataMember ** Member )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::GetParent( const char * ParentPath, TDataMember **Parent )
|
bool CDataTree::DestroyValue( TDataMember * Member )
|
||||||
{
|
{
|
||||||
TDataMember * Member;
|
// Valdate
|
||||||
char * ParentName;
|
if (!Member)
|
||||||
char * Pos;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!Parent) {
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Destroy values
|
||||||
|
if (Member->Value) {
|
||||||
|
free( Member->Value );
|
||||||
|
Member->Value = NULL;
|
||||||
}
|
}
|
||||||
|
while (Member->FirstChild) {
|
||||||
// Set first Parent
|
DestroyMember( &(Member->FirstChild) );
|
||||||
*Parent = RootObject;
|
}
|
||||||
|
Member->Len = 0;
|
||||||
// Check if path provided
|
|
||||||
if (!ParentPath || !*ParentPath) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char * Path, bool Create, TDataMember ** Parent )
|
||||||
|
{
|
||||||
|
char * WorkPath = NULL;
|
||||||
|
TDataMember * Member;
|
||||||
|
TDataMember ** Child = NULL;
|
||||||
|
char * Pos;
|
||||||
|
char * EndPos;
|
||||||
|
char * MemberName;
|
||||||
|
int Index;
|
||||||
|
int Count;
|
||||||
|
bool Last = false;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!Path || !*Path) {
|
||||||
|
if (Parent) *Parent = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
WorkPath = (char*)malloc( strlen(Path)+1 );
|
||||||
|
strcpy( WorkPath, Path );
|
||||||
|
|
||||||
|
// Set init references
|
||||||
|
if (Parent) *Parent = NULL;
|
||||||
|
Child = NULL;
|
||||||
|
Member = (BaseMember)? BaseMember : RootMember;
|
||||||
|
|
||||||
// Split path
|
// Split path
|
||||||
Pos = (char*)ParentPath;
|
Pos = (char*)WorkPath;
|
||||||
while (*Pos)
|
while (Member && *Pos)
|
||||||
{
|
{
|
||||||
// Set Name start
|
// Reset Child reference
|
||||||
ParentName = Pos;
|
Child = NULL;
|
||||||
|
|
||||||
// Find delimeter
|
// Set Name start
|
||||||
while (*Pos && (*Pos != '/')) {
|
MemberName = Pos;
|
||||||
Pos++;
|
|
||||||
|
// Find delimiter
|
||||||
|
if (*Pos == '[')
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (Create && (Member->Type == jtNull)) {
|
||||||
|
Member->Type = jtArray; // Convert to array
|
||||||
|
}
|
||||||
|
if (Member->Type != jtArray) {
|
||||||
|
break; // Can't convert something else to an array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Index value
|
||||||
|
Pos++;
|
||||||
|
while (*Pos && (*Pos != ']')) {
|
||||||
|
Pos++;
|
||||||
|
}
|
||||||
|
if (*Pos != ']') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Index = (int)strtoul( Pos, &EndPos, 10 );
|
||||||
|
if (EndPos != Pos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Pos++;
|
||||||
|
if (!*Pos) {
|
||||||
|
// Last element
|
||||||
|
Last = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find next parent
|
||||||
|
Child = &(Member->FirstChild);
|
||||||
|
Count = 0;
|
||||||
|
while (*Child && (Count < Index)) {
|
||||||
|
Child = &((*Child)->Next);
|
||||||
|
Count++;
|
||||||
|
}
|
||||||
|
if (!*Child && Create) {
|
||||||
|
if (!Index || (Index = Count + 1)) {
|
||||||
|
*Child = CreateMember( NULL );
|
||||||
|
Member->Value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (Create && (Member->Type == jtNull)) {
|
||||||
|
Member->Type = jtObject; // Convert to object
|
||||||
|
}
|
||||||
|
if (Member->Type != jtObject) {
|
||||||
|
break; // Can't convert something else to an object
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get key value
|
||||||
|
while (*Pos && (*Pos != '/') && (*Pos != '[')) {
|
||||||
|
Pos++;
|
||||||
|
}
|
||||||
|
if (!*Pos) {
|
||||||
|
// Last element
|
||||||
|
Last = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
// Zero terminate name
|
// Zero terminate name
|
||||||
if (*Pos) {
|
|
||||||
*Pos = 0;
|
*Pos = 0;
|
||||||
Pos++;
|
Pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next parent
|
// Find next parent
|
||||||
Member = (*Parent)->FirstChild;
|
Child = &(Member->FirstChild);
|
||||||
while (Member && strcasecmp( Member->Name, ParentName )) {
|
while (*Child && strcasecmp( (*Child)->Name, MemberName )) {
|
||||||
Member = Member->Next;
|
Child = &((*Child)->Next);
|
||||||
|
}
|
||||||
|
if (!*Child && Create) {
|
||||||
|
*Child = CreateMember( MemberName );
|
||||||
|
Member->Len++;
|
||||||
}
|
}
|
||||||
if (!Member) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Next parent
|
// Set Parent
|
||||||
|
if (Last && Parent) {
|
||||||
*Parent = Member;
|
*Parent = Member;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
// Next level
|
||||||
|
Member = *Child;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Child;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TDataMember * CDataTree::GetMember( TDataMember * Parent, const char * Name )
|
TDataMember * CDataTree::GetMember( TDataMember * BaseMember, const char * Path, bool Create )
|
||||||
{
|
|
||||||
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;
|
TDataMember ** Member;
|
||||||
|
|
||||||
// Validate
|
// Get Child
|
||||||
if (!Parent || !Name || !*Name) {
|
Member = GetMemberPtr( BaseMember, Path, Create );
|
||||||
return NULL;
|
return *Member;
|
||||||
}
|
|
||||||
|
|
||||||
// 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 )
|
bool CDataTree::Delete( TDataMember * BaseMember, const char * Path )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
TDataMember * Parent;
|
||||||
TDataMember ** Member;
|
TDataMember ** Member;
|
||||||
|
|
||||||
// Check if exists
|
// Check if exists
|
||||||
if (!GetParent( ParentPath, &Parent ) ||
|
if (!(Member = GetMemberPtr( BaseMember, Path, false, &Parent ))) {
|
||||||
!(Member = GetMemberPtr( Parent, Name ))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,224 +272,179 @@ bool CDataTree::Delete( const char * ParentPath, const char * Name )
|
|||||||
|
|
||||||
bool CDataTree::DeleteAll()
|
bool CDataTree::DeleteAll()
|
||||||
{
|
{
|
||||||
while (RootObject->FirstChild) {
|
// Delete all except root member
|
||||||
DestroyMember( &(RootObject->FirstChild) );
|
while (RootMember->FirstChild) {
|
||||||
|
DestroyMember( &(RootMember->FirstChild) );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetMember( TDataMember * Member, EDataType Type, const char * Value, const int Len )
|
bool CDataTree::SetValuePtr( TDataMember * Member, EDataType Type, char * Value, int Len )
|
||||||
{
|
{
|
||||||
// Clear previous value
|
// Clear previous value
|
||||||
if (Member->Value != NULL) {
|
if (Member->Value != NULL) {
|
||||||
free( Member->Value );
|
DestroyValue( Member );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set type
|
// Set type
|
||||||
Member->Type = Type;
|
Member->Type = Type;
|
||||||
|
Member->Value = Value;
|
||||||
|
Member->Len = Len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Set new value
|
bool CDataTree::SetValue( TDataMember * Member, EDataType Type, const char * Value, const int Len )
|
||||||
switch (Type) {
|
{
|
||||||
case jtNull:
|
char * NewValue = NULL;
|
||||||
case jtObject:
|
|
||||||
case jtArray:
|
|
||||||
Member->Len = 0;
|
|
||||||
Member->Value = NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case jtString:
|
if ((Type == jtString) || (Type == jtFloat) || (Type == jtInt) || (Type == jtBool))
|
||||||
case jtFloat:
|
{
|
||||||
case jtInt:
|
// Create copy of value
|
||||||
case jtBool:
|
NewValue = (char *)malloc( sizeof(Member->Len+1) );
|
||||||
Member->Len = (Len == -1)? strlen(Value) : Len;
|
|
||||||
Member->Value = (char *)malloc( sizeof(Member->Len+1) );
|
|
||||||
if (Value) {
|
if (Value) {
|
||||||
memcpy( Member->Value, Value, Member->Len+1 );
|
memcpy( NewValue, Value, Len );
|
||||||
} else {
|
} else {
|
||||||
memset( Member->Value, 0, Member->Len+1 );
|
memset( NewValue, 0, Len );
|
||||||
}
|
}
|
||||||
Member->Value[Member->Len] = 0;
|
NewValue[Len] = 0;
|
||||||
break;
|
SetValuePtr( Member, Type, NewValue, Len );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Set null value
|
||||||
|
SetValuePtr( Member, Type, NULL, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetObject( const char * ParentPath, const char * Name )
|
bool CDataTree::SetObject( TDataMember * BaseMember, const char * Path )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
TDataMember * Member;
|
||||||
TDataMember ** Member;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
SetValue( Member, jtObject, NULL, -1 );
|
||||||
// Create new param if it doesn't exist
|
|
||||||
if (!(Member = GetMemberPtr( Parent, Name ))) {
|
|
||||||
*Member = CreateMember( Name );
|
|
||||||
}
|
|
||||||
SetMember( *Member, jtObject, NULL, -1 );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetStr( const char * ParentPath, const char * Name, const char * Value, const int Len )
|
bool CDataTree::SetStr( TDataMember * BaseMember, const char * Path, const char * Value, const int Len )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
TDataMember * Member;
|
||||||
TDataMember ** Member;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
SetValue( Member, jtString, Value, Len );
|
||||||
// Create new param if it doesn't exist
|
|
||||||
if (!(Member = GetMemberPtr( Parent, Name ))) {
|
|
||||||
*Member = CreateMember( Name );
|
|
||||||
}
|
|
||||||
SetMember( *Member, jtString, Value, Len );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetInt( const char * ParentPath, const char * Name, const long Value )
|
bool CDataTree::SetInt( TDataMember * BaseMember, const char * Path, const long Value )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
TDataMember * Member;
|
||||||
TDataMember ** Member;
|
char ValueStr[20];
|
||||||
char ValueStr[50];
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new param if it doesn't exist
|
|
||||||
if (!(Member = GetMemberPtr( Parent, Name ))) {
|
|
||||||
*Member = CreateMember( Name );
|
|
||||||
}
|
|
||||||
sprintf( ValueStr, "%ld", Value );
|
sprintf( ValueStr, "%ld", Value );
|
||||||
SetMember( *Member, jtInt, ValueStr, -1 );
|
SetValue( Member, jtInt, ValueStr, -1 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetFloat( const char * ParentPath, const char * Name, const double Value )
|
bool CDataTree::SetFloat( TDataMember * BaseMember, const char * Path, const double Value )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
TDataMember * Member;
|
||||||
TDataMember ** Member;
|
char ValueStr[20];
|
||||||
char ValueStr[50];
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new param if it doesn't exist
|
|
||||||
if (!*(Member = GetMemberPtr( Parent, Name ))) {
|
|
||||||
*Member = CreateMember( Name );
|
|
||||||
}
|
|
||||||
sprintf( ValueStr, "%lf", Value );
|
sprintf( ValueStr, "%lf", Value );
|
||||||
SetMember( *Member, jtFloat, ValueStr, -1 );
|
SetValue( Member, jtFloat, ValueStr, -1 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CDataTree::SetBool( const char * ParentPath, const char * Name, const bool Value )
|
bool CDataTree::SetBool( TDataMember * BaseMember, const char * Path, 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;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SetValue( Member, jtBool, ((Value == 0)? "0" : "1"), -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CDataTree::SetNull( TDataMember * BaseMember, const char * Path )
|
||||||
|
{
|
||||||
|
TDataMember * Member;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!(Member = GetMember( BaseMember, Path, true ))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SetValue( Member, jtNull, NULL, -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
EDataType CDataTree::GetType( TDataMember * BaseMember, const char * Path )
|
||||||
|
{
|
||||||
|
TDataMember * Member;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!(Member = GetMember( BaseMember, Path, false ))) {
|
||||||
return jtNull;
|
return jtNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type
|
|
||||||
if ((Member = GetMember( Parent, Name ))) {
|
|
||||||
return Member->Type;
|
return Member->Type;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return jtNull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const char * CDataTree::GetStr( const char * ParentPath, const char * Name, const char * Default )
|
const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, const char * Default, bool Create )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
|
||||||
TDataMember * Member;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if ((Member = GetMember( BaseMember, Path, Create )) && (Member->Type == jtString)) {
|
||||||
return Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtString)) {
|
|
||||||
return Member->Value;
|
return Member->Value;
|
||||||
}
|
}
|
||||||
|
else if (Member && Create && (Member->Type == jtNull)) {
|
||||||
|
SetValue( Member, jtString, Default, strlen(Default) );
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const char * CDataTree::GetStr( const char * ParentPath, const char * Name, int &Len, const char * Default )
|
const char * CDataTree::GetStr( TDataMember * BaseMember, const char * Path, int &Len, const char * Default, bool Create )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
|
||||||
TDataMember * Member;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if ((Member = GetMember( BaseMember, Path, Create )) && (Member->Type == jtString)) {
|
||||||
return Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtString)) {
|
|
||||||
Len = Member->Len;
|
Len = Member->Len;
|
||||||
return Member->Value;
|
return Member->Value;
|
||||||
}
|
}
|
||||||
|
else if (Member && Create && (Member->Type == jtNull)) {
|
||||||
|
SetValue( Member, jtString, Default, strlen(Default) );
|
||||||
|
Len = Member->Len;
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Len = strlen( Default );
|
Len = strlen( Default );
|
||||||
return Default;
|
return Default;
|
||||||
@@ -408,60 +452,58 @@ const char * CDataTree::GetStr( const char * ParentPath, const char * Name, int
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const long CDataTree::GetInt( const char * ParentPath, const char * Name, long Default )
|
const long CDataTree::GetInt( TDataMember * BaseMember, const char * Path, long Default, bool Create )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
|
||||||
TDataMember * Member;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if ((Member = GetMember( BaseMember, Path, Create )) && (Member->Type == jtInt)) {
|
||||||
return Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtInt)) {
|
|
||||||
return strtol( Member->Value, NULL, 10 );
|
return strtol( Member->Value, NULL, 10 );
|
||||||
}
|
}
|
||||||
|
else if (Member && Create && (Member->Type == jtNull)) {
|
||||||
|
char TempStr[20];
|
||||||
|
sprintf( TempStr, "%ld", Default );
|
||||||
|
SetValue( Member, jtInt, TempStr, strlen(TempStr) );
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const double CDataTree::GetFloat( const char * ParentPath, const char * Name, double Default )
|
const double CDataTree::GetFloat( TDataMember * BaseMember, const char * Path, double Default, bool Create )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
|
||||||
TDataMember * Member;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if ((Member = GetMember( BaseMember, Path, Create )) && (Member->Type == jtFloat)) {
|
||||||
return Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtFloat)) {
|
|
||||||
return strtod( Member->Value, NULL );
|
return strtod( Member->Value, NULL );
|
||||||
}
|
}
|
||||||
|
else if (Member && Create && (Member->Type == jtNull)) {
|
||||||
|
char TempStr[20];
|
||||||
|
sprintf( TempStr, "%lf", Default );
|
||||||
|
SetValue( Member, jtInt, TempStr, strlen(TempStr) );
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const bool CDataTree::GetBool( const char * ParentPath, const char * Name, bool Default )
|
const bool CDataTree::GetBool( TDataMember * BaseMember, const char * Path, bool Default, bool Create )
|
||||||
{
|
{
|
||||||
TDataMember * Parent;
|
|
||||||
TDataMember * Member;
|
TDataMember * Member;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Name || !*Name || !GetParent( ParentPath, &Parent )) {
|
if ((Member = GetMember( BaseMember, Path, Create )) && (Member->Type == jtBool)) {
|
||||||
return Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
if ((Member = GetMember( Parent, Name )) && (Member->Type == jtBool)) {
|
|
||||||
return ((!strcasecmp( Member->Value, "0" ))? false : true );
|
return ((!strcasecmp( Member->Value, "0" ))? false : true );
|
||||||
}
|
}
|
||||||
|
else if (Member && Create && (Member->Type == jtNull)) {
|
||||||
|
SetValue( Member, jtInt, ((Default)? "1" : "0"), 1 );
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,41 +43,46 @@ struct SDataMember
|
|||||||
class CDataTree
|
class CDataTree
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
TDataMember * RootObject;
|
TDataMember * RootMember;
|
||||||
|
|
||||||
// Manage Members
|
// Manage Members
|
||||||
TDataMember * CreateMember( const char * Name );
|
TDataMember * CreateMember( const char * Name );
|
||||||
|
bool AddMember( TDataMember * Parent, TDataMember * Member );
|
||||||
bool DestroyMember( TDataMember ** Member );
|
bool DestroyMember( TDataMember ** Member );
|
||||||
|
bool DestroyValue( TDataMember * Member );
|
||||||
|
|
||||||
// Find Member
|
// Find Member
|
||||||
bool GetParent( const char * ParentPath, TDataMember **Parent );
|
TDataMember * GetRootMember() { return RootMember; };
|
||||||
TDataMember * GetMember( TDataMember * Parent, const char * Name );
|
TDataMember ** GetMemberPtr( TDataMember * BaseMember, const char * Path, bool Create, TDataMember ** Parent = NULL );
|
||||||
TDataMember ** GetMemberPtr( TDataMember * Parent, const char * Name );
|
|
||||||
|
|
||||||
// Set Member value
|
// Set Member value
|
||||||
bool SetMember( TDataMember * Member, EDataType Type, const char * Value, const int Len );
|
bool SetValue( TDataMember * Member, EDataType Type, const char * Value, const int Len );
|
||||||
|
bool SetValuePtr( TDataMember * Member, EDataType Type, char * Value, int Len );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDataTree();
|
CDataTree();
|
||||||
~CDataTree();
|
~CDataTree();
|
||||||
|
|
||||||
bool SetObject( const char * ParentPath, const char * Name );
|
EDataType GetType( TDataMember * BaseMember, const char * Path );
|
||||||
bool SetStr( const char * ParentPath, const char * Name, const char * Value = NULL, const int Len = -1 ); // Use Len param if Value contains NULL values
|
TDataMember * GetMember( TDataMember * BaseMember, const char * Path, bool Create = false );
|
||||||
bool SetInt( const char * ParentPath, const char * Name, const long Value );
|
|
||||||
bool SetFloat( const char * ParentPath, const char * Name, const double Value );
|
|
||||||
bool SetBool( const char * ParentPath, const char * Name, const bool Value );
|
|
||||||
bool SetNull( const char * ParentPath, const char * Name );
|
|
||||||
|
|
||||||
const EDataType GetType( const char * ParentPath, const char * Name );
|
const char * GetStr( TDataMember * BaseMember, const char * Path, const char * Default = NULL, bool Create = false );
|
||||||
|
const char * GetStr( TDataMember * BaseMember, const char * Path, int &Len, const char * Default = NULL, bool Create = false );
|
||||||
|
const long GetInt( TDataMember * BaseMember, const char * Path, long Default = 0, bool Create = false );
|
||||||
|
const double GetFloat( TDataMember * BaseMember, const char * Path, double Default = 0.0, bool Create = false );
|
||||||
|
const bool GetBool( TDataMember * BaseMember, const char * Path, bool Default = false, bool Create = false );
|
||||||
|
|
||||||
const char * GetStr( const char * ParentPath, const char * Name, const char * Default = NULL );
|
bool SetObject( TDataMember * BaseMember, const char * Path );
|
||||||
const char * GetStr( const char * ParentPath, const char * Name, int &Len, const char * Default = NULL );
|
bool SetStr( TDataMember * BaseMember, const char * Path, const char * Value = NULL, const int Len = -1 ); // Use Len param if Value contains NULL values
|
||||||
const long GetInt( const char * ParentPath, const char * Name, long Default = 0 );
|
bool SetInt( TDataMember * BaseMember, const char * Path, const long Value );
|
||||||
const double GetFloat( const char * ParentPath, const char * Name, double Default = 0.0 );
|
bool SetFloat( TDataMember * BaseMember, const char * Path, const double Value );
|
||||||
const bool GetBool( const char * ParentPath, const char * Name, bool Default = false );
|
bool SetBool( TDataMember * BaseMember, const char * Path, const bool Value );
|
||||||
|
bool SetNull( TDataMember * BaseMember, const char * Path );
|
||||||
|
|
||||||
bool Delete( const char * ParentPath, const char * Name );
|
bool Delete( TDataMember * BaseMember, const char * Path );
|
||||||
bool DeleteAll();
|
bool DeleteAll();
|
||||||
|
|
||||||
|
friend class CJSONparse;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* REDACORE_DATATREECORE_H_ */
|
#endif /* REDACORE_DATATREECORE_H_ */
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
CJSONparse::CJSONparse( CDataTree * pDataTree )
|
CJSONparse::CJSONparse( CDataTree * pDataTree )
|
||||||
{
|
{
|
||||||
// Parameter tree
|
// Object tree
|
||||||
DataTree = pDataTree;
|
DataTree = pDataTree;
|
||||||
|
|
||||||
// File Operation
|
// File Operation
|
||||||
@@ -54,10 +54,13 @@ CJSONparse::~CJSONparse()
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::LoadFile( const char * FilePath, int pBufLen )
|
bool CJSONparse::LoadFromFile( const char * FilePath, int pBufLen )
|
||||||
{
|
{
|
||||||
TDataMember * RootObject = NULL;
|
TDataMember * RootObject = NULL;
|
||||||
|
|
||||||
|
// Clear Error
|
||||||
|
Error = false;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!FilePath || !FilePath[0]) {
|
if (!FilePath || !FilePath[0]) {
|
||||||
Error = true;
|
Error = true;
|
||||||
@@ -87,7 +90,7 @@ bool CJSONparse::LoadFile( const char * FilePath, int pBufLen )
|
|||||||
|
|
||||||
// Create Root object
|
// Create Root object
|
||||||
DataTree->DeleteAll();
|
DataTree->DeleteAll();
|
||||||
DataTree->GetParent( NULL, &RootObject );
|
RootObject = DataTree->GetRootMember();
|
||||||
Level = 0;
|
Level = 0;
|
||||||
|
|
||||||
// Parse Root Object
|
// Parse Root Object
|
||||||
@@ -112,6 +115,7 @@ bool CJSONparse::LoadFile( const char * FilePath, int pBufLen )
|
|||||||
|
|
||||||
// Success
|
// Success
|
||||||
close( InputHandle );
|
close( InputHandle );
|
||||||
|
InputHandle = -1;
|
||||||
FreeBuffer();
|
FreeBuffer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -164,119 +168,21 @@ void CJSONparse::FreeBuffer()
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::ParseObject( TDataMember * Object )
|
bool CJSONparse::ParseString( char ** Value, int &pLen )
|
||||||
{
|
|
||||||
TDataMember ** ParamPtr = NULL;
|
|
||||||
TDataMember * Param = NULL;
|
|
||||||
char * ParamName = NULL;
|
|
||||||
int Len = 0;
|
|
||||||
|
|
||||||
// Clear Values
|
|
||||||
Error = false;
|
|
||||||
|
|
||||||
// Check for start of Object
|
|
||||||
if (*BufPos != '{') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BufPos++;
|
|
||||||
|
|
||||||
// Set Type
|
|
||||||
Level++;
|
|
||||||
DataTree->SetMember( Object, jtObject, NULL, -1 );
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
// Look for Param Name
|
|
||||||
SkipWhiteSpace();
|
|
||||||
if (*BufPos == '}') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!ParseString( &ParamName, &Len )) {
|
|
||||||
if (!Error) {
|
|
||||||
Error = true;
|
|
||||||
sprintf( ErrorText, "Expect quoted key name on line %d:%ld", LineNo, BufPos-LineMark );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (!Len) {
|
|
||||||
Error = true;
|
|
||||||
sprintf( ErrorText, "Empty parameter name on line %d:%ld", LineNo, BufPos-LineMark );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if Param exists
|
|
||||||
ParamPtr = &(Object->FirstChild);
|
|
||||||
while (*ParamPtr && strcasecmp( (*ParamPtr)->Name, ParamName )) {
|
|
||||||
ParamPtr = &((*ParamPtr)->Next);
|
|
||||||
}
|
|
||||||
// If not exist, add to end of list
|
|
||||||
if (!*ParamPtr) {
|
|
||||||
*ParamPtr = DataTree->CreateMember( NULL );
|
|
||||||
(*ParamPtr)->Name = ParamName;
|
|
||||||
}
|
|
||||||
Param = *ParamPtr;
|
|
||||||
|
|
||||||
// Check for delimiter
|
|
||||||
SkipWhiteSpace();
|
|
||||||
if (*BufPos != ':') {
|
|
||||||
Error = true;
|
|
||||||
sprintf( ErrorText, "Expected ':' delimiter on line %d:%ld", LineNo, BufPos-LineMark );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BufPos++;
|
|
||||||
|
|
||||||
// Get Value
|
|
||||||
SkipWhiteSpace();
|
|
||||||
if (!ParseObject( Param ) &&
|
|
||||||
!Error &&
|
|
||||||
!ParseString( &Param->Value, &Param->Len, &Param->Type ) &&
|
|
||||||
!Error &&
|
|
||||||
!ParsePrimitive( &Param->Value, &Param->Len, &Param->Type )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// One item added
|
|
||||||
Object->Len++;
|
|
||||||
|
|
||||||
// Check if more parameters to follow
|
|
||||||
SkipWhiteSpace();
|
|
||||||
if (*BufPos != ',') {
|
|
||||||
// No more parameters
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BufPos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect end of object
|
|
||||||
if (*BufPos != '}') {
|
|
||||||
Error = true;
|
|
||||||
sprintf( ErrorText, "Closing brace for object '}' expected on line %d:%ld", LineNo, BufPos-LineMark );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BufPos++;
|
|
||||||
Level--;
|
|
||||||
|
|
||||||
// success
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool CJSONparse::ParseString( char ** Value, int *pLen, EDataType *pType )
|
|
||||||
{
|
{
|
||||||
char * Mark;
|
char * Mark;
|
||||||
char * EndMark;
|
char * EndMark;
|
||||||
int Len;
|
int Len;
|
||||||
|
|
||||||
// Clear value
|
|
||||||
Error = false;
|
|
||||||
*Value = NULL;
|
|
||||||
Len = 0;
|
|
||||||
|
|
||||||
// Check for opening quote
|
// Check for opening quote
|
||||||
if (*BufPos != '"') {
|
if (*BufPos != '"') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear values
|
||||||
|
*Value = NULL;
|
||||||
|
Len = 0;
|
||||||
|
|
||||||
// Mark start of quote
|
// Mark start of quote
|
||||||
Mark = BufPos;
|
Mark = BufPos;
|
||||||
BufPos++;
|
BufPos++;
|
||||||
@@ -321,7 +227,7 @@ bool CJSONparse::ParseString( char ** Value, int *pLen, EDataType *pType )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate size of Param name
|
// Validate size of name
|
||||||
Len = BufPos-Mark-2;
|
Len = BufPos-Mark-2;
|
||||||
|
|
||||||
// Create Return value pointer
|
// Create Return value pointer
|
||||||
@@ -330,26 +236,186 @@ bool CJSONparse::ParseString( char ** Value, int *pLen, EDataType *pType )
|
|||||||
(*Value)[Len] = 0;
|
(*Value)[Len] = 0;
|
||||||
|
|
||||||
// Set other parameters
|
// Set other parameters
|
||||||
if (pType)
|
pLen = Len;
|
||||||
*pType = jtString;
|
|
||||||
if (pLen)
|
|
||||||
*pLen = Len;
|
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::ParsePrimitive( char ** Value, int * pLen, EDataType * pType )
|
bool CJSONparse::ParseObject( TDataMember * Object )
|
||||||
{
|
{
|
||||||
|
TDataMember * Member = NULL;
|
||||||
|
char * MemberName = NULL;
|
||||||
|
int Len = 0;
|
||||||
|
|
||||||
|
// Check for start of Object
|
||||||
|
if (*BufPos != '{') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
|
||||||
|
// Set Type
|
||||||
|
Level++;
|
||||||
|
DataTree->SetValue( Object, jtObject, NULL, -1 );
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Look for Member Name
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (*BufPos == '}') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!ParseString( &MemberName, Len )) {
|
||||||
|
if (!Error) {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Expect quoted key name on line %d:%ld", LineNo, BufPos-LineMark );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!Len) {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Empty parameter name on line %d:%ld", LineNo, BufPos-LineMark );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if Member exists
|
||||||
|
Member = DataTree->GetMember( Object, MemberName, true );
|
||||||
|
|
||||||
|
// Check for delimiter
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (*BufPos != ':') {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Expected ':' delimiter on line %d:%ld", LineNo, BufPos-LineMark );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
|
||||||
|
// Get Value
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (!ParseObject( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParseArray( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParseString( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParsePrimitive( Member ))
|
||||||
|
{
|
||||||
|
DataTree->Delete( Object, MemberName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if more parameters to follow
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (*BufPos != ',') {
|
||||||
|
// No more parameters
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect end of object
|
||||||
|
if (*BufPos != '}') {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Closing brace for object '}' expected on line %d:%ld", LineNo, BufPos-LineMark );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
Level--;
|
||||||
|
|
||||||
|
// success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ParseArray( TDataMember * Array )
|
||||||
|
{
|
||||||
|
TDataMember * Member = NULL;
|
||||||
|
|
||||||
|
// Check for start of Object
|
||||||
|
if (*BufPos != '[') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
|
||||||
|
// Set Type
|
||||||
|
Level++;
|
||||||
|
DataTree->SetValue( Array, jtArray, NULL, -1 );
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Look for Member Name
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (*BufPos == ']') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new element
|
||||||
|
Member = DataTree->CreateMember( NULL );
|
||||||
|
|
||||||
|
// Get Value
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (!ParseObject( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParseArray( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParseString( Member ) &&
|
||||||
|
!Error &&
|
||||||
|
!ParsePrimitive( Member ))
|
||||||
|
{
|
||||||
|
DataTree->DestroyMember( &Member );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DataTree->AddMember( Array, Member );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if more parameters to follow
|
||||||
|
SkipWhiteSpace();
|
||||||
|
if (*BufPos != ',') {
|
||||||
|
// No more parameters
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect end of object
|
||||||
|
if (*BufPos != ']') {
|
||||||
|
Error = true;
|
||||||
|
sprintf( ErrorText, "Closing brace for array ']' expected on line %d:%ld", LineNo, BufPos-LineMark );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BufPos++;
|
||||||
|
Level--;
|
||||||
|
|
||||||
|
// success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::ParseString( TDataMember * Member )
|
||||||
|
{
|
||||||
|
char * Value = NULL;
|
||||||
|
int Len = 0;
|
||||||
|
|
||||||
|
// Try to parse
|
||||||
|
if (!ParseString( &Value, Len )) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set string
|
||||||
|
DataTree->SetValuePtr( Member, jtString, Value, Len );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
bool CJSONparse::ParsePrimitive( TDataMember * Member )
|
||||||
|
{
|
||||||
|
char * Value = NULL;
|
||||||
|
int Len = 0;
|
||||||
char * Mark;
|
char * Mark;
|
||||||
char * EndMark;
|
char * EndMark;
|
||||||
int Len;
|
|
||||||
|
|
||||||
// Clear value
|
|
||||||
Error = false;
|
|
||||||
*Value = NULL;
|
|
||||||
Len = 0;
|
|
||||||
|
|
||||||
// Mark start of value
|
// Mark start of value
|
||||||
Mark = BufPos;
|
Mark = BufPos;
|
||||||
@@ -369,52 +435,31 @@ bool CJSONparse::ParsePrimitive( char ** Value, int * pLen, EDataType * pType )
|
|||||||
|
|
||||||
// Check for primitive values
|
// Check for primitive values
|
||||||
if ((Len == 4) && !strncasecmp( Mark, "null", 4 )) {
|
if ((Len == 4) && !strncasecmp( Mark, "null", 4 )) {
|
||||||
if (pType)
|
DataTree->SetValuePtr( Member, jtNull, NULL, -1 );
|
||||||
*pType = jtNull;
|
|
||||||
if (pLen)
|
|
||||||
*pLen = Len;
|
|
||||||
*Value = (char*)malloc( 5 );
|
|
||||||
strcpy( *Value, "null" );
|
|
||||||
}
|
}
|
||||||
else if ((Len == 4) && !strncasecmp( Mark, "true", 4 )) {
|
else if ((Len == 4) && !strncasecmp( Mark, "true", 4 )) {
|
||||||
if (pType)
|
DataTree->SetValue( Member, jtBool, "1", 1 );
|
||||||
*pType = jtBool;
|
|
||||||
if (pLen)
|
|
||||||
*pLen = Len;
|
|
||||||
*Value = (char*)malloc( 5 );
|
|
||||||
strcpy( *Value, "true" );
|
|
||||||
}
|
}
|
||||||
else if ((Len == 5) && !strncasecmp( Mark, "false", 5 )) {
|
else if ((Len == 5) && !strncasecmp( Mark, "false", 5 )) {
|
||||||
if (pType)
|
DataTree->SetValue( Member, jtBool, "0", 1 );
|
||||||
*pType = jtBool;
|
|
||||||
if (pLen)
|
|
||||||
*pLen = Len;
|
|
||||||
*Value = (char*)malloc( 6 );
|
|
||||||
strcpy( *Value, "false" );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Try conversion to int
|
// Try conversion to int
|
||||||
strtol( Mark, &EndMark, 10 );
|
strtol( Mark, &EndMark, 10 );
|
||||||
if (EndMark == BufPos) {
|
if (EndMark == BufPos) {
|
||||||
if (pType)
|
Value = (char*)malloc( Len+1 );
|
||||||
*pType = jtInt;
|
memcpy( Value, Mark, Len );
|
||||||
if (pLen)
|
Value[Len] = 0;
|
||||||
*pLen = Len;
|
DataTree->SetValuePtr( Member, jtInt, Value, Len );
|
||||||
*Value = (char*)malloc( Len+1 );
|
|
||||||
memcpy( *Value, Mark, Len );
|
|
||||||
(*Value)[Len] = 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Try conversion to float
|
// Try conversion to float
|
||||||
strtod( Mark, &EndMark );
|
strtod( Mark, &EndMark );
|
||||||
if (EndMark == BufPos) {
|
if (EndMark == BufPos) {
|
||||||
if (pType)
|
Value = (char*)malloc( Len+1 );
|
||||||
*pType = jtFloat;
|
memcpy( Value, Mark, Len );
|
||||||
if (pLen)
|
Value[Len] = 0;
|
||||||
*pLen = Len;
|
DataTree->SetValuePtr( Member, jtFloat, Value, Len );
|
||||||
*Value = (char*)malloc( Len+1 );
|
|
||||||
memcpy( *Value, Mark, Len );
|
|
||||||
(*Value)[Len] = 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Error = true;
|
Error = true;
|
||||||
@@ -429,7 +474,26 @@ bool CJSONparse::ParsePrimitive( char ** Value, int * pLen, EDataType * pType )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::SaveFile( const char * FilePath, const int Indent )
|
bool CJSONparse::PrintToScreen( const int Indent )
|
||||||
|
{
|
||||||
|
TDataMember * RootObject;
|
||||||
|
|
||||||
|
// Set to StdOut
|
||||||
|
OutputHandle = 1;
|
||||||
|
|
||||||
|
// Save Root object
|
||||||
|
Level = 0;
|
||||||
|
RootObject = DataTree->GetRootMember();
|
||||||
|
PrintObject( RootObject, Indent );
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
close( OutputHandle );
|
||||||
|
OutputHandle = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::SaveToFile( const char * FilePath, const int Indent )
|
||||||
{
|
{
|
||||||
TDataMember * RootObject;
|
TDataMember * RootObject;
|
||||||
|
|
||||||
@@ -443,73 +507,173 @@ bool CJSONparse::SaveFile( const char * FilePath, const int Indent )
|
|||||||
|
|
||||||
// Save Root object
|
// Save Root object
|
||||||
Level = 0;
|
Level = 0;
|
||||||
DataTree->GetParent( NULL, &RootObject );
|
RootObject = DataTree->GetRootMember();
|
||||||
SaveObject( RootObject, Indent );
|
PrintObject( RootObject, Indent );
|
||||||
|
|
||||||
// Close file
|
// Close file
|
||||||
close( OutputHandle );
|
close( OutputHandle );
|
||||||
|
OutputHandle = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CJSONparse::SaveObject( TDataMember * Object, const int Indent )
|
bool CJSONparse::PrintObject( TDataMember * Object, const int Indent )
|
||||||
{
|
{
|
||||||
TDataMember * Param;
|
TDataMember * Member;
|
||||||
|
bool First = true;
|
||||||
|
bool Last = false;
|
||||||
|
int Count = 0;
|
||||||
|
|
||||||
// Opening brace
|
// Opening brace
|
||||||
dprintf( OutputHandle, "{\n" );
|
write( OutputHandle, "{", 1 );
|
||||||
|
Level++;
|
||||||
|
|
||||||
// Extend spacer
|
// Extend spacer
|
||||||
Level++;
|
|
||||||
memset( &Spacer[SpacerLen], ' ', 2 );
|
memset( &Spacer[SpacerLen], ' ', 2 );
|
||||||
SpacerLen += 2;
|
SpacerLen += 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
|
|
||||||
// Save parameters
|
// Save parameters
|
||||||
for (Param = Object->FirstChild; Param != NULL; (Param = Param->Next))
|
for (Member = Object->FirstChild; Member != NULL; (Member = Member->Next))
|
||||||
{
|
{
|
||||||
// Write parameter name
|
// Write parameter name
|
||||||
dprintf( OutputHandle, "%s\"%s\": ", Spacer, Param->Name );
|
if (First) {
|
||||||
|
First = false;
|
||||||
|
if (Object->Name) {
|
||||||
|
write( OutputHandle, "\n", 1 );
|
||||||
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write( OutputHandle, " ", 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
|
}
|
||||||
|
|
||||||
switch (Param->Type)
|
// Print key name
|
||||||
|
write( OutputHandle, "\"", 1 );
|
||||||
|
write( OutputHandle, Member->Name, strlen(Member->Name) );
|
||||||
|
write( OutputHandle, "\" : ", 4 );
|
||||||
|
|
||||||
|
// Print value
|
||||||
|
Last = (++Count >= Object->Len);
|
||||||
|
switch (Member->Type)
|
||||||
{
|
{
|
||||||
case jtNull :
|
case jtNull :
|
||||||
dprintf( OutputHandle, "%s,\n", "null" );
|
write( OutputHandle, "null", 4 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case jtBool :
|
case jtBool :
|
||||||
case jtInt :
|
case jtInt :
|
||||||
case jtFloat :
|
case jtFloat :
|
||||||
dprintf( OutputHandle, "%s,\n", Param->Value );
|
write( OutputHandle, Member->Value, Member->Len );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case jtString :
|
case jtString :
|
||||||
dprintf( OutputHandle, "\"%s\",\n", Param->Value );
|
write( OutputHandle, "\"", 1 );
|
||||||
|
write( OutputHandle, Member->Value, Member->Len );
|
||||||
|
write( OutputHandle, "\"", 1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case jtArray :
|
case jtArray :
|
||||||
dprintf( OutputHandle, "[],\n" );
|
PrintArray( Member, Indent );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case jtObject :
|
case jtObject :
|
||||||
SaveObject( Param, Indent );
|
PrintObject( Member, Indent );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!Last) {
|
||||||
|
write( OutputHandle, ",", 1 );
|
||||||
|
}
|
||||||
|
write( OutputHandle, "\n", 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shorten spacer
|
// Shorten spacer
|
||||||
SpacerLen -= 2;
|
SpacerLen -= 2;
|
||||||
Spacer[SpacerLen] = 0;
|
Spacer[SpacerLen] = 0;
|
||||||
Level--;
|
|
||||||
|
|
||||||
// Closing brace
|
// Closing brace
|
||||||
if (Level == 0) {
|
Level--;
|
||||||
dprintf( OutputHandle, "%s}\n", Spacer );
|
if (Object->Len) {
|
||||||
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
}
|
}
|
||||||
else {
|
write( OutputHandle, "}", 1 );
|
||||||
dprintf( OutputHandle, "%s},\n", Spacer );
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CJSONparse::PrintArray( TDataMember * Array, const int Indent )
|
||||||
|
{
|
||||||
|
TDataMember * Member;
|
||||||
|
bool First = true;
|
||||||
|
bool Last = false;
|
||||||
|
int Count = 0;
|
||||||
|
|
||||||
|
// Opening brace
|
||||||
|
write( OutputHandle, "[", 1 );
|
||||||
|
Level++;
|
||||||
|
|
||||||
|
// Extend spacer
|
||||||
|
memset( &Spacer[SpacerLen], ' ', 2 );
|
||||||
|
SpacerLen += 2;
|
||||||
|
Spacer[SpacerLen] = 0;
|
||||||
|
|
||||||
|
// Save parameters
|
||||||
|
for (Member = Array->FirstChild; Member != NULL; (Member = Member->Next))
|
||||||
|
{
|
||||||
|
// Write parameter name
|
||||||
|
if (First) {
|
||||||
|
First = false;
|
||||||
|
write( OutputHandle, "\n", 1 );
|
||||||
|
}
|
||||||
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
|
|
||||||
|
Last = (++Count >= Array->Len);
|
||||||
|
switch (Member->Type)
|
||||||
|
{
|
||||||
|
case jtNull :
|
||||||
|
write( OutputHandle, "null", 4 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case jtBool :
|
||||||
|
case jtInt :
|
||||||
|
case jtFloat :
|
||||||
|
write( OutputHandle, Member->Value, Member->Len );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case jtString :
|
||||||
|
write( OutputHandle, "\"", 1 );
|
||||||
|
write( OutputHandle, Member->Value, Member->Len );
|
||||||
|
write( OutputHandle, "\"", 1 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case jtArray :
|
||||||
|
PrintArray( Member, Indent );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case jtObject :
|
||||||
|
PrintObject( Member, Indent );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!Last) {
|
||||||
|
write( OutputHandle, ",", 1 );
|
||||||
|
}
|
||||||
|
write( OutputHandle, "\n", 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shorten spacer
|
||||||
|
SpacerLen -= 2;
|
||||||
|
Spacer[SpacerLen] = 0;
|
||||||
|
|
||||||
|
// Closing brace
|
||||||
|
Level--;
|
||||||
|
if (Array->Len) {
|
||||||
|
write( OutputHandle, Spacer, SpacerLen );
|
||||||
|
}
|
||||||
|
write( OutputHandle, "]", 1 );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -61,18 +61,23 @@ private:
|
|||||||
BufPos++;
|
BufPos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool ParseString( char ** Value, int &pLen );
|
||||||
bool ParseObject( TDataMember * Object );
|
bool ParseObject( TDataMember * Object );
|
||||||
bool ParseString( char ** Value, int * pLen = NULL, EDataType * pType = NULL );
|
bool ParseArray( TDataMember * Array );
|
||||||
bool ParsePrimitive( char ** Value, int * pLen = NULL, EDataType * pType = NULL );
|
bool ParseString( TDataMember * Member );
|
||||||
|
bool ParsePrimitive( TDataMember * Member );
|
||||||
|
|
||||||
bool SaveObject( TDataMember * Object, const int Indent );
|
bool PrintObject( TDataMember * Object, const int Indent );
|
||||||
|
bool PrintArray( TDataMember * Object, const int Indent );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CJSONparse( CDataTree * pDataTree );
|
CJSONparse( CDataTree * pDataTree );
|
||||||
~CJSONparse();
|
~CJSONparse();
|
||||||
|
|
||||||
bool LoadFile( const char * FilePath, int pBufLen = 500 );
|
bool PrintToScreen( const int Indent );
|
||||||
bool SaveFile( const char * FilePath, const int ValueTab = 20 );
|
|
||||||
|
bool LoadFromFile( const char * FilePath, int pBufLen = 500 );
|
||||||
|
bool SaveToFile( const char * FilePath, const int Indent = 2 );
|
||||||
|
|
||||||
const char * GetError() { return ((Error)? ErrorText : "Success"); };
|
const char * GetError() { return ((Error)? ErrorText : "Success"); };
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user