/**************************************************************************
   zfuncs.h      include file for zfuncs functions        v.2.18

   Free software licensed under GNU General Public License v.2
   source URL:  kornelix.squarespace.com
***************************************************************************/

#include <sys/time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <setjmp.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <execinfo.h>
#include <locale.h>
#include <sys/inotify.h>

#define  int8   char                                                       //  number types
#define  int16  short
#define  int32  long
#define  int64  long long
#define  uint8   unsigned char
#define  uint16  unsigned short
#define  uint32  unsigned long
#define  uint64  unsigned long long
#define  uchar  unsigned char
#define  cchar  const char
#define  dub  double

#define  wstrerror(err) strerror(WEXITSTATUS(err))                         //  get text status for child process

#define  mutex          pthread_mutex_t                                    //  abbreviations
#define  mutex_init     pthread_mutex_init
#define  mutex_lock     pthread_mutex_lock
#define  mutex_trylock  pthread_mutex_trylock
#define  mutex_unlock   pthread_mutex_unlock
#define  mutex_destroy  pthread_mutex_destroy

#define  maxfcc 1000                                                       //  max. file pathname cc tolerated
#define  null   NULL
#define  true   1
#define  false  0

//  system functions ======================================================

void appcrash(cchar * pMess, ... );                                        //  fatal exit - works like printf
void apppause();                                                           //  output message and wait for user
void apppause(cchar * pMess, ... );                                        //  same, works like printf
double get_seconds();                                                      //  seconds since 2000.01.01
void start_timer(timeval *time0);                                          //  start a timer
double get_timer(timeval *time0);                                          //  get elapsed time in seconds
double CPUtime();                                                          //  get process CPU time used
void start_CPUtimer(double *time0);                                        //  start a process CPU timer
double get_CPUtimer(double *time0);                                        //  get elapsed CPU time, seconds
void start_detached_thread(void * tfunc(void *), void * arg);              //  start detached thread function
void synch_threads(int NT = 0);                                            //  synchronize NT threads
void zsleep(double dsecs);                                                 //  sleep specified seconds
char * zmalloc(size_t bytes, int log = 0);                                 //  malloc() with auto crash and log option
void zfree(void *buff, int log = 0);                                       //  free() with log option
char * command_output(int &contx, const char *command, ...);               //  get shell command output     v.2.3
int command_status(int contx);                                             //  get exit status of command
int signalProc(cchar * pname, cchar * signal);                             //  pause/resume/kill subprocess
int runroot(const char *sucomm, const char *command);                      //  run command as root via su or sudo
int checkinstall(const char *prog, ...);                                   //  check if programs are installed
char * fgets_trim(char * buff, int maxcc, FILE *, int bf = 0);             //  fgets + trim trailing \n \r (blanks)
int samedirk(cchar *file1, cchar *file2);                                  //  returns 1 if files in same directory
int parsefile(cchar *path, char **dir, char **file, char **ext);           //  parse a filespec
int zmondirk(const char *action, const char *dirk, char **file);           //  monitor a directory for changes   v.2.16

//  measure CPU time spent in a function or code block within a function
extern volatile double   cpu_profile_timer;                                //  internal data tables
extern volatile double   cpu_profile_table[100];
extern volatile double   cpu_profile_elapsed;
void cpu_profile_init();                                                   //  initialize at start of test
void cpu_profile_report();                                                 //  report CPU time per function
inline void cpu_profile_enter(int fnum)                                    //  at entry to measured code block
{  cpu_profile_timer = cpu_profile_elapsed;  }
inline void cpu_profile_exit(int fnum)                                     //  at exit from measured code block
{  cpu_profile_table[fnum] += cpu_profile_elapsed - cpu_profile_timer; }

//  string macros and functions ===========================================

#define strEqu(str1,str2) (! strcmp((str1),(str2)))                        //  TRUE if strings compare equal
#define strcaseEqu(str1,str2) (! strcasecmp((str1),(str2)))                //  TRUE if strings equal, ignoring case
#define strNeq(str1,str2) (strcmp((str1),(str2)))                          //  TRUE if strings compare not-equal
#define strnEqu(str1,str2,cc) (! strncmp((str1),(str2),(cc)))              //  TRUE if strings[cc] compare equal
#define strncaseEqu(str1,str2,cc) (! strncasecmp((str1),(str2),(cc)))      //  TRUE if strings[cc] equal, ignoring case
#define strnNeq(str1,str2,cc) (strncmp((str1),(str2),(cc)))                //  TRUE if strings[cc] compare not-equal

cchar * strField(cchar *string, cchar *delims, int Nth);                   //  get Nth delimited field in string
cchar * strField(cchar *string, cchar delim, int Nth);                     //  get Nth delimited field in string
int  strParms(int &bf, cchar *inp, char *pname, int maxcc, double &pval);  //  parse string: name1=val1 | name2 ...
int  strHash(cchar *string, int max);                                      //  string --> random int 0 to max-1
cchar * strHash2(cchar *string, int outcc);                                //  string --> random printable string
int  strncpy0(char *dest, cchar *source, uint cc);                         //  strncpy, insure null, return 0 if fit
void strnPad(char *dest, cchar *source, int cc);                           //  strncpy with blank padding to cc
int  strTrim(char *dest, cchar *source);                                   //  remove trailing blanks
int  strTrim(char *string);                                                //  remove trailing blanks
int  strTrim2(char *dest, cchar *source);                                  //  remove leading and trailing blanks
int  strCompress(char *dest, cchar *source);                               //  remove all blanks incl. imbedded
int  strCompress(char *string);                                            //  remove all blanks
int  strncatv(char *dest, int maxcc, cchar *source, ...);                  //  catenate strings (last = 0L) 
int  strcmpv(cchar *string, ...);                                          //  compare to N strings, return 1-N or 0
void strToUpper(char *dest, cchar *source);                                //  move and conv. string to upper case
void strToUpper(char *string);                                             //  conv. string to upper case
void strToLower(char *dest, cchar *source);                                //  move and conv. string to lower case
void strToLower(char *string);                                             //  conv. string to lower case
int  repl_1str(cchar *strin, char *strout, cchar *ssin, cchar *ssout);     //  copy string and replace 1 substring
int  repl_Nstrs(cchar *strin, char *strout, ...);                          //  copy string and replace N substrings
void strncpyx(char *out, const char *in, int ccin);                        //  conv. string to hex format
void StripZeros(char *pNum);                                               //  1.230000E+12 --> 1.23E+12
int  blank_null(cchar *string);                                            //  test for blank/null string
char * strdupz(const char *string, int more = 0);                          //  duplicate string in nonvolatile memory
int  strdupz(cchar *source, char *&dest, int more = 0);                    //  same + dest zmalloc if null or too short
int  clean_escapes(char *string);                                          //  replace \x escapes with real characters
int  utf8len(const char *utf8string);                                      //  get graphic cc for UTF8 string   v.2.3
int  utf8substring(char *utf8out, const char *utf8in, int pos, int cc);    //  get graphic substring from UTF8 string
int  utf8_check(const char *string);                                       //  check utf8 string for encoding errors
int  utf8_position(const char *utf8in, int Nth);                           //  get byte position of Nth graphic char.

//  bitmap functions ======================================================

struct bitmap {
   int      nbits;                                                         //  declare bitmap: bitmap  *bmap
   uchar    *bits;
};

bitmap * bitmap_new(int nbits);                                            //  create and initialize all bits to zero
void bitmap_set(bitmap *bm, int bit, bool value);                          //  set a bit true or false
bool bitmap_get(bitmap *bm, int bit);                                      //  get a bit value, true or false
void bitmap_delete(bitmap *bm);                                            //  delete bitmap, release memory

//  variable string list functions ========================================

struct  pvlist {
   int      max;                          //  max. entries
   int      act;                          //  actual entries
   char   **list;                         //  entries
};

pvlist * pvlist_create(int max);                                           //  create pvlist
void pvlist_free(pvlist *pv);                                              //  free pvlist
int pvlist_append(pvlist *pv, cchar *entry, int unique = 0);               //  append new entry (opt. if unique)
int pvlist_prepend(pvlist *pv, cchar *entry, int unique = 0);              //  prepend new entry (opt. if unique)
int pvlist_find(pvlist *pv, cchar *entry);                                 //  find entry by name
int pvlist_remove(pvlist *pv, cchar *entry);                               //  remove entry by name
int pvlist_remove(pvlist *pv, int Nth);                                    //  remove entry by number (0...)
int pvlist_count(pvlist *pv);                                              //  return entry count
int pvlist_replace(pvlist *pv, int Nth, char *entry);                      //  replace Nth entry (0...)
char * pvlist_get(pvlist *pv, int Nth);                                    //  return Nth entry (0...)
int pvlist_sort(pvlist *pv);                                               //  sort list, ascending

//  number conversion =====================================================

int convSI (cchar *inp, int &inum, cchar **delm = 0);                      //  string to int
int convSI (cchar *inp, int &inum, int low, int hi, cchar **delm = 0);     //  (with low/high limit checking)
int convSD (cchar *inp, dub &dnum, cchar **delm = 0);                      //  string to double
int convSD (cchar *inp, dub &dnum, dub low, dub hi, cchar **delm = 0);     //  (with low/high limit checking)
int convIS (int iin, char *outp, int *cc = 0);                             //  int to string, returned cc
int convDS (dub din, int prec, char *outp, int *cc = 0);                   //  double to string, precision, ret. cc

//  wildcard functions ====================================================

int MatchWild(cchar * wildstr, cchar * str);                               //  wildcard string match (0)
cchar * SearchWild(cchar *wpath, int &flag);                               //  wildcard file search

//  search and sort functions =============================================

int bsearch(int element, int nn, int list[]);                              //  binary search sorted list[nn]

typedef int HeapSortUcomp(cchar * rec1, cchar * rec2);                     //  return -1/0/+1 if rec1 </=/> rec2
void HeapSort(int vv[], int nn);                                           //  Heap Sort - integer
void HeapSort(float vv[], int nn);                                         //  Heap Sort - float
void HeapSort(double vv[], int nn);                                        //  Heap Sort - double
void HeapSort(char * vv[], int nn);                                        //  Heap Sort - char *, ascending order
void HeapSort(char * vv[], int nn, HeapSortUcomp);                         //  Heap Sort - char *, user-defined order 
void HeapSort(char * recs, int RL, int NR, HeapSortUcomp);                 //  Heap Sort - records, user-defined order

int MemSort(char * RECS, int RL, int NR, int KEYS[][3], int NK);           //  memory sort, records with multiple keys

//  random number functions ===============================================

int lrandz(int64 * seed);                                                  //  returns 0 to 0x7fffffff
double drandz(int64 * seed);                                               //  returns 0.0 to 0.99999...

//  quick math functions ==================================================
//  (2x-3x faster than C-lib, reduced accuracy, limited argument range)

double qsine(double);                                                      //  quick sine
double qcosine(double);                                                    //  quick cosine
double qarcsine(double);                                                   //  quick arc sine
double qsqrt(double);                                                      //  quick square root

//  spline curve-fitting functions ========================================  v.2.11

void spline1(int nn, double *dx, double *dy);                              //  define a curve using nn data points
double spline2(double x);                                                  //  return y-value for given x-value

/**************************************************************************/

//  application initialization and administration

#define ZTXmaxent 1000                                                     //  max. translation strings
#define ZTXmaxcc 2000                                                      //  max. cc per string

int initz_appfiles(const char *appname, ...);                              //  find app dirs, copy initial files
int ZTXinit(const char *lang);                                             //  setup for message translation
const char *ZTX(const char *english);                                      //  get translation for English message
const char * get_zuserdir();                                               //  get /home/user/.appname/
const char * get_zdatadir();                                               //  get main install directory
void showz_helpfile();                                                     //  show help file in new process
void showz_readme();                                                       //  show README file in popup window
void showz_changelog();                                                    //  show changelog file in popup window
void showz_translations();                                                 //  show TRANSLATIONS file in popup window
void zmake_launcher(const char *categories, const char *genericname);      //  create desktop icon/launcher   v.2.18

/**************************************************************************
   GTK utility functions
***************************************************************************/

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#define  zdcbmax 100                                                       //  max. combo box drop-down list

void zlockInit();                                                          //  lock GTK for threaded applications
void zlock();  
void zunlock();
void zmainloop(int skip = 0);                                              //  do main loop, process menu events

//  text edit/view window utilities
void wprintx(GtkWidget *Win, int line, cchar *mess, cchar *font = 0);      //  write text to line, optional font
void wprintf(GtkWidget *Win, int line, cchar *mess, ...);                  //  "printf" version
void wprintf(GtkWidget *Win, cchar *mess, ... );                           //  "printf" to next line, scroll up
void wscroll(GtkWidget *mLog, int line);                                   //  scroll window to put line on screen
void wclear(GtkWidget *Win);                                               //  clear window
void wclear(GtkWidget *Win, int line);                                     //  clear from line to end
char * wscanf(GtkWidget *Win, int &ftf);                                   //  get text lines from edit widget
int wfiledump(GtkWidget *Win, char *filespec);                             //  dump text window to file
void wfilesave(GtkWidget *Win);                                            //  wfiledump() via file-chooser dialog
void wprintp(GtkWidget *Win);                                              //  print text window to default printer

/**************************************************************************/

//  functions to simplify building menus, tool bars, status bars

#define G_SIGNAL(window,event,func,arg)                 \
  g_signal_connect(G_OBJECT(window),event,G_CALLBACK(func),(void *) arg);

typedef void mtFunc(GtkWidget *, cchar *mname);                            //  menu or button response function

GtkWidget * create_menubar(GtkWidget *vbox, int iconsize);                 //  create menubar in packing box
GtkWidget * add_menubar_item(GtkWidget *mbar, cchar *mname,                //  add menu item to menubar 
                                       mtFunc func = 0);
GtkWidget * add_submenu_item(GtkWidget *mitem, cchar *label,               //  add submenu item to menu item
                             cchar *icon = 0, mtFunc func = 0);            //  (optional icon and function)

GtkWidget * create_toolbar(GtkWidget *vbox,                                //  horiz. toolbar in packing box (vert.)
                           int iconsize = 24, int vert = 0);
GtkWidget * add_toolbar_button(GtkWidget *tbar, cchar *label,              //  add button with stock icon (gtk-quit)
                               cchar *tip, cchar *icon, mtFunc func);      //    or custom icon (iconfile.png)

GtkWidget * create_stbar(GtkWidget *vbox);                                 //  create status bar in packing box
int stbar_message(GtkWidget *stbar, cchar *message);                       //  display message in status bar

/**************************************************************************/

//   functions to implement GTK dialogs with less complexity
//   widgets supported: dialog, hbox, vbox, hsep, vsep, frame, scrwin, label, 
//                      entry, edit, radio, check, button, togbutt, spin, 
//                      combo, comboE, hscale, vscale, colorbutt

#define zdmaxwidgets 300
#define zdsentinel 2138687954

struct zwidget  {
      cchar       *type;                           //  dialog, hbox, vbox, label, entry ...
      cchar       *name;                           //  widget name
      cchar       *pname;                          //  parent (container) name
      char        *data;                           //  widget data, initial / returned
      pvlist      *cblist;                         //  combo box drop-down list
      int         scc;                             //  entry widget: text cc width
      int         homog;                           //  hbox/vbox: equal spacing flag
      int         expand;                          //  expandable flag
      int         space;                           //  extra padding space (pixels)
      GtkWidget   *widget;                         //  GTK widget pointer
};

struct zdialog  {
      int         sentinel;                        //  validity sintenel
      void        *eventCB;                        //  widget event user callback function
      void        *complCB;                        //  dialog completion user callback function
      int         zstat;                           //  dialog status (from completion button)
      int         disabled;                        //  widget signals/events are disabled
      zwidget     widget[zdmaxwidgets];            //  zdialog widgets (EOF = type = 0)
};

zdialog *zdialog_new(cchar *title, GtkWidget *parent, ...);                //  create a zdialog with opt. buttons

int zdialog_add_widget(zdialog *zd,                                        //  add widget to zdialog
      cchar *type, cchar *name, cchar *pname,                              //  required args
      cchar *data = 0, int scc = 0, int homog = 0,                         //  optional args
      int expand = 0, int space = 0);

int zdialog_add_widget(zdialog *zd,                                        //  add widget to zdialog
      cchar *type, cchar *name, cchar *pname,                              //  (alternative form)
      cchar *data, cchar *options);                                        //  "scc=nn|homog|expand|space=nn"

int zdialog_resize(zdialog *zd, int width, int height);                    //  set size > widget sizes
int zdialog_put_data(zdialog *zd, cchar *name, cchar *data);               //  put data in widget (entry, spin ...)
cchar * zdialog_get_data(zdialog *zd, cchar *name);                        //  get widget data
GtkWidget * zdialog_widget(zdialog *zd, cchar *name);                      //  GTK widget from zdialog widget name

typedef int zdialog_event(zdialog *zd, cchar *name);                       //  widget event callback function
typedef int zdialog_compl(zdialog *zd, int zstat);                         //  dialog completion callback function
int zdialog_run(zdialog *zd, zdialog_event = 0, zdialog_compl = 0);        //  run dialog (compl func >> run parallel)
int zdialog_send_event(zdialog *zd, cchar *event);                         //  send an event to an active dialog   v.2.17
int zdialog_destroy(zdialog *zd);                                          //  destroy dialog (caller responsibility)
int zdialog_free(zdialog *zd);                                             //  free zdialog memory

int zdialog_stuff(zdialog *zd, cchar *name, cchar *data);                  //  stuff string data into widget
int zdialog_stuff(zdialog *zd, cchar *name, int  data);                    //  stuff int data
int zdialog_stuff(zdialog *zd, cchar *name, double data);                  //  stuff double data

int zdialog_fetch(zdialog *zd, cchar *name, char *data, int maxcc);        //  get string data from widget
int zdialog_fetch(zdialog *zd, cchar *name, int  &data);                   //  get int data
int zdialog_fetch(zdialog *zd, cchar *name, double &data);                 //  get double data

int zdialog_cb_app(zdialog *zd, cchar *name, cchar *data);                 //  append entry to combo drop down list
int zdialog_cb_prep(zdialog *zd, cchar *name, cchar *data);                //  prepend entry to combo drop down list
char * zdialog_cb_get(zdialog *zd, cchar *name, int Nth);                  //  get combo drop down list Nth entry
int zdialog_cb_delete(zdialog *zd, cchar *name, cchar *data);              //  delete combo drop down list entry   v.2.4
int zdialog_cb_clear(zdialog *zd, cchar *name);                            //  clear all combo box entries         v.2.4

/**************************************************************************/

//   GTK misc. utility functioins

void zappcrash(cchar *pMessage, ...);                                      //  crash with popup message
int write_popup_text(cchar *action, cchar *text, int ww=400, int hh=300);  //  write text to popup window
int popup_command(cchar *command, int ww=400, int hh=300);                 //  shell command, output to popup window
void zmessageACK(cchar *pMess, ... );                                      //  display message, wait for OK
void zmessLogACK(cchar *pMess, ... );                                      //  same, with log to STDOUT
int zmessageYN(cchar *pMess, ... );                                        //  display message, wait for YES or NO
GtkWidget * zmessage_post(cchar *pMess, ...);                              //  display message indefinitely   v.2.6
void zmessage_kill(GtkWidget *dialog);                                     //  kill zmessage_post() message
cchar * dialogText(cchar * title, cchar * inittext);                       //  get short text input from user
char * zgetfile(cchar *title, cchar *file, cchar *rw, cchar *butt = 0);    //  file chooser dialog       v.2.3
void showz_html(const char *url);                                          //  show html via preferred browser  v.2.18

/**************************************************************************/

//   GDK/GTK image file utility functions

GdkPixbuf * gdk_pixbuf_rotate(GdkPixbuf *, double angle, int acolor = 0);  //  rotate pixbuf through any angle

typedef void image_cbfunc(char *file);                                     //  callback function for clicked thumbnail
char * image_xthumbs(cchar *filez, cchar *action, int Nth = 1,             //  display thumbnail index window, navigate,
                                         image_cbfunc ufunc = 0);          //    do user callback for clicked thumbnail

void image_position(const char *file, int &posn, int &count);              //  get curr. image position, total image count
int image_file_type(const char *file);                                     //  determine if directory or image file type
GdkPixbuf * image_thumbnail(cchar *imagefile, int size = 0);               //  get thumbnail pixbuf, create if missing

/**************************************************************************/

//  parameter management functions

int initParmlist(int max);                                                 //  initz. parameter list
int initz_userParms();                                                     //  load or initialize user parms
int loadParms(const char * filename);                                      //  load parameters from a file
int loadParms();                                                           //   + user file select dialog
int saveParms(const char * filename);                                      //  save parameters to a file
int saveParms();                                                           //   + user file select dialog
int setParm(cchar * parmname, double parmval);                             //  set parameter value
double getParm(cchar * parmname);                                          //  get parameter value
char * getParm(int Nth);                                                   //  get Nth parameter name (0-based)
int listParms(GtkWidget *textWin);                                         //  list all parameters in given window 
int editParms(GtkWidget *textWin = 0, int addp = 0);                       //  parameter editor


/**************************************************************************
   C++ classes
***************************************************************************/

//  dynamic string class ==================================================

class xstring
{
      static int  tcount;                                                  //  total xstring count
      static int  tmem;                                                    //  total memory used
      int         wmi;                                                     //  internal ID
      int         xcc;                                                     //  actual cc (excl. NULL)
      int         xmem;                                                    //  memory allocated cc
      char      * xpp;                                                     //  memory pointer
   public:
      xstring(int cc = 0);                                                 //  default constructor
      xstring(cchar * );                                                   //  string constructor
      xstring(const xstring &);                                            //  copy constructor
      ~xstring();                                                          //  destructor
      operator cchar * () const { return xpp; }                            //  conversion operator (const char *)
      xstring operator= (const xstring &);                                 //  operator =
      xstring operator= (cchar *);                                         //  operator =
      friend xstring operator+ (const xstring &, const xstring &);         //  operator +
      friend xstring operator+ (const xstring &, cchar *);                 //  operator +
      friend xstring operator+ (cchar *, const xstring &);                 //  operator +
      void insert(int pos, cchar * string, int cc = 0);                    //  insert substring at position (expand)
      void overlay(int pos, cchar * string, int cc = 0);                   //  overlay substring (possibly expand)
      static void getStats(int & tcount2, int & tmem2);                    //  get statistics
      void validate() const;                                               //  verify integrity
      int getcc() const { return xcc; }                                    //  return string length
};

//  vector (array) of xstring =============================================

class Vxstring
{
   int        nd;                                                          //  count
   xstring  * pdata;                                                       //  xstring[nd]
public:
   Vxstring(int = 0);                                                      //  constructor
   ~Vxstring();                                                            //  destructor
   Vxstring(const Vxstring &);                                             //  copy constructor
   Vxstring operator= (const Vxstring &);                                  //  operator =
   xstring & operator[] (int);                                             //  operator []
   const xstring & operator[] (int) const;                                 //  operator [] (const)
   int search(cchar * string);                                             //  find element in unsorted Vxstring
   int bsearch(cchar * string);                                            //  find element in sorted Vxstring
   int sort(int nkeys, int keys[][3]);                                     //  sort by designated subfields
   int sort(int pos = 0, int cc = 0);                                      //  sort by 1 subfield (cc 0 = all)
   int getCount() const { return nd; }                                     //  get current count
};

//  hash table class ======================================================

class HashTab
{
   static int trys1;                                                       //  insert trys
   static int trys2;                                                       //  find/delete trys
   int     cap;                                                            //  table capacity
   int     count;                                                          //  strings contained
   int     cc;                                                             //  string length
   char  * table;                                                          //  table[cc][cap]
public:
   HashTab(int cc, int cap);                                               //  constructor
   ~HashTab();                                                             //  destructor
   int Add(cchar * string);                                                //  add a new string
   int Del(cchar * string);                                                //  delete a string
   int Find(cchar * string);                                               //  find a string
   int GetCount() { return count; };                                       //  get string count
   int GetNext(int & first, char * string);                                //  get first/next string
   int Dump();                                                             //  dump hash table
};

//  Queue class, FIFO, LIFO or mixed ======================================

class  Queue
{
   char        wmi[8];
   Vxstring  * vd;                                                         //  vector of xstrings
   mutex       qmutex;                                                     //  for multi-thread access
   int         qcap;                                                       //  queue capacity
   int         qcount;                                                     //  curr. queue count
   int         ent1;                                                       //  first entry pointer
   int         entN;                                                       //  last entry pointer
   char      * lastent;                                                    //  last entry retrieved
   int         lcc;                                                        //  last entry cc
private:
   void lock();                                                            //  auto locking and unlocking
   void unlock();                                                          //  (for multi-thread access)
public:
   Queue(int cap);                                                         //  create queue with capacity
   ~Queue();                                                               //  destroy queue
   int getCount();                                                         //  get current entry count
   int push(const xstring * entry, double secs);                           //  add new entry with max. wait time
   xstring * pop1();                                                       //  get 1st entry (oldest)
   xstring * popN();                                                       //  get Nth entry (newest)
};

/*  =======================================================================

       Tree class - sparse array indexed by names or numbers
                  - every element of a Tree is a Tree

       put(): cc is data length to store
       get(): cc is max. data length to retrieve
              actual length is returned, = 0 if not found
              nn is array count for nodes[] arguments
*/

class  Tree
{
   int         wmi;                                                        //  for ID checking
   char       *tname;                                                      //  tree name
   int         tmem;                                                       //  tree data memory
   void       *tdata;                                                      //  tree data[tmem]
   int         nsub;                                                       //  no. sub-nodes (Trees)
   Tree      **psub;                                                       //  pointer to sub-nodes
public:
   Tree(const char * name);                                                //  create Tree
   ~Tree();                                                                //  destroy Tree
   int put(void * data, int cc, char * nodes[], int nn);                   //  put data by node names[]
   int put(void * data, int cc, int nodes[], int nn);                      //  put data by node numbers[]
   int get(void * data, int cc, char * nodes[], int nn);                   //  get data by node names[]
   int get(void * data, int cc, int nodes[], int nn);                      //  get data by node numbers[]
   void stats(int nnodes[], int ndata[]);                                  //  get nodes and data per level
   void dump(int level = 0);                                               //  diagnostic
private:
   Tree * find(char * nodes[], int nn);                                    //  find a sub-node by names[]
   Tree * find(int nodes[], int nn);                                       //  find a sub-node by numbers[]
   Tree * make(char * nodes[], int nn);                                    //  find/create a sub-node by names[]
   Tree * make(int nodes[], int nn);                                       //  find/create a sub-node by numbers[]
};



