// // File: hzChain.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 hzChain_h #define hzChain_h
#include <iostream> #include <fstream>
#include <stdarg.h>
#include "hzBasedefs.h" #include "hzString.h" #include "hzTmplArray.h"
class hzEmaddr ; class hzIpaddr ;
/* ** Section 2: The hzChain class */
class hzChain { // Category: Data // // hzChain is an unlimited char buffer, for any purpose but widely used to assemble complex string values such as HTTP server responses. To this end, hzChain has both standard // append functions and Printf, a vararg printf type member function. String assembly must be as a series of one or more append operations as no INSERT method is provided. The // content is held in a double linked list of fixed sized blocks rather than as contiguous memory. This arrangement avoids reallocation and copying during string assembly, but // not if a hzChain of more than one block is cast to a null terminated character string. Such casting however, is not the norm. hzChain instances are expected to be iterated // from begining to end. An iterator is provided as a sub-class for this purpose. // // Although the double linked list allows iterators to decrement, this facility is not used in any current HadronZoo software and should be considered as deprecated. // // In addition to acting as a single string value container, hzChain allows blocks to be deleted from the front, making it suitable for processing data streams. Incomming data // and requests from connected clients and server responses, are both processed as data streams by the hzIpServer class. Once the iterator processing the incomming data passes // onto the next block, the first block is discarded. Likewise once blocks in the outgoing data have been written to the socket, they are discarded. Doing this prevents chains // becoming ever larger in cases where clients remain connected and make a large number of requests. // // Note that while hzChain is good for string assembly, the fixed block size makes it a poor choice for string storage. Once assembled, strings should be stored as hzString.
struct _chain { // hzChain control area
void* m_Test ; // For corruption testing void* m_Begin ; // Address of first block in chain void* m_End ; // Address of last block in chain uint32_t m_nSize ; // Total size in bytes int16_t m_copy ; // Copy count int16_t m_resv ; // Reserved
_chain (void) ; ~_chain (void) ; } ;
_chain* mx ; // Smart pointer to contents
int32_t _compare (const hzChain& op) const ;
public: struct BlkIter { // Block iterator used for writing out whole chains to sockets
void* m_block ; // Current block address
BlkIter (void) { m_block = 0 ; }
// Operators to set iterator position BlkIter& operator= (const hzChain& I) { // Set a block iterator current block pointer to the current block in the chain if (I.mx) m_block = I.mx->m_Begin ; else m_block = 0 ; return *this ; }
BlkIter& operator= (const BlkIter& I) { // Set this block iterator to another m_block = I.m_block ; return *this ; }
// Advance the block BlkIter& Advance (void) ;
// Advance the block and remove previous BlkIter& Roll (void) ;
// Return block internals, data and data size void* Data (void) ; uint32_t Size (void) ; } ;
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 ; }
char current (void) const ; bool eof (void) const ;
// Operators to set iterator position Iter& operator= (const hzChain& 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 chain iterator 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 hzChain, uchar or char 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) ; //uint32_t Write (hzString& str, 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-- (void) ; Iter& operator-- (int) ; Iter& operator+= (uint32_t nInc) ; Iter& operator-= (uint32_t nDec) ;
// Case sensitive compare functions bool Equal (const char c) const ; bool Equal (const char* s) const ; bool Equal (const hzString& S) const { return Equal(*S) ; }
// Case in-sensitive compare functions bool Equiv (const char c) const ; bool Equiv (const char* s) const ; bool Equiv (const hzString& S) const { return Equiv(*S) ; }
// Compare operators bool operator== (const char c) const { return Equal(c) ; } bool operator== (const char* 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 char c) const { return !Equal(c) ; } bool operator!= (const char* 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 ; }
// Get current or offset char char operator[] (uint32_t nOset) const ; char operator* (void) const ; } ;
void Clear (void) ;
// Constructors/Destructors hzChain (void) ; hzChain (const hzChain& op) ; ~hzChain (void) ;
// Internal use only void* _int_addr (void) const { return mx ; } void _int_set (const void* ptr) { mx = (_chain*) ptr ; } void _int_clr (void) { mx = 0 ; }
// Get hzChain attributes uint32_t Size (void) const { return mx ? mx->m_nSize : 0 ; } uint32_t Copies (void) const { return mx ? mx->m_copy : 0 ; } //uint16_t GetID (void) const { return mx ? mx->m_Id : 0xffff ; }
// Set chain contents hzChain& operator= (const hzChain& op) ; hzChain& operator= (const hzString& S) ; hzChain& 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 (hzChain& Z, uint32_t nStart, uint32_t nBytes) ;
// Append single character hzEcode AddByte (const char c) ;
// Append using varargs uint32_t _vainto (const char*, va_list) ; uint32_t Printf (const char* ...) ;
// Append whole entities by operators hzChain& operator+= (const char* s) ; hzChain& operator+= (const hzString& s) ; hzChain& operator+= (const hzChain& op) ; hzChain& operator+= (std::ifstream& ifs) ;
hzChain& operator<< (const char* s) ; hzChain& operator<< (const hzString& s) ;
hzChain& operator<< (const hzEmaddr& e) ; hzChain& operator<< (const hzIpaddr& i) ;
hzChain& operator<< (uint32_t nValue) ; hzChain& operator<< (uint64_t nValue) ; hzChain& operator<< (int32_t nValue) ; hzChain& operator<< (int64_t nValue) ; hzChain& operator<< (double nValue) ; hzChain& operator<< (const hzChain& op) ; hzChain& operator<< (std::ifstream& is) ;
// Compare operators bool operator== (const hzChain& op) const { return _compare(op) == 0 ? true : false ; } bool operator!= (const hzChain& op) const { return _compare(op) != 0 ? true : false ; } bool operator< (const hzChain& op) const { return _compare(op) < 0 ? true : false ; } bool operator<= (const hzChain& op) const { return _compare(op) <= 0 ? true : false ; } bool operator> (const hzChain& op) const { return _compare(op) > 0 ? true : false ; } bool operator>= (const hzChain& op) const { return _compare(op) >= 0 ? true : false ; }
// Stream operators friend std::istream& operator>> (std::istream& is, hzChain& obj) ; friend std::ostream& operator<< (std::ostream& os, const hzChain& obj) ; } ;
#define chIter hzChain::Iter #define chMark hzChain::Mark
// Global null chain extern hzChain _hz_null_hzChain ;
#endif // hzChain_h