| //+------------------------------------------------------------------+
|
| //| JsonBuilder.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_JSONBUILDER_MQH
|
| #define JSONPARSERBYLEO_SRC_DOM_JSONBUILDER_MQH
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| #include "BuilderDefs.mqh"
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| namespace TSN
|
| {
|
| //+------------------------------------------------------------------+
|
| //| Macros |
|
| //+------------------------------------------------------------------+
|
| #define JSONBUILDER_CHECK_PUT_ENCODE_STR(str, needed) \
|
| const int l = StringLen(str); \
|
| const int ex = JSONESCAPE_CR_ENCODE(l) + (needed); \
|
| JSONBUILDER_EXPAND_E(ex)
|
|
|
| //+------------------------------------------------------------------+
|
| #define JSONBUILDER_CHECK_PUT_ENCODE_STRU(arr, needed) \
|
| if(count==WHOLE_ARRAY) \
|
| count= ArraySize(arr); \
|
| const int ex = JSONESCAPE_CR_ENCODE(count) + (needed); \
|
| JSONBUILDER_EXPAND_E(ex)
|
|
|
| //+------------------------------------------------------------------+
|
| #define JSONBUILDER_GENERIC_VALS(READ, L) \
|
| JSON_BUILDER_COMMA_F \
|
| m_buf[m_pos++] = '"'; \
|
| CJsonEscape::Encode(v, READ, L, m_buf, m_pos); \
|
| m_buf[m_pos++] = '"'; \
|
|
|
| //+------------------------------------------------------------------+
|
| #define JSONBUILDER_GENERIC_VALSTR_WVER \
|
| JSONBUILDER_EXPAND_E(2) \
|
| JSON_BUILDER_COMMA_F \
|
| m_buf[m_pos++] = '"'; \
|
| PutRaw(v); \
|
| JSONBUILDER_EXPAND_E(1) \
|
| m_buf[m_pos++] = '"';
|
|
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| class CJsonBuilder : public CJsonBuilderBase
|
| {
|
| public:
|
| CJsonBuilder(int initial_cap = 1024) : CJsonBuilderBase(initial_cap) {}
|
| ~CJsonBuilder() {}
|
|
|
| //--- Key / Values
|
| CJsonBuilder* Key(const string& k);
|
| CJsonBuilder* KeyWV(const string& k);
|
|
|
| // String- Con validacion
|
| CJsonBuilder* ValS(const string& v);
|
| CJsonBuilder* ValU(const uchar& v[], int read_i = 0, int count = WHOLE_ARRAY);
|
| CJsonBuilder* ValSNoRef(const string v);
|
|
|
| // String- Sin validacion (witohut validation WV)
|
| CJsonBuilder* ValSWV(const string& v);
|
| CJsonBuilder* ValUWV(const uchar& v[], int count = WHOLE_ARRAY); // buffer fijo sobredimensionado (ej. CStringFixed): solo copia count bytes
|
| CJsonBuilder* ValSNoRefWV(const string v);
|
|
|
| // Valor
|
| using CJsonBuilderBase::Val;
|
| bool Val(CJsonNode& node);
|
|
|
| // Valid json
|
| CJsonBuilder* ValidJson(const uchar& v[], int count = WHOLE_ARRAY);
|
| CJsonBuilder* ValidJson(const string& fragment);
|
| CJsonBuilder* ValidJsonNoRef(const string fragment);
|
| };
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| bool CJsonBuilder::Val(CJsonNode& node)
|
| {
|
| switch(node.GetType())
|
| {
|
| case JSON_VTYPE_UINTEGER:
|
| {
|
| ulong v;
|
| if(!node.ToUIntSafe(v))
|
| return false;
|
| Val(v);
|
| break;
|
| }
|
| case JSON_VTYPE_INTEGER:
|
| {
|
| long v;
|
| if(!node.ToIntSafe(v))
|
| return false;
|
| Val(v);
|
| break;
|
| }
|
| case JSON_VTYPE_REAL:
|
| {
|
| const double v = node.ToDouble(double("inf"));
|
| if(v == double("inf"))
|
| return false;
|
| Val(v);
|
| break;
|
| }
|
| case JSON_VTYPE_BOOLEAN:
|
| {
|
| bool v;
|
| if(!node.ToBoolSafe(v))
|
| return false;
|
| Val(v);
|
| break;
|
| }
|
| case JSON_VTYPE_STRING:
|
| {
|
| const int start = node.StrStart();
|
| const int len = node.StrLenRaw();
|
| ValU(node.m_ctx.m_raw, start, len);
|
| break;
|
| }
|
| case JSON_VTYPE_NULL:
|
| {
|
| Null();
|
| break;
|
| }
|
| default:
|
| return false;
|
| }
|
| return true;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::Key(const string& k)
|
| {
|
| //---
|
| JSONBUILDER_CHECK_PUT_ENCODE_STR(k, 4)
|
|
|
| //---
|
| JSON_BUILDER_COMMA_F
|
| m_buf[m_pos++] = '"';
|
| CJsonEscape::Encode(k, 0, l, m_buf, m_pos);
|
| m_buf[m_pos++] = '"';
|
| m_buf[m_pos++] = ':';
|
|
|
| //---
|
| m_stack_first[m_sp] = true;
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValU(const uchar &v[], int read_i, int count)
|
| {
|
| JSONBUILDER_CHECK_PUT_ENCODE_STRU(v, 3)
|
| JSONBUILDER_GENERIC_VALS(read_i, count)
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValS(const string& v)
|
| {
|
| JSONBUILDER_CHECK_PUT_ENCODE_STR(v, 3)
|
| JSONBUILDER_GENERIC_VALS(0, l)
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValSNoRef(const string v)
|
| {
|
| JSONBUILDER_CHECK_PUT_ENCODE_STR(v, 3)
|
| JSONBUILDER_GENERIC_VALS(0, l)
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| // WV en key solo acepta ASCCI puro no caracteres de control (no espca) menos emojis (tipico en keys harcodeadas)
|
| // Si reuiqer full use la version completa
|
| CJsonBuilder* CJsonBuilder::KeyWV(const string &k)
|
| {
|
| //---
|
| const int l = StringLen(k);
|
| const int req = l + 4;
|
| JSONBUILDER_EXPAND_E(req)
|
|
|
| //---
|
| JSON_BUILDER_COMMA_F
|
| m_buf[m_pos++] = '"';
|
|
|
| //---
|
| for(int i = 0; i < l; i++)
|
| m_buf[m_pos++] = (uchar)k[i];
|
|
|
| //--
|
| m_buf[m_pos++] = '"';
|
| m_buf[m_pos++] = ':';
|
|
|
| //---
|
| m_stack_first[m_sp] = true;
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| // WV aqui implcia no escape pero UTF si se soporta (en string en uchar NO)
|
| CJsonBuilder* CJsonBuilder::ValSWV(const string& v)
|
| {
|
| JSONBUILDER_GENERIC_VALSTR_WVER
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValSNoRefWV(const string v)
|
| {
|
| JSONBUILDER_GENERIC_VALSTR_WVER
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValUWV(const uchar &v[], int count)
|
| {
|
| //---
|
| JSONBUILDER_EXPAND_E(2)
|
| JSON_BUILDER_COMMA_F
|
| m_buf[m_pos++] = '"';
|
| PutRaw(v, count);
|
| JSONBUILDER_EXPAND_E(1)
|
| m_buf[m_pos++] = '"';
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValidJson(const uchar& v[], int count = WHOLE_ARRAY)
|
| {
|
| JSON_BUILDER_COMMA
|
| PutRaw(v, count);
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValidJson(const string& fragment)
|
| {
|
| JSON_BUILDER_COMMA
|
| PutRaw(fragment);
|
| return &this;
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| CJsonBuilder* CJsonBuilder::ValidJsonNoRef(const string fragment)
|
| {
|
| JSON_BUILDER_COMMA
|
| PutRaw(fragment);
|
| return &this;
|
| }
|
|
|
| //---
|
| //+------------------------------------------------------------------+
|
| //| |
|
| //+------------------------------------------------------------------+
|
| // Nota deje esto pero tengan cuidado con esto... dado que no hay garantias de uso lo puse mas que todo para evitar tener que instancia un segundo builder
|
| // ahora el uso adecuado es digmoas en una funcion usarlo todo de golpe (sin llamar a funciones intermedias o aseguramente que esa funcion intermedia no lo llame) y listo
|
| // osea uso y desecho... algo asi... no tatno como "si fuera mio" si requieres cache o algo asi.. lo mejors es tener miembro CJsonBuilder...
|
| CJsonBuilder g_json_builder;
|
| } // namespace TSN
|
| //+------------------------------------------------------------------+
|
| #endif // JSONPARSERBYLEO_SRC_DOM_JSONBUILDER_MQH
|