//+------------------------------------------------------------------+ //| Qwen3.8Max.mqh | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com/" #property strict //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // Same prompt claude\mql5 lite /* 1. ITERACION Tengo errores: wrong parameters count Qwen3.8Max.mqh 1753 17 built-in: string DoubleToString(double,int) Qwen3.8Max.mqh 1753 17 implicit conversion from 'unknown' to 'string' Qwen3.8Max.mqh 1753 17 wrong parameters count Qwen3.8Max.mqh 1784 13 built-in: double StringToDouble(const string) Qwen3.8Max.mqh 1784 13 cannot convert parameter 'CJson&' to 'CJson*' Qwen3.8Max.mqh 1825 22 wrong parameters count, 2 passed, but 0 requires Qwen3.8Max.mqh 1825 14 could be one of 3 function(s) Qwen3.8Max.mqh 1825 14 implicit JsonRef::JsonRef(const JsonRef&) Qwen3.8Max.mqh 92 8 JsonRef::JsonRef(CJson*,int) Qwen3.8Max.mqh 104 4 JsonRef::JsonRef() Qwen3.8Max.mqh 98 4 cannot convert parameter 'CJson&' to 'CJson*' Qwen3.8Max.mqh 1830 22 wrong parameters count, 2 passed, but 0 requires Qwen3.8Max.mqh 1830 14 could be one of 3 function(s) Qwen3.8Max.mqh 1830 14 implicit JsonRef::JsonRef(const JsonRef&) Qwen3.8Max.mqh 92 8 JsonRef::JsonRef(CJson*,int) Qwen3.8Max.mqh 104 4 JsonRef::JsonRef() Qwen3.8Max.mqh 98 4 6 errors, 1 warnings 6 1 Los corregir todos yo ire dejando comentarios.. 2. Iteracion Al probarlo da error ni siuieqera funciona 2026.07.27 19:52:46.618 Qwen3.8Max (EURUSD,M1) false 2026.07.27 19:52:46.618 Qwen3.8Max (EURUSD,M1) array out of range in 'Qwen3.8Max.mqh' (1695,40) Bueno lo tengo 2026.07.27 20:05:30.350 Qwen3.8Max (EURUSD,M1) false 2026.07.27 20:05:30.350 Qwen3.8Max (EURUSD,M1) JSON error: Invalid escape sequence pos=220961 line=6031 col=28 BUeno conitnuare otro dia con qwen me canse ya con glm.. hoy... .. */ //// Code ai start.. //+------------------------------------------------------------------+ //| High Performance JSON Parser for MQL5 | //| Pure MQL5, no DLL, no external libraries | //+------------------------------------------------------------------+ #ifndef JSON_MQH #define JSON_MQH #define JSON_CP_UTF8 65001 #define JSON_FNV_INIT ((uint)0x811C9DC5) #define JSON_FNV_PRIME ((uint)16777619) #define JSON_FLAG_KEY_DECODED 1 #define JSON_FLAG_VAL_DECODED 2 //+------------------------------------------------------------------+ //| Error codes | //+------------------------------------------------------------------+ enum ENUM_JSON_ERROR { JSON_OK = 0, JSON_UNKNOWN_ERROR, JSON_UNEXPECTED_CHARACTER, JSON_UNEXPECTED_END, JSON_INVALID_NUMBER, JSON_INVALID_STRING, JSON_INVALID_ESCAPE, JSON_INVALID_UNICODE, JSON_EXPECTED_COLON, JSON_EXPECTED_COMMA, JSON_EXPECTED_OBJECT, JSON_EXPECTED_ARRAY, JSON_EXPECTED_KEY, JSON_EXPECTED_VALUE, JSON_INVALID_LITERAL, JSON_MAX_DEPTH, JSON_MEMORY_ERROR, JSON_TRAILING_DATA }; //+------------------------------------------------------------------+ //| Node types | //+------------------------------------------------------------------+ enum ENUM_JSON_TYPE { JSON_NONE = -1, JSON_NULL = 0, JSON_BOOL = 1, JSON_NUMBER = 2, JSON_STRING = 3, JSON_ARRAY = 4, JSON_OBJECT = 5 }; //+------------------------------------------------------------------+ //| Parser states | //+------------------------------------------------------------------+ enum ENUM_JSON_STATE { JSON_STATE_OBJ_KEY_OR_END = 0, JSON_STATE_OBJ_KEY = 1, JSON_STATE_OBJ_COLON = 2, JSON_STATE_OBJ_VALUE = 3, JSON_STATE_OBJ_COMMA_OR_END = 4, JSON_STATE_ARRAY_VALUE_OR_END = 5, JSON_STATE_ARRAY_VALUE = 6, JSON_STATE_ARRAY_COMMA_OR_END = 7 }; class CJson; //+------------------------------------------------------------------+ //| Lightweight reference to a JSON node | //+------------------------------------------------------------------+ struct JsonRef { public: CJson *json; int node; JsonRef() { json = NULL; node = -1; } JsonRef(CJson *j, int n) { json = j; node = n; } JsonRef operator[](const string key); // quite el & por "implicit conversion from 'string' to 'int' Qwen3.8Max.mq5 28 23" JsonRef operator[](const int index); bool Exists(); int Type(); int Size(); double ToDouble(); long ToInteger(); bool ToBool(); string ToString(); bool IsObject(); bool IsArray(); bool IsString(); bool IsNumber(); bool IsBool(); bool IsNull(); }; //+------------------------------------------------------------------+ //| Internal node | //+------------------------------------------------------------------+ struct JsonNode { public: uchar type; uchar flags; int parent; int first_child; int last_child; int next_sibling; int child_count; int key_start; int key_len; uint key_hash; int val_start; int val_len; double num; }; //+------------------------------------------------------------------+ //| Main JSON parser class | //+------------------------------------------------------------------+ class CJson { public: // Public input buffer. Fill it directly for best performance. uchar Buffer[]; // If InputSize >= 0, parser uses only InputSize bytes from Buffer. // If InputSize < 0, parser uses ArraySize(Buffer). int InputSize; // Maximum nested container depth. int MaxDepth; // Build hash index for object member lookup. bool UseHashIndex; // Minimum number of object members before building hash index. int HashThreshold; protected: int m_size; int m_root; ENUM_JSON_ERROR m_error; int m_error_pos; int m_node_used; JsonNode m_nodes[]; int m_children[]; uchar m_pool[]; int m_pool_used; int m_stack[]; uchar m_state[]; int m_stack_used; int m_member_count; int m_hash_size; int m_hash_mask; int m_hash_parent[]; uint m_hash_key[]; int m_hash_node[]; int m_pending_key_start; int m_pending_key_len; uint m_pending_key_hash; uchar m_pending_flags; bool m_pending_valid; //+---------------------------------------------------------------+ //| Small helpers | //+---------------------------------------------------------------+ int Resolve(int node) const { return(node < 0 ? m_root : node); } bool SetError(ENUM_JSON_ERROR code, int pos) { m_error = code; m_error_pos = pos; return(false); } void SkipWs(int &pos) { while(pos < m_size) { uchar c = Buffer[pos]; if(c != 0x20 && c != 0x09 && c != 0x0A && c != 0x0D) break; pos++; } } //+---------------------------------------------------------------+ //| Memory helpers | //+---------------------------------------------------------------+ bool EnsureNodes(int count, int pos) { int cap = ArraySize(m_nodes); if(count <= cap) return(true); int new_cap = cap * 2; if(new_cap < count) new_cap = count; if(new_cap < 1024) new_cap = 1024; if(ArrayResize(m_nodes, new_cap, new_cap + 4096) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); return(true); } bool EnsureStack(int count, int pos) { int cap = ArraySize(m_stack); if(count <= cap) return(true); int new_cap = cap * 2; if(new_cap < count) new_cap = count; if(new_cap < 64) new_cap = 64; if(ArrayResize(m_stack, new_cap, new_cap + 256) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); if(ArrayResize(m_state, new_cap, new_cap + 256) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); return(true); } bool EnsurePool(int add, int pos) { int cap = ArraySize(m_pool); if(m_pool_used + add <= cap) return(true); int new_cap = cap * 2; if(new_cap < m_pool_used + add) new_cap = m_pool_used + add; if(new_cap < 1024) new_cap = 1024; if(ArrayResize(m_pool, new_cap, new_cap + 4096) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); return(true); } //+---------------------------------------------------------------+ //| Pool and hashing helpers | //+---------------------------------------------------------------+ bool AppendPoolByte(uchar b, uint &h, int pos) { if(!EnsurePool(1, pos)) return(false); m_pool[m_pool_used++] = b; h = ((h ^ b) * JSON_FNV_PRIME); return(true); } bool AppendPoolUtf8(uint cp, uint &h, int pos) { if(cp < 0x80) return(AppendPoolByte((uchar)cp, h, pos)); if(cp < 0x800) { if(!AppendPoolByte((uchar)(0xC0 | (cp >> 6)), h, pos)) return(false); return(AppendPoolByte((uchar)(0x80 | (cp & 0x3F)), h, pos)); } if(cp < 0x10000) { if(!AppendPoolByte((uchar)(0xE0 | (cp >> 12)), h, pos)) return(false); if(!AppendPoolByte((uchar)(0x80 | ((cp >> 6) & 0x3F)), h, pos)) return(false); return(AppendPoolByte((uchar)(0x80 | (cp & 0x3F)), h, pos)); } if(cp <= 0x10FFFF) { if(!AppendPoolByte((uchar)(0xF0 | (cp >> 18)), h, pos)) return(false); if(!AppendPoolByte((uchar)(0x80 | ((cp >> 12) & 0x3F)), h, pos)) return(false); if(!AppendPoolByte((uchar)(0x80 | ((cp >> 6) & 0x3F)), h, pos)) return(false); return(AppendPoolByte((uchar)(0x80 | (cp & 0x3F)), h, pos)); } return(SetError(JSON_INVALID_UNICODE, pos)); } bool ParseHex4(int &cur, uint &val) { if(cur + 4 > m_size) return(SetError(JSON_INVALID_UNICODE, cur)); val = 0; for(int i = 0; i < 4; i++) { uchar c = Buffer[cur]; int hv; if(c >= 0x30 && c <= 0x39) hv = c - 0x30; else if(c >= 0x41 && c <= 0x46) hv = c - 0x41 + 10; else if(c >= 0x61 && c <= 0x66) hv = c - 0x61 + 10; else return(SetError(JSON_INVALID_UNICODE, cur)); val = (val << 4) | (uint)hv; cur++; } return(true); } //+---------------------------------------------------------------+ //| String parser | //+---------------------------------------------------------------+ bool ParseStringSlow(int start, int p, uint h, int &pos, int &out_start, int &out_len, bool &out_decoded, uint &out_hash) { int pool_start = m_pool_used; int n = p - start; if(n > 0) { if(!EnsurePool(n, start)) return(false); int base = m_pool_used; for(int i = 0; i < n; i++) m_pool[base + i] = Buffer[start + i]; m_pool_used += n; } int cur = p; while(cur < m_size) { int run = cur; while(run < m_size) { uchar c = Buffer[run]; if(c == 0x22 || c == 0x5C || c < 0x20) break; run++; } int rn = run - cur; if(rn > 0) { if(!EnsurePool(rn, cur)) return(false); int base = m_pool_used; for(int i = 0; i < rn; i++) { uchar b = Buffer[cur + i]; m_pool[base + i] = b; h = ((h ^ b) * JSON_FNV_PRIME); } m_pool_used += rn; cur = run; } if(cur >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[cur]; if(c == 0x22) { out_start = pool_start; out_len = m_pool_used - pool_start; out_decoded = true; out_hash = h; pos = cur + 1; return(true); } if(c < 0x20) return(SetError(JSON_INVALID_STRING, cur)); // c == backslash cur++; if(cur >= m_size) return(SetError(JSON_UNEXPECTED_END, cur)); uchar e = Buffer[cur]; switch(e) { case 0x22: // \" if(!AppendPoolByte(0x22, h, cur)) return(false); cur++; break; case 0x5C: // \\ if(!AppendPoolByte(0x5C, h, cur)) return(false); cur++; break; case 0x2F: // \/ if(!AppendPoolByte(0x2F, h, cur)) return(false); cur++; break; case 0x62: // \b if(!AppendPoolByte(0x08, h, cur)) return(false); cur++; break; case 0x66: // \f if(!AppendPoolByte(0x0C, h, cur)) return(false); cur++; break; case 0x6E: // \n if(!AppendPoolByte(0x0A, h, cur)) return(false); cur++; break; case 0x72: // \r if(!AppendPoolByte(0x0D, h, cur)) return(false); cur++; break; case 0x74: // \t if(!AppendPoolByte(0x09, h, cur)) return(false); cur++; break; case 0x75: // \uXXXX { cur++; uint cp; if(!ParseHex4(cur, cp)) return(false); if(cp >= 0xD800 && cp <= 0xDBFF) { if(cur + 6 <= m_size && Buffer[cur] == 0x5C && Buffer[cur + 1] == 0x75) { cur += 2; uint low; if(!ParseHex4(cur, low)) return(false); if(low >= 0xDC00 && low <= 0xDFFF) cp = 0x10000 + ((cp - 0xD800) << 10) + (low - 0xDC00); else return(SetError(JSON_INVALID_UNICODE, cur)); } else { return(SetError(JSON_INVALID_UNICODE, cur)); } } else if(cp >= 0xDC00 && cp <= 0xDFFF) { return(SetError(JSON_INVALID_UNICODE, cur)); } if(!AppendPoolUtf8(cp, h, cur)) return(false); break; } default: return(SetError(JSON_INVALID_ESCAPE, cur)); } } return(SetError(JSON_UNEXPECTED_END, pos)); } bool ParseStringToken(int &pos, int &out_start, int &out_len, bool &out_decoded, uint &out_hash) { if(pos >= m_size || Buffer[pos] != 0x22) return(SetError(JSON_INVALID_STRING, pos)); int start = pos + 1; int p = start; uint h = JSON_FNV_INIT; while(p < m_size) { uchar c = Buffer[p]; if(c == 0x22) { out_start = start; out_len = p - start; out_decoded = false; out_hash = h; pos = p + 1; return(true); } if(c == 0x5C) return(ParseStringSlow(start, p, h, pos, out_start, out_len, out_decoded, out_hash)); if(c < 0x20) return(SetError(JSON_INVALID_STRING, p)); h = ((h ^ c) * JSON_FNV_PRIME); p++; } return(SetError(JSON_UNEXPECTED_END, pos)); } //+---------------------------------------------------------------+ //| Number parser | //+---------------------------------------------------------------+ bool ParseNumberToken(int &pos, double &val) { int start = pos; bool neg = false; if(pos < m_size && Buffer[pos] == 0x2D) { neg = true; pos++; } if(pos >= m_size) return(SetError(JSON_INVALID_NUMBER, start)); uchar c = Buffer[pos]; double intpart = 0.0; if(c == 0x30) { pos++; if(pos < m_size && Buffer[pos] >= 0x30 && Buffer[pos] <= 0x39) return(SetError(JSON_INVALID_NUMBER, pos)); } else if(c >= 0x31 && c <= 0x39) { while(pos < m_size) { uchar d = Buffer[pos]; if(d < 0x30 || d > 0x39) break; intpart = intpart * 10.0 + (double)(d - 0x30); pos++; } } else { return(SetError(JSON_INVALID_NUMBER, pos)); } if(pos < m_size && Buffer[pos] == 0x2E) { pos++; if(pos >= m_size || Buffer[pos] < 0x30 || Buffer[pos] > 0x39) return(SetError(JSON_INVALID_NUMBER, pos)); double frac = 0.0; double scale = 0.1; while(pos < m_size) { uchar d = Buffer[pos]; if(d < 0x30 || d > 0x39) break; frac += (double)(d - 0x30) * scale; scale *= 0.1; pos++; } intpart += frac; } int exp = 0; bool exp_neg = false; if(pos < m_size && (Buffer[pos] == 0x65 || Buffer[pos] == 0x45)) { pos++; if(pos < m_size && (Buffer[pos] == 0x2B || Buffer[pos] == 0x2D)) { exp_neg = (Buffer[pos] == 0x2D); pos++; } if(pos >= m_size || Buffer[pos] < 0x30 || Buffer[pos] > 0x39) return(SetError(JSON_INVALID_NUMBER, pos)); while(pos < m_size) { uchar d = Buffer[pos]; if(d < 0x30 || d > 0x39) break; if(exp < 100000) exp = exp * 10 + (d - 0x30); pos++; } } val = neg ? -intpart : intpart; if(exp != 0) { int e = exp; if(e > 308) e = 308; double de = (double)e; val *= MathPow(10.0, exp_neg ? -de : de); } return(true); } //+---------------------------------------------------------------+ //| Node construction helpers | //+---------------------------------------------------------------+ int NewNode(uchar type, int parent, int pos) { if(!EnsureNodes(m_node_used + 1, pos)) return(-1); int idx = m_node_used++; m_nodes[idx].type = type; m_nodes[idx].flags = 0; m_nodes[idx].parent = parent; m_nodes[idx].first_child = -1; m_nodes[idx].last_child = -1; m_nodes[idx].next_sibling = -1; m_nodes[idx].child_count = 0; m_nodes[idx].key_start = 0; m_nodes[idx].key_len = 0; m_nodes[idx].key_hash = 0; m_nodes[idx].val_start = 0; m_nodes[idx].val_len = 0; m_nodes[idx].num = 0.0; return(idx); } bool AssignPendingKey(int node, int parent, int pos) { if(parent < 0) { m_pending_valid = false; return(true); } if(m_nodes[parent].type != (uchar)JSON_OBJECT) { m_pending_valid = false; return(true); } if(!m_pending_valid) return(SetError(JSON_EXPECTED_KEY, pos)); m_nodes[node].key_start = m_pending_key_start; m_nodes[node].key_len = m_pending_key_len; m_nodes[node].key_hash = m_pending_key_hash; if((m_pending_flags & JSON_FLAG_KEY_DECODED) != 0) m_nodes[node].flags = (uchar)(m_nodes[node].flags | JSON_FLAG_KEY_DECODED); m_pending_valid = false; return(true); } void AddChild(int parent, int child) { if(parent < 0) return; if(m_nodes[parent].first_child < 0) { m_nodes[parent].first_child = child; } else { m_nodes[m_nodes[parent].last_child].next_sibling = child; } m_nodes[parent].last_child = child; m_nodes[parent].child_count++; if(m_nodes[parent].type == (uchar)JSON_OBJECT) m_member_count++; } bool PushStack(int node, uchar state, int pos) { if(m_stack_used >= MaxDepth) return(SetError(JSON_MAX_DEPTH, pos)); if(!EnsureStack(m_stack_used + 1, pos)) return(false); m_stack[m_stack_used] = node; m_state[m_stack_used] = state; m_stack_used++; return(true); } bool ParseObjectKey(int &pos) { int s, l; bool dec; uint h; if(!ParseStringToken(pos, s, l, dec, h)) return(false); m_pending_key_start = s; m_pending_key_len = l; m_pending_key_hash = h; m_pending_flags = dec ? (uchar)JSON_FLAG_KEY_DECODED : 0; m_pending_valid = true; return(true); } //+---------------------------------------------------------------+ //| Create a value node at current position | //+---------------------------------------------------------------+ bool CreateValueNode(int &pos, int parent, int &out_node) { if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; // Object if(c == 0x7B) { int node = NewNode((uchar)JSON_OBJECT, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); AddChild(parent, node); pos++; if(!PushStack(node, (uchar)JSON_STATE_OBJ_KEY_OR_END, pos)) return(false); out_node = node; return(true); } // Array if(c == 0x5B) { int node = NewNode((uchar)JSON_ARRAY, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); AddChild(parent, node); pos++; if(!PushStack(node, (uchar)JSON_STATE_ARRAY_VALUE_OR_END, pos)) return(false); out_node = node; return(true); } // String if(c == 0x22) { int s, l; bool dec; uint h; if(!ParseStringToken(pos, s, l, dec, h)) return(false); int node = NewNode((uchar)JSON_STRING, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); m_nodes[node].val_start = s; m_nodes[node].val_len = l; if(dec) m_nodes[node].flags = (uchar)(m_nodes[node].flags | JSON_FLAG_VAL_DECODED); AddChild(parent, node); out_node = node; return(true); } // true if(c == 0x74) { if(pos + 4 > m_size || Buffer[pos + 1] != 0x72 || Buffer[pos + 2] != 0x75 || Buffer[pos + 3] != 0x65) { return(SetError(JSON_INVALID_LITERAL, pos)); } int node = NewNode((uchar)JSON_BOOL, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); m_nodes[node].num = 1.0; AddChild(parent, node); pos += 4; out_node = node; return(true); } // false if(c == 0x66) { if(pos + 5 > m_size || Buffer[pos + 1] != 0x61 || Buffer[pos + 2] != 0x6C || Buffer[pos + 3] != 0x73 || Buffer[pos + 4] != 0x65) { return(SetError(JSON_INVALID_LITERAL, pos)); } int node = NewNode((uchar)JSON_BOOL, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); m_nodes[node].num = 0.0; AddChild(parent, node); pos += 5; out_node = node; return(true); } // null if(c == 0x6E) { if(pos + 4 > m_size || Buffer[pos + 1] != 0x75 || Buffer[pos + 2] != 0x6C || Buffer[pos + 3] != 0x6C) { return(SetError(JSON_INVALID_LITERAL, pos)); } int node = NewNode((uchar)JSON_NULL, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); m_nodes[node].num = 0.0; AddChild(parent, node); pos += 4; out_node = node; return(true); } // Number if(c == 0x2D || (c >= 0x30 && c <= 0x39)) { double v; if(!ParseNumberToken(pos, v)) return(false); int node = NewNode((uchar)JSON_NUMBER, parent, pos); if(node < 0) return(false); if(!AssignPendingKey(node, parent, pos)) return(false); m_nodes[node].num = v; AddChild(parent, node); out_node = node; return(true); } return(SetError(JSON_UNEXPECTED_CHARACTER, pos)); } //+---------------------------------------------------------------+ //| Build contiguous child index | //+---------------------------------------------------------------+ bool BuildChildren(int pos) { int total = 0; for(int i = 0; i < m_node_used; i++) { m_nodes[i].last_child = total; total += m_nodes[i].child_count; } if(total == 0) { ArrayFree(m_children); for(int i = 0; i < m_node_used; i++) m_nodes[i].first_child = 0; return(true); } if(ArrayResize(m_children, total, total + 1024) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); for(int i = 0; i < m_node_used; i++) { int offset = m_nodes[i].last_child; int child = m_nodes[i].first_child; int idx = 0; while(child != -1) { m_children[offset + idx] = child; child = m_nodes[child].next_sibling; idx++; } m_nodes[i].first_child = offset; m_nodes[i].last_child = -1; } return(true); } //+---------------------------------------------------------------+ //| Hash helpers | //+---------------------------------------------------------------+ uint HashMix(int parent, uint key_hash) const { uint h = key_hash ^ ((uint)parent * (uint)0x9E3779B9); h ^= (h >> 16); h *= (uint)0x85EBCA6B; h ^= (h >> 13); h *= (uint)0xC2B2AE35; h ^= (h >> 16); return(h); } uint HashBytes(uchar &data[], int len) const { uint h = JSON_FNV_INIT; for(int i = 0; i < len; i++) h = ((h ^ data[i]) * JSON_FNV_PRIME); return(h); } bool KeyEquals(int node, uchar &key[], int len, uint hash) { if(node < 0 || node >= m_node_used) return(false); if(m_nodes[node].key_len != len) return(false); if(m_nodes[node].key_hash != hash) return(false); if(len == 0) return(true); int start = m_nodes[node].key_start; if((m_nodes[node].flags & JSON_FLAG_KEY_DECODED) != 0) { for(int i = 0; i < len; i++) { if(m_pool[start + i] != key[i]) return(false); } } else { for(int i = 0; i < len; i++) { if(Buffer[start + i] != key[i]) return(false); } } return(true); } void InsertHash(int parent, uint key_hash, int node) { if(m_hash_size <= 0) return; uint pos = HashMix(parent, key_hash) & (uint)m_hash_mask; int scanned = 0; while(m_hash_parent[pos] != -1 && scanned < m_hash_size) { pos = (pos + 1) & (uint)m_hash_mask; scanned++; } if(scanned >= m_hash_size) return; m_hash_parent[pos] = parent; m_hash_key[pos] = key_hash; m_hash_node[pos] = node; } bool BuildHash(int pos) { m_hash_size = 0; m_hash_mask = 0; if(m_member_count <= 0) return(true); int target = m_member_count * 2; if(target <= 0) target = 0x40000000; if(target < 16) target = 16; int table_size = 1; while(table_size < target && table_size < 0x40000000) table_size <<= 1; if(ArrayResize(m_hash_parent, table_size, table_size + 1024) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); if(ArrayResize(m_hash_key, table_size, table_size + 1024) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); if(ArrayResize(m_hash_node, table_size, table_size + 1024) < 0) return(SetError(JSON_MEMORY_ERROR, pos)); for(int i = 0; i < table_size; i++) m_hash_parent[i] = -1; m_hash_size = table_size; m_hash_mask = table_size - 1; for(int i = 0; i < m_node_used; i++) { int p = m_nodes[i].parent; if(p >= 0 && m_nodes[p].type == (uchar)JSON_OBJECT) InsertHash(p, m_nodes[i].key_hash, i); } return(true); } public: //+---------------------------------------------------------------+ //| Reset / Clear | //+---------------------------------------------------------------+ void Reset() { m_size = 0; m_root = -1; m_error = JSON_OK; m_error_pos = -1; m_node_used = 0; m_pool_used = 0; m_stack_used = 0; m_member_count = 0; m_hash_size = 0; m_hash_mask = 0; m_pending_key_start = 0; m_pending_key_len = 0; m_pending_key_hash = 0; m_pending_flags = 0; m_pending_valid = false; } void Clear() { ArrayFree(m_nodes); ArrayFree(m_children); ArrayFree(m_pool); ArrayFree(m_stack); ArrayFree(m_state); ArrayFree(m_hash_parent); ArrayFree(m_hash_key); ArrayFree(m_hash_node); Reset(); } //+---------------------------------------------------------------+ //| Constructor / Destructor | //+---------------------------------------------------------------+ CJson() { InputSize = -1; MaxDepth = 1024; UseHashIndex = true; HashThreshold = 16; Reset(); } ~CJson() { Clear(); } //+---------------------------------------------------------------+ //| Main parse function | //+---------------------------------------------------------------+ bool Parse() { Reset(); if(MaxDepth <= 0) MaxDepth = 1024; if(HashThreshold < 0) HashThreshold = 0; ArraySetAsSeries(Buffer, false); int buf_size = ArraySize(Buffer); if(InputSize >= 0) m_size = (InputSize < buf_size ? InputSize : buf_size); else m_size = buf_size; if(m_size < 0) m_size = 0; int pos = 0; // Optional UTF-8 BOM. if(m_size >= 3 && Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) pos = 3; SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); int root; if(!CreateValueNode(pos, -1, root)) return(false); m_root = root; while(m_stack_used > 0) { int si = m_stack_used - 1; int node = m_stack[si]; uchar st = m_state[si]; if(st == (uchar)JSON_STATE_OBJ_KEY_OR_END) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c == 0x7D) { pos++; m_stack_used--; continue; } if(c != 0x22) return(SetError(JSON_EXPECTED_KEY, pos)); if(!ParseObjectKey(pos)) return(false); m_state[si] = (uchar)JSON_STATE_OBJ_COLON; } else if(st == (uchar)JSON_STATE_OBJ_KEY) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c != 0x22) return(SetError(JSON_EXPECTED_KEY, pos)); if(!ParseObjectKey(pos)) return(false); m_state[si] = (uchar)JSON_STATE_OBJ_COLON; } else if(st == (uchar)JSON_STATE_OBJ_COLON) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); if(Buffer[pos] != 0x3A) return(SetError(JSON_EXPECTED_COLON, pos)); pos++; m_state[si] = (uchar)JSON_STATE_OBJ_VALUE; } else if(st == (uchar)JSON_STATE_OBJ_VALUE) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); m_state[si] = (uchar)JSON_STATE_OBJ_COMMA_OR_END; int child; if(!CreateValueNode(pos, node, child)) return(false); } else if(st == (uchar)JSON_STATE_OBJ_COMMA_OR_END) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c == 0x2C) { pos++; m_state[si] = (uchar)JSON_STATE_OBJ_KEY; } else if(c == 0x7D) { pos++; m_stack_used--; } else { return(SetError(JSON_EXPECTED_COMMA, pos)); } } else if(st == (uchar)JSON_STATE_ARRAY_VALUE_OR_END) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c == 0x5D) { pos++; m_stack_used--; continue; } m_state[si] = (uchar)JSON_STATE_ARRAY_COMMA_OR_END; int child; if(!CreateValueNode(pos, node, child)) return(false); } else if(st == (uchar)JSON_STATE_ARRAY_VALUE) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c == 0x5D) return(SetError(JSON_EXPECTED_VALUE, pos)); m_state[si] = (uchar)JSON_STATE_ARRAY_COMMA_OR_END; int child; if(!CreateValueNode(pos, node, child)) return(false); } else if(st == (uchar)JSON_STATE_ARRAY_COMMA_OR_END) { SkipWs(pos); if(pos >= m_size) return(SetError(JSON_UNEXPECTED_END, pos)); uchar c = Buffer[pos]; if(c == 0x2C) { pos++; m_state[si] = (uchar)JSON_STATE_ARRAY_VALUE; } else if(c == 0x5D) { pos++; m_stack_used--; } else { return(SetError(JSON_EXPECTED_COMMA, pos)); } } else { return(SetError(JSON_UNKNOWN_ERROR, pos)); } } SkipWs(pos); if(pos != m_size) return(SetError(JSON_TRAILING_DATA, pos)); if(!BuildChildren(pos)) return(false); if(UseHashIndex && m_member_count >= HashThreshold) { if(!BuildHash(pos)) return(false); } else { m_hash_size = 0; } return(true); } //+---------------------------------------------------------------+ //| Error API | //+---------------------------------------------------------------+ ENUM_JSON_ERROR GetError() const { return(m_error); } bool HasError() const { return(m_error != JSON_OK); } string GetErrorMessage() const { switch(m_error) { case JSON_OK: return("OK"); case JSON_UNKNOWN_ERROR: return("Unknown error"); case JSON_UNEXPECTED_CHARACTER: return("Unexpected character"); case JSON_UNEXPECTED_END: return("Unexpected end of input"); case JSON_INVALID_NUMBER: return("Invalid number"); case JSON_INVALID_STRING: return("Invalid string"); case JSON_INVALID_ESCAPE: return("Invalid escape sequence"); case JSON_INVALID_UNICODE: return("Invalid unicode sequence"); case JSON_EXPECTED_COLON: return("Expected colon"); case JSON_EXPECTED_COMMA: return("Expected comma"); case JSON_EXPECTED_OBJECT: return("Expected object"); case JSON_EXPECTED_ARRAY: return("Expected array"); case JSON_EXPECTED_KEY: return("Expected object key"); case JSON_EXPECTED_VALUE: return("Expected value"); case JSON_INVALID_LITERAL: return("Invalid literal"); case JSON_MAX_DEPTH: return("Maximum depth exceeded"); case JSON_MEMORY_ERROR: return("Memory allocation error"); case JSON_TRAILING_DATA: return("Trailing data after JSON document"); } return("Unknown error"); } int GetErrorPosition() const { return(m_error_pos); } int GetLine() const { if(m_error_pos < 0) return(0); int limit = m_error_pos; if(limit > m_size) limit = m_size; int line = 1; for(int i = 0; i < limit; i++) { if(Buffer[i] == 0x0A) line++; } return(line); } int GetColumn() const { if(m_error_pos < 0) return(0); int limit = m_error_pos; if(limit > m_size) limit = m_size; int col = 1; for(int i = limit - 1; i >= 0; i--) { if(Buffer[i] == 0x0A) break; col++; } return(col); } //+---------------------------------------------------------------+ //| Basic node API | //+---------------------------------------------------------------+ int Root() const { return(m_root); } bool Exists(int node = -1) { int n = Resolve(node); return(n >= 0 && n < m_node_used); } ENUM_JSON_TYPE GetType(int node = -1) { int n = Resolve(node); if(n < 0 || n >= m_node_used) return(JSON_NONE); return((ENUM_JSON_TYPE)m_nodes[n].type); } bool IsObject(int node = -1) { return(GetType(node) == JSON_OBJECT); } bool IsArray(int node = -1) { return(GetType(node) == JSON_ARRAY); } bool IsString(int node = -1) { return(GetType(node) == JSON_STRING); } bool IsNumber(int node = -1) { return(GetType(node) == JSON_NUMBER); } bool IsBool(int node = -1) { return(GetType(node) == JSON_BOOL); } bool IsNull(int node = -1) { return(GetType(node) == JSON_NULL); } int Size(int node = -1) { int n = Resolve(node); if(n < 0 || n >= m_node_used) return(0); uchar t = m_nodes[n].type; if(t == (uchar)JSON_OBJECT || t == (uchar)JSON_ARRAY) return(m_nodes[n].child_count); return(0); } int Count(int node = -1) { return(Size(node)); } //+---------------------------------------------------------------+ //| Child access | //+---------------------------------------------------------------+ int GetChild(int parent, int index) { int p = (parent < 0 ? m_root : parent); if(p < 0 || p >= m_node_used) return(-1); uchar t = m_nodes[p].type; if(t != (uchar)JSON_OBJECT && t != (uchar)JSON_ARRAY) return(-1); if(index < 0 || index >= m_nodes[p].child_count) return(-1); return(m_children[m_nodes[p].first_child + index]); } int FindChild(int parent, uchar &key[], int key_len) { int p = (parent < 0 ? m_root : parent); if(p < 0 || p >= m_node_used) return(-1); if(m_nodes[p].type != (uchar)JSON_OBJECT) return(-1); if(key_len < 0) return(-1); uint qhash = HashBytes(key, key_len); if(m_hash_size > 0) { uint pos = HashMix(p, qhash) & (uint)m_hash_mask; int scanned = 0; while(m_hash_parent[pos] != -1 && scanned < m_hash_size) { if(m_hash_parent[pos] == p && m_hash_key[pos] == qhash) { int child = m_hash_node[pos]; if(KeyEquals(child, key, key_len, qhash)) return(child); } pos = (pos + 1) & (uint)m_hash_mask; scanned++; } return(-1); } int offset = m_nodes[p].first_child; int count = m_nodes[p].child_count; for(int i = 0; i < count; i++) { int child = m_children[offset + i]; if(KeyEquals(child, key, key_len, qhash)) return(child); } return(-1); } int FindChild(int parent, const string &key) { uchar bytes[]; int len = StringToCharArray(key, bytes, 0, -1, JSON_CP_UTF8); if(len < 0) { len = StringToCharArray(key, bytes); if(len < 0) return(-1); } if(len > 0 && bytes[len - 1] == 0) len--; return(FindChild(parent, bytes, len)); } //+---------------------------------------------------------------+ //| Key and value access | //+---------------------------------------------------------------+ string GetKey(int node) { if(node < 0 || node >= m_node_used) return(""); int parent = m_nodes[node].parent; if(parent < 0 || parent >= m_node_used) return(""); if(m_nodes[parent].type != (uchar)JSON_OBJECT) return(""); int len = m_nodes[node].key_len; if(len <= 0) return(""); int start = m_nodes[node].key_start; if((m_nodes[node].flags & JSON_FLAG_KEY_DECODED) != 0) return(CharArrayToString(m_pool, start, len, JSON_CP_UTF8)); return(CharArrayToString(Buffer, start, len, JSON_CP_UTF8)); } string GetString(int node = -1) { int n = Resolve(node); if(n < 0 || n >= m_node_used) return(""); uchar t = m_nodes[n].type; if(t == (uchar)JSON_STRING) { int len = m_nodes[n].val_len; if(len <= 0) return(""); int start = m_nodes[n].val_start; if((m_nodes[n].flags & JSON_FLAG_VAL_DECODED) != 0) return(CharArrayToString(m_pool, start, len, JSON_CP_UTF8)); return(CharArrayToString(Buffer, start, len, JSON_CP_UTF8)); } // [CORRECION POR NIQUE](DOUBLE TO STRING NO TIENE UN 3 PARAMETRO) // VERSION ORIGINAL: DoubleToString(m_nodes[n].num, 16, false) // Correcion: if(t == (uchar)JSON_NUMBER) return(DoubleToString(m_nodes[n].num, 16)); if(t == (uchar)JSON_BOOL) return(m_nodes[n].num != 0.0 ? "true" : "false"); if(t == (uchar)JSON_NULL) return("null"); return(""); } double GetDouble(int node = -1) { int n = Resolve(node); if(n < 0 || n >= m_node_used) return(0.0); uchar t = m_nodes[n].type; if(t == (uchar)JSON_NUMBER) return(m_nodes[n].num); if(t == (uchar)JSON_BOOL) return(m_nodes[n].num); if(t == (uchar)JSON_STRING) { string s = GetString(n); // CORRECION POR NIQUE_372 // SOLO RECIBE 1 PARAMETRO NO 2.. ORIGINAL "StringToDouble(s, v)" (infiero que se pasa por referncia..) // Correcion: return StringToDouble(s); } return(0.0); } long GetInteger(int node = -1) { return((long)GetDouble(node)); } bool GetBool(int node = -1) { int n = Resolve(node); if(n < 0 || n >= m_node_used) return(false); uchar t = m_nodes[n].type; if(t == (uchar)JSON_BOOL) return(m_nodes[n].num != 0.0); if(t == (uchar)JSON_NUMBER) return(m_nodes[n].num != 0.0); if(t == (uchar)JSON_STRING) { string s = GetString(n); return(s == "true" || s == "1"); } return(false); } //+---------------------------------------------------------------+ //| Convenient root access | //+---------------------------------------------------------------+ JsonRef operator[](const string key) { // ORIGINAL: return(JsonRef(this, FindChild(m_root, key))); // CORRECION POR NIQUE (THIS ES REF NO PTR) return(JsonRef(&this, FindChild(m_root, key))); } JsonRef operator[](const int index) { // ORIGINAL: return(JsonRef(this, GetChild(m_root, index))); // CORRECION POR NIQUE (THIS ES REF NO PTR) return(JsonRef(&this, GetChild(m_root, index))); } }; //+------------------------------------------------------------------+ //| JsonRef implementation | //+------------------------------------------------------------------+ JsonRef JsonRef::operator[](const string key) // qyuite el & por ese error que mencione { if(json == NULL || node < 0) return(JsonRef()); return(JsonRef(json, json.FindChild(node, key))); } JsonRef JsonRef::operator[](const int index) { if(json == NULL || node < 0) return(JsonRef()); return(JsonRef(json, json.GetChild(node, index))); } bool JsonRef::Exists() { if(json == NULL || node < 0) return(false); return(json.Exists(node)); } int JsonRef::Type() { if(json == NULL || node < 0) return(JSON_NONE); return(json.GetType(node)); } int JsonRef::Size() { if(json == NULL || node < 0) return(0); return(json.Size(node)); } double JsonRef::ToDouble() { if(json == NULL || node < 0) return(0.0); return(json.GetDouble(node)); } long JsonRef::ToInteger() { if(json == NULL || node < 0) return(0); return(json.GetInteger(node)); } bool JsonRef::ToBool() { if(json == NULL || node < 0) return(false); return(json.GetBool(node)); } string JsonRef::ToString() { if(json == NULL || node < 0) return(""); return(json.GetString(node)); } bool JsonRef::IsObject() { return(Type() == JSON_OBJECT); } bool JsonRef::IsArray() { return(Type() == JSON_ARRAY); } bool JsonRef::IsString() { return(Type() == JSON_STRING); } bool JsonRef::IsNumber() { return(Type() == JSON_NUMBER); } bool JsonRef::IsBool() { return(Type() == JSON_BOOL); } bool JsonRef::IsNull() { return(Type() == JSON_NULL); } #endif