Home
Name Modified Size InfoDownloads / Week
Lnkdlst-v0.3.4.tar.gz 2022-11-22 294.5 kB
uws-Lnkdlst-readme.txt 2022-11-22 36.9 kB
Lnkdlst-v0.3.3.zip 2021-05-21 326.1 kB
Lnkdlst-v0.3.2.tar.gz 2019-10-28 289.2 kB
Lnkdlst-v0.3.1.tar.gz 2017-05-13 172.1 kB
Lnkdlst-v0.3.tar.gz 2017-01-30 221.1 kB
Lnkdlst-v0.2.tar.gz 2017-01-11 300.0 kB
Lnkdlst-v0.1.tar.gz 2016-12-22 212.9 kB
Totals: 8 Items   1.9 MB 1
 L n k d l s t
===============

### content
+ overview
+ release-notes
+ tutorial
+ work flow
+ debug facilities
+ testing
+ old readme
+/+



### overview

Lnkdlst is an C implementation of a 
single  sided  linked  list  (LiNKeD-LiST).

A light version is available for basic functionality in C++ and java too 
(assumed it is not very high sophysticated code, but should work properly 
as well but - as for C - is not itself type-safe).

In programming language C lnkdlst.c (and lnkdlst.h of course) supports 
3 major function groups till now (0.3.2 xxx):
- Basic                 -> generic Lnkdlst functions, without memory control 
- Auto-mem-functions    -> easy usage of Lnkdlst with malloc memory
- OA.List01 functions   -> secur, multithread-able handling of two list (idle/busy)
-/- 

At first it is to say, that this generic list or container ~library~ is - 
of course (C) - not type safe!
Programmers should do this by wrapping functions which is highly 
recommended. At least use CPP (my alternative word for C++) to be more 
typesafe, but at least usage of CPP instead of C alone(?) will do not solve 
all programming issues like type-safety in my opinion.

Secondly this list is a general purpose, generic list functionality 
without (!) special behaviour such as : 
- very fast access to elements 
- supporting of very huge lists (with timing optimization)
- hashed access at elements 
- and so on.
If you had not much heavy timing or other constraints you can do all container 
tasks with this ~library~; of course, just IMHO. Using wrapping functions will 
bring you into the position to substitute the lnkdlst functions later if some 
aim is not longer reached with lnkdlst underlayer.
But - as before too: If you like to write smarter, safer(?) and compacter code 
you'll be addressed to use CPP and use  std:: container libraries
(Best: libraries >= C++11, avoid using lesser CPP versions; try to use 
boost-library for older CPP compilers but try to use std:: library functions 
before using other libraries; of course, just imho).


Now see a short explanation of Basic Lnkdlst functions (fn=function).

All functions which do not include the text "*noBasic*" in the fn-group-comment 
header, are Lnkdlst fns of the Basic group.

We have the List change functions:
lnkdlst_appendLLEl(),*_insertLLEl(),*_insLLElAtPos(),*_deleteLLEl(),*_delLLElAtPos().
-
If the position of one element, a LLEl (LLEl is short for Linked-List-Element), 
is not important you only need the 
->  'insert' and the 
->  'delete' fn, which uses the element pointer to 
bring the element in the list {lnkdlst_insertLLEl()}
and remove it from the list {lnkdlst_deleteLLEl()}, 
no matter where this LLEl has it memory - memory-management of LLEl's is 
outside of the Basic-Lnkdlst-fn scope!
Hint: Functions of the other fn groups could help you easily if you had no idea 
how to do and manage this.
-
What you only need to use the Basic fn-set is one or more LLEl's - adressed by 
the pointer of them usually - and a Lnkdlst Root-Pointer (shortly named RootP), 
which is the holder of the complete list (->Lnkdlst in C). 

On the other side we have List check & get & get-info & search functions. 

Before having a look at these, i'll have to explain why an element has a 
generic character:
It contains only 3 elements or - in speech of CPP - 3 member-variables:
- next-Ptr      (Ptr or P is a short form of 'pointer')
- Identifier
- void-Ptr
-/-
And - if you had spend enough memory behind - you could use the memory behind 
the LLEl as a 4th member. If this is done 
(- easy by using dyn-mem group fn "lnkdlst_memallocateAappendLLEl()" with
   a size-value in arg2 >0, which allocates memory for the LLEl and optionally 
   - in this case - for a free memory behind this LLEl.
-) 
you could acccess these 4th element - e.g. for an own struct variable belonging 
to this LLEl - easily accessible via a specific macro
{LNKDLST_GET_P2ADDDATA(LLEl_ptr) or - for direct casting - LNKDLST__GET_P2ADDDATA()}.
The according memory i called "AddData" - short for additional-data for this 
LLEl - and hence i had spend the name Enhanced-LLEl, or ELLEl, for this 
construction where the 4th element - the Add.Data - in an LLEl is available.
(No info what type this addData is; better to use special wrapper-functions 
to use specific Lnkdlst's, imho).
-
So you have free data (*2) in a LLEl to use: 
"Identifier"        - an unsigned integer Identifier variable, *1 
"pValue"            - an untyped pointer (void-Ptr) and 
-optional- AddData  - an reserved memory area for your fix needs in a 
specific LLEl; yes: also for this (AddData) you must take care 
when access is allowed and what does it mean. 
Usually - to make it easier - you have one data-construction for one Lnkdlst; 
if you like to have this data-construction for many Lnkslst's in your 
program, i suggest to build an extra type (C-derived from the LLEl type 
"tstLnkdlstEl" via typedef) and use only this type for these lists.
( *1: type could be your own type but must be an integer type
  *2: do not use the next-Ptr {pstNextLLEl} by yourself, especially do not 
      write at this member; like private member-vars in CPP classes.
)
-
!!! Important:
    Describe your data for each Lnkdlst list (type) you [want to] use.
    Do not use the system member next-Ptr of a LLEl and beware that one LLEl 
    could be only in one Lnkdlst (linked-in) or is not in any Lnkdlst 
    (not in any: free, e.g. to save it in a new list or to free memory.
     Also have a look at tutorial 004 which shows the basics (beginner) and 
     tutorial 003 for deeper info about failures in usage (advanced).
    ).
!!!


Now let's have a look at some Lnkdlst-non-list-changing Basic functions:
-
* example-1: lnkdlst_searchLLElbyID()
This functions uses the 1st member of a LLEl, the Identifier (ID), where you can 
search for it. And more: you could use bit-by-bit to search for LLEl's.
(masked search).
Your are free to devide the ID in various parts or to use it fully as one ID 
in the member-variable Identifier; this function could found both LLEl in 
a list.
-
For instance: You like to save one Data-Collection of one person in a Lnkdlst.
This means - like a data-base - you need as many Lnkdlst's as you like to 
save persons data in this temporary memory. (For persistant savings you had to 
bring the lists-data into a non-volatile memory, like a file-system - of coures). 
Give every item of the Data-Collection an own ->ID. E.g. take ID 1 for Name 
(AddData is type of "const char*" and contains the C-string) 
and ID 2 for address (AddData is used in the same way as for ID 1).
Now you like to show the address of "Peter":
    Search in every person-List the ID 1; if a valid ptr is returned you could 
    check if it is "Peter" {strcmp(LLEl-AddData,"Peter)==0}; if this matches 
    you'll have to see if an LLEl with ID 2 exist in this persons List 
    -> a valid ptr after searching means : yes -> you'll get the address of 
    Peter and now could make them visible e.g.  by printing the AddData 
    of the found LLEl with ID 2.
Of course, there are many ways to do this without Lnkdlst. If you want to 
make enhancements without disturbing existing code then this way is one 
good approach - imho. {type-safety is another topic, which is important 
and could only be handled by wrapper functions - but willB not as secur as in 
CPP usually}.
E.g. you decide to use the bits 8..11 of lists LLEl-ID to define a 'type' of 
every LLEl (place for 15 types - ;-)), you could found them by using this 
search function and the searchNext function.
example-code: >>
    ..
    tstLnkdlstEl*   pCurLLEl;
    ..
    /* found every LLEl with type-Id 13 */
    for( pCurLLEl= lnkdlst_searchLLElbyID( RootP, 13<<8, 0xF<<8);
     pCurLLEl != NULL;
     pCurLLEl= lnkdlst_searchNextLLElbyID( RootP, pCurLLEl, 13<<8, 0xF<<8) ) {
         do-something-with-LLEl-type13( pCurLLEl ); /* e.g. make data-changes on those elements */
    }
<<
Of course, this example uses literals which is just for demonstration; in real 
world you should use enum's, constants or defines for the Types as well as for 
the mask!
-
* example-2: lnkdlst_numofLLEl()
This functions returns a value like an index in an array, but not fixed.
Not-fixed: if you use the Basic insert-fn, all other LLEl's will be moved 
behind this newly inserted LLEl; hence an number of an exsiting LLEl before the 
insertion is increased by 1 - all numbers of previously existing LLEl's in 
this list. Hence - for me - the number is not very much important due to 
dynamic changing. 
E.g. if you like to put a new LLEl in a Lnkdlst, but you do not want to have 
it before a specific LLEl in this list, you could use this fn and the 
'insAt' fn. example code: >>

    int  insertNewLLElBehindExisting( tstLnkdlstEl** p2RootP, tstLnkdlstEl* pNewLLEl, tstLnkdlstEl* pExistingLLEl)
    {
        int     iNumber;
        
        assert(p2RootP!=NULL);          /*debug* must be a valid ptr to the RootP of the list */
        
        iNumber= lnkdlst_numofLLEl( * p2RootP, pExistingLLEl);
        if( iNumber < 0 ) { return 1;   /*1* we do not found a member (ExistingLLEl) in this list (RootP) - MewLLEl is NOT inserted */ }
        iRC= lnkdlst_insLLElAtPos( p2RootP, pNewLLEl, (unsigned)( iNumber +1));
        
        assert(iRC==0);                 /*debug* we do not assume an error */
        /* now the new LLEl is just behind the old, existing one, in the list */
        return  0  ;                    /*0* successfully inserted the NewLLEl */
    }
<<


This should give you an idea what is possible with Lnkdlst.
Hope it is not too difficult to understand and will help you to decide wheather 
you could use this or not.
Please let me know - if you use it - what you are using in what way or 
if you have unresolved issues which seems to be important for all or 
if need more integrated functions with generic character.

Thanks for reading.

-------------------------------------------------------------------------------





### release-notes

0.1     start with C-code

0.2     add C++ basic feature set (step1)

0.3     java:   add java basic feature set (step1)
        C++:    bug fix in destructor
        C:      add functions lnkdlst_insLLElAtPos()  ~insert-at-position~
                and lnkdlst_delLLElAtPos()  ~delete-at-position~
                to meet same basic function set as in java and C++ 
                (without class o.c.)

0.3.1   java:   -
        C++:    docu->  insert readme section with restriction info
                chg->   do not use "using namespace std;" in cpp-header
                deb->   additional debug checks eg. for compilation (C vs. CPP)
                fix->   use "extern "C" " blocks for plain C header/src  
        C:      fix->   local-tracing supports WIN environment (traceam.h,eg VS)
                deb->   control via std. Debug macros is used per default in 
                        local-tracing (traceam.h)
                add->   local-tracing (traceam.h) add short-mac to cast to 
                        unsigned long (ULC x brings x to unsigned long for 
                        DCLTRC macros or printf too; format: %lu)

0.3.2   java:   -
        C++:    -       
        

* 0.3.2 * 
- gen:  ..
  Add   This informational file.
  -
- java: -
- C++:  -       (traceam.h implicit)
  -
- C:    ..
  Add   CC-switch "LNKDLST_CDEF_LOCKSMANDA". Set to 1 if Locktype is necessary
  Impl  CC-switch "LNKDLST_DEBUG_CHECK" (List validation, not for C++)
  Impl  Active DCLNKDLST_* macros if (LNKDLST_DEBUG_CHECK!=0)
  Add   LNKDLST_REGISTER_ to use 'register' variables in plain C case only!
  Chg   Make OALIST error-codes global (OALIST_ECOD_*)
  Add   macro LNKDLST_DEINIT_ROOTPTR() {necessary for LNKDLST_DEBUG_CHECK!=0)
  Chg   More/corrected info in comments
  Add   dyn-mem fn "lnkdlst_memallocateAinsLLElAtPos()"  (insert-linking)
  Add   dyn-mem fn "lnkdlst_memallocateLLEl()" (without linking!)
  Add   dyn-mem fn "lnkdlst_freeLLEl()" (after de-linking ONLY!)
  Add   base fn "lnkdlst_getp2PrevLLEl()"
  Add   base fn "lnkdlst_searchLLElbyPVal()"
  Add   base fn "lnkdlst_searchNextLLElbyPVal()"
  Add   traceam feature 'DCLTRC_INCLUDE_TIME' (add relative time f. DCLTRC)
  Add   traceam feature 'DCLTRC_FILE_LOGGING_' (
  ..    needs one file with TRACEAM_MAIN_ and dcltrc_init(),dcltrc_deinit())
  Add   traceam fn 'util_getSysUpTime()'
  Add   traceam fn 'dcltrc_getTimeString()'
  Chg   script 'kill-lnkdlst-DCdebug.sh' for *DC* + DCLNKDLST line filter (C,H)
  Chg   DCdebug free lnkdlst files are in folder code/test/debugcodefree/
  Impl  makefile: with env.var "LLDCFREE" set to YES use debugcodefree lnkdlst
  Add   makefile: support of TESTNO (-> C-define 'LNKDLST_STEST_TESTNO' opt. 
  ..    and 'LNKDLST_STESTn' always)
  Impl  makefile: BUILD_TYPE (DEBUG|RELEASE/default)
  Add   maintutor: tutor's 1..4 (makefile-target: tutor)
  Add   implicite lnkdlst main-test (makefile-target: lnkdlst)
  Add   makefile: explicite make DCfree lnkdlst code target (lnkdlstDCfree)
  Add   Variable OS sub-make 'makeosdefs.mi' for 3 OS base support
  -
-/-

* 0.3.3 * 
- gen:  ..
  Add   
  Chg   
  Impl  
  Fix   
  -
- java: -
- C++:  -       (traceam.h implicit)
  -
- C:    ..
  Add   Test-shell script (autotest-C.sh) for using maintest with little checks
  Add   more checks for debug
  Impl  define "LNKDLST__VERSION", which could be used for unreleased also
  Fix   LNKDLST_REGISTER_ is permanently not used. could be set for C-only use
  Chg   correct & add miscellaneous info comments/texts, little restyling
  Add   "LNKDLST__GET_P2ADDDATA" to set the AddData type as arg1 (mac with casting)
  Add   new type 'eLNKDLST_NUMBALLOC' to allow more LLEls for OAList01 objs
  Fix   DCLNKDLST_IS_TYPE (arg 0 should ignore type check, is NYI)
  Chg   make OAList01 more typesafe, arg1 is now a obj ptr instead of void*
  Add   OAList01: optionally support a UpperInstance ptr for every obj
  Add   OAList01: API "getInfo()" to get various info of a OAList01 obj
  Chg   OAList01: typedef renamed (old av if deprecated is enable) to tstLnkdlst_OAList01PubCB
  Chg   init fns renamed (Lnkdlst_OAInitialize, old av if deprecated is enable)
  Impl  OAList:init fn with name to allow multiple inits from various OAList01 users
  Impl  OAList:deinit fn integrated to cleanup fully dynamically
  Chg   traceam: support util_getSysUpTime() always
  Fix   traceam: DCLTRC_SYSERR() and more for _WIN32
  Add   traceam: DCCONDINCL() allows temp. code insertion (~ DCABORT enable)
  Add   traceam: support sleep(x) for _WIN32 (x= seconds)
  Add   traceam: new feature hex-converter (dcltrc_cr_hexconv)
  Add   traceam: need special free fn for time-str (dcltrc_freeTimeString) yet
  Add   traceam: some other news (DCLTRC_STRIZE - build str from define,..)
  Add   make: sub make file "makedebdefs.mi" for debug-feature selection (e.g. DCDEBUGCONTROL_MASK)
  Add   make: LLDEBUG_CHECK controls LNKDLST_DEBUG_CHECK externally
  Impl  test: test06 for maintest: a multithreading fifo stress test
  Add   test: easy thr. feature incl. integrated small test facility
  Add   LOCKTYPE 21 for _WIN32 (CriticalSection) for OAList01 & debug
  Chg   OAList01: integrate faster access ~define OALIST_FASTACC_NO (faster ifdef, old ifndef)
  Chg   OAList01: allow more LLEls in a OAList01 obj (LNKDLST_OAList01_MAX_LLEL)
  Fix   OAList01: when going through list and delete LLEls (CHKaCONDCLEAR_CURRENT_SEARCHLLEL..)
  Add   OAList01: support integrated locks (before: only external supported)
  Chg   use __FATALERROR_HDLG in some fns and make them a void (ret-code) fn
  Fix   OAList01: API fn exitOALLElList01C() now supported for dyn. list cr&del
  Impl  Enhanced integrated 'main' test in lnkdlst.c, e.g. test OAList01 fns too
-/-


* 0.3.4 * 
- gen:  ..
  % -
- java: 
  % -
- C++:  -       (traceam.h implicit)
  % -
- C:    ..
    - traceam.h changes
      Impl  a define 'DCLTRC_CDEF_STDFP_VAR' could be used for std. usage 
            of traceam DCLTRC_xyz macros to decide what level goes to stderr 
            and what to stdout.
            If using file-tracing (def. DCLTRC_FILE_LOGGING_) and you do not 
            initialize it (correctly), stderr is used always.
      Add   own strdup fn 'util_makeMemString()' which delivers a const char*.
      Chg   for DCLTRC_INCLUDE_TIME you now could choose decimal linear 
            timestamp (default yet) instead of a hexadecimal (alternative,
            in former version only hexa).
      Impl  a new fn to print out a hex-dump (util_dumpBufInHex())
      Chg   for DCABif macros the wait time is increased to 7 seconds, if an 
            abort has occured due to a invalid condition. Could be reduced by 
            a define.
      Add   convert() fn for dcltrc_cr_hexconv() C-objects. Could use the 
            ~object~ multiple times.
      Impl  C ~object~ for a stop-watch {DCLTRC_tstStopWatch* 
            dcltrc_cr_stopwatch()}. start/stop/gap.
            Easy use also by start-tm via create object, stop time via 
            destroy object.
    -
    - lnkdlst.h changes
      Impl  auto-mem-functions lnkdlst_memallocateAappendAinitLLEl() and 
            lnkdlst_memallocateAappendAinit0LLEl() for more easy handling 
            of get-LLEl-memory, init this LLEl and put in into a list.
      Impl  auto-mem-function lnkdlst_cleanup_memallocList() to clean (destroy) 
            a complete Linked-List of auto-mem type.
      Chg   and add Error-Code definitions. Also put the error-codes only in 
            the h-file.
    -/-
-/-


-------------------------------------------------------------------------------





### tutorial

The maintutor.c file could help you to understand the functionality of 
the usage of Lnkdlst library functions.

There is at least one example, choose the correct number (tutor#) by setting 
the define "LNKDLST_TUTOR_TESTNO" and enter 
> make tutor
<, then you can start this example by entering 
> ./tutor
<.
But please read the information above this example at 1st to know what will 
happen.

Every example has a main function and a specific init-function 
(tutor-number at the end of the init function name).

For more information pls. read the readme section in maintutor.c !

To see detailed information about a specific tutor-lesson you could search 
for the "LNKDLST_TUTOR_TESTNO" (#elif...) and below this the informational 
text could be found.

* List:
tutor#| easy/mid/hard   | brief info    
      |              Y T| 
---   | ------------ - -| --------------------------------------------------
001   | easy         I S| basic usage of Lnkdlst                    run-only
002   | mid          c S| simple FIFO realization with dyn memory
003   | harder       c S| various cases to show wrong usage of Lnkdlst parts
004   | easy         I S| easy compare example for a Lnkdlst (a queue)    *1
---   + ------------ - -+ --------------------------------------------------
legend:
T:      thread-info:    S->single-thread, M->multi-thread. (preemptive only)
Y:      tutor-type:     I->Interactive-tutor lesson, run tutor only;
                        c->code-example, read code and see tutor prints and realize.. 
-
*1: may be use this tutor at 1st, more easy to understand imho
-------------------------------------------------------------------------------
  




### work flow

0. Preconditions
Lnkdlst (programming language C) based only on a few system libraries, some 
depends on settings (like for LNKDLST_LOCKTYPE).
Own needed features : not one.


1. Initialisation of one Lnkdlst
Get a static RootP by declaration. Life-time of this Ptr shouldB at least longer 
than life-time of the holded list!
Has to be initiated before usage. example code:
>>
  tstLnkdlstEl*     pstListRootPtr;
  ...
  LNKDLST_INIT_ROOTPTR( pstListRootPtr );
  Lnkdlst_OAInitiate();                 /* optional if OAList01 will be used in the program */
  ...                                   /* now the list could be used */
<<
The Basic Lnkdlst fns are not thread-save! Use own mutex-wrapper functions or 
OAList01 instances {~~ object-like} via calling Lnkdlst_newOAList01().
--
 

2. Get Lnkdlst element (LLEl)
Allocate one LLEl. Either by using the Auto-mem-functions, at easiest the 
fn "lnkdlst_memallocateAappendLLEl()" which uses at 1st malloc ('new' in CPP) 
to reserve a continoues block of memory with a start-adress (identical with 
the LLEl Ptr) and a length of the block in bytes, than (- 'A' for 'and' -) the 
given LLEl willB automatically appended in the list, given by a Ptr to the 
RootP (this may be a changed element).
It could be sawn synonym like a array of char-variables, where at least 
one LLEl is placable.

Easy dyn. usage (take RootP from step-1), example code:
>>
  tstLnkdlstEl*     pstLL;              /* the current element */
  ..
  typedef struct {
    char    Name[100], Address[200], Phone[50], Mobile[50];
    struct {
        unsigned char   day, month, year;
    } Birthday;
  } tstPersonalData;
  ..
  pstLL= lnkdlst_memallocateAappendLLEl( &pstListRootPtr, 
                                         sizeof(tstPersonalData) );
  assert(pstLL!=NULL);                  /* we do not expect no-mem case! */
  {
    tstPersonalData*    pstPDt= (tstPersonalData*) LNKDLST_GET_P2ADDDATA(pstLL);
    
    pstPDt->Name=       "Ulrich Angstreng";
    pstPDt->Address=    "Amazonas, Indystreet 23";
    pstPDt->Phone=      "+007008009010011";
    pstPDt->Mobile=     "+007654321234567";
    pstPDt->Birthday.day=       8;
    pstPDt->Birthday.month=     2;
    pstPDt->Birthday.year=      97;
  }
  ..
<<                                      {LLEl now saved in list 'pstListRootPtr'}

Static usage (take RootP from step-1), own memory management, example code:
>>
  #define MaxLLElInPool 20
  ..
  tstLnkdlstEl*     pstLL;              /* the current element */
  tstLnkdlstEl      astFreeLLElArray[ MaxLLElInPool ];
  tstLnkdlstEl*     pstFreeLLElPoolRootP;
  unsigned          ix;
  ..
  /* build a pool of free LLEl */
  LNKDLST_INIT_ROOTPTR( pstFreeLLElPoolRootP );
  for( ix= 0;  ix<MaxLLElInPool;  ++ix) {
        lnkdlst_insertLLEl( &pstFreeLLElPoolRootP, &astFreeLLElArray[ix]);
  }                                     /* all LLEl now in the free-pool-Lnkdlst */
  ..
  ..
  /* get a new LLEl without using malloc */
  pstLL= pstFreeLLElPoolRootP;
  if( pstLL==NULL) {                    /* wrong dimensioning or mem-leak (lost 'free' call) */
        printf("we got out of LLEl - fatal-error\n");
        exit(1);
  }
  lnkdlst_deleteLLEl( &pstFreeLLElPoolRootP, pstLL); /* LLEl is now out-of-list */
  ..
  pstLL->Identifier=    1;
  pstLL->pValue=        (void*) "Mark Muller";
  lnkdlst_appendLLEl( &pstListRootPtr, pstLL);  /* LLEl is now in a working Lnkdlst */
  ..
<<
--


3. Use element(s) in Buffer
The Lnkdlst contents could be easily transfered via RooP argument, 
read-only(!) to other functions, off course - list changing functions must
have access to the RootP.
Here LLEl could be identified - for instance - by the ID.
If searching for an ID just 2 actions could happen (assumed, the RootP is valid 
and the containing list is not inconsistent):
-
A- LLEl with ID (or part-of-ID) has been found (may be further LLEl with this 
   ID are in this list, is not been permitted);
   .. LLEl could be accessed
-
B- LLEl with ID has not been found; this argument/parameter/attribut... could 
   not been used yet;
   1.   leave function with failure-code
   or
   2.   exit program (for instance if the argument is mandatory)
   or
   3.   use default value for this argument to go ahead with this.
--/-

Usage in finding a specific LLEl in a specific Lnkdlst,
default-action if LLEl not exist. example code:
>>
  tstLnkdlstEl*     pstLL;              /* the current element */
  const char*       myStr;
  ..
  pstLL= lnkdlst_searchLLElbyID( pstListRootPtr, 1, 0); /*
  * arg1:   search for a LLEl in 'pstListRootPtr' with a specific ID
  * arg2:   1 -> search for an LLEl with the specific ID 1
  * arg3:   0 -> search for arg2 as the complete ID in the LLEl
  *         (LLEl.ID == 1), if pstLL is not NULL after calling
  */
  if( pstLL!=NULL) {
        do-something-with-this-LLEl-with-ID1( pstLL );
        myStr= (const char*) pst->pValue;
  }
  else {
        myStr= "default-info/-data";
  }
  do-something-with-the-myString( myStr );
  ..
<<

Usage in checking a list with a dedicated struct var in pValue, to get 
at least one element with a specific flag set. example code:
>>
  typedef struct {
    unsigned    flags;
  #define HIGH_TEMPERATURE_SFlag        0x8000
    ..
  } tstSensorData;
  ..
  int checkHighTempflag( tstLnkdlstEl* pstRootP)
  {
        tstLnkdlstEl*     pstLoopLL;          /* the current element in the Lnkdlst loop */
        tstSensorData*    pstSensor;
        
        LNKDLST_FORLOOP_OVERALLLLEL( pstRootP, pstLoopLL)  {
            pstSensor= (tstSensorData*) pstLL->pValue;
            if( pstSensor->flags & HIGH_TEMPERATURE_SFlag) {
                return 1;               /*1* we got a HighTemp. flagged element */
            }
        }
        return 0 ;                      /*0* not one Sensor-element flagged HighTemp. */
  }
  ..
        if( checkHighTempflag( pstListRootPtr)) {
            printf("ATTENTION: we got a heating issue - cool it down\n");
        }
  ..
<<
--


4. Free one element which is not longer used in a working list
If an element is no longer needed (e.g. if this represents an attribut which 
has to be removed), it could be easily removed.

Free an element. example code only for dyn.memory usage:
>>
    int            iRC;                 /* for error-checking */
    tstLnkdlstEl*  pstLL;               /* the current element */
    ..
    /* get the 2nd LLEl in the list (1 == 2-1) */
    pstLL= lnkdlst_getp2LLElWithNumX( pstListRootPtr, 1);
    ..
    if( pstLL!=NULL) {
        lnkdlst_deleteAfreeLLEl( &iRC, &pstListRootPtr, pstLL, 0);
        if( iRC!=0) {
            printf("ERROR: issue due to inconsistend list (%d) - abort\n", iRC);
            exit(1);
        }
    }
    ..
<<
-
The delete action removes/unlinks the LLEl from the given list (by p2 RootP).
The special dyn.mem fn lnkdlst_deleteAfreeLLEl() additonal frees afterwards the 
LLEl memory, due to the fact that this should be malloc-memory (given - for 
instance - by calling of fn lnkdlst_memallocateAappendLLEl()).
--


5. Optionally clean Lnkdlst before the lifetime of the list ends
Especial for dynamically created and deleted lists, the list should be 
freed if lifetime of the list ends.

Free elements of complete list. example code only for dyn.memory usage:
>>

    int            iRC;
    tstLnkdlstEl*  pstLL;               /* the current element */
    ..
    while(( pstLL= pstListRootPtr)!=NULL) {
        lnkdlst_deleteAfreeLLEl( &iRC, &pstListRootPtr, pstLL, 0);
        assert(iRC==0);
    };
<<
--
-------------------------------------------------------------------------------
  




### debug facilities

There are many debug possibilities build in.
You have to switch it on. And off usually for a release-version.

Before: if you want to read the lnkdlst C-code more clearly (without debug),
try 
> make lnkdlstDCfree
< and you'll get the debug-free code in folder ..code/test/debugcodefree/.
This may be very much easier to get an idea what happens in the code  ;-).


The newest debug-feature in Lnkdlst (>0.3.2) is switchable via define 
>> LNKDLST_DEBUG_CHECK <<.
This checks valid root-ptr and valid LLEls, if set to a value >0. 
But if you use own memory for LLEls (in Basic feature set only this is 
available), you had to insert some Debug Macros in your code, if you want to 
use LNKDLST_DEBUG_CHECK.
If you create a LLEl which is usable afterwards, set them as a valid LLEl with 
>> DCLNKDLST_SET_VALIDATION(pLLEl) <<.
This macro could be still left in your code either if this debug-feature is 
enable or not; a dummy macro exist in disable case.
-
If you like to make some LLEl unusable, because - for instance - the 
corresponding malloc-memory will be freed in a short time, you should declare 
the LLEls invalid with macro 
>> DCLNKDLST_CLR_VALIDATION(pLLEl) <<.
This should be used either if the memory is not lost (reserved static variables) 
or if is was malloc-memory (this may be invalid either, but not directly after 
freeing ths LLEl).
For automem Lnkdlst and OAList01 features this has not to be done; this 
features supports (alloc/free) the LLEls implicite and the Validation Macros 
are already included.
-
Also you MUST use the Lnkdlst INIT macro LNKDLST_INIT_ROOTPTR() and - if you 
like to destroy a Lnkdlst during run-time - the DEINIT macro. 
This costs a little time, but every access at a Lnkdlst and LLEls for 
linking and unlinking is checked. (After disabling this needs no plus time, 
of course).
 
Hence, if you afterwards use a wrong Root-Ptr  or  if you try to link an 
already linked LLEl a second time without pre unlinking, you got a run-time 
abortion.

---

All debug features are marked with the pre-text DC; all of thes Macros (...) 
you could ignore if you like to understand the inside programming (@1st).

To make it more easier to have a better overview of the real functions 
you could create a Debug-Free version of Lnkdlst; use 
"make test/lnkdlst-debfree.c". 

TODO: check this, wio, use /*DC*/ before any DC-~fn~-

-------------------------------------------------------------------------------



### testing
gen-info:
    > xyz   -> this means, enter xyz in a command-line window. short: in a CLI
            which stands for Command-Line-Interface (a type of a 
            Computer user-interface,UI).
            e.g. "> ./maintest 1".
            CLI will also be used in short for the CLI window/screen.
            Could be directly started (ubuntu for instance by holding keys 
            <Alt> + <Ctrl>, than press <T> {for Terminal}. more ways possible, 
            e.g. remote via ssh).
            This is now only described for linux/POSIX systems. There is no 
            integration and test done for windows, sry. May be only a ticker 
            is needed, but the tests based on linux systems.
            Test-Execution may take a lot of time; be patient. Although, if 
            output is not redirected, the time to display a new line or show 
            some changes in the CLI should not be more than 2 minutes.
            -
    <-> blabla
            -> this means, blabla is the expected result of the test before.
            "ok" means, the command returns with 0 exit code (
            in linux checkable by entering > echo $? <; in windows 
            by entering > echo %ERRORLEVEL% <).
            -
    i:      -> this means, behind i: is only some additional info which may 
            help in understanding.
            -
    preset  -> before testing at all use 
            > make clean
            <. Just before starting the tests do this.
            -
    Hint:   -> you could insert "BUILD_TYPE=RELEASE" before any make, which 
            disables all debug-code.
            -
    --

Lnkdlst-test-info:
    ++  maintest  ++
    subj    
        a small enhancable test programm, currently with upto 6 sub tests
    make
        > make maintest                 - currently std. tests containing (not #6)
        or
        > make ADD6_CPP=YES maintest    - add maintest#6 with CPP threads
        alternativly you could use ADD6_PT=YES for pthread-using
    using
        > ./maintest X  [options]       - X=1..5 (6 with ADD6_xx YES)
        options: depends on test, may be no option available
    help
        a.  read code, maintest.c & testXX.c (may be .cpp too)
        b.  only german language (DE)
            > ./maintest X help
            example:
            > ./maintest 3 -p 999       - print without delaying and time print out 
    ---
    
    ++  autotest-C.sh  ++
    subj
        a test-shell script which tests smth via maintest automatically
        optional you could build specific 'maintest' executables
    make
        if maintest exist there is no make necessary.
        with using option 
        - deb1      for std. debug or
        - debF      for more debug or
        - rel       for release, without debug usually
        maintest will be build automatically
    restrictions
        currently only for MACOS and linux
    using
        > ./autotest-C.sh [ deb1 | debF | rel ]
    help
        no help.
        read script and maintest help to know what is done.
    ---

++  short tests before a new release (linux & MACOS)  ++

1.
    > make clean
    <-> ok
    > ./multivaricall.sh  autotest-C.sh  debF rel
    <-> ok
    --
2.
    > make maintestDF
    <-> ok
    > ./maintest 3 -p 999
    <-> ok
    --
3.
    > make lnkdlst
    <-> ok
    > ./llIm
    <-> ok
    --
4.
    > TESTNO=1 make tutor
    <-> ok
    > ./tutor ...
    <-> the tutor works, shows at first some info.
        With key <Enter> the tutor info is showed more and more.
    > rm tutor
    <-> ok
    > ls tutor
    <-> the executable 'tutor' is not seen in the directory list.
    -
    > TESTNO=2 make tutor
    <-> ok
    > ./tutor
    <-> ok (this tutor is without dialog with <Enter> key pressing)
    <-> some output is produced on the CLI
    > rm tutor
    <-> ok
    > ls tutor
    <-> the executable 'tutor' is not seen in the directory list.
    -
    > TESTNO=3 make tutor
    <-> ok
    > ./tutor ...
    <-> the tutor works, shows at first some info.
        With key <Enter> the tutor info is showed more and more.
    <-> ok
    > rm tutor 
    <-> ok
    > ls tutor
    <-> the executable 'tutor' is not seen in the directory list.
    -
    > TESTNO=4 make tutor
    <-> ok
    > ./tutor ...
    <-> the tutor works, shows at first some info.
        With key <Enter> the tutor info is showed more and more.
    <-> ok
    > rm tutor 
    <-> ok
    > ls tutor
    <-> the executable 'tutor' is not seen in the directory list.
    --
5.
    > make cppmaintest
    <-> ok
    > ./cppmaintest t
    <-> ok
    --
6.
    > make clean
    <-> ok
    > make methr_itest
    <-> ok
    > ./myeasythread_itest
    <-> ok
    --
7.
    > make jmaintest
    <-> ok
    > ./jmaintest.sh t
    > make clean
    --
---

+    
-------------------------------------------------------------------------------



### old readme
--- Lnkdlst ---              A single-sided-linked-list feature set


The main code is in programming language  C  ! 
(Folders inc/ & src/, synonym for C feature: lnkdlst)
See "Additional Support" for further programming languages.

For  function-overview  see readme-section in lnkdlst.c.

For inhere given C-tests the sub-folders inc/, src/ and test/ are valid, 
"make maintest" for instance and 
run tests with "./maintest <test-number>".  (In folder ..Lnkdlst/code/ o.c.) 
An additional argument  [help]  behind the test-number may gave information, 
currently in german only (may someone want to translate..?). 
test-~number~ 't' for temporary tests.
make cppmaintest    -> start CPP tests with > ./cppmaintest ...
make jmaintest      -> start java tests with > ./jmaintest.sh ...
{Tests usually done for C, for CPP&java not very much given!}

Folder test/ do not contain files which are necessary to use lnkdlst 
feature in your own code.

-

Additional Support:

*   C++, step1
    Gives feature "class LnkdLst", fns similar to those in C-lnkdlst, basic.
    Automatic mem-alloc possible, static mem for LLEls either.
    -
    Sub-folder cpp/ contains additional files. 
    Additional means: These files needed additional to the C-lnkdlst files.
    In 1st step it is not possible to use C++ files stand-alone;
    C-files for lnkdlst are needed too to be compiled in the same 
    project. 
    Reason -> many C++ functions based upon the C functions 
    due to have not much new functions and effort.
    Side effect: you can use both - class LnkdLst in C++ code and 
    feature lnkdlst in C code.
    -
    Tests are possible via own cpp test file(s): test/maintest.cpp (+ testX.cpp)
    (build with "make cppmaintest" & run with "./cppmaintest <test-number>",
    test-number := t  for special own tests).

*   java, step1
    Gives feature "class LnkdLst", fns similar to those in C++-LnkdLst.
    Automatic mem-alloc possible - called automem mode, static mem for LLEls 
    (and members) either.
    .
    Needs "class LnkdLstEl" for one LLEl to handle.
    -
    Sub-folder java/  without folder java/test/  contains .java files to 
    support this feature.
    - 
    Tests are possible via own java test file(s): java/test/maintest.java 
    (+ TestX.java)
    (build with "make jmaintest" & run with "./jmaintest.sh <test-number>",
    test-number := t  for special own tests).
    
*/*


### 
---
-------------------------------------------------------------------------------
Source: uws-Lnkdlst-readme.txt, updated 2022-11-22