forked from nique_372/JsonParserByLeo
449 lines
13 KiB
MQL5
449 lines
13 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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_DOM_BUILDERSDEFS_MQH
| |
#define JSONPARSERBYLEO_SRC_DOM_BUILDERSDEFS_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "..\\JsonNode\\JsonNode.mqh"
| |
#include "..\\Ser\\JsonEscape.mqh"
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#define JSONBUILDER_EXPAND_E(need) if(m_pos + (need) >= m_cap) { m_cap += (need) + 32; ArrayResize(m_buf, m_cap, m_cap); }
| |
#define JSONBUILDER_EXPAND(need) JSONBUILDER_EXPAND_E(need)
| |
| |
//---
| |
#ifndef JSONBUILDER_MAX_STACK
| |
#define JSONBUILDER_MAX_STACK (16)
| |
#endif // JSONBUILDER_MAX_STACK
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
namespace TSN
| |
{
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#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;
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
struct pack(sizeof(int)) JsonBuilderSnapshot
| |
{
| |
int pos;
| |
uchar sp;
| |
bool stack_first;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
struct JsonBuilderFSnapshot : JsonBuilderSnapshot
| |
{
| |
uchar buf[];
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class CJsonBuilderBase
| |
{
| |
public:
| |
uchar m_buf[];
| |
int m_pos;
| |
int m_cap;
| |
| |
protected:
| |
bool m_stack_first[JSONBUILDER_MAX_STACK];
| |
uchar m_sp;
| |
| |
public:
| |
CJsonBuilderBase(int initial_cap = 1024);
| |
~CJsonBuilderBase() {}
| |
| |
//---
| |
// limpieza
| |
void Clear();
| |
// truncar tamaño del arra
| |
__forceinline void Truncate() { m_cap = ArrayResize(m_buf, m_pos); }
| |
| |
//---
| |
// 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
| |
__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();
| |
| |
//--- Valores
| |
//- Integer
| |
CJsonBuilderBase* Val(int v);
| |
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);
| |
| |
// Null
| |
CJsonBuilderBase* Null();
| |
| |
//---
| |
void CheckCap();
| |
void CheckComma();
| |
| |
//--- 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);
| |
| |
//---
| |
__forceinline void GetSnapshot(JsonBuilderSnapshot& snap);
| |
__forceinline void ApplySnapshot(const JsonBuilderSnapshot& snap);
| |
| |
//---
| |
__forceinline void GetSnapshotF(JsonBuilderFSnapshot& snap);
| |
__forceinline void ApplySnapshotF(JsonBuilderFSnapshot& snap);
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
__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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
__forceinline void CJsonBuilderBase::GetSnapshotF(JsonBuilderFSnapshot &snap)
| |
{
| |
snap.sp = m_sp;
| |
snap.pos = m_pos;
| |
snap.stack_first = m_stack_first[m_sp];
| |
ArraySwap(snap.buf, m_buf); // snap buff ahora es m_buf
| |
m_cap = ArraySize(m_buf); // Actulizamos
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
__forceinline void CJsonBuilderBase::ApplySnapshotF(JsonBuilderFSnapshot &snap)
| |
{
| |
m_sp = snap.sp;
| |
m_pos = snap.pos;
| |
m_stack_first[m_sp] = snap.stack_first;
| |
ArraySwap(m_buf, snap.buf); // ahora somso snap buff
| |
m_cap = ArraySize(m_buf); // Actulizamos
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CJsonBuilderBase::CheckCap(void)
| |
{
| |
if(m_pos >= m_cap)
| |
{
| |
m_cap = m_pos + 4096;
| |
ArrayResize(m_buf, m_cap, m_cap);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CJsonBuilderBase::CheckComma(void)
| |
{
| |
JSON_BUILDER_COMMA
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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)
| |
{
| |
//---
| |
const int l = count == WHOLE_ARRAY ? ArraySize(s) : fmin(ArraySize(s), count);
| |
const int max_bytes = l + 1;
| |
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);
| |
const int max_bytes = (l << 2) + 1;
| |
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);
| |
const int max_bytes = (l << 2) + 1;
| |
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++] = '{';
| |
| |
//---
| |
m_sp++;
| |
m_stack_first[m_sp] = true;
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::EndObj()
| |
{
| |
//---
| |
if(m_sp)
| |
m_sp--;
| |
| |
//---
| |
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++] = '[';
| |
| |
//---
| |
m_sp++;
| |
m_stack_first[m_sp] = true;
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::EndArr()
| |
{
| |
//---
| |
if(m_sp)
| |
m_sp--;
| |
| |
//---
| |
JSON_BUILDER_PUT(']')
| |
m_stack_first[m_sp] = false;
| |
return &this;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::Val(int v)
| |
{
| |
//---
| |
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_I + 1))
| |
JSON_BUILDER_COMMA_F
| |
STRCONV_VALTOBUFFER_SIGNED(v, m_buf, m_pos, uint, uvalue)
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::Val(long v)
| |
{
| |
//---
| |
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_L + 1))
| |
JSON_BUILDER_COMMA_F
| |
STRCONV_VALTOBUFFER_SIGNED(v, m_buf, m_pos, ulong, uvalue)
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::Val(uint v)
| |
{
| |
//---
| |
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_I + 1))
| |
JSON_BUILDER_COMMA_F
| |
STRCONV_VALTOBUFFER_USIGNED(v, m_buf, m_pos)
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::Val(ulong v)
| |
{
| |
//---
| |
JSONBUILDER_EXPAND_E((MQLARTICLES_CONV_MAXDIG_UL + 1))
| |
JSON_BUILDER_COMMA_F
| |
STRCONV_VALTOBUFFER_USIGNED(v, m_buf, m_pos);
| |
return &this;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
CJsonBuilderBase* CJsonBuilderBase::Val(double v, uchar digits = 8)
| |
{
| |
//---
| |
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;
| |
}
| |
| |
//---
| |
CValueToBuffer::ToValue(v, m_buf, m_pos, digits);
| |
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';
| |
}
| |
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';
| |
return &this;
| |
}
| |
| |
//--- end namespace
| |
}
| |
| |
#endif // JSONPARSERBYLEO_SRC_DOM_BUILDERSDEFS_MQH
|