/** * @file * @brief container data types API * @ingroup public_apis * * **CDT** manages run-time dictionaries using standard container data types: * unordered set/multiset, ordered set/multiset, list, and stack. * * [man 3 cdt](https://graphviz.org/pdf/cdt.3.pdf) * */ #pragma once #ifdef __cplusplus extern "C" { #endif /* Public interface for the dictionary library ** ** Written by Kiem-Phong Vo */ #define CDT_VERSION 20241216L #include /* size_t */ #include #ifdef GVDLL #ifdef EXPORT_CDT #define CDT_API __declspec(dllexport) #else #define CDT_API __declspec(dllimport) #endif #endif #ifndef CDT_API #define CDT_API /* nothing */ #endif typedef struct dtlink_s_ Dtlink_t; typedef struct dtdisc_s_ Dtdisc_t; typedef struct dt_s_ Dt_t; typedef struct dt_s_ Dict_t; /* for libdict compatibility */ typedef void *(*Dtsearch_f)(Dt_t *, void *, int); typedef void *(*Dtmake_f)(void *, Dtdisc_t *); typedef void (*Dtfree_f)(void *); typedef int (*Dtcompar_f)(void *, void *); struct dtlink_s_ { Dtlink_t *right; /* right child */ union { unsigned int _hash; /* hash value */ Dtlink_t *_left; /* left child */ } hl; }; /* private structure to hold an object */ typedef struct { Dtlink_t hdr; /* header */ void *obj; /* user object */ } Dthold_t; /* method to manipulate dictionary structure */ typedef struct { Dtsearch_f searchf; /* search function */ int type; /* type of operation */ } Dtmethod_t; /* stuff that may be in shared memory */ typedef struct { int type; /* type of dictionary */ Dtlink_t *here; /* finger to last search element */ union { Dtlink_t **_htab; /* hash table */ Dtlink_t *_head; /* linked list */ } hh; int ntab; /* number of hash slots */ int size; /* number of objects */ int loop; /* number of nested loops */ } Dtdata_t; /* structure to hold methods that manipulate an object */ struct dtdisc_s_ { int key; /* where the key begins in an object */ int size; /* key size and type */ int link; /* offset to Dtlink_t field */ Dtmake_f makef; /* object constructor */ Dtfree_f freef; /* object destructor */ Dtcompar_f comparf; /* to compare two objects */ }; #define DTDISC(dc, ky, sz, lk, mkf, frf, cmpf) \ ((dc)->key = (ky), (dc)->size = (sz), (dc)->link = (lk), \ (dc)->makef = (mkf), (dc)->freef = (frf), (dc)->comparf = (cmpf)) /* the dictionary structure itself */ struct dt_s_ { Dtsearch_f searchf; /* search function */ Dtdisc_t *disc; /* method to manipulate objs */ Dtdata_t data; ///< sharable data Dtmethod_t *meth; /* dictionary method */ int nview; /* number of parent view dictionaries */ Dt_t *view; /* next on viewpath */ Dt_t *walk; /* dictionary being walked */ void *user; /* for user's usage */ }; /* structure to get status of a dictionary */ typedef struct { int dt_meth; /* method type */ int dt_size; /* number of elements */ size_t dt_n; // number of chains or levels size_t dt_max; // max size of a chain or a level size_t *dt_count; // counts of chains or levels by size } Dtstat_t; /* supported storage methods */ #define DT_SET 0000001 /* set with unique elements */ #define DT_OSET 0000004 /* ordered set (self-adjusting tree) */ #define DT_OBAG 0000010 /* ordered multiset */ #define DT_METHODS 0000377 /* all currently supported methods */ /* types of search */ #define DT_INSERT 0000001 /* insert object if not found */ #define DT_DELETE 0000002 /* delete object if found */ #define DT_SEARCH 0000004 /* look for an object */ #define DT_NEXT 0000010 /* look for next element */ #define DT_PREV 0000020 /* find previous element */ #define DT_RENEW 0000040 /* renewing an object */ #define DT_CLEAR 0000100 /* clearing all objects */ #define DT_FIRST 0000200 /* get first object */ #define DT_LAST 0000400 /* get last object */ #define DT_MATCH 0001000 /* find object matching key */ #define DT_VSEARCH 0002000 /* search using internal representation */ #define DT_DETACH 0010000 /* detach an object from the dictionary */ CDT_API extern Dtmethod_t *Dtset; ///< set with unique elements CDT_API extern Dtmethod_t *Dtoset; ///< ordered set (self-adjusting tree) CDT_API extern Dtmethod_t *Dtobag; ///< ordered multiset CDT_API extern Dtmethod_t *Dttree; CDT_API Dt_t *dtopen(Dtdisc_t *, Dtmethod_t *); CDT_API int dtclose(Dt_t *); CDT_API Dt_t *dtview(Dt_t *, Dt_t *); CDT_API Dtdisc_t *dtdisc(Dt_t *dt, Dtdisc_t *); CDT_API Dtmethod_t *dtmethod(Dt_t *, Dtmethod_t *); CDT_API Dtlink_t *dtflatten(Dt_t *); CDT_API Dtlink_t *dtextract(Dt_t *); CDT_API int dtrestore(Dt_t *, Dtlink_t *); CDT_API int dtwalk(Dt_t *, int (*)(void *, void *), void *); CDT_API void *dtrenew(Dt_t *, void *); CDT_API int dtsize(Dt_t *); CDT_API int dtstat(Dt_t *, Dtstat_t *, int); CDT_API unsigned int dtstrhash(void *, int); /* internal functions for translating among holder, object and key */ #define _DT(dt) ((Dt_t *)(dt)) #define _DTDSC(dc, ky, sz, lk, cmpf) \ (ky = dc->key, sz = dc->size, lk = dc->link, cmpf = dc->comparf) #define _DTLNK(o, lk) ((Dtlink_t *)((char *)(o) + lk)) #define _DTOBJ(e, lk) \ (lk < 0 ? ((Dthold_t *)(e))->obj : (void *)((char *)(e) - lk)) #define _DTKEY(o, ky, sz) \ (void *)(sz < 0 ? *((char **)((char *)(o) + ky)) : ((char *)(o) + ky)) #define _DTCMP(k1, k2, cmpf, sz) \ (cmpf ? (cmpf)(k1, k2) \ : (sz <= 0 ? strcmp(k1, k2) : memcmp(k1, k2, (size_t)sz))) #define dtlink(d, e) (((Dtlink_t *)(e))->right) #define dtobj(d, e) _DTOBJ((e), _DT(d)->disc->link) #define dtfinger(d) (_DT(d)->data.here ? dtobj((d), _DT(d)->data.here) : NULL) #define dtfirst(d) (*(_DT(d)->searchf))((d), (void *)(0), DT_FIRST) #define dtnext(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_NEXT) #define dtlast(d) (*(_DT(d)->searchf))((d), (void *)(0), DT_LAST) #define dtprev(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_PREV) #define dtsearch(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_SEARCH) #define dtmatch(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_MATCH) #define dtinsert(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_INSERT) #define dtdelete(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_DELETE) #define dtdetach(d, o) (*(_DT(d)->searchf))((d), (void *)(o), DT_DETACH) #define dtclear(d) (*(_DT(d)->searchf))((d), (void *)(0), DT_CLEAR) /** * @dir lib/cdt * @brief container data types, API cdt.h * * [man 3 cdt](https://graphviz.org/pdf/cdt.3.pdf) * */ #ifdef __cplusplus } #endif