//
// arcHelp.h: low-level archiving functions.
//
// Written by John A deLaubenfels, https://www.adaptune.com/steg.htm .
// Permission granted to use freely in any non-fraudulent way.
//
//
//
//
// Ways to pass through a Binary Stream (BS) data set with appending:
//    . Copy the original, cut off the termination, add the new data, and re-terminate.
//    . Some fancy keyword I came up with; what the flock is it??   BS_ARC_KEYWORD .  Two options:
//       . BSarcUcharArry(vB1, BS_ARC_KEYWORD, &vBSin[0], vBSin.size());
//       . BSarcStarSing(vB1,  BS_ARC_KEYWORD, (void *)(&vBSin));
//      Use the first for data that may be archived and called back later; use the second for greater speed
//      when archiving will not take place (so the pointer won't go stale and then be dereferenced).
//
//
// ArcMe/Unarc (AU) vs. Binary Stream (BS):
//    . AU is decoded by functions that know the order and type of data.  BS data is in any order, tagged by keyword(s).
//    . BS data can easily contain sub-BS and/or sub-AU info.  AU probably wouldn't do that.
//    . AU is typically used to store member data; BS is used for arbitrary parameter passing to a function.
//    . AU doesn't do arrays directly; caller must pump individual items.  BS does arrays.  ooo: archiveBytes().
//
//
// Irritating BS contradiction caused by including a sub-BS within the BS: include length?  That's for arrays,
// but also for a single sub-BS.
//
//

#ifndef ARCHELP_H
#define ARCHELP_H

#include <vector>
#include <map>
#include <set>
#include <string>
#include <assert.h>


#define NADA  (-1)
#define BS_ARC_KEYWORD "BSarcStream"

#ifdef IS_ARCHELP_CPP
   #define EXTERN_ARC
   #define GLOB_INIT_ARC(x)      x
#else
   // #define EXTERN_ARC extern
   // #define GLOB_INIT_ARC(x)
   #define EXTERN_ARC
   #define GLOB_INIT_ARC(x)      x
#endif // !IS_ARCHELP_CPP



typedef const std::vector<unsigned char> &BSref;


//
//
//
//
//
//
//
// qxspitObj
//

struct spitObj {
   FILE                       *fp_out;
   std::vector<unsigned char> *pvcOut;
   long long                   nBytesOut;

   spitObj(FILE *fp=NULL, std::vector<unsigned char> *pvc=NULL) : fp_out(fp), pvcOut(pvc), nBytesOut(0) {}
   ~spitObj() {}   // we don't "own" fp_out or pvcOut.
};



//
//
//
//
// qxsucqMark

struct sucqMark {
   const unsigned char *pcHold;
   long                 lTell;

   sucqMark(const unsigned char *pc=NULL, long lT=0) : pcHold(pc), lTell(lT) {}
   sucqMark(const sucqMark &rs) : pcHold(rs.pcHold) , lTell(rs.lTell) {}
   const sucqMark &operator=(const sucqMark &rs) {
      if(&rs != this) {
         pcHold = rs.pcHold;
         lTell  = rs.lTell;
      } // if(&rs != this)
      return *this;
   } // const sucqMark &operator=(const sucqMark &rs)
}; // struct sucqMark




//
//
//
//
//
// qxsucqObj
//

struct sucqObj {
   FILE                *fp_in;
   const unsigned char *pcWalk;
   const unsigned char *pcTooFar;
   long long            nBytesIn;

   sucqObj(FILE *fp=NULL, const unsigned char *pcw=NULL, const unsigned char *pctf=NULL) : fp_in(fp), pcWalk(pcw), pcTooFar(pctf), nBytesIn(0) {}
   ~sucqObj() {}   // we don't "own" our members.

   sucqMark stell() const {
      sucqMark asqm;
      if(fp_in == NULL) {
         asqm.pcHold = pcWalk;
      } else {
         asqm.lTell  = ftell(fp_in);
      } // !if(fp_in == NULL)
      return asqm;
   } // sucqMark stell() const

   int ssett(const sucqMark &asqm) {
      int iRet = 0;
      if(fp_in == NULL) {
         pcWalk = asqm.pcHold;
      } else {
         iRet = fseek(fp_in, asqm.lTell, SEEK_SET);
      } // !if(fp_in == NULL)
      return iRet;
   } // int ssett(const sucqMark &asqm)
};





// the following definitions/declarations are for the BS (Binary Stream) process.

EXTERN_ARC const unsigned char cucNuttin        GLOB_INIT_ARC(= 0xFF);

EXTERN_ARC const unsigned char cucSignedChar    GLOB_INIT_ARC(= 0x00);
EXTERN_ARC const unsigned char cucUnsignedChar  GLOB_INIT_ARC(= 0x01);
EXTERN_ARC const unsigned char cucSignedShort   GLOB_INIT_ARC(= 0x02);
EXTERN_ARC const unsigned char cucUnsignedShort GLOB_INIT_ARC(= 0x03);
EXTERN_ARC const unsigned char cucSignedInt4    GLOB_INIT_ARC(= 0x04);
EXTERN_ARC const unsigned char cucUnsignedInt4  GLOB_INIT_ARC(= 0x05);
EXTERN_ARC const unsigned char cucSignedLL8     GLOB_INIT_ARC(= 0x06);
EXTERN_ARC const unsigned char cucUnsignedLL8   GLOB_INIT_ARC(= 0x07);
EXTERN_ARC const unsigned char cucDouble        GLOB_INIT_ARC(= 0x08);
EXTERN_ARC const unsigned char cucFloat         GLOB_INIT_ARC(= 0x09);
EXTERN_ARC const unsigned char cucVoidStar      GLOB_INIT_ARC(= 0x0A);
EXTERN_ARC const unsigned char cucKeyValData    GLOB_INIT_ARC(= 0x0B);


EXTERN_ARC const unsigned char carSignedChar    GLOB_INIT_ARC(= 0x10);
EXTERN_ARC const unsigned char carUnsignedChar  GLOB_INIT_ARC(= 0x11);
EXTERN_ARC const unsigned char carSignedShort   GLOB_INIT_ARC(= 0x12);
EXTERN_ARC const unsigned char carUnsignedShort GLOB_INIT_ARC(= 0x13);
EXTERN_ARC const unsigned char carSignedInt4    GLOB_INIT_ARC(= 0x14);
EXTERN_ARC const unsigned char carUnsignedInt4  GLOB_INIT_ARC(= 0x15);
EXTERN_ARC const unsigned char carSignedLL8     GLOB_INIT_ARC(= 0x16);
EXTERN_ARC const unsigned char carUnsignedLL8   GLOB_INIT_ARC(= 0x17);
EXTERN_ARC const unsigned char carDouble        GLOB_INIT_ARC(= 0x18);
EXTERN_ARC const unsigned char carFloat         GLOB_INIT_ARC(= 0x19);
EXTERN_ARC const unsigned char carVoidStar      GLOB_INIT_ARC(= 0x1A);
EXTERN_ARC const unsigned char carKeyValData    GLOB_INIT_ARC(= 0x1B);    // not used at present.


//
// This class interprets a Binary Stream, keywords and values, pulling into different maps for different data types.
//
// Duplicate keywords and values are preserved by using multimaps, not maps.  ooo: we change to a vector
// of values, thus definitely preserving input order.
//
// Order of items in the stream is not preserved (except within a given keyword).  Nor is there nesting of data.  
// However, anything may be contained, including archives of classes, etc.  As long as the sender and the receiver 
// understand each other, all is well.  Also: there really IS nesting, as Binary Streams may be stuffed into inner 
// containers.
//
//
// Note: construction of this class is a work in progress; I add as I have need.
//
//
//
// 11-15-16: makeBS().
//
// qxKeyValData
//

class KeyValData {
private:
   // single values (vector in case keyword passed multiple times):
   std::map<std::string, std::vector<unsigned char>>                   m_uchSing;
   std::map<std::string, std::vector<int>>                             m_intSing;
   std::map<std::string, std::vector<signed long long>>                m_sllSing;
   std::map<std::string, std::vector<double>>                          m_doubSing;
   std::map<std::string, std::vector<void *>>                          m_starSing;
   std::map<std::string, std::vector<KeyValData>>                      m_kvdSing;

   // arrays (vector in case keyword passed multiple times):
   std::map<std::string, std::vector<std::vector<unsigned char>>>      m_uchArry;
   std::map<std::string, std::vector<std::vector<signed char>>>        m_schArry;
   std::map<std::string, std::vector<std::vector<int>>>                m_intArry;
   std::map<std::string, std::vector<std::vector<signed long long>>>   m_sllArry;
   std::map<std::string, std::vector<std::vector<unsigned long long>>> m_ullArry;
   std::map<std::string, std::vector<std::vector<double>>>             m_doubArry;

public:
   KeyValData();
   KeyValData(const KeyValData &rs);
   KeyValData(const std::vector<unsigned char> &vcValData);
   KeyValData(const unsigned char *pcStart, int nChar);
   ~KeyValData();

   const KeyValData &operator=(const KeyValData &rs);
   bool operator==(const KeyValData &rs) const;

   int clearMe();
   int fleshMe(const unsigned char *&pcWalk, const unsigned char *pcTooFar, bool bAppend=false, bool bNoPtrFollow=false);
   int fleshMe(const std::vector<unsigned char> &params, bool bAppend=false, bool bNoPtrFollow=false);
   int dumpKvd(FILE *fp_out) const;




   // accessor functions for single values:
   int nUchKeys() const {return (int)m_uchSing.size();}
   int getUchKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nUchSing(const char *pcKey) const;
   int getUchSing(const char *pcKey, std::vector<unsigned char> &vUchsOut) const;
   const std::vector<unsigned char> &getUchSing(const char *pcKey) const;
   unsigned char getLastUchSing(const char *pcKey, unsigned char ucDefault=0) const;
   unsigned char getIthUchSing(int ith, const char *pcKey, unsigned char ucDefault=0) const;
   int setLastUchSing(const char *pcKey, unsigned char ucNew);          // replaces the last entry.  adds if none.
   int setIthUchSing(int ith, const char *pcKey, unsigned char ucNew);  // replaces the ith entry
   int addUchSing(const char *pcKey, unsigned char ucNew);        // appends new one to whoever's there.
   int clrUchSing(const char *pcKey);                             // clears entry
   int replaceUchSing(const char *pcKey, unsigned char ucNew);    // clears entry, then adds ucNew back


   int nIntKeys() const {return (int)m_intSing.size();}
   int getIntKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nIntSing(const char *pcKey) const;
   int getIntSing(const char *pcKey, std::vector<int> &vIntsOut) const;
   const std::vector<int> &getIntSing(const char *pcKey) const;
   int getLastIntSing(const char *pcKey, int iDefault=0) const;
   int getIthIntSing(int ith, const char *pcKey, int iDefault=0) const;
   int setLastIntSing(const char *pcKey, int iNew);          // replaces the last entry.  adds if none.
   int setIthIntSing(int ith, const char *pcKey, int iNew);  // replaces the ith entry
   int addIntSing(const char *pcKey, int iNew);        // appends new one to whoever's there.
   int clrIntSing(const char *pcKey);                             // clears entry
   int replaceIntSing(const char *pcKey, int iNew);    // clears entry, then adds iNew back


   int nSllKeys() const {return (int)m_sllSing.size();}
   int getSllKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nSllSing(const char *pcKey) const;
   int getSllSing(const char *pcKey, std::vector<signed long long> &vIntsOut) const;
   const std::vector<signed long long> &getSllSing(const char *pcKey) const;
   signed long long getLastSllSing(const char *pcKey, signed long long sllDefault=0) const;
   signed long long getIthSllSing(int ith, const char *pcKey, signed long long sllDefault=0) const;
   int setLastSllSing(const char *pcKey, signed long long sllNew);          // replaces the last entry.  adds if none.
   int setIthSllSing(int ith, const char *pcKey, signed long long sllNew);  // replaces the ith entry
   int addSllSing(const char *pcKey, signed long long sllNew);        // appends new one to whoever's there.
   int clrSllSing(const char *pcKey);                             // clears entry
   int replaceSllSing(const char *pcKey, signed long long sllNew);    // clears entry, then adds sllNew back


   int nDoubKeys() const {return (int)m_doubSing.size();}
   int getDoubKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nDoubSing(const char *pcKey) const;
   int getDoubSing(const char *pcKey, std::vector<double> &vDoubsOut) const;
   const std::vector<double> &getDoubSing(const char *pcKey) const;
   double getLastDoubSing(const char *pcKey, double dDefault=0.0) const;
   double getIthDoubSing(int ith, const char *pcKey, double dDefault=0.0) const;
   int setLastDoubSing(const char *pcKey, double dNew);          // replaces the last entry.  adds if none.
   int setIthDoubSing(int ith, const char *pcKey, double dNew);  // replaces the ith entry
   int addDoubSing(const char *pcKey, double dNew);        // appends new one to whoever's there.
   int clrDoubSing(const char *pcKey);                             // clears entry
   int replaceDoubSing(const char *pcKey, double dNew);    // clears entry, then adds dNew back


   int nPtrKeys() const {return (int)m_starSing.size();}
   int getPtrKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nPtrSing(const char *pcKey) const;
   int getPtrSing(const char *pcKey, std::vector<void *> &vPtrsOut) const;  // we need vector out in case keyword repeated.
   const std::vector<void *> &getPtrSing(const char *pcKey) const;
   void *getLastPtrSing(const char *pcKey, void *pvDefault=NULL) const;
   void *getIthPtrSing(int ith, const char *pcKey, void *pvDefault=NULL) const;
   int whichIthPtrSing(const char *pcKey, void *pvFind) const;
   int setLastPtrSing(const char *pcKey, void *pvNew);          // replaces the last entry.  adds if none.
   int setIthPtrSing(int ith, const char *pcKey, void *pvNew);  // replaces the ith entry
   int addPtrSing(const char *pcKey, void *pvNew);        // appends new one to whoever's there.
   int clrPtrSing(const char *pcKey);                             // clears entry
   int delIthPtrSing(const char *pcKey, int ith);
   int delValPtrSing(const char *pcKey, void *pvDelMe);
   int replacePtrSing(const char *pcKey, void *pvNew);    // clears entry, then adds pvNew back


   int nKvdKeys() const {return (int)m_kvdSing.size();}
   int getKvdKeys(std::vector<std::string> &vcSsKeysOut) const;
   int nKvdSing(const char *pcKey) const;
   int getKvdSing(const char *pcKey, std::vector<KeyValData> &vKvdsOut) const;   // huge copy possible; try to avoid.
   const std::vector<KeyValData> &getKvdSing(const char *pcKey) const;
   //
   const KeyValData &getLastKvdSing(const char *pcKey, const KeyValData &kvdDefault) const;
   KeyValData &getLastKvdSing(const char *pcKey, KeyValData &kvdDefault) {return ((KeyValData &)(((const KeyValData *)this)->getLastKvdSing(pcKey, (const KeyValData &)kvdDefault)));}
   //
   const KeyValData &getIthKvdSing(int ith, const char *pcKey, const KeyValData &kvdDefault) const;
   KeyValData &getIthKvdSing(int ith, const char *pcKey, KeyValData &kvdDefault) {return ((KeyValData &)(((const KeyValData *)this)->getIthKvdSing(ith, pcKey, (const KeyValData &)kvdDefault)));}
   //
   int setLastKvdSing(const char *pcKey, const KeyValData &kvdNew);       // replaces the last entry.  adds if none.
   int setIthKvdSing(int ith, const char *pcKey, const KeyValData &kvdNew);  // replaces the ith entry
   int addKvdSing(const char *pcKey, const KeyValData &kvdNew);        // appends new one to whoever's there.
   int clrKvdSing(const char *pcKey);                             // clears entry
   int replaceKvdSing(const char *pcKey, const KeyValData &kvdNew);    // clears entry, then adds iNew back







   // accessor functions for arrays:
   int nSchKeya() const {return (int)m_schArry.size();}
   int getSchKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nSchArry(const char *pcKey) const;
   int getSchArry(const char *pcKey, std::vector<std::vector<signed char>> &vvSchsOut) const;
   const std::vector<std::vector<signed char>> &getSchArry(const char *pcKey) const;
   int getSchArr2(const char *pcKey, std::vector<std::string> &vssOut) const;
   // 
   const std::vector<signed char> &getLastSchArry(const char *pcKey, const std::vector<signed char> &vSchDefault) const;
   const std::vector<signed char> &getIthSchArry(int ith, const char *pcKey, const std::vector<signed char> &vSchDefault) const;
   //
   std::string getLastSchArr2(const char *pcKey, const std::string &ssDefault) const;
   std::string getIthSchArr2(int ith, const char *pcKey, const std::string &ssDefault) const;
   //
   int setLastSchArry(const char *pcKey, const std::vector<signed char> &vvSchNew);       // replaces the last entry.  adds if none.
   int setIthSchArry(int ith, const char *pcKey, const std::vector<signed char> &vvSchNew);  // replaces the ith entry
   int addSchArry(const char *pcKey, const std::vector<signed char> &vvSchNew);        // appends new one to whoever's there.
   int addSchArAr(const char *pcKey, const std::vector<std::string> &vcSs);            // 02-28-23
   int clrSchArry(const char *pcKey);                             // clears entry
   int replaceSchArry(const char *pcKey, const std::vector<signed char> &vvSchNew);    // clears entry, then adds vvSchNewNew back



   int nUchKeya() const {return (int)m_uchArry.size();}
   int getUchKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nUchArry(const char *pcKey) const;
   int getUchArry(const char *pcKey, std::vector<std::vector<unsigned char>> &vvUchsOut) const;
   const std::vector<std::vector<unsigned char>> &getUchArry(const char *pcKey) const;
   const std::vector<unsigned char> &getLastUchArry(const char *pcKey, const std::vector<unsigned char> &vUchDefault) const;
   const std::vector<unsigned char> &getIthUchArry(int ith, const char *pcKey, const std::vector<unsigned char> &vUchDefault) const;
   int setLastUchArry(const char *pcKey, const std::vector<unsigned char> &vvUchNew);       // replaces the last entry.  adds if none.
   int setIthUchArry(int ith, const char *pcKey, const std::vector<unsigned char> &vvUchNew);  // replaces the ith entry
   int addUchArry(const char *pcKey, const std::vector<unsigned char> &vvUchNew);        // appends new one to whoever's there.
   int clrUchArry(const char *pcKey);                             // clears entry
   int replaceUchArry(const char *pcKey, const std::vector<unsigned char> &vvUchNew);    // clears entry, then adds vvUchNew back



   int nIntKeya() const {return (int)m_intArry.size();}
   int getIntKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nIntArry(const char *pcKey) const;
   int getIntArry(const char *pcKey, std::vector<std::vector<int>> &vvIntsOut) const;
   const std::vector<std::vector<int>> &getIntArry(const char *pcKey) const;
   const std::vector<int> &getLastIntArry(const char *pcKey, const std::vector<int> &vIntDefault) const;
   const std::vector<int> &getIthIntArry(int ith, const char *pcKey, const std::vector<int> &vIntDefault) const;
   int setLastIntArry(const char *pcKey, const std::vector<int> &vvINew);       // replaces the last entry.  adds if none.
   int setIthIntArry(int ith, const char *pcKey, const std::vector<int> &vvINew);  // replaces the ith entry
   int addIntArry(const char *pcKey, const std::vector<int> &vvINew);        // appends new one to whoever's there.
   int clrIntArry(const char *pcKey);                             // clears entry
   int replaceIntArry(const char *pcKey, const std::vector<int> &vvINew);    // clears entry, then adds vvINew back



   int nSllKeya() const {return (int)m_sllArry.size();}
   int getSllKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nSllArry(const char *pcKey) const;
   int getSllArry(const char *pcKey, std::vector<std::vector<signed long long>> &vvUllsOut) const;
   const std::vector<std::vector<signed long long>> &getSllArry(const char *pcKey) const;
   const std::vector<signed long long> &getLastSllArry(const char *pcKey, const std::vector<signed long long> &vUllDefault) const;
   const std::vector<signed long long> &getIthSllArry(int ith, const char *pcKey, const std::vector<signed long long> &vUllDefault) const;
   int setLastSllArry(const char *pcKey, const std::vector<signed long long> &vvSllNew);       // replaces the last entry.  adds if none.
   int setIthSllArry(int ith, const char *pcKey, const std::vector<signed long long> &vvSllNew);  // replaces the ith entry
   int addSllArry(const char *pcKey, const std::vector<signed long long> &vvSllNew);        // appends new one to whoever's there.
   int clrSllArry(const char *pcKey);                             // clears entry
   int replaceSllArry(const char *pcKey, const std::vector<signed long long> &vvSllNew);    // clears entry, then adds vvSllNew back



   int nUllKeya() const {return (int)m_ullArry.size();}
   int getUllKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nUllArry(const char *pcKey) const;
   int getUllArry(const char *pcKey, std::vector<std::vector<unsigned long long>> &vvUllsOut) const;
   const std::vector<std::vector<unsigned long long>> &getUllArry(const char *pcKey) const;
   const std::vector<unsigned long long> &getLastUllArry(const char *pcKey, const std::vector<unsigned long long> &vUllDefault) const;
   const std::vector<unsigned long long> &getIthUllArry(int ith, const char *pcKey, const std::vector<unsigned long long> &vUllDefault) const;
   int setLastUllArry(const char *pcKey, const std::vector<unsigned long long> &vvUllNew);       // replaces the last entry.  adds if none.
   int setIthUllArry(int ith, const char *pcKey, const std::vector<unsigned long long> &vvUllNew);  // replaces the ith entry
   int addUllArry(const char *pcKey, const std::vector<unsigned long long> &vvUllNew);        // appends new one to whoever's there.
   int clrUllArry(const char *pcKey);                             // clears entry
   int replaceUllArry(const char *pcKey, const std::vector<unsigned long long> &vvUllNew);    // clears entry, then adds vvUllNew back



   int nDoubKeya() const {return (int)m_doubArry.size();}
   int getDoubKeya(std::vector<std::string> &vcSsKeysOut) const;
   int nDoubArry(const char *pcKey) const;
   int getDoubArry(const char *pcKey, std::vector<std::vector<double>> &vvDoubsOut) const;
   const std::vector<std::vector<double>> &getDoubArry(const char *pcKey) const;
   const std::vector<double> &getLastDoubArry(const char *pcKey, const std::vector<double> &vDoubDefault) const;
   const std::vector<double> &getIthDoubArry(int ith, const char *pcKey, const std::vector<double> &vDoubDefault) const;
   int setLastDoubArry(const char *pcKey, const std::vector<double> &vvDoubNew);       // replaces the last entry.  adds if none.
   int setIthDoubArry(int ith, const char *pcKey, const std::vector<double> &vvDoubNew);  // replaces the ith entry
   int addDoubArry(const char *pcKey, const std::vector<double> &vvDoubNew);        // appends new one to whoever's there.
   int clrDoubArry(const char *pcKey);                             // clears entry
   int replaceDoubArry(const char *pcKey, const std::vector<double> &vvDoubNew);    // clears entry, then adds vvDoubNew back




   // misc functions:
   int makeBS(std::vector<unsigned char> &vcBSout) const;      // make a new BS that could be fleshed out to us again.
   int condenseEveryone();
   int replacePointers(const std::map<const void *, void *> &mpOldNew, const std::map<std::string, void *> &mpKeyToAddr, int &nNulledOut, bool bStaleOk=false, const std::set<std::string> *pStLeaveAlone=NULL);
}; // class KeyValData 



int archiveBytes(std::vector<unsigned char> &vecGrowing, const unsigned char *pBytes, long long nBytes);

inline int archiveDoub(std::vector<unsigned char> &vecGrowing, double d) {return archiveBytes(vecGrowing, (const unsigned char *)(&d), sizeof(double));}

inline int archiveChar(std::vector<unsigned char> &vecGrowing, char c) {return archiveBytes(vecGrowing, (const unsigned char *)(&c), sizeof(char));}

inline int archiveUchar(std::vector<unsigned char> &vecGrowing, unsigned char c) {return archiveBytes(vecGrowing, (const unsigned char *)(&c), sizeof(unsigned char));}

inline int archiveShort(std::vector<unsigned char> &vecGrowing, short i) {return archiveBytes(vecGrowing, (const unsigned char *)(&i), sizeof(short));}

inline int archiveUshort(std::vector<unsigned char> &vecGrowing, unsigned short i) {return archiveBytes(vecGrowing, (const unsigned char *)(&i), sizeof(unsigned short));}

inline int archiveInt(std::vector<unsigned char> &vecGrowing, int i) {return archiveBytes(vecGrowing, (const unsigned char *)(&i), sizeof(int));}

inline int archiveUint(std::vector<unsigned char> &vecGrowing, unsigned int i) {return archiveBytes(vecGrowing, (const unsigned char *)(&i), sizeof(unsigned int));}

inline int archiveLong(std::vector<unsigned char> &vecGrowing, long l) {return archiveBytes(vecGrowing, (const unsigned char *)(&l), sizeof(long));}

inline int archiveUlong(std::vector<unsigned char> &vecGrowing, unsigned long ul) {return archiveBytes(vecGrowing, (const unsigned char *)(&ul), sizeof(unsigned long));}

inline int archiveLlong(std::vector<unsigned char> &vecGrowing, long long ll) {return archiveBytes(vecGrowing, (const unsigned char *)(&ll), sizeof(long long));}

inline int archiveUllong(std::vector<unsigned char> &vecGrowing, unsigned long long ull) {return archiveBytes(vecGrowing, (const unsigned char *)(&ull), sizeof(unsigned long long));}

int archivePtr(std::vector<unsigned char> &vecGrowing, const void *p);    // not inline

int archiveVarQty(std::vector<unsigned char> &vecGrowing, unsigned long long ull);



// 01-06-18: new versions:

int archiveBytes(spitObj &mySpit, const unsigned char *pBytes, long long nBytes);

inline int archiveDoub(spitObj &mySpit, double d) {return archiveBytes(mySpit, (const unsigned char *)(&d), sizeof(double));}

inline int archiveChar(spitObj &mySpit, char c) {return archiveBytes(mySpit, (const unsigned char *)(&c), sizeof(char));}

inline int archiveUchar(spitObj &mySpit, unsigned char c) {return archiveBytes(mySpit, (const unsigned char *)(&c), sizeof(unsigned char));}

inline int archiveShort(spitObj &mySpit, short i) {return archiveBytes(mySpit, (const unsigned char *)(&i), sizeof(short));}

inline int archiveUshort(spitObj &mySpit, unsigned short i) {return archiveBytes(mySpit, (const unsigned char *)(&i), sizeof(unsigned short));}

inline int archiveInt(spitObj &mySpit, int i) {return archiveBytes(mySpit, (const unsigned char *)(&i), sizeof(int));}

inline int archiveUint(spitObj &mySpit, unsigned int i) {return archiveBytes(mySpit, (const unsigned char *)(&i), sizeof(unsigned int));}

inline int archiveLong(spitObj &mySpit, long l) {return archiveBytes(mySpit, (const unsigned char *)(&l), sizeof(long));}

inline int archiveUlong(spitObj &mySpit, unsigned long ul) {return archiveBytes(mySpit, (const unsigned char *)(&ul), sizeof(unsigned long));}

inline int archiveLlong(spitObj &mySpit, long long ll) {return archiveBytes(mySpit, (const unsigned char *)(&ll), sizeof(long long));}

inline int archiveUllong(spitObj &mySpit, unsigned long long ull) {return archiveBytes(mySpit, (const unsigned char *)(&ull), sizeof(unsigned long long));}

int archivePtr(spitObj &mySpit, const void *p);    // not inline

int archiveVarQty(spitObj &mySpit, unsigned long long ull);





// qxl: flesh out functions, even the ones I haven't needed yet:

int BSarcUcharSing(std::vector<unsigned char> &vecGrowing, const char *pcKey, unsigned char     uc);
int BSarcIntSing(std::vector<unsigned char>   &vecGrowing, const char *pcKey, int               i);
int BSarcSllSing(std::vector<unsigned char>   &vecGrowing, const char *pcKey, signed long long  sll);
int BSarcDoubSing(std::vector<unsigned char>  &vecGrowing, const char *pcKey, double            d);
int BSarcStarSing(std::vector<unsigned char>  &vecGrowing, const char *pcKey, void             *pv);
int BSarcKvdSing(std::vector<unsigned char>   &vecGrowing, const char *pcKey, const KeyValData &kvd);


int BSarcScharArry(std::vector<unsigned char> &vecGrowing, const char *pcKey, const signed char        *pSch,  int nElem);
int BSarcUcharArry(std::vector<unsigned char> &vecGrowing, const char *pcKey, const unsigned char      *pUch,  int nElem);
int BSarcIntArry(std::vector<unsigned char>   &vecGrowing, const char *pcKey, const int                *pInt,  int nElem);
int BSarcSllArry(std::vector<unsigned char>   &vecGrowing, const char *pcKey, const signed long long   *pSll,  int nElem);
int BSarcUllArry(std::vector<unsigned char>   &vecGrowing, const char *pcKey, const unsigned long long *pUll,  int nElem);
int BSarcDoubArry(std::vector<unsigned char>  &vecGrowing, const char *pcKey, const double             *pDoub, int nElem);

int BSarcTerminate(std::vector<unsigned char> &vecGrowing);


// added 02-27-23:
int BSarcScharArAr(std::vector<unsigned char> &vecGrowing, const char *pcKey, const std::vector<std::string> &vcSs);




int unArcBytes(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned char *pBytes, long long nBytes);

int unArcChar(const unsigned char *&pcWalk, const unsigned char *pcTooFar, char &cOut);
int unArcUchar(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned char &ucOut);
int unArcShort(const unsigned char *&pcWalk, const unsigned char *pcTooFar, short &iOut);
int unArcUshort(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned short &uiOut);
int unArcInt(const unsigned char *&pcWalk, const unsigned char *pcTooFar, int &iOut);
int unArcUint(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned int &uiOut);
int unArcLong(const unsigned char *&pcWalk, const unsigned char *pcTooFar, long &lOut);
int unArcUlong(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned long &ulOut);
int unArcLlong(const unsigned char *&pcWalk, const unsigned char *pcTooFar, long long &llOut);
int unArcUllong(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned long long &ullOut);

int unArcDoub(const unsigned char *&pcWalk, const unsigned char *pcTooFar, double &dOut);
int unArcPtr(const unsigned char *&pcWalk, const unsigned char *pcTooFar, void *&pOut);

int unArcVarUll(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned long long &ullOut);
int unArcVarUin(const unsigned char *&pcWalk, const unsigned char *pcTooFar, unsigned int &uiOut);



// 01-06-18: new versions with sucqObj for either memory or file source:

int unArcBytes(sucqObj &suq,  unsigned char *pBytes, long long nBytes);
const unsigned char *unArcBytes(sucqObj &suq, std::vector<unsigned char> &vcBuffer, long long nBytes);

int unArcChar(sucqObj &suq,   char               &cOut);
int unArcUchar(sucqObj &suq,  unsigned char      &ucOut);
int unArcShort(sucqObj &suq,  short              &iOut);
int unArcUshort(sucqObj &suq, unsigned short     &uiOut);
int unArcInt(sucqObj &suq,    int                &iOut);
int unArcUint(sucqObj &suq,   unsigned int       &uiOut);
int unArcLong(sucqObj &suq,   long               &lOut);
int unArcUlong(sucqObj &suq,  unsigned long      &ulOut);
int unArcLlong(sucqObj &suq,  long long          &llOut);
int unArcUllong(sucqObj &suq, unsigned long long &ullOut);

int unArcDoub(sucqObj &suq,   double             &dOut);
int unArcPtr(sucqObj &suq,    void              *&pOut);

int unArcVarUll(sucqObj &suq, unsigned long long &ullOut);
int unArcVarUin(sucqObj &suq, unsigned int       &uiOut);






// special function: leave pcWalk unadvanced:
int peekInt(const unsigned char *&pcWalk, const unsigned char *pcTooFar, int &iOut);


int replaceBSpointers(std::vector<unsigned char> &vcBSData, const std::map<const void *, void *> &mpOldNew, const std::map<std::string, void *> &mpKeyToAddr);

int elementSize(const unsigned char ucDataType);


int suckUchFile(const char *pFileName, std::vector<unsigned char> &vcFillMe);
int spitUchFile(const char *pFileName, const std::vector<unsigned char> &vcSpitMe, bool bArchiveExisting=true);





#endif // ARCHELP_H


