//
//  File:   hzXbuf.h
//
//  Legal Notice: This file is part of the HadronZoo C++ Class Library.
//
//  Copyright 2025 HadronZoo Project (http://www.hadronzoo.com)
//
//  The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free
//  Software Foundation, either version 3 of the License, or any later version.
//
//  The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
//  A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses.
//
#ifndef hzXbuf_h
#define hzXbuf_h
#include <iostream>
#include <fstream>
#include <stdarg.h>
#include "hzBasedefs.h"
#include "hzString.h"
#include "hzTmplArray.h"
class   hzEmaddr ;
class   hzIpaddr ;
/*
**  Section 2:  The hzXbuf class
*/
class   hzXbuf
{
    //  Category:   Data
    //
    //  hzXbuf can be considered a variant of hzChain. Both are chains of blocks that act as unlimited buffers, but where hzChain is aimed at string value assembly, hzXbuf is aimed
    //  at storing internal RAM Primacy data. hzXbuf is used in the data cache of the HDB data object repository, hdbObjRepos, and by the hdbIdset class.
    //
    //  To these ends, hzXbuf uses a different allocation regime, does not support a Printf function, and cannot be reverse iterated.
    struct _xbuf
    {
        //  hzXbuf control area
        uint32_t    m_nSize ;           //  Total size in bytes
        uint16_t    m_copy ;            //  Copy count
        uint16_t    m_blox ;            //  Block count
        void*       m_Begin ;           //  Address of first block in chain
        void*       m_End ;             //  Address of last block in chain
        _xbuf   (void) ;
        ~_xbuf  (void) ;
    } ;
    _xbuf*      mx ;    //  Smart pointer to contents
    int32_t     _compare    (const hzXbuf& op) const ;
public:
    struct  Iter
    {
        //  Standard bytewise chain iterator
        void*       m_block ;       //  Current block address
        uint32_t    m_nLine ;       //  For tracking line numbers
        uint32_t    m_nCol ;        //  Column number
        uint16_t    m_nOset ;       //  Current offset within block
        char        m_cDefault ;    //  Default char
        char        m_Reserved ;    //  Not used at present
        Iter    (void)
        {
            //  Construct and init the chain iterator
            m_block = 0 ;
            m_nLine = 1 ;
            m_nCol = 0 ;
            m_nOset = 0 ;
            m_cDefault = 0 ;
        }
        //  Read unicode char
        hzEcode ReadUnicodeChar (uint32_t& uniVal) ;
        //  Skip whitespace
        Iter&       Skipwhite   (void) ;
        //  Misc functions
        uint32_t    Line    (void)          { return m_nLine ; }
        uint32_t    Col     (void)          { return m_nCol ; }
        void        Line    (uint32_t n)    { m_nLine = n ; }
        uchar   current     (void) const ;
        bool    eof         (void) const ;
        //  Operators to set iterator position
        Iter&   operator=    (const hzXbuf& I)
        {
            //  Set this chain iterator to the start of the supplied chain
            if (I.mx)
                m_block = I.mx->m_Begin ;
            else
                m_block = 0 ;
            m_nLine = 1 ;
            m_nCol = 0 ;
            m_nOset = 0 ;
            return *this ;
        }
        Iter&   operator=    (const Iter& I)
        {
            //  Set this chain iterator to another
            m_block = I.m_block ;
            m_nLine = I.m_nLine ;
            m_nOset = I.m_nOset ;
            m_cDefault = I.m_cDefault ;
            return *this ;
        }
        //  Write out block of chars to buffer. Return bytes written out but don't increment iterator (do that in app with the return value)
        uint32_t    Write   (void* pBuf, uint32_t maxBytes) ;
        bool    operator==   (const Iter& I) const  { return m_block == I.m_block && m_nOset == I.m_nOset ? true : false ; }
        bool    operator!=   (const Iter& I) const  { return m_block == I.m_block && m_nOset == I.m_nOset ? false : true ; }
        //  Advance (increment without column/line accounting)
        uint32_t    Advance     (uint32_t nInc) ;
        //  Increment and decrement
        Iter&   operator++  (void) ;
        Iter&   operator++  (int) ;
        Iter&   operator+=  (uint32_t nInc) ;
        //  Case sensitive compare functions
        bool    Equal       (const uchar c) const ;
        bool    Equal       (const uchar* s) const ;
        bool    Equal       (const hzString& S) const   { return Equal(*S) ; }
        //  Case in-sensitive compare functions
        bool    Equiv       (const uchar c) const ;
        bool    Equiv       (const uchar* s) const ;
        bool    Equiv       (const hzString& S) const   { return Equiv(*S) ; }
        //  Compare operators
        bool    operator==  (const uchar c) const   { return Equal(c) ; }
        bool    operator==  (const uchar* s) const  { return Equal(s) ; }
        bool    operator==  (hzString& S) const     { return Equal(S) ; }
        bool    operator==  (Iter& I) const         { return m_block == I.m_block && m_nOset == I.m_nOset ? true : false ; }
        bool    operator!=  (const uchar c) const   { return !Equal(c) ; }
        bool    operator!=  (const uchar* s) const  { return !Equal(s) ; }
        bool    operator!=  (hzString& S) const     { return !Equal(S) ; }
        bool    operator!=  (Iter& I) const         { return m_block == I.m_block && m_nOset == I.m_nOset ? false : true ; }
        //  Set current char
        uchar   operator=   (const uchar c) ;
        //  Get current or offset char
        uchar   operator[]  (uint32_t nOset) const ;
        uchar   operator*   (void) const ;
        //  Diagnostics
        uint32_t    _oset   (void)  { return m_nOset ; }
    } ;
    void    Clear   (void) ;
    //  Constructors/Destructors
    hzXbuf  (void) ;
    hzXbuf  (const hzXbuf& op) ;
    ~hzXbuf (void) ;
    //  Get hzXbuf attributes
    uint32_t    Size    (void) const    { return mx ? mx->m_nSize : 0 ; }
    //  Set chain contents
    hzXbuf& operator=   (const hzXbuf& op) ;
    hzXbuf& operator=   (const hzString& S) ;
    hzXbuf& operator=   (const char* pStr) ;
    //  Test operator
    bool        operator!   (void)  { return Size() > 0 ? false : true ; }
    //  Append void* data to the chain. Note as there is no null termination the number of bytes to append must be specified.
    uint32_t    Append      (const void* vpBuf, uint32_t nBytes) ;
    //  Append a sub-chain
    //uint32_t  AppendSub   (hzXbuf& Z, uint32_t nStart, uint32_t nBytes) ;
    //  Append single character
    hzEcode     AddByte     (const char c) ;
    //  Append whole entities by operators
    hzXbuf& operator+=  (const uchar* s) ;
    hzXbuf& operator+=  (const hzString& s) ;
    hzXbuf& operator+=  (const hzXbuf& op) ;
    hzXbuf& operator+=  (const hzChain& Z) ;
    //  Compare operators
    bool    operator==  (const hzXbuf& op) const    { return _compare(op) == 0 ? true : false ; }
    bool    operator!=  (const hzXbuf& op) const    { return _compare(op) != 0 ? true : false ; }
    bool    operator<   (const hzXbuf& op) const    { return _compare(op) <  0 ? true : false ; }
    bool    operator<=  (const hzXbuf& op) const    { return _compare(op) <= 0 ? true : false ; }
    bool    operator>   (const hzXbuf& op) const    { return _compare(op) >  0 ? true : false ; }
    bool    operator>=  (const hzXbuf& op) const    { return _compare(op) >= 0 ? true : false ; }
} ;
#define xbufIter     hzXbuf::Iter
#endif  //  hzXbuf_h