Core of XTLP are two classes - xtlpNode and xtlpNodesStack.
Their definition looks like:
typedef struct xtlpNode_t
{
   char* Name;
   xtlpPair* Pairs;
   struct xtlpNode_t** Childs;
   void* private__;
} xtlpNode;
typedef struct xtlpNodesStack_t
{
   void* private__0;
   void* private__1;
} xtlpNodesStack;
xtlpNode
Every xtlpNode represents section of XTL file. Due to every section may be named or unnamed,
Name member may contain empty string (pointer always is valid).
Pairs are keys and their values defined in node scope.
Access to subsections is done through
Childs member.
private__ member is only for internal usage.
xtlpNodesStack
This class keeps all necessary resources. Do not free this manually - for creation you must use
xtlpMakeStack and for deallocation
xtlpRemoveStack. All private memebers are for only internal usage.
Access to subsections is done through
Childs member.
private__ member is only for internal usage.
Memory management
Firstly for open, read and process XTL file you have to call
xtlpMakeStack function. It takes two arguments - FileName and StackAddress. FileName is just path to your xtl file. StackAddress is output parameter. It must be not NULL. If it is not, then undefined behavior will appear.
Recommended way is just define xtlpNodesStack on memory stack, initialize it as zero and pass it by reference. Returned value is array of pointers to nodes in root scope.
Second function is
xtlpRemoveStack. It deallocates everything what has been allocated earlier by xtlpMakeStack function. What do you have to pass are just xtlpNodesStack data passed by reference and returned array of nodes in root scope.
How to use - example
Firstly, define XTL file named cfg.xtl:
<XTH
    v='100'
<students
    <student0
        name='Ben'
        age='23'
    <student1
        name='John
        age='28'
        <grades
            physical_education='4'
            biology='3'
            chemistry='2'
            physics='5'
<
    unnamed_key='ghf'
Now define our C code in xtl.c:
#include <xtlp-100.h>
#include <stddef.h>
#include <stdio.h>
void DisplayContent(const xtlpNodes Nodes)
{
    for (int NodeID = 0; Nodes[NodeID] != NULL; NodeID++)
    {
        printf("Node name: %s\n", Nodes[NodeID]->Name);
        for (int PairID = 0; Nodes[NodeID]->Pairs[PairID].Key != NULL; PairID++)
        {
            printf("Pair: %s = %s\n", Nodes[NodeID]->Pairs[PairID].Key, Nodes[NodeID]->Pairs[PairID].Value);
        }
        DisplayContent(Nodes[NodeID]->Childs);
    }
}
int main()
{
    xtlpNodesStack Stack = {};
    xtlpNodes RootNodes = xtlpMakeStack("cfg.xtl", &Stack);
    DisplayContent(Nodes);
    xtlpRemoveStack(&Stack, Nodes);
    return 0;
}
We will start overview from setup to read XTL file. As you can see
xtlpNodesStack is initialized with zeros.
This is important, because on other hand potential undefined behavior will appear.
Nextly we just call
xtlpMakeStack function which read and process XTL file to achieve data structure based on tree. Make attention to pass our earlier created xtlpNodesStack object by reference!
Passing invalid pointer will result as undefined behavior. After processing we get RootNodes variable which contains all nodes from root scope of tree. Starting from them we can check data recursively. This is what is going on in our
DisplayContent function.
After printing everything into console we should deallocate all memory by calling
xtlpRemoveStack function.
So, when walkthrough of code is done, now compile our code:
$ gcc -std=c23 -O3 -o xtl_exe xtl.c -lxtpc
$ sudo chmod +x xtl_exe
$ ./xtl_exe
Then we will see content of our xtl file:
Node name: XTH
Pair: v = 100
Node name: students
Node name: student0
Pair: age = 23
Pair: name = Ben
Node name: student1
Pair: age = 28
Pair: name = John
Node name: grades
Pair: biology = 3
Pair: chemistry = 2
Pair: physical_education = 4
Pair: physics = 5
Node name: null
Pair: unnamed_key = ghf
Make some attention for node named
null. This is unnamed section - just XTLP automatically renames unnamed sections into
null.