alcjzk / Webserv

0 stars 0 forks source link

Initial TINI parser implementation #5

Closed lsileoni closed 10 months ago

lsileoni commented 10 months ago

Work done

This is the primary implementation of a parser to the TINI format, a format, which is somewhere between INI and TOML.

The basic premise of the format goes as follows:

You have context switches, which determine at which point in the tree you are inserting and how. Then you have insertions to those contexts via simple key-value insertion.

As an example

[a.b.c] first checks if a map 'a' exists, if it doesn't, it will create it and repeat the process until all the maps have been created. This means the "context" of the parser points at map c, which is nested inside of b and a. Then any subsequent key-value pairs in the following lines will append to that context.

So if we have

[a.b]
key=value
one=two

Maps a, b will be created and map b will contain the aforementioned two key value pairs.

TINI also has vectors. Vectors are denoted via two square brackets. [[vector]] A repetition of a vector with the same name denotes a new map appended to the vector's context. This can be seen in the servers example within the main.cpp file.

This statment creates a vector of TiniNodes. TiniNodes are effectively an optional type of one of the following types:

std::vector<TiniNode *> *_vectorValue;
std::map<std::string, TiniNode *> *_mapValue;
std::string *_stringValue;

Within the TiniNode class, they are tagged by an enum. Before TiniNodes are created at all, there's a validation loop, that runs on the input, which checks for errors in the configuration and gives detailed line by line analysis on where those errors are and what category they are.

The basic validation loop

image

Demonstration

Input:

qdqjd;][d;][;e]1[]
[[spamvector]]
    key=value
    value=key
[d dijqwdoijqw oidq- spamvector]]
    key=value
    value=key
[abc[=[[][][][]
    key=value
    value=key
[[spa..mvector]]
    key=value
    value=key
    [key=value]

[a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u
    key
    value=key

    key

Output:

                 v
qdqjd;][d;][;e]1[]
Error: Only Key Provided at R: 1 C: 18

                 v
[ddijqwdoijqwoidq-spamvector]]
Error: Unexpected Token at R: 5 C: 18

    v
[abc[=[[][][][]
Error: Unexpected Token at R: 8 C: 5

      v
[[spa..mvector]]
Error: Unexpected Token at R: 11 C: 7

    v
[key=value]
Error: Unexpected Token at R: 14 C: 5

                                         v
[a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u
Error: Brackets Imbalanced at R: 16 C: 42

  v
key
Error: Only Key Provided at R: 17 C: 3

  v
key
Error: Only Key Provided at R: 20 C: 3

Found a total of 8 errors in the configuration!
[error] TiniTree: constructTree: FATAL (in ./src/main.cpp:45)

Usage of TINI in code

I provided an example usage of TINI in the main.cpp file.

TiniTree tree; // Creates an instance of the TINI tree (this can throw)
TiniNode& root = tree.getRoot(); // Once the tree has been created, you can get a reference to the root TiniNode

// With how the TiniNode is structured, you can recursively print and traverse any TiniNode from top down easily.

root.printContents(0, ""); // This prints the whole tree

root["a"]["b"]["c"].printContents(0, ""); // This prints the contents of the "c" map.

// This is how you print the maps of a vector.  for example one that contains servers
for (auto n : root["http"]["servers"].getVectorValue())
    n->printContents(0, "");

// This is how you get access to a single value of a key-value pair in TINI
auto v = root["root_map_value"].getStringValue();
lsileoni commented 10 months ago

Valgrind shows no leaks, static analysis from scan-build shows no issues, merging.