JsonParserByLeo/Src/BuilderDefs.mqh

421 líneas
12 KiB
MQL5

2026-09-19 22:46:26 -05:00
//+------------------------------------------------------------------+
2026-07-13 18:47:16 -05:00
//| BuilderDefs.mqh |
//| Copyright 2026, Niquel Mendoza. |
//| https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
#property link "https://www.mql5.com/"
#property strict
#ifndef JSONPARSERBYLEO_SRC_BUILDERSDEFS_MQH
#define JSONPARSERBYLEO_SRC_BUILDERSDEFS_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "JsonDefines.mqh"
2026-09-20 11:21:36 -05:00
#include "JsonEscape.mqh"
2026-09-19 22:46:26 -05:00
#include <TSN\\MQLArticles\\Utils\\FA\\Str\\Conv.mqh>
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-09-26 11:38:15 -05:00
#define JSONBUILDER_EXPAND_E(need) if(m_pos + (need) >= m_cap) { m_cap += (need) + 32; ArrayResize(m_buf, m_cap, m_cap); }
2026-09-19 22:46:26 -05:00
#define JSONBUILDER_EXPAND(need) JSONBUILDER_EXPAND_E(need)
//---
#ifndef JSONBUILDER_MAX_STACK
2026-09-23 18:12:17 -05:00
#define JSONBUILDER_MAX_STACK (16)
2026-09-19 22:46:26 -05:00
#endif // JSONBUILDER_MAX_STACK
2026-07-13 18:47:16 -05:00
2026-09-23 15:25:08 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define JSON_BUILDER_PUT(c) \
JSONBUILDER_EXPAND(1) \
m_buf[m_pos++] = c; \
//---
#define JSON_BUILDER_COMMA \
if(!m_stack_first[m_sp]) \
{ \
JSON_BUILDER_PUT(',') \
} \
m_stack_first[m_sp] = false;
//---
#define JSON_BUILDER_COMMA_F \
if(!m_stack_first[m_sp]) \
{ \
m_buf[m_pos++] = ','; \
} \
m_stack_first[m_sp] = false;
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-09-23 15:25:08 -05:00
struct pack(sizeof(int)) JsonBuilderSnapshot
{
int pos;
uchar sp;
bool stack_first;
};
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CJsonBuilderBase
{
public:
uchar m_buf[];
int m_pos;
int m_cap;
protected:
2026-09-19 22:46:26 -05:00
bool m_stack_first[JSONBUILDER_MAX_STACK];
2026-09-23 15:25:08 -05:00
uchar m_sp;
2026-07-13 18:47:16 -05:00
public:
CJsonBuilderBase(int initial_cap = 1024);
~CJsonBuilderBase() {}
//---
2026-09-26 11:38:15 -05:00
// limpieza
2026-07-13 18:47:16 -05:00
void Clear();
2026-09-26 11:38:15 -05:00
// truncar tamaño del arra
__forceinline void Truncate() { m_cap = ArrayResize(m_buf, m_pos); }
2026-07-13 18:47:16 -05:00
//---
2026-09-26 11:38:15 -05:00
// Chekear si se peude soporta cap.. si no se revera de golope (esto no incluye la reserva extra..)
__forceinline void CheckReserve(int cap) { if(m_pos + cap >= m_cap) { m_cap += cap; ArrayResize(m_buf, m_cap); } }
//--- contruir
2026-07-13 18:47:16 -05:00
__forceinline string Build() const { return CharArrayToString(m_buf, 0, m_pos, CP_UTF8); }
__forceinline int Build(uchar& out[], int dst_start = 0) const { return ArrayCopy(out, m_buf, dst_start, 0, m_pos); }
//--- Structure
CJsonBuilderBase* Obj();
CJsonBuilderBase* EndObj();
CJsonBuilderBase* Arr();
CJsonBuilderBase* EndArr();
2026-07-13 18:47:16 -05:00
2026-09-19 22:46:26 -05:00
//--- Valores
//- Integer
CJsonBuilderBase* Val(int v);
2026-09-19 22:46:26 -05:00
CJsonBuilderBase* Val(long v);
CJsonBuilderBase* Val(uint v);
CJsonBuilderBase* Val(ulong v);
//- Double
CJsonBuilderBase* Val(double v, uchar digits = 8);
//- Bool
CJsonBuilderBase* Val(bool v);
2026-07-13 18:47:16 -05:00
// Null
CJsonBuilderBase* Null();
2026-07-13 18:47:16 -05:00
//---
void CheckCap();
2026-07-15 12:23:27 -05:00
void CheckComma();
2026-07-13 18:47:16 -05:00
//--- Put raw
void PutChar(const uchar c);
void PutRawNoRef(const string s);
void PutRaw(const string& s);
void PutRaw(const uchar& s[], int count = WHOLE_ARRAY);
2026-09-23 15:25:08 -05:00
//---
__forceinline void GetSnapshot(JsonBuilderSnapshot& snap);
__forceinline void ApplySnapshot(const JsonBuilderSnapshot& snap);
2026-07-13 18:47:16 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonBuilderBase::CJsonBuilderBase(int initial_cap)
{
m_cap = initial_cap;
ArrayResize(m_buf, m_cap);
m_pos = 0;
m_sp = 0;
m_stack_first[0] = true;
}
2026-09-23 15:25:08 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
__forceinline void CJsonBuilderBase::GetSnapshot(JsonBuilderSnapshot &snap)
{
snap.sp = m_sp;
snap.pos = m_pos;
snap.stack_first = m_stack_first[m_sp];
}
//+------------------------------------------------------------------+
__forceinline void CJsonBuilderBase::ApplySnapshot(const JsonBuilderSnapshot &snap)
{
m_sp = snap.sp;
m_pos = snap.pos;
m_stack_first[m_sp] = snap.stack_first;
}
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CJsonBuilderBase::CheckCap(void)
{
if(m_pos >= m_cap)
{
m_cap = m_pos + 4096;
ArrayResize(m_buf, m_cap, m_cap);
}
}
2026-07-15 12:23:27 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CJsonBuilderBase::CheckComma(void)
{
JSON_BUILDER_COMMA
}
2026-07-13 18:47:16 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CJsonBuilderBase::Clear()
{
m_pos = 0;
m_sp = 0;
m_stack_first[0] = true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CJsonBuilderBase::PutChar(const uchar c)
{
JSON_BUILDER_PUT(c)
}
//+------------------------------------------------------------------+
void CJsonBuilderBase::PutRaw(const uchar& s[], int count = WHOLE_ARRAY)
{
//---
2026-09-19 22:46:26 -05:00
const int l = count == WHOLE_ARRAY ? ArraySize(s) : fmin(ArraySize(s), count);
const int max_bytes = l + 1;
2026-07-13 18:47:16 -05:00
JSONBUILDER_EXPAND(max_bytes)
//---
m_pos += ArrayCopy(m_buf, s, m_pos, 0, l);
}
//+------------------------------------------------------------------+
void CJsonBuilderBase::PutRaw(const string& s)
{
//---
const int l = StringLen(s);
2026-09-19 22:46:26 -05:00
const int max_bytes = (l << 2) + 1;
2026-07-13 18:47:16 -05:00
JSONBUILDER_EXPAND(max_bytes)
//---
int written = StringToCharArray(s, m_buf, m_pos, WHOLE_ARRAY, CP_UTF8);
if(written > 0 && m_buf[m_pos + written - 1] == 0)
written--;
m_pos += written;
}
//+------------------------------------------------------------------+
void CJsonBuilderBase::PutRawNoRef(const string s)
{
//---
const int l = StringLen(s);
2026-09-19 22:46:26 -05:00
const int max_bytes = (l << 2) + 1;
2026-07-13 18:47:16 -05:00
JSONBUILDER_EXPAND(max_bytes)
//---
int written = StringToCharArray(s, m_buf, m_pos, WHOLE_ARRAY, CP_UTF8);
if(written > 0 && m_buf[m_pos + written - 1] == 0)
written--;
m_pos += written;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Obj()
{
JSONBUILDER_EXPAND_E(3)
JSON_BUILDER_COMMA_F
m_buf[m_pos++] = '{';
//---
2026-09-19 22:46:26 -05:00
m_sp++;
m_stack_first[m_sp] = true;
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::EndObj()
{
2026-09-19 22:46:26 -05:00
//---
2026-09-23 15:25:08 -05:00
if(m_sp)
2026-07-13 18:47:16 -05:00
m_sp--;
//---
2026-07-13 18:47:16 -05:00
JSON_BUILDER_PUT('}')
m_stack_first[m_sp] = false;
return &this;
}
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Arr()
{
//---
JSONBUILDER_EXPAND_E(3)
JSON_BUILDER_COMMA_F
m_buf[m_pos++] = '[';
//---
2026-09-19 22:46:26 -05:00
m_sp++;
m_stack_first[m_sp] = true;
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::EndArr()
{
2026-09-19 22:46:26 -05:00
//---
2026-09-23 15:25:08 -05:00
if(m_sp)
2026-07-13 18:47:16 -05:00
m_sp--;
2026-09-19 22:46:26 -05:00
//---
2026-07-13 18:47:16 -05:00
JSON_BUILDER_PUT(']')
m_stack_first[m_sp] = false;
return &this;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Val(int v)
{
//---
2026-09-21 12:52:37 -05:00
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_I + 1))
JSON_BUILDER_COMMA_F
2026-09-21 12:52:37 -05:00
STRCONV_VALTOBUFFER_SIGNED(v, m_buf, m_pos, uint, uvalue)
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
2026-09-19 22:46:26 -05:00
CJsonBuilderBase* CJsonBuilderBase::Val(long v)
2026-07-13 18:47:16 -05:00
{
//---
2026-09-21 12:52:37 -05:00
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_L + 1))
JSON_BUILDER_COMMA_F
2026-09-21 12:52:37 -05:00
STRCONV_VALTOBUFFER_SIGNED(v, m_buf, m_pos, ulong, uvalue)
2026-09-19 22:46:26 -05:00
return &this;
}
2026-09-19 22:46:26 -05:00
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Val(uint v)
{
//---
2026-09-21 12:52:37 -05:00
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_I + 1))
2026-09-19 22:46:26 -05:00
JSON_BUILDER_COMMA_F
2026-09-21 12:52:37 -05:00
STRCONV_VALTOBUFFER_USIGNED(v, m_buf, m_pos)
2026-09-19 22:46:26 -05:00
return &this;
}
2026-09-19 22:46:26 -05:00
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Val(ulong v)
{
//---
2026-09-21 12:52:37 -05:00
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_UL + 1))
2026-09-19 22:46:26 -05:00
JSON_BUILDER_COMMA_F
2026-09-21 12:52:37 -05:00
STRCONV_VALTOBUFFER_USIGNED(v, m_buf, m_pos);
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
2026-09-19 22:46:26 -05:00
//| |
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Val(double v, uchar digits = 8)
2026-07-13 18:47:16 -05:00
{
//---
2026-09-19 22:46:26 -05:00
JSONBUILDER_EXPAND_E(MQLARTICLES_CONV_MAXDIG_DBL(digits))
JSON_BUILDER_COMMA_F
//---
if(!MathIsValidNumber(v))
{
m_buf[m_pos++] = 'n';
m_buf[m_pos++] = 'u';
m_buf[m_pos++] = 'l';
m_buf[m_pos++] = 'l';
return &this;
}
//---
2026-09-19 22:46:26 -05:00
CValueToBuffer::ToValue(v, m_buf, m_pos, digits);
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Val(bool v)
{
JSONBUILDER_EXPAND_E(7)
JSON_BUILDER_COMMA_F
if(v)
{
m_buf[m_pos++] = 't';
m_buf[m_pos++] = 'r';
m_buf[m_pos++] = 'u';
m_buf[m_pos++] = 'e';
}
else
{
m_buf[m_pos++] = 'f';
m_buf[m_pos++] = 'a';
m_buf[m_pos++] = 'l';
m_buf[m_pos++] = 's';
m_buf[m_pos++] = 'e';
}
2026-07-13 18:47:16 -05:00
return &this;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CJsonBuilderBase* CJsonBuilderBase::Null()
{
JSONBUILDER_EXPAND_E(6)
JSON_BUILDER_COMMA_F
m_buf[m_pos++] = 'n';
m_buf[m_pos++] = 'u';
m_buf[m_pos++] = 'l';
m_buf[m_pos++] = 'l';
2026-07-13 18:47:16 -05:00
return &this;
}
//--- end namespace
}
#endif // JSONPARSERBYLEO_SRC_BUILDERSDEFS_MQH