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).
*/*
###
---
-------------------------------------------------------------------------------