Important Update:
- Improve "printing" for JSON with single & multi line objects - Fix bugs in getting, setting & creating array elements - "array[]" allowed to create/add element at end of an array - No longer duplicate get() path (reduce memory allocation) - added NameLen to TMember to eliminate zero-terminate requirement - Fix ReadfromXXX() return values
This commit is contained in:
@@ -40,7 +40,8 @@ TDataMember * CDataTree::CreateMember( const char * Name )
|
||||
Member = (TDataMember *)calloc( 1, sizeof(TDataMember) );
|
||||
if (Name && *Name)
|
||||
{
|
||||
Member->Name = (char *)malloc( strlen( Name )+1 );
|
||||
Member->Len = strlen( Name );
|
||||
Member->Name = (char *)malloc( Member->Len+1 );
|
||||
strcpy( Member->Name, Name );
|
||||
}
|
||||
return Member;
|
||||
@@ -119,12 +120,12 @@ bool CDataTree::DestroyValue( TDataMember * Member )
|
||||
|
||||
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;
|
||||
char * Key;
|
||||
unsigned short KeyLen;
|
||||
int Index;
|
||||
int Count;
|
||||
bool Last = false;
|
||||
@@ -134,8 +135,6 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
|
||||
if (Parent) *Parent = NULL;
|
||||
return NULL;
|
||||
}
|
||||
WorkPath = (char*)malloc( strlen(Path)+1 );
|
||||
strcpy( WorkPath, Path );
|
||||
|
||||
// Set init references
|
||||
if (Parent) *Parent = NULL;
|
||||
@@ -143,15 +142,12 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
|
||||
Member = (BaseMember)? BaseMember : RootMember;
|
||||
|
||||
// Split path
|
||||
Pos = (char*)WorkPath;
|
||||
Pos = (char*)Path;
|
||||
while (Member && *Pos)
|
||||
{
|
||||
// Reset Child reference
|
||||
Child = NULL;
|
||||
|
||||
// Set Name start
|
||||
MemberName = Pos;
|
||||
|
||||
// Find delimiter
|
||||
if (*Pos == '[')
|
||||
{
|
||||
@@ -163,40 +159,61 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
|
||||
break; // Can't convert something else to an array
|
||||
}
|
||||
|
||||
// Set Index start
|
||||
Pos++;
|
||||
Key = Pos;
|
||||
|
||||
// Get Index value
|
||||
Pos++;
|
||||
while (*Pos && (*Pos != ']')) {
|
||||
while (*Pos && (*Pos != ']'))
|
||||
Pos++;
|
||||
}
|
||||
if (*Pos != ']') {
|
||||
if (!*Pos)
|
||||
break;
|
||||
}
|
||||
Index = (int)strtoul( Pos, &EndPos, 10 );
|
||||
if (EndPos != Pos) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if last
|
||||
Pos++;
|
||||
if (!*Pos) {
|
||||
// Last element
|
||||
if (!*Pos)
|
||||
Last = true;
|
||||
|
||||
if (Pos == Key+1) {
|
||||
// Empty bracket only allowed for create
|
||||
if (!Create)
|
||||
break;
|
||||
|
||||
// find end of list
|
||||
Child = &(Member->FirstChild);
|
||||
while (*Child)
|
||||
Child = &((*Child)->Next);
|
||||
}
|
||||
else {
|
||||
// Get requested index
|
||||
Index = (int)strtoul( Key, &EndPos, 10 );
|
||||
if (EndPos != Pos-1)
|
||||
break;
|
||||
|
||||
// Find element at requested index
|
||||
Child = &(Member->FirstChild);
|
||||
Count = 0;
|
||||
while (*Child && (Count < Index)) {
|
||||
Child = &((*Child)->Next);
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Find next parent
|
||||
Child = &(Member->FirstChild);
|
||||
Count = 0;
|
||||
while (*Child && (Count < Index)) {
|
||||
Child = &((*Child)->Next);
|
||||
Count++;
|
||||
}
|
||||
// Create element if needed
|
||||
if (!*Child && Create) {
|
||||
if (!Index || (Index = Count + 1)) {
|
||||
*Child = CreateMember( NULL );
|
||||
Member->Value++;
|
||||
Member->Len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip separator
|
||||
if (*Pos == '/') {
|
||||
Pos++;
|
||||
}
|
||||
|
||||
// Validate
|
||||
if (Create && (Member->Type == jtNull)) {
|
||||
Member->Type = jtObject; // Convert to object
|
||||
@@ -206,26 +223,25 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
|
||||
}
|
||||
|
||||
// Get key value
|
||||
Key = Pos;
|
||||
KeyLen = 0;
|
||||
while (*Pos && (*Pos != '/') && (*Pos != '[')) {
|
||||
KeyLen++;
|
||||
Pos++;
|
||||
}
|
||||
|
||||
// More elements?
|
||||
if (!*Pos) {
|
||||
// Last element
|
||||
Last = true;
|
||||
}
|
||||
else {
|
||||
// Zero terminate name
|
||||
*Pos = 0;
|
||||
Pos++;
|
||||
}
|
||||
|
||||
// Find next parent
|
||||
Child = &(Member->FirstChild);
|
||||
while (*Child && strcasecmp( (*Child)->Name, MemberName )) {
|
||||
while (*Child && ((*Child)->NameLen != KeyLen) && strncasecmp( (*Child)->Name, Key, KeyLen )) {
|
||||
Child = &((*Child)->Next);
|
||||
}
|
||||
if (!*Child && Create) {
|
||||
*Child = CreateMember( MemberName );
|
||||
*Child = CreateMember( Key );
|
||||
Member->Len++;
|
||||
}
|
||||
}
|
||||
@@ -238,10 +254,6 @@ TDataMember ** CDataTree::GetMemberPtr( TDataMember * BaseMember, const char *
|
||||
// Next level
|
||||
Member = *Child;
|
||||
}
|
||||
|
||||
// Destroy temp path
|
||||
free( WorkPath );
|
||||
|
||||
return Child;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user