//+------------------------------------------------------------------+ //| Iteradores.mqh | //| Copyright 2026, Niquel Mendoza | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza" #property link "https://www.mql5.com" #property strict #ifndef CRYPTOBYLEO_RSPPARSER_ITERADORES_MQH #define CRYPTOBYLEO_RSPPARSER_ITERADORES_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "Node.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| Por defecto | //+------------------------------------------------------------------+ MQLARTICLES_STRUCTBYTES_CRE(3) MQLARTICLES_STRUCTBYTES_CRE(4) MQLARTICLES_STRUCTBYTES_CRE(5) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CRSPIteradorBase { protected: CRSPParser* m_ctx; // contrexto int m_pos; // indice de lectura int m_cinta_len; int m_readed_pars; int m_par_size; int m_last_pos; public: CRSPIteradorBase(CRSPParser* _ctx, const int init_pos, const int psize); ~CRSPIteradorBase(void) {} //--- Get virtual __forceinline CRSPNode Get(const string& key) const = 0; //--- General // es valido seguir iterando __forceinline bool IsValid() const { return m_pos < m_cinta_len; } // avanza un "chunk" entero de lectura void Next(); // mata el puntero de lecutra.. void Kill() { m_last_pos = m_pos; m_pos = m_cinta_len; } //--- setters __forceinline void RecalcLen() { m_cinta_len = m_ctx.m_cinta_pos; } // setear el puntero de lectura void operator=(const int p) { m_pos = p; m_readed_pars = 0; } // lo resetea en la ultima poscion (justo en KEY meta) de la iteracion previa __forceinline void ResetLast() { m_pos = m_last_pos; m_readed_pars = 0; } //--- getters __forceinline int ReadLastPos() const { return m_last_pos; } __forceinline int ReadPointer() const { return m_pos; } __forceinline int ReadPars() const { return m_readed_pars; } //--- at (base indice) __forceinline CRSPNode At(const int index) const; // obtiene por indice posicion }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CRSPIteradorBase::CRSPIteradorBase(CRSPParser* _ctx, const int init_pos, const int psize) : m_ctx(_ctx), m_pos(init_pos), m_cinta_len((_ctx == NULL ? 0 : _ctx.m_cinta_pos)), m_readed_pars(0), m_par_size(psize) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CRSPIteradorBase::Next() { if(m_pos >= m_cinta_len) return; // avanzamos m_pos += (RSPDATA_TRIPLET_KEYVALUEMETA * m_par_size); m_readed_pars++; // verificamos que en caso qeu el meta sea del tipo metacor entonces paramos ya no hay nada mas que hacer if(((m_ctx.m_cinta[m_pos + 1] >> TSN_SBL_BIT_START_ENDTYPE)&RSPDATA_MASK_META_IS) != 0) // justo en meta { m_last_pos = m_pos; m_pos = m_cinta_len; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ __forceinline CRSPNode CRSPIteradorBase::At(const int index) const { return CRSPNode(m_pos + (index * RSPDATA_TRIPLET_KEYVALUEMETA), m_ctx); } //+------------------------------------------------------------------+ //| IOterador por hash perfecto | //+------------------------------------------------------------------+ #define CRSPIteratorPHashFast TSN::CRSPIteratorPHash #define CRSPIteratorPHashFastP(P) TSN::CRSPIteratorPHash //--- template class CRSPIteratorPHash : public CRSPIteradorBase { private: //--- pfh int m_offets[]; // offets ulong m_seeds[]; // seeds ulong m_key_hash[]; // array de key hashes ulong m_bucket_l; // Buckets ulong m_final_table_l; // Tamaño de pos index (tabla final) bool m_valid_it; public: CRSPIteratorPHash(const string& keys[], CRSPParser* _ctx, const int init_pos); CRSPIteratorPHash() : CRSPIteradorBase(NULL, -1, 0) {} ~CRSPIteratorPHash() {} //--- using CRSPIteradorBase::operator=; //---- __forceinline bool IsHashValid() const { return m_valid_it; } //--- // No se permite modifacion es una tabla de hash perfecta //--- at por key CRSPNode operator[](const string& key) const; // obtiene por key //--- __forceinline CRSPNode Get(const string& key) const override final { return this[key]; } //--- static const CRSPIteratorPHash EMPTY; }; //+------------------------------------------------------------------+ template const CRSPIteratorPHash CRSPIteratorPHash::EMPTY; //+------------------------------------------------------------------+ template CRSPIteratorPHash::CRSPIteratorPHash(const string& keys[], CRSPParser* _ctx, const int init_pos) : CRSPIteradorBase(_ctx, init_pos, ArraySize(keys)) { // se asume que keys size = TNumHash (sizeof) // iteramos por todas las key contruimos hashes CPerfectHashByLeo* pf = m_ctx.m_pfh; //--- ulong key_h[]; ArrayResize(key_h, m_par_size); int off[]; ArrayResize(off, m_par_size); //--- for(int j = 0; j < m_par_size; j++) { key_h[j] = TBaseHash::Hash(keys[j]); off[j] = (j * RSPDATA_TRIPLET_KEYVALUEMETA) + 1; } //--- pf.MaxValSeed(m_ctx.m_max_att++); pf.InitAlg(m_par_size, 0.70, fmin(m_par_size, 4)); //--- const int fn = pf.m_final_table_size; m_bucket_l = pf.m_buckets_size_last; m_final_table_l = pf.m_final_table_size_last; // Iniciamos.. ArrayResize(m_offets, fn); ArrayResize(m_key_hash, fn); ArrayInitialize(m_offets, -1); ArrayInitialize(m_key_hash, 0ULL); //--- pf.RunWValue(key_h, off, m_seeds, m_offets, m_key_hash); } //+------------------------------------------------------------------+ template CRSPNode CRSPIteratorPHash::operator[](const string& key) const { //--- calculo del hash const ulong key_hash = TBaseHash::Hash(key); //--- alg const int seed_index = int(key_hash & m_bucket_l); SBL_HASH_ALG(key_hash, m_seeds[seed_index]) //--- const int fi = int(h & m_final_table_l); return m_key_hash[fi] == key_hash ? CRSPNode(m_pos + m_offets[fi], m_ctx) : CRSPNode::EMPTY_NODE; } //+------------------------------------------------------------------+ //| Iterador por hash custom | //+------------------------------------------------------------------+ // TNumHashes = cuantos hashes hay #define CRSPIteratorHashFast(NH ) TSN::CRSPIteratorHash #define CRSPIteratorHashFastP(NH, P) TSN::CRSPIteratorHash //--- template class CRSPIteratorHash : public CRSPIteradorBase { private: //--- hash ulong m_hashes[sizeof(TNumHashes)]; // tamaño fijo maxima velocidad public: CRSPIteratorHash(const string& keys[], CRSPParser* _ctx, const int init_pos); CRSPIteratorHash() : CRSPIteradorBase(NULL, -1, 0) {} ~CRSPIteratorHash() {} //--- using CRSPIteradorBase::operator=; //--- // modifiacion void HashPos(const int j, const string& key) { m_hashes[j] = TBaseHash::Hash(key); } // obtencion de hash __forceinline ulong HashPos(const int j) { return m_hashes[j]; } //--- at por key CRSPNode operator[](const string& key) const; // obtiene por key //--- __forceinline CRSPNode Get(const string& key) const override final { return this[key]; } //--- static const CRSPIteratorHash EMPTY; }; //+------------------------------------------------------------------+ template const CRSPIteratorHash CRSPIteratorHash::EMPTY; //+------------------------------------------------------------------+ template CRSPIteratorHash::CRSPIteratorHash(const string& keys[], CRSPParser* _ctx, const int init_pos) : CRSPIteradorBase(_ctx, init_pos, sizeof(TNumHashes)) { for(int j = 0; j < sizeof(TNumHashes); j++) m_hashes[j] = TBaseHash::Hash(keys[j]); } //+------------------------------------------------------------------+ template CRSPNode CRSPIteratorHash::operator[](const string& key) const { //--- calculo del hash const ulong h = TBaseHash::Hash(key); //--- ahora iteramos for(int i = 0; i < sizeof(TNumHashes); i++) { if(m_hashes[i] == h) { // coincide .. aparitr de aqui calculamos.. const int idx = m_pos + (i * RSPDATA_TRIPLET_KEYVALUEMETA); return CRSPNode(idx + 1, m_ctx); } } //--- No se encontro return CRSPNode::EMPTY_NODE; } //+------------------------------------------------------------------+ //| Iterador por hash custom (dinamico | //+------------------------------------------------------------------+ // TNumHashes = cuantos hashes hay #define CRSPIteratorHashDyncFast TSN::CRSPIteratorHashDync #define CRSPIteratorHashDyncFastP(P) TSN::CRSPIteratorHashDync //--- template class CRSPIteratorHashDync : public CRSPIteradorBase { private: //--- hash ulong m_hashes[]; // tamaño fijo maxima velocidad public: CRSPIteratorHashDync(const string& keys[], CRSPParser* _ctx, const int init_pos); CRSPIteratorHashDync() : CRSPIteradorBase(NULL, -1, 0) {} ~CRSPIteratorHashDync() {} //--- using CRSPIteradorBase::operator=; //--- void Size(const int new_s); __forceinline int Size() const { return m_par_size; } // modifiacion void HashPos(const int j, const string& key) { m_hashes[j] = TBaseHash::Hash(key); } // obtencion de hash __forceinline ulong HashPos(const int j) { return m_hashes[j]; } //--- at por key CRSPNode operator[](const string& key) const; // obtiene por key //--- __forceinline CRSPNode Get(const string& key) const override final { return this[key]; } //--- static const CRSPIteratorHashDync EMPTY; }; //+------------------------------------------------------------------+ template const CRSPIteratorHashDync CRSPIteratorHashDync::EMPTY; //+------------------------------------------------------------------+ template CRSPIteratorHashDync::CRSPIteratorHashDync(const string& keys[], CRSPParser* _ctx, const int init_pos) : CRSPIteradorBase(_ctx, init_pos, ArraySize(keys)) { ArrayResize(m_hashes, m_par_size); for(int j = 0; j < m_par_size; j++) m_hashes[j] = TBaseHash::Hash(keys[j]); } //+------------------------------------------------------------------+ template void CRSPIteratorHashDync::Resize(const int new_s) { if(new_s <= m_par_size) m_par_size = new_s; else { if(new_s > ArraySize(m_hashes)) ArrayResize(m_hashes, new_s, new_s); m_par_size = new_s; } } //+------------------------------------------------------------------+ template CRSPNode CRSPIteratorHashDync::operator[](const string& key) const { //--- calculo del hash const ulong h = TBaseHash::Hash(key); //--- ahora iteramos for(int i = 0; i < m_par_size; i++) { if(m_hashes[i] == h) { // coincide .. aparitr de aqui calculamos.. const int idx = m_pos + (i * RSPDATA_TRIPLET_KEYVALUEMETA); return CRSPNode(idx + 1, m_ctx); } } //--- No se encontro return CRSPNode::EMPTY_NODE; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template CRSPIteradorBase* CRSPNode::MakeInteligentIterador(const string& keys[]) const { if(RSPDATA_IS_NOT_VALID) return NULL; //--- const int t = ArraySize(keys); if(t >= RSPNODE_ITERADOR_MIN_PFH) { CRSPIteradorBase* it = new CRSPIteratorPHash(keys, m_ctx, m_idx); if(!it.IsHashValid()) delete it; // fallo en formarse fallback a normal.. else return it; } //--- return new CRSPIteratorHashDync(keys, m_ctx, m_idx); } //--- } //+------------------------------------------------------------------+ #endif // CRYPTOBYLEO_RSPPARSER_ITERADORES_MQH