Fast parser of SetFile format
  • MQL5 86.5%
  • MQL4 13.5%
Find a file
Nique_372 1dcaae57ae
2026-07-10 13:34:09 -05:00
Src new files added 2026-07-07 18:35:33 -05:00
Test 2026-07-10 13:34:09 -05:00
dependencies.json Actualizar dependencies.json 2026-07-07 23:48:15 +00:00
LICENSE Añadir LICENSE 2026-07-07 15:13:26 +00:00
README.md new files added 2026-07-07 18:45:06 -05:00
SetFileByLeo.mqproj Generated by MQL5 Wizard 2026-07-06 12:43:43 -05:00

A high-performance, memory-free .set file parser for MQL5, based on a flat tape architecture.
Single-pass iterative state machine (as is, without extra loops, "pure" O(n)): no recursion, no dynamic memory fragmentation, no overhead from function calls.


Main Features

  • Tape-based zero-alloc model: the entire .set file is parsed into a single contiguous long[] array
  • Single flat loop: one switch over a token enum, no helper function calls during parsing, strictly O(n)
  • JIT perfect-hash over the ROOT: unlike JSON, a .set file is always a flat key=value map with no nested objects or arrays, so there can only ever be one hashable table per file (the ROOT). Access starts as linear scanning (StrEquals); once the ROOT passes TSN_SETFILE_JIT_MIN_REF_TO_HASING accesses, a minimal perfect hash table is built for it on the fly (k = n, no slack), promoting subsequent lookups to O(1). No FNV hashing is computed upfront during parsing.
  • Two value formats per line: key=value (non-optimizable) and key=value||start||step||stop||Y / ...||N (optimizable, with an enabled/disabled flag)
  • Handle-based navigation: CSetNode is a lightweight struct (pointer + two ints), copying is free
  • In-place mutation: SetInt, SetDbl, SetBool, SetEnabled modify the tape directly without re-parsing
  • Iterator support: CSetIteratorObj to walk every entry in the file
  • Comment detection: lines starting with ; are skipped during parsing
  • Compiled tape cache (.settc): SaveCompiled persists the tape, the source .set (or a reference to its file), and the perfect-hash table already built — so a reload via AssingFile skips parsing entirely and keeps the ROOT already hashed at O(1)

Parse and access

#include "Src\Node.mqh"

TSN::CSetFileParser setfile;
const string set = "InpValor=10\n"
                    "InpVa=aaaaaaaa\n"
                    "InpS=10.0\n"
                    "InpMul=10||20||1||30||Y\n"
                    "InpBoolean=true||false||0||true||Y\n";

setfile.Assing(set);
setfile.CorrectPading();
setfile.Parse();

TSN::CSetNode root = setfile.GetRoot();
int valor = (int)root["InpValor"].Value().ToInt();
string va = root["InpVa"].Value().ToString();
int step = (int)root["InpMul"].Step().ToInt();
bool b = root["InpBoolean"].Value().ToBool();

Iterate every entry

TSN::CSetIteratorObj it = root.BeginObj();
while(it.IsValid())
 {
  PrintFormat("%s : %s", it.Key(), it.Val().ToString());
  it.Next();
 }

Positional and key-based access

string keys[];
int total = root.GetKeys(keys);

string key_two = root.AtObjKey(2);
int pos  = root.KeyToPosition(key_two);
bool exists = root.HasKey("InpMul");

Parse from file

TSN::CSetFileParser setfile;
setfile.AssingFile("data.set", false);
setfile.Parse();

Compile and reload a .settc tape cache

SaveCompiled writes the parsed tape (plus the source .set and the perfect-hash table, if already built) to a binary .settc file. Reloading it via AssingFile skips parsing entirely:

//--- Compile once
TSN::CSetFileParser setfile;
setfile.AssingFile("data.set", false);
setfile.Parse();
setfile.GetRoot()["InpMul"]; // (optional) warm up the perfect-hash table before saving
setfile.SaveCompiled("data.settc", false);

//--- Reload later — no Parse() needed, tape and hash table are restored as-is
TSN::CSetFileParser setfile2;
setfile2.AssingFile("data.settc", false);
TSN::CSetNode root = setfile2.GetRoot();

There's also an overload that stores a reference to an external .set file instead of embedding it:

setfile.SaveCompiled("data.settc", false, "data.set", false);

Performance

Benchmark: TestOptim.set (100.0 KB, 1891 lines — a mix of strings, booleans, numbers, and optimizable entries), 6000 iterations, same file and same machine.

Note: here we measure how quickly the .set file is parsed. All benchmarks are located in: Test\

There are currently no other public .set parsing libraries in MQL5 to compare against, so as a reference we use Test\AiCode.mqh — an alternative, AI-generated implementation over the same tape format.

Parser Language Time (ms, total / 6000 iter)
SetFileByLeo MQL5 1050.3
Claude Sonnet 5 (Effort=Max) (AI reference, tape-based, 90 minutes for devoloping fast setfile parser, iterations +20) MQL5 1503.9

Performance notes

  • Machine: Laptop Lenovo (~2017), Windows 10 build 19045, Intel Core i5-8250U @ 1.60GHz, AVX2, GMT-5
  • MQL5 run: MetaTrader 5 x64 build 5836

Repository Structure

SetFileByLeo/
├── Src/  # Full code (Def, Node, Parser)
└── Test/ # Test and Benchmarks (vs)

License

Read Full License By downloading or using this repository, you accept the license terms.


Requirements

See dependencies.json for the full list.


Installation

cd "C:\Users\YOUR_USER\AppData\Roaming\MetaQuotes\Terminal\YOUR_ID\MQL5\Shared Projects"
tsndep install "https://forge.mql5.io/nique_372/SetFileByLeo.git"

Requires the tsndep package, available on PyPI. It automatically downloads and installs all declared dependencies.


Quick Start

1. Include the library:

#include "..\SetFileByLeo\Src\Node.mqh"

2. Parse and access:

TSN::CSetFileParser setfile;
setfile.Assing(my_set_string);
setfile.CorrectPading();
if(setfile.Parse())
 {
  TSN::CSetNode root = setfile.GetRoot();
  double lot = root["LotSize"].Value().ToDouble(0.0);
 }

3. Re-parse without re-copying (benchmark pattern):

setfile.Assing(raw_string);  // copy once
for(int i = 0; i < 1000; i++)
  setfile.Parse();            // re-parse in-place

Contact