LZLE List Engine with user friendly powerfull syntax - BETA 0.994 -

User projects written in or related to FreeBASIC.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

LZLE List Engine with user friendly powerfull syntax - BETA 0.994 -

Postby Lost Zergling » Mar 26, 2018 16:10

Hi everybody !

Here is the latest version of LZLE. I hope it can help you. To use it copy-paste source code part 1 & 2 & 3 and save in LZLE.bi
Product specifications :
1) The goal is to integrate the product via a library as a real extension of the programming language: if it is already difficult to code a set of instructions, it is even more difficult to do it by consuming quite a few resources compared to the same specifically integrated code.
2) Languages ​​like Python or Java use their own syntax to manipulate memory intuitively. It is not a question here of copying the syntax of languages ​​admittedly called free but at the same time competitors, but to try to create our own syntax, original and adapted to the spirit of FB language. The syntax conditions the working method of the programmer while being the tool he uses: creating a set of instructions is also creating a tool and designing the working method (programming style) that goes with it.
3) The product must be written entirely in basic and basic standard instructions without the need for libraries, thus freeing itself from any external license constraints but also and above all from any integration constraints linked to the language (the product is linked to the Basic language because it is designed for it, but it is not necessary to modify the compiler to extend its capabilities) (it is a library but a library of keywords with the ability to integrate naturally the native instructions of the language as if natively coded in). The product can thus be adopted by a developer without constraints of versions, limitations, etc.
4 °) The product is an object architecture whose performances shall be little degraded compared to c language
5 °) The instruction set must be easy enough to understand and use while being able to simply propose extended and complex functionalities, RAD spirit compliant.
Documentation is here : https://freebasic.net/forum/viewtopic.php?f=9&t=26551
Suggestions, ideas, bugs report or features requests welcomes here : https://freebasic.net/forum/viewtopic.php?f=2&t=26637

New version Beta 0.993 : (06/2019)
What's new ?
- Dim Shared gCollector As List : Centralization of nodes / memory addresses to recycle (*)
- Several small bugs fixes (kinematic of keywords leading to a crash)(rare).
- Sort feature optimised and using gCollector (sorting nodes in memory) (*).
- New Parsers : nKeyStep & nKeyStepRev : parsing a TRI (retrieve) (cascaded string order) in numeric order (*).
(*)=> will be used especially by array extensions

New version Beta 0.994 : (07/2019)
New features
- Few bug fixes in kinematics (snatch)
- RestoreHash and HasKey now supports Multi-keys features :
can restore a multi key index from flat list, can parse MultiKey tree using while MyList.HasKey("key")
- NodeFlat can target last created entry in tree without having to Root : MyList.HashTag("LastKey") : MyList.NodeFlat does not crash
- Minimum requirements for LZAE (array extensions). Ones may have look to LZAE(https://freebasic.net/forum/viewtopic.php?f=8&t=27695) to get exemples of use of the new features. (ps : Although distinct, lzae must be seen as a "companion" software that establishes a link in terms of integration between lzle lists and FB arrays, between a non-contiguous indexed organization and contiguous direct access. Lzae targets integration with related uses: matrix, data presentation interface and so on).

Code PART 1/3 :

Code: Select all

' NOTICE : Thank you to remove first single quote on the line below once you accepted the licence.
 /'   In case redistribution of SOURCES you may ensure to reactivate the acceptance of the license. This notice may be anywhere in source code till licensed user is aware it exists.
CONST PRODUCT_LIC =_
"_______________________________________________________________________________" & chr(10) &_
"  LZListsEngine/ListsVM by Etienne Carfagnini - contact:etienne.carfa@gmail.com" & chr(10) &_
"  Bd Henri Barbusse 92700 Colombes France 01 46 49 99 02" & chr(10) &_
"-------------------------------------------------------------------------------"  & chr(10) &_
"  This Freeware/Openware licence specify the rights to use the software" & chr(10) &_
"* Distribution of derivating software : " & chr(10) & "  The information access to the original software must be guaranteed to" & chr(10) & "  developers and users (https://freebasic.net/forum/ or alternative mentionned)" & chr(10) &_
"* Right to use the software and its derivating : 2 options : " & chr(10) & " >OPTION 1 (Openware) :"  & chr(10) & "  The software is free for any use (under FreeBasic)." & chr(10) &_
"  'LZLE Openware licence' is mentionned in licence contributors." & chr(10) &_
"  The software must be compiled using any official GPL FreeBasic Compiler." & chr(10) & "  https://freebasic.net/forum/viewforum.php?f=1 Or" & chr(10) & "  http://users.freebasic-portal.de/stw/builds/)" & chr(10) &_
" >OPTION 2 (Freeware) (any language) :"  & chr(10) & "  The software is free for any use except the following limitation as to its"  & chr(10) & "  fields of application : not for use on virtual machine or on virtual server." & chr(10) &_
"  'LZLE Freeware licence' is mentionned in licence contributors." & chr(10) &_
"* Apart from the restrictions of use (options 1 and 2) which are not compatible"  & chr(10) & "  with the rights of uses specified in clause 5.1, the legal clauses whenever"  & chr(10) &_
"  compatible will be those specified by the CeCILL-C license"  & chr(10) & "  ( http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt )" & chr(10) &_
"  Disclaimer :"  & chr(10) & "  This licence refers to CeCILL-C but is NOT a CeCILL-C because the right to"  & chr(10) & "  use the software with no restriction is limited to the FreeBasic ecosystem." & chr(10) &_
"  This because it aims to be an extension of the language instructions set."  & chr(10) &_
"  LZLE (instruction set architecture,coding style) is dedicated to FreeBasic."  & chr(10) &_
"  This notice constitutes a whole that must be present in the source code." & chr(10) &_
"-------------------------------------------------------------------------------"  & chr(10) &_
"  Cette licence Freeware/Openware precise les droits a utiliser le logiciel" & chr(10) &_
"* Distribution de logiciels derives :" & chr(10) & "  L'acces informatif au logiciel original doit etre garanti aux" & chr(10) & "  developpeurs et aux utilisateurs (https://freebasic.net/forum/ ou autre)." & chr(10) &_
"* Droit d'utiliser le logiciel et ses derives : 2 options : " & chr(10) & " >OPTION 1 (Libre) :"  & chr(10) & "  Le logiciel est gratuit pour toute utilisation (sous FreeBasic)." & chr(10) &_
"  'LZLE licence Openware' est mentionne dans les contributions." & chr(10) &_
"  Le logiciel doit etre compile en utilisant n'importe quel compilateur GPL" & chr(10) & "  FreeBasic 'officiel' " & chr(10) & "  https://freebasic.net/forum/viewforum.php?f=1 ou bien" & chr(10) & "  http://users.freebasic-portal.de/stw/builds/" & chr(10) &_
" >OPTION 2 (Gratuiciel) (tout langage):"  & chr(10) & "  Le logiciel est gratuit pour tout usage sauf la limitation suivante quant a"  & chr(10) & "  son champs d'application : pas d'utilisation sur machine ou serveur virtuel." & chr(10) &_
"  'LZLE licence Freeware' est mentionne dans les contributions." & chr(10) &_
"* En dehors des restrictions d'utilisation (options 1 et 2) lesquelles ne sont "  & chr(10) & "  pas compatibles avec les droits d'utilisation prevus a la clause 5.1, les"  & chr(10) &_
"  clauses applicables seront celles compatibles specifiees par la licence"  & chr(10) & "  CeCILL-C ( http://www.cecill.info/licences/Licence_CeCILL-C_V1-fr.txt )" & chr(10) &_
"  Avertissement :"  & chr(10) & "  Cette licence fait reference a la licence CeCILL-C mais n'en est PAS une car"  & chr(10) & "  le droit a utiliser librement le logiciel est limite a l'ecosysteme FreeBasic" & chr(10) &_
"  Ce moteur de liste a jeu d'instructions est dedie au langage FreeBasic" & chr(10) &_
"  Cette notice constitue un tout lequel doit etre present dans le code source." & chr(10) &_
"_______________________________________________________________________________"
Dim k As String
Print PRODUCT_LIC : Print
Print "Please press 'Y' (Yes) to accept the licence or Esc to abort"
Print "Merci d'appuyer sur 'O' (Oui) pour accepter la licence ou echap pour annuler"
Do : k = Inkey : Select Case k : Case "Y" : Exit Do : Case "y" : Exit Do : Case "O" : Exit Do : Case "o" : Exit Do : Case Chr(27) : System : End Select : Loop
Print "Removing first single quote on line 2 in source code will activate the licence" : Print "Retirer la premiere simple quote en ligne 2 du code source activera la licence" : Print "Thank you for chosing this software - Merci d'avoir choisi ce logiciel" : Print
'/ ' END NOTICE

Dim Shared As uInteger AllocateDeallocateCounter=0
Function _Callocate(Byval n As Integer) As Any Ptr : AllocateDeallocateCounter += 1 : Return Callocate(n) : End Function
Sub _Deallocate(Byval p As Any Ptr) : AllocateDeallocateCounter -= 1 : Deallocate(p) : End Sub

CONST MAX_KEYLEN=50
CONST RUP_COLS=2 : CONST MAX_COLS=7 : CONST MAX_TRACKS=20 ' RUP_COLS = ListNode ArraySize / MAX_COLS = Extended range ListNode ArraySize / MAX_TRACKS = all tracks are on a same single track beware not to overwrite elements otherwise overwritten track will be rerouted
CONST LIST_RES=Chr(18) : CONST LIST_DEL=Chr(3)  : CONST LIST_ROOT=Chr(4)

Type ListContainer 'Data Segment Level
    Dim str_tag_C(RUP_COLS+1 to MAX_COLS-1) As String
    Dim str_item as String : Dim pNextContainer as ListContainer Ptr
End Type
Type ListNode 'ListNode Level
    Dim Tag(0 to RUP_COLS) As String : Dim As ListContainer Ptr ListData : Dim  As ListNode Ptr pNext, pPrev, pBranch, pBranchLastNode : Dim BranchCount As uInteger=0
End Type
Type ListContext ' Branch context Level   
    Dim  As ListNode Ptr pNode, pFirstNode, pLastNode : Dim As String LcHashTag : Dim  As uInteger  uCount : Dim As uByte bLcHashLen
End Type

Type List
    Declare Constructor() : Declare Destructor()   
   
    Private:
    Dim As zString Ptr Listptemp=_Callocate(MAX_KEYLEN), Listptemp2=_Callocate(MAX_KEYLEN), zp3=_Callocate(1)
    Dim  As ListContext Lcontext(0 to MAX_COLS-1), Tracks(0 to MAX_COLS-1)
    Dim As ListNode Ptr pNode, pFirstNode, pLastNode, pFirstFIRSTNode, pLastLASTNode, pGarbage, pEndFlat, pLocalRoot, pLocalMove, pWhyteMove, pFlatRoot, pSearchNode, pValTmp, TrackTrace(0 to MAX_COLS-1), pLatestHTag
    Dim As ListContainer Ptr pPanCakeGarbage, pLastPanCake
    Dim As uInteger uNodeCOUNT, uGarbCt, uCount, uContainerGarbCt,  uContainerGivenCt, PVS_Count=0, KR_Count=0 ' uSortThreshold=300 ', iLenDelta  ', iLenStrTmp, iLenpNode, iLenCumul, iLenDiff
    Dim As Byte uTag=0, bSearchRes=0, bRHByPass=0, bHashStepRev=0, bfStepZero=0, bTrackingMethod=0, bTracking=0, bHTMethod=1, bHashKeyUnique=1, uSortTag=0,_
                        bSortMT=1, bNFmethod=1, bRHmethod=-1, bAutoCursor=1, bSeekMethod=2, bBranchCountDown=0, bPickReduce=0, bCopyCatMethod=0, bCopyCatRelation=0,_
                        bColBcountLocked=0, bColTrackLocked=0, bAlrdyTracked=0, bSnatchBLMethod=0, bHStepTrace=0, bTrackMultiKeys=1, bPVSmethod=-1, bnStepByPass=0
                       
    Dim As uByte bHashLen=1, IsDestroyed=0, PVS_ratio=3, ubKeysRegister=0, uB_CurLevel=1, uB_Level=1, uB_KeyStepCumul=1, uB_MaxLevel=1, uB_BottomLevel=255, uB_BottomByPass=0, uB_tmp ', nbloops=0
    Dim As String  sSearchTag, sLatestHTag, Str_tmp, str_arbo , Str_tmp2, str_testTMP, sMV_Tag
    Declare Property AllowCake() As ListNode Ptr                      ' Cooking here
    Declare Property AllowPanCake() As ListContainer Ptr          ' No comment
    Declare Property AllRecycle() As uInteger   
    Declare Property Branch() As Byte                                        ' Descend dans la liste enfants, creation de nouvelles entrées
    Declare Property UpLevel() As Byte                                      ' Revient à la liste parente   
    Declare Property NodeRecycle() as Byte                              ' Supression en décalé (NodeFlat)
    Declare Property NodeRecycle2() as Byte                            ' Supression en décalé (RestoreHash)
    Declare Property RootPrivate As Byte                                   ' Accès direct rapide à la racine
    Declare Property FlatStack(uB as uByte) As Byte                 ' Construction de la Flat List avec retour à la racine(0) ou accès à la flat liste (1)
    Declare Property BCountDown(i As Byte) As Byte                ' CountDown calculation   
    Declare Property ValPrivate(str_Value As String) As Byte
    Declare Property ValPrivate As String
    Declare Property AllOfPrivate As uInteger
    Declare Property TrackCompute As Byte
    Declare Property HashStepTrace As Byte                              ' Required by Sort (for optimization)   
   
    Public:   
    'Special features - Private declared Public   
    Declare Property SetRelation(by as Byte) as Byte
    Declare Property SetRelation1(pRelNode As ListNode Ptr) As ListNode Ptr
    Declare Property SetRelation2(pRelFirstNode As ListNode Ptr) As ListNode Ptr
    Declare Property Relation As ListNode Ptr   
    Declare Property GiveBranchDown As ListNode Ptr
    Declare Property GiveBranch As ListNode Ptr
    Declare Property GiveFlat As ListNode Ptr
    Declare Property GiveGarbage As ListNode Ptr
    Declare Property GivePanCake As ListContainer Ptr
    Declare Property GiveLastPanCake As ListContainer Ptr
    Declare Property GivePanCakeCount As uInteger
    'Flat control
    Declare Property Tag(str_Tag As String) As Byte                 ' Create a new ListNode with Key=str_Tag OR retrieve position of an existing Tag
    Declare Property Tag As String                                            ' Return current Tag value in a list =Tag(0)
    Declare Property Tag(iTag As Integer) As String                  ' Return current Tag value of the specified entry in array
    Declare Property HasTag(str_Tag As String) As Byte           ' Return 1 if Tag exists
    Declare Property BlindTag(str_Tag As String) As Byte          ' Create a new ListNode with Key=str_Tag at end of the list
    Declare Property RwTag(s_Tag As String) As Byte               ' Rewrite Tag Value of current Node : if current node is Hashed, just rewrite HashTag Value not effective Key value
    Declare Property RwTag0(s_Tag As String) As Byte                ' Rewrite Tag Value(0)
    Declare Property RwTag1(s_Tag As String) As Byte                ' Rewrite Tag Value(1) => eqivalent to MyList.ColTags(1) : MyList.RwTag("Label") : MyList.ColTags(0)
    Declare Property RwTag2(s_Tag As String) As Byte                ' Rewrite Tag Value(2)
    Declare Property RwTag3(s_Tag As String) As Byte                ' Rewrite Tag Value(3)
    Declare Property RwTag4(s_Tag As String) As Byte                ' Rewrite Tag Value(4)
    Declare Property ColTags As Byte                                       ' Renvoie le numéro de la colonne de tag active       
    Declare Property ColTags(i as Byte) As Byte                        ' Définie la colonne de tag active de 0 à MAX_COLS, par défaut 0   
    Declare Property AllOf As uInteger                                       ' Return number of node in  considered Flat List (root or branch), set position to the first node of current branch
    Declare Property Count As uInteger                                     ' Return current node Count of considered Flat List
    Declare Property First As Byte                                              'Set current node to first node considering flat list (root or branch)   
    Declare Property Last As Byte                                              'Set current node to Last node considering flat list (root or branch)       
    Declare Property Val(str_value As String) As Byte                ' Assign a string (+50 len) to the current node that is identified by a Tag
    Declare Property Val As String                                             ' Return current node string datas   
    Declare Property ValTag(str_value As String) As String        ' Considering current Flat list (root or branch as a flat list) return string data identified by Key=str_Tag
    Declare Property fStep As Byte                                            ' FOR EACH - While MyList.fStep : .. : Wend Jump to next node till current flat list end
    Declare Property fStepRev As Byte                                     ' FOR EACH - Idem fStep Jump to previous node till current flat list reach firstnode
    Declare Property bStep As Byte                                           ' FOR NEXT - For i=1 to MyList.AllOf : MyList.bStep : ..... : Next i    -> Jump to next node (NO CHECK)
    Declare Property BlindStep As Byte                                     ' FOR EACH - While MyList.BlindStep : .. : Wend -And- FOR NEXT - For i=1 to MyList.AllOf : MyList.BlindStep : ..... : Next i  Jump to next node  (check)   
    Declare Property BlindStep(i As Integer) As Byte                  ' Jump to +/-n nodes BlindStep(0) equiv Last : goto LastNode  (NO CHECK)
    Declare Property fMove(i As Integer) As Byte                      ' Move a node +/- n positions
    'Sorting
    Declare Property ColSort(i as Byte) As Byte                          'The column number to sort on (0-n) col 0 is indexed. Définie la colonne de tri active de 0 à MAX_COLS, par défaut 0
    Declare Property fSortMethod(bsortM As Byte) As Byte        'FLAT  1=ascending / -1=descending
    Declare Property fSort As Byte                                              'FLAT sort
    Declare Property HashSort(ub as Byte) as Byte                   '0=No sort on mapping, 1=ascending sort on HashTag mapping or on RestoreHash remapping
    Declare Property Sort As Byte
    Declare Property Sort(bSortmt As Byte) As Byte                  ' CASCADED : 1=ascending / -1=descending : sort(-1) returns a sorted list that is same result as sort(1)+HashStepRev except that sort impacts in memory tree structure
    'Hash control handling
    Declare Property Root As Byte                                           ' Check/Restore List integrity & set cursor to First node of root flat list - Shall be called before HashStep or After NodeFlat or RestoreHash
    Declare Property FlatStack As Byte                                    ' Flat List Access : use it before RestoreHash
    Declare Property RootNode As Byte                                  ' Set cursor to Root node of root flat list
    Declare Property EndNode As Byte                                   ' Set cursor to the last logical node  ( = While MyList.HashStep : Wend ) which is the last node of the last branch of last root flat node
    Declare Property HashStep As Byte                                   ' FOR EACH - recursive  parse property : syntax : While MyList.HashStep=1 : ... : Wend
    Declare Property HashStepRev As Byte                            ' FOR EACH - idem HashStep
    Declare Property KeyStep As Byte                                      ' FOR EACH - While MyList.KeyStep=1 : ... : Wend idem HashStep but show only Keys tagged by user, not the tree structure
    Declare Property KeyStepRev As Byte                               ' FOR EACH - idem KeyStep
    Declare Property nCurLevel(t as uByte) As Byte                 ' used by numericKeyStep & numericKeyStepRev
    Declare Property nHashStep(t as uByte) As Byte                ' used by numericKeyStep
    Declare Property nKeyStep(t as uByte) As Byte                  ' used by numericKeyStep
    Declare Property nKeyStep As Byte                                   ' numericKeyStep : numeric order
    Declare Property nHashStepRev(t as uByte) As Byte        ' used by numericKeyStepRev
    Declare Property nKeyStepRev(t as uByte) As Byte           ' used by numericKeyStepRev
    Declare Property nKeyStepRev as Byte                             ' numericKeyStepRev : numeric order
    Declare Property HashTag(str_Tag As String) As Byte       ' Build a hash Key on str_Tag, Return 1 if already exits otherwise return 0   
    Declare Property HashTag As String                                  ' Return Hash key value of current node 
    Declare Property HasHashTag(str_Tag As String) As Byte ' Return 1 if str_Tag is a hash key otherwise return 0
    Declare Property HasKey(str_Tag As String) As Byte          ' Idem HasHashTag Return 1 only for values specified with HashTag (not all cascaded index values)
    Declare Property NodeFlat As Byte                                   ' Déréférence une arborescence de clefs (un HashTag), et traite les données en conséquence       
    Declare Property RestoreHash As Byte                             ' Envoi un node de la Flat List en Hash List (réindexation)
    'Hash Control - Object's properties parameters
    Declare Property AutoCursor(i As Byte) As Byte                 'Method for HasTag(string), HasHashTag and HasKey:  0=do nothing current node is unchanged,  1 -DEFAULT- =move current to found on success (HasHashTag), 2=move current to found on success (HasKey), 3=move on partial success
    Declare Property BranchCountDown(i As Byte) As Byte     ' 1/0 Activate(1) or desactivate(0) BranchCountDown, default 0
    Declare Property CopyCatMethod(i As Byte) As Byte          '0 or 1 : CopyCat(1) : tracking is using tracking (no HoldBack/track) OR CopyCat(0) : tracking to source is on BranchCount (no BranchCountDown enabled) but tracking possible inside index !
    Declare Property HashKeyUnique(ub as Byte) As Byte      ' Default=1  HashKeyUnique(0)=>HashTag always create a new key even though a key already exists
    Declare Property HashLen(bHashLen As uByte) As Byte  ' Longueur des clefs en cascade
    Declare Property KeysRegister(ub As uByte) As Byte         ' Enregistrement du hashTag parent en premier node caché : optimise l'enregistrement et la récupération de la clef (propriété hashTag) mais ralenti le mapping hashTag("key")
    Declare Property NFmethod(i As Byte) As Byte                  ' Determine le fonctionnement de NodeFlat : NFmethod=-1 node=>GarbageCollector  NFmethod=0 node=>FlatList sauf parents reliquataires NFmethod=1 node=>FlatList même les nodes parents contenant toujours des dépendances
    Declare Property NFrecursive(i As Byte) As Byte               ' NFrecursive=0 Standard / NFrecursive=1 parents nodes auto send to garbage collector till no other child and till they are not keys
    Declare Property PVSmethod(ub As Byte) As Byte            ' Predictive Vectors Static (optimization algo for HashTag) -1=no PVS / disabled (default), 0= PVS on, 1=PVS with priority forced
    Declare Property PVSratio(ub As uByte) As Byte               ' Static coeff for PVS dynamic adjustement
    Declare Property RHmethod(i As Byte) As Byte                 ' Determine le fonctionnement de RestoreHash par rapport aux doublons : RHmethod=-1 : Hashnode->GarbageCollector  / RHmethod=0 : no swap / RHmethod=1 : Hashnode->FlatList - RHmethod has no effect on multivalues lists ( HashKeyUnique(0) )
    Declare Property SeekMethod(i as Byte) As Byte              ' Method for Tag(string), HasTag(string), HashTag(string), HasHashTag and HasKey: 1(default)=seek from First to Last | 2: seek from Lastnode to firstNode | 0 :seek from currentnode to last node (Flat multikeys)
    Declare Property SnatchBLmethod(i As Byte) As Byte      ' For SnatchBelow 0=Source ParentNode snatched below target / 1=Source Child Nodes snatched below target (leaving ex-parent node in source list) (for intuitive key pairing between source & target)
    Declare Property TrackMethod(by As Byte) As Byte          ' MyList.TrackMethod(0)=might be faster (Default) / MyList.TrackMethod(1)=slow, might be more secure in specific cases (Pretty useless)
    Declare Property TrackMultiKeys(uB as uByte) As Byte    ' If <>0 multikeys will be automatically tracked (Track & TrackStep) on specified track each HashTag : working with CopyCat and RestoreHash as well
    Declare Property VectorUnlock As Byte                            ' Unlock auto security : Track vector is ONE choice between HoldBack/Track OR CopyCatMethod(1)/Follow - BranchCount vector is ONE choice between CopyCatMethod(0)/Follow OR BranchCountDown(1) OR PVSmethod(1+) - Using CopyCat index let you one choice left between Tracking, CountDown or PVS optimization
    Declare Property VectorClear As Byte                               ' If list structure has been changed (ie snatch, NodeFlat), tracking links or others (count down, PVS, or Follow) might be corrupted : working like CopyCat targeting current node and the whole child tree, clearing corrupted (or so called) links
    'Flow control
    Declare Property BranchCount As uInteger                        'Return Branch Count
    Declare Property Up As Byte                                              'idem UpLevel
    Declare Property Down As Byte                                         'idem Branch but prevent from creating an orphan sublist entry   
    Declare Property HoldBack As Byte                                  ' Works with Track : First Holback is initialiazing tracking, then each HolBack is recording a new tracked node. Track indicates to set cursor to first holbacked node & TrackStep is tracking all holbacked nodes in chronological order
    Declare Property HoldBack(i As Byte) As Byte                  ' Works with Track : indicates the number the track working with
    Declare Property TrackStep As Byte                                ' -SELECTIVE- FOR EACH - While MyList.TrackStep=1 : ... : Wend : selective PARSE only Keys marked for tracking by HoldBack
    Declare Property Track As Byte                                      ' Set track pointer to first tracked node
    Declare Property Track(i As Byte) As Byte                       ' Only one track but several track pointers
    Declare Property TrackSet As Byte                                 ' Create a breaking point in tracking : next List.Track+TrackStep will iterate from next tracked node just following breaking point / does not break track list, just replacing track starting point
    Declare Property TrackSet(i As Byte) As Byte
    Declare Property IsTracked As Byte                                ' When working with several tracks (pointers) it can be usefull to know wether a node has been already tracked or not to control tracking overwrite
    Declare Property TrackClear As Byte
    Declare Property TrackClear(i As Byte) As Byte              ' Indicates to reinitialize Track n°i : next HolBack will initialize a track to current node
    Declare Property Aside As Byte                                      ' Memorise ListNode ptr dans le pointeur n°0
    Declare Property Aside(i As Byte) As Byte                       ' Memorise ListNode ptr dans le pointeur n°i
    Declare Property Recover As Byte                                 ' Repositionne l'élément courant de la liste sur celui mémorisé par Take, si cet élément existe toujours, sinon renvoie False
    Declare Property Recover(i As Byte) As Byte                  ' Repositionne l'élément courant de la liste sur celui mémorisé par Take(i)
    Declare Property Follow(pList As List) As Byte
    'Memory management
    Declare Property FlatCount As uInteger                         ' Return number of values stored in Flat List
    Declare Property GarbageCount As uInteger                 ' Return number of nodes available in garbage collector
    Declare Property ContainerCount As uInteger                ' Return number of nodes container available in hidden garbage collector
    Declare Property NodeCount As uInteger                      ' Return number of nodes including not visible ones
    Declare Property GarbageFlat As Byte                            'Send all Flat List to GarbageCollector
    Declare Property Recycle As uInteger                            'AllFlat+GarbageCollector : détruit une arborescence et envoi tout en GarabgeCollector - do NOT garbage protected flat list
    Declare Property DropAll As uInteger                              'Remove all elements in list, except a 5/6 listnodes subset                         
    Declare Property Destroy As Byte                                   'Manual destructor
    'List Data Links & Exchange   
    Declare Property Snatch(pList As List) As Byte                  'Snatch a whole branch from another List to next node
    Declare Property SnatchBelow(pList As List) As Byte        'Snatch a whole branch from another List Below current node
    Declare Property FlatSnatch(pList As List) As Byte            'Target's Flat list is transfered to current list
    Declare Property GarbageSnatch(pList As List) As Byte    'Target's Garbage Collector is transfered to current list
    Declare Property CopyCat(pList As List) As Byte                'Create an index (linked to source)  from a flat (node per node) or indexed column (if so current node + its whole child tree), element by element (auto support multivalues) can work from loops (filtering)   
    'Debug
  '  Declare Property NextNode As String       
  '  Declare Property PrevNode As String   
End Type
'Shared
Dim Shared gCollector As List
' Improvments : RestoreHash and HasKey now support Multivalues /  FlatSnatch : BugFix /
' to do : Code Review+doc /   CopyCat+HashStep KO / Check tracking / Check Snatch & Snatch Below /
' BUGs :
'
' Property List.NextNode As String : Dim str_tmp as string="-" : If pNode->pNext<>0 Then : this.Aside : pNode=pNode->pNext : str_tmp= "next tag=" & pNode->Tag(0) & " & next hashtag=" & this.HashTag : this.Recover : Return str_tmp : End If : End Property
' Property List.PrevNode As String : Dim str_tmp as string="-" : If pNode->pPrev<>0 Then : this.Aside : pNode=pNode->pPrev : str_tmp= " prev tag=" & pNode->Tag(0) & " & prev hashtag=" & this.HashTag  & "  branch=" & Str(pNode->pBranch) : this.Recover : Return str_tmp : End If : End Property

'==========================================================================================CONSTRUCTOR & DESTRUCTOR  :  this.pFirstNode->pBranch->pBranchLastNode=0
Constructor List
    pFlatRoot = _Callocate(Len(ListNode)) : pNode = _Callocate(Len(ListNode)) : this.uNodeCOUNT+=2  ' Moment angulaire(petite masse)
    pPanCakeGarbage=_Callocate(Len(ListContainer)) : pPanCakeGarbage->pNextContainer=pPanCakeGarbage ': pTestContainer=pPanCakeGarbage ' Moment Angulaire(petite masse)
    pFirstNode = pNode : pLastNode = pNode : bSeekMethod = 1 : uCount = 0 : uTag = 0 :     
    pFirstFIRSTNode = pNode : pLastLASTNode = pNode  : this.pFirstNode->BranchCount=0 : pNode->Tag(0) = LIST_RES     
    pFirstFIRSTNode->pNext=pFlatRoot : pFlatRoot->pPrev=pFirstFIRSTNode : pFlatRoot->Tag(0)=LIST_ROOT
    this.Root : this.AllOf
End Constructor
Destructor List : this.Destroy : End Destructor

'==========================================================================================TYPE LIST PRIVATE PROPERTIES
Property List.AllowCake As ListNode Ptr ' This.Vralloc
    Dim pTemp as ListNode Ptr=pFlatRoot->pNext ' uGarbCt>1 ' If pTemp<>0 Then : If pTemp->pNext=0  Then  : pTemp=pGarbage : pTemp=_Callocate(Len(ListNode)) : this.uNodeCOUNT+=1 :  Return pTemp : End If  : End If
    If pTemp<>pGarbage Then : pFlatRoot->pNext=pTemp->pNext : pTemp->pNext->pPrev=pFlatRoot : This.uGarbCt-=1 : ' And pTemp<>0 ' pTemp->pNext=0 : pTemp->pPrev=0 : pTemp->pBranch=0 :
    Else : pTemp=_Callocate(Len(ListNode)) : this.uNodeCOUNT+=1 ': this.pLastLASTNode=pTemp ' Moment Angulaire(petite masse)         
    End If : Return pTemp
End Property
Property List.AllowPanCake As ListContainer Ptr
    Dim pPanTemp As ListContainer Ptr : dim uB As uByte
    If pPanCakeGarbage->pNextContainer<>pPanCakeGarbage Then
        pPanTemp=pPanCakeGarbage->pNextContainer : pPanTemp->str_item="" : For uB=RUP_COLS+1 To MAX_COLS-1 : pPanTemp->str_tag_C(uB)="" : Next uB
        pPanCakeGarbage->pNextContainer=pPanCakeGarbage->pNextContainer->pNextContainer : uContainerGarbCt-=1 : pPanTemp->pNextContainer=0
    Else : pPanTemp=_Callocate(Len(ListContainer)) ': If pTestContainer2=0 Then : pTestContainer2=pPanTemp : End If  ' : pPanTemp->str_item=""  ' Moment Angulaire(petite masse)
    End If : Return pPanTemp
End Property

Property List.AllRecycle As uInteger
    Dim pTemp As ListNode Ptr : Dim pTemp2 As ListNode Ptr : Dim pContextRetour As ListContext       
    Dim NbCollected As uInteger=0 : Dim as uByte ub1
    If this.pNode->pNext=0 Or this.pGarbage->pNext=0 Then : Return 0 : End If
    If pGarbage->ListData<>0 Then : pGarbage->ListData->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pGarbage->ListData : pGarbage->ListData=0 : uContainerGarbCt+=1 : End If
    If pLocalMove=pLastLASTNode Then : pLastLASTNode=pLastLASTNode->pPrev : End If : this.NodeRecycle : This.RootPrivate
    If this.pFirstNode=this.pFirstFIRSTNode Then : pNode= this.pGarbage->pNext : Else : pNode= this.pFirstNode->pNext : End If  : If pNode=0 Then : Return 0 : End If
    If pNode <>0 Then
        Do
            If pNode->Tag(0)<>LIST_RES And pNode->pBranch<>0 Then   
                pNode->pNext->pPrev=pNode->pBranch->pBranchLastNode : pNode->pBranch->pBranchLastNode->pNext=pNode->pNext
                pNode->pNext=pNode->pBranch : pNode->pBranch->pBranch=0 : pNode->pBranch=0 : pNode->BranchCount=0
                pNode->pNext->pPrev=pNode : pNode->pNext->pBranchLastNode=0 ':  pNode->pBranchLastNode=0
            Else
                If this.pNode->pNext<>0 Then
                    pNode->Tag(0) = LIST_DEL : For ub1=1 To RUP_COLS : pNode->Tag(ub1)="" : Next ub1 : pNode->BranchCount=0 : NbCollected +=1 ':  pNode->pBranchLastNode=0 ': iLong+=1
                    If pNode->ListData<>0 Then : pNode->ListData->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pNode->ListData : pNode->ListData=0 : uContainerGarbCt+=1 : End If                           
                    this.pNode=this.pNode->pNext
                End If               
            End If
        Loop Until pNode->pNext=0 Or pNode->pNext->Tag(0) = LIST_DEL
    End If
    If NbCollected>0 Then : This.uGarbCt+=NbCollected : uCount=0 : this.pFirstNode->BranchCount=this.uCount : pLastNode=pNode : If pFirstNode=pFirstFIRSTNode Then : pLastLASTNODE=pNode : End If : End If   
    This.RootPrivate : pGarbage=pLastNode->pPrev :pTemp=pNode : pNode=pGarbage : this.Val(LIST_DEL) : pNode=pTemp
    Return NbCollected
End Property

Property List.Branch As Byte
    Dim pTemp As ListNode Ptr :  Dim pTemp1 As ListNode Ptr   
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    pTemp = this.pNode
    If this.pNode->pBranch=0 Then ' this.NewHash(this.pNode)
        pTemp1 = this.pLastNode : this.uCount+=1 : pTemp1->pNext = this.AllowCake 'And eat it
        pTemp1->pNext->pPrev = pTemp1 : pTemp1->pNext->Tag(uTag) = LIST_RES
        pTemp1 = pTemp1->pNext : this.pLastNode = pTemp1 : pNode=pTemp1  ' this.BlindTag(LIST_RES) :
        this.pNode->pPrev=this.pFirstNode : pNode->pBranch = pTemp
        pTemp->pBranch=this.pNode : pTemp->BranchCount=0 : this.uCount=0 : pTemp->pBranchLastNode=this.pNode     
        this.pFirstNode=pTemp->pBranch : this.pNode = this.pFirstNode : this.bSearchRes = 0 : Return 0
    Else 'Branche déjà créée
        this.pFirstNode = this.pNode->pBranch : this.uCount = this.pFirstNode->BranchCount
        this.pLastNode = this.pNode->pBranch->pBranchLastNode         
        this.pNode = this.pNode->pBranch : this.bSearchRes = 0 : Return 1
    End If   
End Property

Property List.UpLevel As Byte   
    If this.pFirstNode->pPrev = 0 Then : Return 0 : End If
    If this.pFirstNode->pBranch <> 0 Then ' Retour node de départ pour faciliter un parcours éventuel
        this.pNode = this.pFirstNode->pBranch : this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
        this.pFirstNode = this.pFirstNode->pPrev : this.uCount = this.pFirstNode->BranchCount : this.pLastNode = this.pFirstNode->pBranchLastNode         
        this.bSearchRes = 0 ': this.sSearchTag = ""
        Return 1
    Else : Return 0
    End If               
End Property

Property List.NodeRecycle as Byte
    If pLocalMove<>0 Then 'pLocalMove est un node à suppression décalée       
        pLocalMove->pPrev=this.pFlatRoot : pLocalMove->pNext=this.pFlatRoot->pNext : pLocalMove->BranchCount=0 ' :  pLocalMove->Tag(1)="" : pLocalMove->pBranch=0 :  pLocalMove->Tag(0)=LIST_DEL :
        If pLocalMove->ListData<>0 Then : pLocalMove->ListData->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pLocalMove->ListData : pLocalMove->ListData=0 : uContainerGarbCt+=1 : End If
        this.pFlatRoot->pNext->pPrev=pLocalMove : this.pFlatRoot->pNext=pLocalMove : this.uGarbCt+=1
        pLocalMove = 0       
    End If
    Return 1
End Property
Property List.NodeRecycle2 as Byte
    If pLocalRoot<>0 Then 'pLocalRoot est un node LIST_RES             
        pLocalRoot->pPrev=this.pFlatRoot : pLocalRoot->pNext=this.pFlatRoot->pNext : pLocalRoot->Tag(0)=LIST_DEL  : pLocalRoot->BranchCount=0
        this.pFlatRoot->pNext->pPrev=pLocalRoot : this.pFlatRoot->pNext=pLocalRoot : This.uGarbCt+=1
        pLocalRoot->pBranch->pBranch=0 : pLocalRoot->pBranch->pBranchLastNode=0 : pLocalRoot->pBranch->BranchCount=0 :
        pLocalRoot->BranchCount=0 : pLocalRoot->pBranch=0 : pLocalRoot = 0
    End If
    Return 1
End Property

Property List.RootPrivate As Byte   
    this.AllOfPrivate : While UpLevel : Wend    ' While this.pFirstNode->pBranch <> 0 : this.UpLevel : Wend   '
    this.pFirstNode = this.pFirstFIRSTNode : this.bSearchRes = 0 : this.sSearchTag = ""
    this.pNode = this.pGarbage   
    Return 1
End Property

Property List.FlatStack(uB As Ubyte) As Byte
    'Gestion du contexte de la Flat List qui doit contenir un dernier node à blanc   
    Dim pTemp1 As ListNode Ptr   
    This.RootPrivate
    this.pNode=this.pFlatRoot : this.Branch
    If this.pLastNode=this.pFlatRoot->pBranch Then
        If this.pEndFlat<>0 Then : this.pFlatRoot->pBranch->pNext=pEndFlat : pEndFlat->pPrev=this.pFlatRoot->pBranch : this.pEndFlat->pNext=0 : this.pLastNode=this.pEndFlat
        Else : this.BlindTag("") : this.pEndFlat=this.pNode : this.uCount -=1         
        End If
    ElseIf this.pLastNode<>this.pEndFlat Then           
        If this.pEndFlat<>0 Then
            this.pEndFlat->pPrev->pNext=this.pEndFlat->pNext : this.pEndFlat->pNext->pPrev=this.pEndFlat->pPrev
            this.pEndFlat->pPrev=this.pLastNode : this.pLastNode->pNext=this.pEndFlat : this.pEndFlat->pNext=0 : this.pLastNode=this.pEndFlat
        Else : this.BlindTag("") : this.pEndFlat=this.pNode : this.uCount -=1
        End If                       
    End If     
    this.pFirstNode->pBranchLastNode = this.pLastNode
    If uB=0 Then : this.UpLevel : End If : this.AllOfPrivate
    Return 1
End Property
Property List.BCountDown(i As Byte) As Byte : Dim pTemp As ListNode Ptr=pFirstNode : While pTemp->pPrev<>0 : If pTemp->pBranch<>0 Then : pTemp->pBranch->BranchCount+=i : End If : pTemp=pTemp->pPrev : Wend : Return 1 : End Property
Property List.ValPrivate(str_value As String) As Byte : If this.pValTmp->ListData=0 Then : this.pValTmp->ListData=this.AllowPanCake : End If : this.pValTmp->ListData->str_item=str_value : Return 1 : End Property
Property List.ValPrivate As String : If this.pValTmp->ListData=0 Then : Return "" : End If : Return this.pValTmp->ListData->str_item : End Property

Property List.AllOfPrivate As uInteger
    this.pNode = this.pFirstNode
    If this.pFirstNode=this.pFirstFIRSTNode Then           
        this.pNode = this.pGarbage
        If pWhyteMove<>0 And pWhyteMove<>pLastNode Then  'Changement de fonctionnement - Patch de compatibilité - : il faut un dernier node logique à blanc
            If pWhyteMove->pNext<>0 Then : pWhyteMove->pPrev->pNext=pWhyteMove->pNext : pWhyteMove->pNext->pPrev=pWhyteMove->pPrev : pLastNode->pNext=pWhyteMove : pWhyteMove->pPrev=pLastNode :  End If     
            pLastNode=pWhyteMove : pLastNode->pNext=pFirstFIRSTNode '0
        End If   
    End If : Return this.Count
End Property

Property List.TrackCompute As Byte
    Dim As ListNode Ptr pTemp1=pNode
    If bAlrdyTracked=1 Then : Return 1 : End If
    While pTemp1->Tag(0)<>LIST_RES And pTemp1<>pGarbage
        If pTemp1->pBranch<>0 Then : pTemp1=pTemp1->pBranch->pPrev : Exit While : End If ' This code is naturally using one Swap, Cast and Exit for aesthetic and legitimate reasons, Gosub @ Extends are unfortunately missing.
        pTemp1=pTemp1->pPrev
    Wend
    If pTemp1=pGarbage Then : pTemp1=pFirstFIRSTNode : End If
    pFirstNode=pTemp1 : pLastNode=pTemp1->pBranchLastNode : uCount=pTemp1->BranchCount : bAlrdyTracked=1 : Return 1
End Property

Property List.HashStepTrace As Byte
    While this.pnode->pBranch<>0
        bHStepTrace=-1
        this.pFirstNode=this.pNode->pBranch : this.uCount=this.pFirstNode->BranchCount
        this.pLastNode=this.pNode->pBranch->pBranchLastNode : this.pNode=this.pNode->pBranch
        If pnode<>pLastNode Then : pnode=pnode->pNext : If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    Wend : bHStepTrace=0 : If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    While pFirstNode->pBranch<>0
         bHStepTrace=1 : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : uCount=pFirstNode->BranchCount
        pLastNode=pFirstNode->pBranchLastNode : If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    Wend : this.RootPrivate : Return 0
End Property

'==========================================================================================TYPE LIST PUBLIC PROPERTIES destination is PRIVATE USE
Property List.SetRelation(by as Byte) as Byte : If by=0 Then : bColBcountLocked=1 : ElseIf by=1 Then : bColTrackLocked=1 : Else : Return 0 : End If : bCopyCatRelation=by : Return 1  : End Property
Property List.SetRelation1(pRelNode As ListNode Ptr) As ListNode Ptr : pNode->pBranchLastNode=pRelNode : Return pNode : End Property
Property List.SetRelation2(pRelFirstNode As ListNode Ptr) As ListNode Ptr : this.pNode->BranchCount=CuInt(pRelFirstNode) : Return pNode : End Property
Property List.Relation As ListNode Ptr : If this.bCopyCatRelation=1 Then : Return pNode->pBranchLastNode : ElseIf this.bCopyCatRelation=0 Then : Return Cast(ListNode Ptr, pNode->BranchCount) : Else : Return 0 : End If : End Property

Property List.GiveBranchDown As ListNode Ptr
    Dim As ListNode Ptr pTemp1, pTemp2   
    If pNode->pBranch=0 Or pNode->Tag(0)=LIST_RES Or pNode->Tag(0)=LIST_DEL Or pNode=pWhyteMove Or pNode=pFlatRoot Or pNode->Tag(0)="" Then : Return 0
    ElseIf pNode->pBranch->Tag(0)<>LIST_RES Then : Return 0 : End If
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    this.NodeRecycle : this.NodeRecycle2 : this.VectorClear
    pTemp1=pNode->pBranch : pNode->pBranch=0 :
    Return pTemp1
End Property

Property List.GiveBranch As ListNode Ptr
    Dim As ListNode Ptr pTemp1, pTemp4
    If pNode->Tag(0)=LIST_RES Or pNode->Tag(0)=LIST_DEL Or pNode=pWhyteMove Or pNode=pFlatRoot Then : Return 0 : End If     
    bfStepZero=0 : this.NodeRecycle : this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    pTemp4=pNode->pPrev : pTemp1=pNode :
    If bBranchCountDown=1 Then : this.BCountDown(-pNode->BranchCount) : End If
    If pTemp1=pLastNode  Then : this.NodeRecycle2 : pFirstNode->pBranch->pBranch=0 : pLocalRoot=pFirstNode : pLocalRoot->Tag(1)="" : pLocalRoot->Tag(0)=LIST_DEL : this.UpLevel : this.NodeRecycle2 : bfStepZero=1 :  Return pTemp1
    Else
        pNode->pPrev->pNext=pNode->pNext : pNode->pNext->pPrev=pNode->pPrev : uCount-=1 : pFirstNode->BranchCount-=1       
        If pTemp1=pLastNode And pFirstNode<>pFirstFIRSTNode Then
            this.NodeRecycle2 : pFirstNode->pBranch->pBranch=0 : pLocalRoot=pFirstNode : pLocalRoot->Tag(1)="" : pLocalRoot->Tag(0)=LIST_DEL : this.UpLevel :  this.NodeRecycle2 : bfStepZero=1 : Return pTemp1
        End If         
    End If
    If pTemp4<>pFirstNode Then : pNode=pTemp4 : Else : pNode=pFirstNode->pNext : End If
    Return pTemp1
End Property

Property List.GiveFlat As ListNode Ptr       
    Dim As ListNode Ptr pTemp1, pTemp2
    If pNode->pPrev->Tag(0)=LIST_DEL Then : this.FlatStack(0) : End If
    If pFirstNode->pNext->Tag(0)=LIST_ROOT Then : this.Root : End If
    If pFlatRoot->pBranch=0 Then : Return 0 : End If         
    If pFlatRoot->pBranch->pNext=pFlatRoot->pBranch->pBranchLastNode Or pFlatRoot->pBranch->pNext=pFlatRoot->pBranch  Then : Return 0 : End If
    pTemp1=pFlatRoot->pBranch->pNext : pTemp2=pEndFlat->pPrev : If pTemp2=0 Or pTemp1=pTemp2 Then : Return 0 : End If
    pTemp1->pBranch=pTemp2 : pFlatRoot->pBranch->pNext=pEndFlat : pEndFlat->pPrev=pFlatRoot->pBranch
    pTemp1->BranchCount=pFlatRoot->pBranch->BranchCount : uNodeCOUNT-=pFlatRoot->pBranch->BranchCount 'this.FlatCount :
    this.pFlatRoot->pBranch->BranchCount=0 : If pFirstNode->pBranch=pFlatRoot Then : uCount=0 : End If  ' this.FlatStack : uCount=0
    Return pTemp1   
End Property

Property List.GiveGarbage As ListNode Ptr
    Dim As ListNode Ptr pTemp1, pTemp2
    If uGarbCt<2 Then : Return 0 : End If : pTemp1=pFlatRoot->pNext : pTemp2=pGarbage->pPrev : If pTemp1=pTemp2 Then : Return 0 : End If
    pFlatRoot->pNext=pGarbage : pGarbage->pPrev=pFlatRoot : pTemp1->pBranch=pTemp2 : pTemp1->BranchCount=uGarbCt
    uNodeCOUNT-= uGarbCt : uGarbCt=0
    Return pTemp1
End Property
Property List.GivePanCake As ListContainer Ptr
    Dim As ListContainer Ptr pPanTemp1, pPanTemp2
    If uContainerGarbCt<2 Then : Return 0 : End If : pLastPanCake=0
    pPanTemp1=pPanCakeGarbage->pNextContainer : pPanTemp2=pPanTemp1
    While pPanTemp2->pNextContainer<>pPanCakeGarbage : pPanTemp2=pPanTemp2->pNextContainer : Wend : pPanTemp2->pNextContainer=0 : pLastPanCake=pPanTemp2
    pPanCakeGarbage->pNextContainer=pPanCakeGarbage : uContainerGivenCt=uContainerGarbCt : uContainerGarbCt=0
    Return pPanTemp1
End Property
Property List.GiveLastPanCake As ListContainer Ptr : Return pLastPanCake : End Property
Property List.GivePanCakeCount As uInteger : Return this.uContainerGivenCt : End Property

'==========================================================================================TYPE LIST PUBLIC PROPERTIES - FLAT CONTROL
Property List.Tag(str_Tag As String) As Byte
    Dim pTemp As ListNode Ptr : Dim item As ListContainer Ptr
    If this.sSearchTag = str_Tag Then
        If this.bSearchRes=1 Then
            this.pNode = this.pSearchNode : Return 1 'pNode
        Else
            pTemp = this.pLastNode : this.uCount+=1 : pTemp->pNext = this.AllowCake 'And eat it
            pTemp->pNext->pPrev = pTemp : pTemp->pNext->Tag(uTag) = str_Tag ' pTemp->pNext->ListData = item :
            pTemp = pTemp->pNext : this.pLastNode = pTemp : If bBranchCountDown=1 Then : this.BCountDown(1) : End If
            this.pNode = pTemp : Return 0
        End If
    Else
        If this.bSeekMethod=1 Then : pTemp = this.pFirstNode : If this.pGarbage<>0 And this.pFirstNode=this.pFirstFIRSTNode Then : pTemp = this.pGarbage  : End If
            While (pTemp->pNext <> 0 And pTemp->Tag(uTag) <> str_Tag) : pTemp = pTemp->pNext : Wend
        ElseIf this.bSeekMethod=2 Then : pTemp = this.pLastNode
            While (pTemp->pPrev <> 0 And pTemp->Tag(uTag) <> str_Tag  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : Wend
        Else
            pTemp = this.pNode : If pTemp->pNext <> 0 Then : pTemp = pTemp->pNext : End If
            While (pTemp->pNext <> 0 And pTemp->Tag(uTag) <> str_Tag) : pTemp = pTemp->pNext : Wend
        End If
        If pTemp->Tag(uTag)<>str_Tag then ' New node
            pTemp = this.pLastNode : this.uCount+=1 : pTemp->pNext = this.AllowCake 'And eat it
            pTemp->pNext->pPrev = pTemp : pTemp->pNext->ListData = item : pTemp->pNext->Tag(uTag) = str_Tag
            pTemp = pTemp->pNext : this.pLastNode = pTemp : If bBranchCountDown=1 Then : this.BCountDown(1) : End If           
            If pFirstNode=pFirstFIRSTNode And pWhyteMove<>pLastNode Then
                pWhyteMove->pPrev->pNext=pWhyteMove->pNext : pWhyteMove->pNext->pPrev=pWhyteMove->pPrev : pLastNode->pNext=pWhyteMove : pWhyteMove->pPrev=pLastNode : pLastNode=pWhyteMove : pLastNode->pNext=0
            End If : this.pNode = pTemp : Return 0
        End If   
    End If
    this.pNode = pTemp : Return 1 'pTemp
End Property

Property List.Tag As String
 '  Return this.pNode->Tag(uTag)
    If uTag<=RUP_COLS Then : Return this.pNode->Tag(uTag)
    ElseIf pNode->ListData=0 Then : Return ""
    Else : Return pNode->ListData->str_tag_C(uTag)
    End If
End Property
Property List.Tag(i As Integer) As String
    If i<=RUP_COLS Then : Return this.pNode->tag(i) : Else : If pNode->ListData<>0 Then : Return pNode->ListData->str_tag_C(i) : Else : Return "" : End If : End If
End Property

Property List.HasTag(str_Tag As String) As Byte
    Dim pTemp As ListNode Ptr
    this.sSearchTag = str_Tag
    If this.bSeekMethod=1 Then
        pTemp = this.pFirstNode : If this.pGarbage<>0 And this.pFirstNode=this.pFirstFIRSTNode Then : pTemp = this.pGarbage  : End If
        While (pTemp->pNext <> 0 And pTemp->Tag(uTag) <> str_Tag  AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : Wend
    ElseIf this.bSeekMethod=2 Then
        pTemp = this.pLastNode
        While (pTemp->pPrev <> 0 And pTemp->Tag(uTag) <> str_Tag  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : Wend
    Else
        pTemp = this.pNode : If pTemp=0 Then : pTemp = this.pFirstNode : End If
        While (pTemp->pNext <> 0  And pTemp->Tag(uTag) <> str_Tag AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : Wend
    End If   
    If pTemp->Tag(uTag) = str_Tag Then
        this.pSearchNode=pTemp : this.bSearchRes=1 : If this.bAutoCursor=1 Then : pNode=pTemp : End If  : Return 1
    Else : this.bSearchRes = 0 : Return 0 : End If   
End Property

Property List.BlindTag(str_Tag As String) As Byte
    Dim pTemp As ListNode Ptr : Dim item As ListContainer
    pTemp = this.pLastNode : this.uCount+=1 : pTemp->pNext = this.AllowCake 'And eat it
    pTemp->pNext->pPrev = this.pLastNode : pTemp->pNext->Tag(uTag) = str_Tag
    pTemp = pTemp->pNext : this.pLastNode = pTemp : this.pNode = pTemp
    If bBranchCountDown=1 Then : this.BCountDown(1) : End If : Return 1
End Property

Property List.RwTag(s_Tag As String) As Byte : If uTag<=RUP_COLS Then : this.pNode->tag(this.uTag)=s_Tag : Return 1 : Else : If pNode->ListData=0 Then : this.pValTmp=this.pNode : this.ValPrivate("") : End If : pNode->ListData->str_tag_C(uTag)=s_Tag : Return 1 : End If : End Property
Property List.RwTag0(s_Tag As String) As Byte : this.pNode->tag(0)=s_Tag : Return 1 : End Property
Property List.RwTag1(s_Tag As String) As Byte : this.pNode->tag(1)=s_Tag : Return 1 : End Property
Property List.RwTag2(s_Tag As String) As Byte : uB_tmp=uTag : uTag=2 : this.RwTag(s_Tag ) : uTag=uB_tmp : Return 1 : End Property
Property List.RwTag3(s_Tag As String) As Byte : uB_tmp=uTag : uTag=3 : this.RwTag(s_Tag ) : uTag=uB_tmp : Return 1 : End Property
Property List.RwTag4(s_Tag As String) As Byte : uB_tmp=uTag : uTag=4 : this.RwTag(s_Tag ) : uTag=uB_tmp : Return 1 : End Property

Property List.ColTags As Byte : Return(this.uTag) : End Property
Property List.ColTags(i as Byte) As Byte : this.sSearchTag = "" : this.bSearchRes=0 : If i > MAX_COLS-1 then : this.uTag=MAX_COLS-1 : Return 0 : Else : this.uTag=i : Return 1 : End If : End Property

Property List.AllOf As uInteger
    Dim pContextRetour As ListContext
    If this.IsDestroyed=1 Then : Print "Error List destroyed : instance can't be re-used" : Return 0 : End If :
    Dim  As ListNode Ptr pTemp, pTemp2 : If bTracking=1 Then : this.TrackCompute :  bTracking=0 : End If
    If pFirstNode=pFIRSTFIRSTNode Then : If pLastNode<>pWhyteMove Then : this.Root : End If : End If
    this.NodeRecycle : this.NodeRecycle2
    pContextRetour.pNode=pNode : pContextRetour.pFirstNode=This.pFirstNode : pContextRetour.pLastNode=This.pLastNode : pContextRetour.uCount=This.uCount
    this.AllOfPrivate
    pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : uCount=pContextRetour.uCount
    pNode=AllowCake : pLocalMove=pNode
    If this.pFirstNode=this.pFirstFIRSTNode Then : pNode->pNext=pGarbage->pNext : Else : pNode->pNext=pFirstNode->pNext : End If
    If pLastNode=pWhyteMove And pLastNode->pPrev<>0 Then : pNode->pPrev=pLastNode->pPrev : Else : pNode->pPrev=pLastNode : End If
    Return this.Count
End Property

Property List.Count As uInteger
    Dim pTemp As ListNode Ptr
    If pWhyteMove=0 And pFirstNode=pFIRSTFIRSTNode Then : pTemp=this.pNode : this.uCount-=2 : this.BlindTag("") : this.pWhyteMove=this.pNode : this.pNode=pTemp : End If : Return this.uCount
End Property

Property List.First As Byte : If pFirstNode=pFirstFIRSTNode Then : pNode=pGarbage : Else : this.pNode=This.pFirstNode->pNext : End If : Return 1 : End Property
Property List.Last As Byte : this.pNode=This.pLastNode : Return 1 : End Property

Property List.Val(str_value As String) As Byte : this.pValTmp=this.pNode : this.ValPrivate(str_value) : Return 1 : End Property
Property List.Val As String : pValTmp=pNode : Return this.ValPrivate : End Property
Property List.ValTag(str_value As String) As String
    If bSearchRes=1 Then : If str_value=this.Tag(0) Then : pValTmp=pSearchNode : Return this.ValPrivate : End If
    ElseIf this.HasTag(str_value)=1 Then : pValTmp=pSearchNode : Return this.ValPrivate
    End If : Return("")
End Property

Property List.fStep As Byte : If pNode=pLastNode Or bfStepZero=1 Or pNode->pNext=pWhyteMove Then : bfStepZero=0 : Return 0 : Else : pNode = pNode->pNext : Return 1 : End If : End Property '
Property List.fStepRev As Byte : If pNode->pPrev=pFirstNode Or pNode->pPrev=pGarbage Or bfStepZero=1 Then : bfStepZero=0 : Return 0 : Else : pNode = pNode->pPrev : Return 1 : End If : End Property
Property List.bStep As Byte : this.pNode = this.pNode->pNext : Return 1 : End Property
Property List.BlindStep As Byte : If this.pNode->pNext<>0 Then : this.pNode = this.pNode->pNext : Return 1 : Else   : Return 0 : End If : End Property ' : Print "*Warning : list parse or count down error"
Property List.BlindStep(top As Integer) As Byte
    Dim As Integer i : Dim As Byte istep
    If top>0 Then : istep=1 : For i=1 To top step istep : this.pNode = this.pNode->pNext : Next i : ElseIf top = 0 Then : this.pNode = this.pLastNode : Return 1 : Else : istep=-1 : For i=-1 To top step istep : this.pNode = this.pNode->pPrev : Next i : End If
    Return 1
End Property
Property List.fMove(nbMove As Integer) As Byte
    Dim As ListNode Ptr pFirst, pTemp : Dim i As Integer=0
    If pNode->Tag(0)=LIST_DEL Or pNode->Tag(0)=LIST_RES Or pNode=pWhyteMove Or pNode=pEndFlat  Or pNode=pLocalMove Or pNode=pLocalRoot Then : Return 0 : End If
    If pFirstNode=pFirstFIRSTnode Then : pFirst=pGarbage : Else : pFirst=pFirstNode : End If
    If pNode=pLastNode Then : pLastNode=pNode->pPrev : Else : pNode->pNext->pPrev=pNode->pPrev : End If
    pNode->pPrev->pNext=pNode->pNext : pTemp=pNode
    If nbMove>0 Then : For i=0 To nbMove-1 : If pNode<>pLastNode Then : pTemp=pTemp->pNext : End If : Next i
    Else : For i=nbMove To 0 : If pTemp<>pFirstNode Then : pTemp=pTemp->pPrev : End If : Next i
    End If
    If pTemp<>pLastNode Then : pTemp->pNext->pPrev=pNode : pNode->pNext=pTemp->pNext
    Else : If  pTemp->pNext<>0 Then : pNode->pNext=pTemp->pNext : End If : pLastNode=pNode
    End If
    pTemp->pNext=pNode : pNode->pPrev=pTemp
    Return 1
End Property
Last edited by Lost Zergling on Jul 09, 2019 19:51, edited 96 times in total.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 26, 2018 16:13

Code PART 2/3 :

Code: Select all


'==========================================================================================TYPE LIST PUBLIC PROPERTIES - SORTING
Property List.ColSort(i as Byte) As Byte : If i > MAX_COLS-1 then : this.uTag=MAX_COLS-1 : Return 0 : Else : this.uSortTag=i : Return 1 : End If : End Property
Property List.fSortMethod(bsortM As Byte) As Byte : If bsortM=-1 Then : this.bSortMT=-1 : Else : this.bSortMT=1 : End If : Return 1 : End Property
Property List.fSort As Byte
    Dim As ListNode Ptr pTemp1=pFirstNode, pTemp2, pTemp3, pTemp4, pTemp5=pLastNode->pNext : Dim as byte  by=1
    If pFirstNode=pFirstFIRSTnode Then : pTemp1=pGarbage : End If   
    'Trie+Insert Sort - non recursive   
    gCollector.SetRelation(1) : gCollector.HashKeyUnique(1) : gCollector.HashSort(1) : gCollector.fSortMethod(1) : gCollector.HashLen(1) : gCollector.GarbageSnatch(this)
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    pTemp3=pTemp1 : pNode=pTemp1->pNext : If pNode=pFirstNode Then : pTemp4=pFirstNode->pNext : Else : pTemp4=pNode : End If
    While pNode<>pLastNode and by=1 : gCollector.HashTag( this.Tag) : gCollector.SetRelation1(this.pNode) : by=this.fStep : Wend ' gCollector.HashTag( this.pNode->Tag(uTag) ) <> gCollector.HashTag( this.Tag ) wheras pNode->Tag(uTag) = this.Tag ?
    If pFirstNode<>pFirstFIRSTnode Then : gCollector.HashTag( this.Tag ) : gCollector.SetRelation1(this.pNode)  : End If
    gCollector.Root
    If this.bSortMT=1 Then : While gCollector.KeyStep : If this.Follow(gCollector) Then : pTemp3->pNext=this.pNode : pNode->pPrev=pTemp3 : pTemp3=pNode : End If : Wend         
    Else : While gCollector.KeyStepRev : If this.Follow(gCollector) Then : pTemp3->pNext=this.pNode : pNode->pPrev=pTemp3 : pTemp3=pNode : End If : Wend
    End If
    pFirstNode->pBranchLastNode=pTemp3 : this.pLastNode=pTemp3 : pNode=pTemp4
    If pFirstNode=pFirstFIRSTnode Then : pWhyteMove->pPrev=pLastNode : End If
    gCollector.Recycle : this.AllOf : this.GarbageSnatch(gCollector)
    Return 1
End Property

Property List.Sort as Byte : this.Sort(this.bSortMT) : Return 1 : End Property
Property List.Sort(bSortMth As Byte) as Byte
    Dim As ListNode Ptr s_pNode=pNode, s_pFirstNode=pFirstNode
    Dim As uInteger s_uCount=uCount
    If this.Up Then : this.Down : End If : If bSortMth=-1 Then : this.fSortMethod(-1) : Else : this.fSortMethod(1) : End If   
    this.Root : this.fSort : this.pNode=pGarbage
    While this.HashStepTrace : If bHStepTrace=-1 Then : this.fSort : pNode=this.pFirstNode->pNext : End If : Wend
    pNode=s_pNode : pFirstNode=s_pFirstNode : pLastNode=pFirstNode->pBranchLastNode : uCount=s_uCount
    Return 1
End Property
Property List.HashSort(ub as Byte) As Byte : If ub=1 And this.bSortMT=-1 Then : this.bSortMT=1 : End If : If ub=0 Or ub=1 Then : bHTmethod=ub : uSortTag=uTag : Return 1 : Else : Return 0 : End If : End Property

'==========================================================================================TYPE LIST PUBLIC PROPERTIES - HASH CONTROL
Property List.Root As Byte
    Dim pTemp As ListNode Ptr : Dim pTemp2 As ListNode Ptr : Dim pContextRetour As ListContext     
    If bTracking=1 Or pFirstNode->Tag(0)<>LIST_RES Then : this.TrackCompute :  bTracking=0 : End If :' this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode   
    If this.IsDestroyed=1 Then : Print "Error List destroyed : instance can't be re-used" : Beep : Return 0 : End If
    this.RootPrivate : If pLocalMove<>0 Then : pLocalMove->Tag(1)="" : pLocalMove->pBranch=0 :  pLocalMove->Tag(0)=LIST_DEL : End If
    this.NodeRecycle : this.NodeRecycle2 : bSearchRes=0 : pTemp2=0 : this.bHashStepRev=0 : pLatestHTag=0
    'Changement de fonctionnement - Patch de compatibilité - : il faut un dernier node logique à blanc qui ne soit jamais 'flaté'
    If this.pWhyteMove<>0 Then
        pWhyteMove->Tag(0)=""
        If this.pWhyteMove->pNext<>0 And pWhyteMove->pNext->Tag(0)<>LIST_RES Then           
            If pWhyteMove->pPrev<>0 Then : this.pWhyteMove->pPrev->pNext=this.pWhyteMove->pNext : End If
            If pWhyteMove->pNext<>0 Then :this.pWhyteMove->pNext->pPrev=this.pWhyteMove->pPrev : End If         
        End If       
    End If ' If pPanCakeGarbage=0 Then : pPanCakeGarbage=AllowPanCake : pPanCakeGarbage->pNextContainer=pPanCakeGarbage : End If   
    If pGarbage=0 Then  ' This.Tag(LIST_DEL) :
        This.BlindTag(LIST_DEL) : pGarbage=this.pNode : this.Val(LIST_DEL) : pGarbage->pPrev=pFlatRoot
        If pFlatRoot->pNext<>pGarbage Then : pGarbage->pNext=pFlatRoot->pNext : End If : pFlatRoot->pNext=pGarbage
        If pGarbage->pNext<>0 Then : pGarbage->pNext->pPrev=pGarbage : End If : this.pNode = pGarbage
    End If
    If pFirstNode->pPrev=0 And pNode->pNext=0 Then : pTemp=pNode : this.AllOf : pNode=pTemp : End If
    'Gestion du contexte de la Flat List qui doit contenir un dernier node à blanc
    this.FlatStack(0)
    'Corrections  - Patch de compatibilité - : pFlatRoot se balade, il faut le remettre au début -
    If pFlatRoot->pPrev<>0 Then : pFlatRoot->pPrev->pNext=pFlatRoot->pNext : End If : If pFlatRoot->pNext<>0 Then :  pFlatRoot->pNext->pPrev=pFlatRoot->pPrev : End If
    pFlatRoot->pPrev=this.pFirstFIRSTNode : pFlatRoot->pNext=this.pFirstFIRSTNode->pNext : If this.pFirstFIRSTNode->pNext<>0 Then : this.pFirstFIRSTNode->pNext->pPrev=pFlatRoot : End If : this.pFirstFIRSTNode->pNext=pFlatRoot
    'Changement de fonctionnement - Patch de compatibilité - pLastLAST devient dernier node LOGIQUE : on le remet à jour
    If this.pFirstFIRSTNode->pBranchLastNode<>0 Then
        pTemp=this.pFirstFIRSTNode->pBranchLastNode : While pTemp->pBranchLastNode<>0 And pTemp<>pTemp2 : pTemp2=pTemp : pTemp=pTemp->pBranchLastNode : Wend : this.pLastLASTNode=pTemp       
    End If     
    'NodeFlat+Restorehash nécessite la présence d'un dernier node fictif
    If this.pLastNode->Tag(0)<>"" Then : If pWhyteMove<>0 Then : this.AllOf  : Else : pTemp=this.pNode : this.pFirstNode->BranchCount=this.uCount : this.BlindTag("") : this.pWhyteMove=this.pNode : this.pNode=pTemp : End If : End If
    this.pNode=pGarbage : this.uCount=this.pFirstFIRSTNode->BranchCount : this.pLastLASTNode->pPrev->pNext=this.pLastLASTNode
    If this.pLastLASTNode->pNext->Tag(0)=LIST_RES Then : this.pLastLASTNode->pNext=0 : End If
  ' Option for .Root become compatible with Rev parse with no need to jump to Last node (List.Last)
    this.pNode=AllowCake : pNode->Tag(0)="" : pLocalMove=pNode : pNode->pNext=pGarbage->pNext : pLocalMove->Tag(1)="" : pLocalMove->pBranch=0 :  pLocalMove->Tag(0)=LIST_DEL
    If pLastNode=pWhyteMove Then : pNode->pPrev=pLastNode->pPrev : Else : pNode->pPrev=pLastNode : End If
    this.NodeRecycle2 : this.pFirstNode->BranchCount=this.uCount : this.pFirstNode->pBranchLastNode=this.pLastNode
    uB_CurLevel=1 : uB_Level=1 : If bnStepByPass=0 Then :  uB_BottomLevel=255 : uB_MaxLevel=1 : uB_KeyStepCumul=1 : End If
    Return 1
End Property

Property List.FlatStack As Byte : this.FlatStack(1) : this.AllOf : bSearchRes=0 : Return 1 : End Property
Property List.RootNode As Byte : bSearchRes=0 : this.Root : this.pNode=This.pFirstFIRSTNode : Return 1 : End Property
Property List.EndNode As Byte : bSearchRes=0 : this.Root : this.pNode=This.pLastLASTNode : Return 1 : End Property

Property List.HashStep As Byte
    While this.pnode->pBranch<>0
        this.pFirstNode=this.pNode->pBranch : this.uCount=this.pFirstNode->BranchCount : this.pLastNode=this.pNode->pBranch->pBranchLastNode : this.pNode=this.pNode->pBranch
        If pnode<>pLastNode Then : pnode=pnode->pNext : If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If ' If pNode=pWhyteMove Then : Return 0 : Else : Return 1 : End If
    Wend : If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    While pFirstNode->pBranch<>0
        pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : uCount=pFirstNode->BranchCount
        pLastNode=pFirstNode->pBranchLastNode : If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    Wend : this.RootPrivate : Return 0
End Property

Property List.HashStepRev As Byte
    this.bHashStepRev=1
    While this.pnode->pBranch<>0
        this.pFirstNode=this.pNode->pBranch : this.uCount=this.pFirstNode->BranchCount : this.pLastNode=this.pNode->pBranch->pBranchLastNode : this.pNode=this.pNode->pBranch
        If pLastNode=pWhyteMove And pLastNode->pPrev<>0 Then : pNode=pLastNode->pPrev : Else : pnode=pLastNode : End If : Return 1
    Wend : If pnode->pPrev=pGarbage Then : bHashStepRev=0 : Return 0 : End If : If pnode->pPrev<>pFirstNode Then : this.pnode = this.pnode->pPrev : Return 1 : End If ' And pnode->pPrev->Tag(0)<>LIST_RES
    While pFirstNode->pBranch<>0
        pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : uCount=pFirstNode->BranchCount
        pLastNode=pFirstNode->pBranchLastNode : If this.pnode <> this.pFirstNode->pNext Then : this.pnode = this.pnode->pPrev : If pnode=pGarbage Then : bHashStepRev=0 : Return 0 : End If : Return 1 : End If ' And pnode->pPrev->Tag(0)<>LIST_RES
    Wend : this.bHashStepRev=0 : Return 0
End Property

Property List.KeyStep As Byte : While this.HashStep=1 : If pNode->Tag(1)<>"" And pNode->Tag(1)<>LIST_DEL Then : Return 1 : End If : Wend : End Property
Property List.KeyStepRev As Byte : While this.HashStepRev=1 : If pNode->Tag(1)<>"" And pNode->Tag(1)<>LIST_DEL Then : Return 1 : End If : Wend : End Property

'Numeric parse optimization
Property List.nCurLevel(uB_len as uByte) As Byte : If uB_len=uB_CurLevel Then : Return 1 : Else : Return 0 : End If : End Property

'Numeric sorted parse
Property List.nHashStep(uB_len as uByte) As Byte   
    While this.pnode->pBranch<>0 And uB_CurLevel<=uB_len
        uB_CurLevel +=1 : If uB_CurLevel>uB_MaxLevel Then : uB_MaxLevel=uB_CurLevel : End If
        this.pFirstNode=this.pNode->pBranch : this.uCount=this.pFirstNode->BranchCount : this.pLastNode=this.pNode->pBranch->pBranchLastNode : this.pNode=this.pNode->pBranch
        If pnode<>pLastNode Then : pnode=pnode->pNext : If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If
    Wend :     
    If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : Return 0 : Else : Return 1 : End If : End If   
    While pFirstNode->pBranch<>0
        uB_CurLevel -=1
        pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : uCount=pFirstNode->BranchCount
        pLastNode=pFirstNode->pBranchLastNode : If pnode<>pLastNode Then : pnode=pnode->pNext :  If pNode=pWhyteMove Then : this.AllOf : uB_Level+=1 : Return 0 : Else : Return 1 : End If : End If
    Wend :
    this.RootPrivate : Return 0
End Property
Property List.nKeyStep(uB_len as uByte) As Byte : While this.nHashStep(uB_len)=1 : If pNode->Tag(1)<>"" And pNode->Tag(1)<>LIST_DEL Then : Return 1 : End If : Wend : Return 0 : End Property
Property List.nKeyStep as Byte
    While uB_KeyStepCumul<=uB_MaxLevel
        While this.nKeyStep(uB_Level) : If this.nCurLevel(uB_Level)=1 Then : Return 1 : End If : Wend
        bnStepByPass=1 : this.Root : bnStepByPass=0 : uB_Level+=uB_KeyStepCumul : uB_KeyStepCumul+=1
    Wend : uB_CurLevel=1 : uB_Level=1 : uB_MaxLevel=1 : uB_KeyStepCumul=1 : Return 0
End Property

'Numeric sorted Reverse parse
Property List.nHashStepRev(uB_len as uByte) As Byte   
    this.bHashStepRev=1
    While this.pnode->pBranch<>0 And uB_CurLevel<=uB_len
        uB_CurLevel +=1 : If uB_CurLevel>uB_MaxLevel Then : uB_MaxLevel=uB_CurLevel : uB_BottomLevel = uB_MaxLevel+1 : End If
        this.pFirstNode=this.pNode->pBranch : this.uCount=this.pFirstNode->BranchCount : this.pLastNode=this.pNode->pBranch->pBranchLastNode : this.pNode=this.pNode->pBranch
        If pLastNode=pWhyteMove And pLastNode->pPrev<>0 Then : pNode=pLastNode->pPrev : Else : pnode=pLastNode : End If : Return 1
    Wend : If pnode->pPrev=pGarbage Then : Return 0 : End If : If pnode->pPrev<>pFirstNode Then : this.pnode = this.pnode->pPrev : Return 1 : End If
    While pFirstNode->pBranch<>0
        uB_CurLevel -=1
        pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : uCount=pFirstNode->BranchCount
        pLastNode=pFirstNode->pBranchLastNode : If this.pnode <> this.pFirstNode->pNext Then : this.pnode = this.pnode->pPrev : If pnode=pGarbage Then : Return 0 : End If : Return 1 : End If
    Wend : Return 0
End Property
Property List.nKeyStepRev(uB_len as uByte) As Byte : While this.nHashStepRev(uB_len)=1 : If pNode->Tag(1)<>"" And pNode->Tag(1)<>LIST_DEL Then : Return 1 : End If : Wend : Return 0 : End Property
Property List.nKeyStepRev as Byte
   Dim t as Integer
   For t=uB_BottomLevel to 1 Step-1
        While this.nKeyStepRev(uB_BottomLevel) : If this.nCurLevel(uB_BottomLevel)=1 Then : Return 1 : End If : Wend : bnStepByPass=1 : this.Root : bnStepByPass=0 : uB_BottomLevel-=uB_KeyStepCumul
    Next t : uB_CurLevel=1 : uB_BottomLevel=255 : uB_KeyStepCumul=1 : Return 0
End Property

Property List.HashTag(str_Tag As String) As Byte
   Dim As ListNode Ptr pTemp,  pTemp02, pTemp03 , pTemp04
    Dim As uInteger i=0, iLen=Len(str_tag), iLenStrTmp, iLenpNode, iLenCumul, iLenDiff, iLenDelta=0, PvsiStep
    Dim As uByte HadHashTag=1, istep=this.bHashLen, IsLast=0, IsPt2Swp=0, IsPtSwp=0, bSeekMethod_TMP=bSeekMethod, bAutoCursor_TMP=bAutoCursor
    Dim As zString Ptr zp1, zp2, Listptemp2_b, Listptemp_b : Dim As String str_testTMP
    If iLen>MAX_KEYLEN Then : Listptemp2_b=_CAllocate(iLen+1) : Swap Listptemp2,Listptemp2_b : IsPt2Swp=1 : End If
    str_testTMP=str_Tag : If bTracking=1 And bTrackingMethod=0 Then : This.TrackCompute : End If

    If pFirstNode<>pFirstFIRSTNode Then 'Déclenchement optimisation // Si pFirstNode=pFirstFIRSTNode il est possible que la liste soit vide ou que le node en cours soit en cours d'envoi au garbage collector
        If pLatestHTag=pNode Then : Str_tmp=sLatestHTag '  Algo optimisation 1 : basé sur la récupération la + rapide possible de la position dans l'arbre // And bPVSmethod=0 //  l'algo d'optimisation le plus simple est souvent le + efficace et reste prioritaire sur PVS
        Else : pNode=pFirstNode->pNext : If pFirstNode->Tag(1)<>"" Then : Str_tmp=pFirstNode->Tag(1) & pNode->Tag(0) : Else : Str_tmp=this.HashTag : If ubKeysRegister=1 Then : pFirstNode->Tag(1)=Left(Str_tmp, Len(Str_tmp)-istep) : End If : End If
        End If
        iLenStrTmp=Len(Str_tmp)         
        If iLenStrTmp>MAX_KEYLEN Then : Listptemp_b=_CAllocate(iLenStrTmp+1) : Swap Listptemp,Listptemp_b : IsPtSwp=1 : End If
        If iLen>iLenStrTmp Then : iLenDiff=iLen-iLenStrTmp : End If
       
        *Listptemp=Str_tmp : zp1=Listptemp : zp1+=istep : (*zp1)[0]=0 ' *Alternative to *Listptemp=Left(Str_tmp,istep)
        *Listptemp2=str_tag : zp2=Listptemp2 : zp2+=istep : (*zp2)[0]=0 ' *Alternative to *Listptemp2=Left(str_tag,istep)
        If *Listptemp=*Listptemp2  And bPVSmethod<1 Then  ' Algo optimisation 1 & 2 : on cale la longueur de la clef predictive sur celle de la clef à atteindre ou à créer, en remontant dans l'arbre le cas échéant (en utilisant la fonction d'upwelling de l'arbre : pointeurs directs) // And bPVSmethod=0
            pFirstNode->BranchCount=uCount :  pFirstNode->pBranchLastNode=pLastNode
            iLenpNode=Len(pNode->Tag(uTag)) 'iLenpNode=iLen :
            While iLen<iLenStrTmp : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenStrTmp=Len(Str_tmp)-iLenpNode :  Str_tmp=Left(Str_tmp, iLenStrTmp) : iLenpNode=Len(pNode->Tag(uTag)) :  Wend   
            pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
       '     While iLen<Len(Str_tmp) : this.UpLevel : Str_tmp=this.HashTag :  Wend  '  pNode=pFirstNode->pNext :
            iLenStrTmp=Len(Str_tmp) ': i=1 ': iLenpNode=Len(pNode->Tag(uTag)) :
            pFirstNode->BranchCount=uCount :  pFirstNode->pBranchLastNode=pLastNode
            While Left(str_tag, iLenStrTmp)<>Str_tmp  ' Algo optimisation 1 & 2 : on redescendra ensuite dans l'arbre depuis le point de l'arbre le plus bas commun aux deux clefs = économie de lookup si la prédiction est réalisée
                Str_tmp=Left(Str_tmp, iLenStrTmp-iLenpNode)
                iLenStrTmp-=iLenpNode : iLenCumul +=iLenpNode : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenpNode=istep
            Wend : pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
            iLen=iLenCumul+istep+iLenDiff : str_Tag=Right(str_Tag, iLen) : pTemp02=pFirstNode : iLenDelta=iLenStrTmp-iLenpNode
            If pFirstNode=pFirstFIRSTNode Then : pTemp02=pGarbage : End If ' And pLatestHTag=pNode             
           
        ElseIf bPVSmethod>-1 Then ' Algo optimisation 2 : basé sur l'enregistrement à un niveau PvsiStep càd (lngClef/n)+1 de la longueur de la clef, d'un pointeur "prédictif" vers une branche plus basse de l'arbre
            PvsiStep=iLen/PVS_ratio+1
            *Listptemp=Str_tmp : zp1=Listptemp : zp1+=PvsiStep : (*zp1)[0]=0 ' *Alternative to *Listptemp=Left(Str_tmp,istep)
            *Listptemp2=str_tag : zp2=Listptemp2 : zp2+=PvsiStep : (*zp2)[0]=0 ' *Alternative to *Listptemp2=Left(str_tag,istep)       
            If  *Listptemp<>*Listptemp2 Then' *Alternative to If Left(Str_tmp,istep)<>Left(str_tag,istep) Then   *Listptemp<>*Listptemp2     
                pFirstNode->BranchCount=uCount : pFirstNode->pBranchLastNode=pLastNode : pFirstNode=pFirstFIRSTNode
                this.uCount = this.pFirstNode->BranchCount : pLastNode=this.pFirstNode->pBranchLastNode : pTemp02=pGarbage
                this.HashTag(*Listptemp2 ) 'youpi
                If pNode->BranchCount<>0 Then : pFirstNode=Cast(ListNode Ptr, pNode->BranchCount) : pLastNode=pFirstNode->pBranchLastNode : End If :  pTemp04=pNode : PVS_Count+=1               
                pNode=pFirstNode->pNext : pNode=pFirstNode->pNext
                If pFirstNode->Tag(1)<>"" Then : Str_tmp=pFirstNode->Tag(1) & pNode->Tag(0) : Else : Str_tmp=this.HashTag : If ubKeysRegister=1 Then : pFirstNode->Tag(1)=Left(Str_tmp, Len(Str_tmp)-istep) : End If : End If
                *Listptemp=Str_tmp : zp1=Listptemp : zp1+=istep : (*zp1)[0]=0 ' *Alternative to *Listptemp=Left(Str_tmp,istep)
            End If
            If *Listptemp=*Listptemp2 Then  ' Algo optimisation 1 & 2 : on cale la longueur de la clef predictive sur celle de la clef à atteindre ou à créer, en remontant dans l'arbre le cas échéant (en utilisant la fonction d'upwelling de l'arbre : pointeurs directs)
                pFirstNode->BranchCount=uCount :  pFirstNode->pBranchLastNode=pLastNode
                iLenpNode=Len(pNode->Tag(uTag)) 'iLenpNode=iLen :
                While iLen<iLenStrTmp : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenStrTmp=Len(Str_tmp)-iLenpNode :  Str_tmp=Left(Str_tmp, iLenStrTmp) : iLenpNode=Len(pNode->Tag(uTag)) :  Wend   
                pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
           '     While iLen<Len(Str_tmp) : this.UpLevel : Str_tmp=this.HashTag :  Wend  '  pNode=pFirstNode->pNext :
                iLenStrTmp=Len(Str_tmp) ': i=1 ': iLenpNode=Len(pNode->Tag(uTag)) :
                pFirstNode->BranchCount=uCount :  pFirstNode->pBranchLastNode=pLastNode
                While Left(str_tag, iLenStrTmp)<>Str_tmp  ' Algo optimisation 1 & 2 : on redescendra ensuite dans l'arbre depuis le point de l'arbre le plus bas commun aux deux clefs = économie de lookup si la prédiction est réalisée
                    Str_tmp=Left(Str_tmp, iLenStrTmp-iLenpNode)
                    iLenStrTmp-=iLenpNode : iLenCumul +=iLenpNode : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenpNode=istep
                Wend : pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
                iLen=iLenCumul+istep+iLenDiff : str_Tag=Right(str_Tag, iLen) : pTemp02=pFirstNode : iLenDelta=iLenStrTmp-iLenpNode
                If pFirstNode=pFirstFIRSTNode Then : pTemp02=pGarbage : End If ' And pLatestHTag=pNode   
            Else               
                pFirstNode->BranchCount=uCount : pFirstNode->pBranchLastNode=pLastNode : pFirstNode=pFirstFIRSTNode
                this.uCount = this.pFirstNode->BranchCount : pLastNode=this.pFirstNode->pBranchLastNode : pTemp02=pGarbage : bSeekMethod_TMP=1               
            End If 
           
        Else
            pFirstNode->BranchCount=uCount : pFirstNode->pBranchLastNode=pLastNode : pFirstNode=pFirstFIRSTNode
            this.uCount = this.pFirstNode->BranchCount : pLastNode=this.pFirstNode->pBranchLastNode : pTemp02=pGarbage : bSeekMethod_TMP=1
        End If
    Else
        pTemp02=pGarbage : bSeekMethod_TMP=1
    End If ' Fin algo optimisation   
   
    iLenCumul=0 : *Listptemp2=str_Tag : zp1=Listptemp2 ' * Alternative to Mid
    For i=1 to Len(str_Tag) step istep
        zp2=zp1 : zp1+=istep : (*zp3)[0]=(*zp1)[0] : (*zp1)[0]=0 : Str_tmp=*zp2 : (*zp1)[0]=(*zp3)[0] ' * Alternative to Mid :  Str_tmp=Mid(str_Tag,i, istep)
        iLenCumul+=iStep
        If bHTmethod=0 Then
            If bSeekMethod_TMP=2 Then : pTemp = this.pLastNode : While ( pTemp->Tag(uTag)<>Str_tmp  AndAlso pTemp<>pTemp02 ) : pTemp = pTemp->pPrev : Wend
            Else : pTemp = pTemp02 : While ( pTemp->Tag(uTag)<>Str_tmp  AndAlso pTemp<>pLastNode ) : pTemp = pTemp->pNext : Wend
            End If
        Else
            If bSeekMethod_TMP=2 Then
                pTemp = this.pLastNode : If pTemp=pWhyteMove Then : pTemp = pTemp->pPrev : End If
                While ( pTemp->Tag(uSortTag)>Str_tmp  And pTemp<>pTemp02 ) : pTemp = pTemp->pPrev : Wend
                If pTemp=pLastNode Then : IsLast=1 : End If : If pTemp=pFirstNode Then : pTemp=pTemp->pNext : End If
            Else
                pTemp=pTemp02 : While (pTemp->Tag(uSortTag)<Str_tmp  AndAlso pTemp<>pLastNode) : pTemp=pTemp->pNext : Wend               
                If pTemp->Tag(uSortTag)<Str_tmp  AndAlso pTemp=pLastNode Then : IsLast=1 : End If
            End If
        End If       
        If pTemp->Tag(uTag)=Str_tmp And bHashKeyUnique=1 Then : this.pNode = pTemp  'bHashKeyUnique
        ElseIf pTemp->Tag(uTag)=Str_tmp And bHashKeyUnique=0 And iLenCumul<iLen Then : this.pNode = pTemp
        ElseIf bHTmethod=1 And IsLast=0 Then
            pTemp03=AllowCake : this.uCount+=1
            pTemp03->pNext=pTemp : pTemp03->pPrev=pTemp->pPrev : pTemp->pPrev->pNext=pTemp03 : pTemp->pPrev=pTemp03         
            If bBranchCountDown=1 Then : this.BCountDown(1) : End If
            pTemp03->Tag(uTag) = Str_tmp : HadHashTag=0 : pFirstNode->BranchCount+=1 : pNode = pTemp03           
            If bTrackMultiKeys>0 And bCopyCatRelation=0 Then                 
                If pTemp->Tag(uTag)=Str_tmp Then : If pNode->pNext->pBranchLastNode=0 Then : pNode=pNode->pNext : this.HoldBack(bTrackMultiKeys) : pNode=pTemp03 : End If : this.HoldBack(bTrackMultiKeys) : End If
            End If           
        Else ' If pTemp=pTemp02 Then : this.BlindTag(Str_tmp)                           
            pTemp03 = this.pLastNode : this.uCount+=1 : pTemp03->pNext = this.AllowCake 'And eat it
            pTemp03->pNext->pPrev = this.pLastNode : pTemp03->pNext->Tag(uTag) = Str_tmp
            this.pLastNode = pTemp03->pNext : this.pNode = pTemp03->pNext : If bBranchCountDown=1 Then : this.BCountDown(1) : End If
            pLastNode->pPrev = pTemp03 : HadHashTag=0 : pFirstNode->BranchCount+=1
            If bTrackMultiKeys>0 And bCopyCatRelation=0 Then                 
                If pTemp->Tag(uTag)=Str_tmp Then : If pNode->pNext->pBranchLastNode=0 Then : pNode=pNode->pNext : this.HoldBack(bTrackMultiKeys) : pNode=pTemp03 : End If : this.HoldBack(bTrackMultiKeys) : End If
            End If
     '  Else : Print "LZLE error - attempt to clean process and aborting."  : Print this.DropAll & " / " & this.NodeCount : sleep : system
        End If
        If iLenCumul<iLen Then  '  If u*istep<iLen Then   ' this.Branch
            pFirstNode->BranchCount=this.uCount : pFirstNode->pBranchLastNode=pLastNode : pTemp=pNode
            If this.pNode->pBranch=0 Then ' New 'Hash' : this.BlindTag(LIST_RES) :
                pTemp03 = this.pLastNode : this.uCount+=1 : pTemp03->pNext = this.AllowCake 'And eat it
                pTemp03->pNext->pPrev = pTemp03 : pTemp03->pNext->Tag(uTag) = LIST_RES
                pTemp03 = pTemp03->pNext : this.pLastNode = pTemp03 : pNode=pTemp03
                this.pNode->pPrev=this.pFirstNode : pNode->pBranch = pTemp : pTemp->pBranch=this.pNode
                this.uCount=0 :' pTemp->pBranchLastNode=this.pNode     pTemp->BranchCount=0 :
                this.pFirstNode=pTemp->pBranch : this.pNode = this.pFirstNode : If ubKeysRegister=1 Then : pFirstNode->Tag(1)=Left(str_testTMP, iLenCumul+iLenDelta) : End If      '
            Else 'Branche déjà créée
                this.pFirstNode = this.pNode->pBranch : this.uCount = this.pFirstNode->BranchCount
                this.pLastNode = this.pNode->pBranch->pBranchLastNode : this.pNode = this.pNode->pBranch
            End If
        End If : pTemp02=pFirstNode
    Next i
    this.pLatestHTag=this.pNode : this.sLatestHTag=str_testTMP :
    this.pFirstNode->pBranchLastNode = this.pLastNode
    If this.pNode->Tag(1)="" And bRHByPass=0 Then : this.pNode->Tag(1)=" " : End If
    If pTemp04<>0 Then : pTemp04->BranchCount=CuInt(pFirstNode)  : End If
    If IsPt2Swp=1 Then : Swap Listptemp2,Listptemp2_b : _Deallocate(Listptemp2_b) : End If : If IsPtSwp=1 Then : Swap Listptemp,Listptemp_b : _Deallocate(Listptemp_b) : End If     
  ' If pNode=pFirstNode Then : Print "Error  : pNode=pFirstNode  !! " : beep : sleep : End IF
 '  If this.HashTag<>str_testTMP Then : Print "Erreur sur " & this.HashTag & " <> " & str_testTMP : beep : sleep : End If ' Debug & tests
'  If bHashKeyUnique=0 Then : HadHashTag=0 : End If
    Return HadHashTag
End Property

Property List.HashTag As String
    Dim As ListNode Ptr pTemp01= this.pFirstNode, pTemp02=this.pNode
    If bTracking=1 And bTrackingMethod=0 Then : This.TrackCompute :  pTemp01 = this.pFirstNode : pTemp02 = this.pNode : End If     
    Str_tmp = this.Tag(uTag) ' this.pnode->Tag(uTag)
    If pTemp01->pPrev<>0  AndAlso pFirstNode->Tag(1)<>"" AndAlso ubKeysRegister=1 Then : KR_Count+=1 : Return pFirstNode->Tag(1) & pTemp02->Tag(0) : End If
    While pTemp01->pPrev<>0
        pTemp02 = pTemp01->pBranch
        Str_tmp = pTemp02->Tag(0)  + Str_tmp                 
        pTemp01 = pTemp01->pPrev
    Wend   
    Return Str_tmp
End Property

Property List.HasHashTag(str_Tag As String) As Byte
    Dim As zString Ptr  zp1, zp2
    Dim pContextRetour As ListContext
    Dim HadHashTag As Byte=0 : Dim IsEtoile As Byte=0 : Dim i as uByte=1 : Dim t as uByte=Len(str_Tag) : Dim istep As uByte=this.bHashLen
    pContextRetour.pNode=pNode : pContextRetour.pFirstNode=This.pFirstNode : pContextRetour.pLastNode=This.pLastNode : pContextRetour.uCount=This.uCount
    pFirstNode->BranchCount=uCount : pFirstNode->pBranchLastNode=pLastNode : pFirstNode=pFirstFIRSTNode :  'this.RootPrivate
    this.uCount = this.pFirstNode->BranchCount : pLastNode=this.pFirstNode->pBranchLastNode   
    zp1=Listptemp+Len(str_Tag)+1 : (*zp1)[0]=0 : *Listptemp=str_Tag : zp1=Listptemp' * Alternative to Mid
    Do
        zp2=zp1 : zp1+=istep : (*zp3)[0]=(*zp1)[0] : (*zp1)[0]=0 : Str_tmp=*zp2 : (*zp1)[0]=(*zp3)[0] ' * Alternative to Mid : Str_tmp=Mid(str_Tag,i, istep)
        If this.HasTag(Str_tmp)=1 Then           
            this.pNode = this.pSearchNode
            If this.pNode->Tag(1)="*" Then : HadHashTag=1 : IsEtoile=1 : i=t
            ElseIf this.pNode->Tag(1)="!*" Then : HadHashTag=0 : i=t
            ElseIf this.pNode->Tag(1)="!" And i=t Then : HadHashTag=0
            ElseIf i>=t Then : HadHashTag=1
            Else :  HadHashTag=0 : End If   
        ElseIf IsEtoile=0 Then : HadHashTag=0 : i=t
        End If
        If i<t Then
            If this.pNode->pBranch=0 Then
                If bAutoCursor<3 Then : pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount : End If
                If bHashKeyUnique=1 Then : pNode=pNode->pNext : Return 1 : Else : If bHashStepRev=1 Then : Return this.KeyStepRev : Else : Return this.KeyStep :  End If  : End If                 
            Else : this.pFirstNode = this.pNode->pBranch : this.uCount = this.pFirstNode->BranchCount : this.pLastNode = this.pFirstNode->pBranchLastNode : this.pNode = this.pFirstNode
            End If : this.bSearchRes = 0
        End If
        i+=istep
    Loop Until i>t
    If HadHashTag=1 Then : bSearchRes=1 : pSearchNode=pNode
        If bAutoCursor=1 Then : Return 1
        ElseIf bAutoCursor=2 Then : If pNode->Tag(1)="" Then : HadHashTag=0 : Else : Return 1 : End If
        End If
    End If
    pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount
    Return HadHashTag   
End Property

Property List.HasKey(str_Tag As String) As Byte : If this.HasHashTag(str_Tag)=1 Then : If pNode->Tag(1)<>"" And pNode->Tag(1)<>LIST_DEL Then : Return 1 : Else : Return 0 : End If : Else : Return 0 : End If : End Property
Property List.BranchCount As uInteger : If this.pNode->pBranch<>0 Then : Return pNode->BranchCount : Else : Return 0 : End If : End Property ' Return this.pNode->BranchCount

Property List.NodeFlat As Byte 'Réallocation sélective dynamique multimodes rétro-récursive (virtuelle/reelle glissante 0/-n) de la structure de l'index en memoire virtuelle (Reduce) - Compatible HashStep, HashStepRev(?), KeyStep, KeyStepRev(?), fStep, TrackStep
    Dim As ListContext pContext, pContextRetour : Dim  As ListNode Ptr pTemp1, pTemp2, pTemp3, pTemp4, pTemp5, pTemp6, pTemp7 : Dim As uByte IsLastNode=0       
    this.NodeRecycle : NodeRecycle2 ': If pFirstNode->pPrev=0 And pNode->pNext=0 Then : Print "LZLE : NodeFlat attempted on last written node without previous Root = unsupported feature" : Return 0 : End If
    'Contrôle multimode en entrée + contrôle du Token de fin de liste + gestion continuité des ptr
    If pNode->Tag(0)=LIST_RES Or pNode->Tag(0)=LIST_DEL Or pNode=pWhyteMove Or pNode=pGarbage Then : Return 0
    ElseIf bTracking=1 Then
        If pFirstNode->pBranch=pFlatRoot Then : Return 0 : End If
        If bTrackingMethod=0 Then : this.TrackCompute : pLastNode->pNext=0 : End If : pTemp6=pNode->pBranchLastNode
    ElseIf pFirstNode->pPrev=0 And pNode->pNext=0 Then : pTemp1=pNode : this.AllOf : pNode=pTemp1
    End If : pTemp5=pFirstNode : pTemp2 = this.pNode : If uTag=0 Then : Str_tmp=this.HashTag : Else : Str_tmp=pNode->Tag(uTag) : End If : pLatestHTag=0
    'Gestion (swapping) des nodes parents                                                   ---------------------------------------------------------------------------
    If this.pNode->pBranch<>0  Then
        'Validation du mouvement mémoire : ' Fonctionnalité Tree List =>FlatList / ByPass Garbage ou 'Déjà swappé 
        If this.bNFmethod<>1 Then : Return 0 : ElseIf this.pNode->Tag(1)=LIST_DEL Then : Return 0 : ElseIf bHashStepRev=1 And pNode->pNext->Tag(0)=LIST_DEL Then : Return 0 : End If  ' PATCHED !!
        pTemp1=AllowCake : pTemp4=this.pFlatRoot->pBranch : If this.pNode->pPrev<>0 Then : this.pNode->pPrev->pNext=pTemp1 : End If
        If this.pNode->pNext->pPrev=this.pNode Then this.pNode->pNext->pPrev=pTemp1 : End If       
        pTemp1->pPrev=this.pNode->pPrev : pTemp1->pNext=this.pNode->pNext : pTemp1->pBranch=this.pNode->pBranch
        pTemp1->BranchCount=this.pNode->BranchCount : pTemp1->Tag(0)=this.pNode->Tag(0) : pTemp1->Tag(1)=LIST_DEL
        pTemp1->pBranchLastNode=this.pNode->pBranchLastNode
        If pTemp2=pLastNode Then : pLastNode=pTemp1 : End If
        this.pNode->pBranch->pBranch=pTemp1 : this.pNode->pBranch=0 : this.pNode->Tag(0) = Str_tmp
        this.pNode->pPrev=pTemp4 : pTemp4->pNext->pPrev=this.pNode : this.pNode->pNext=pTemp4->pNext : pTemp4->pNext=this.pNode : this.pNode=pTemp1
    Else : this.uCount-=1 : pFirstNode->BranchCount-=1 :  If bBranchCountDown=1 Then : this.BCountDown(-1) : End If
    End If   
    'Gestion (/optimisation) du parsing (rétro-récursivité) ds le HashStep       ---------------------------------------------------------------------------       
    If pNode->pPrev<>pFirstNode Then
        If this.pNode->pNext->Tag(0)=LIST_DEL Then : This.pLastNode=this.pNode->pPrev : This.pFirstNode->pBranchLastNode=this.pNode->pPrev : End If
        If bHashStepRev=1 Then : pContextRetour.pNode=pNode->pNext : Else : pContextRetour.pNode=pNode->pPrev : End If
        pContextRetour.pFirstNode=This.pFirstNode : pContextRetour.pLastNode=This.pLastNode : pContextRetour.uCount=This.uCount   
    Else
        pContext.pNode=This.pNode : pContext.pFirstNode=This.pFirstNode : pContext.pLastNode=This.pLastNode : pContext.uCount=This.uCount       
        If pNode=pLastNode Then : pTemp3=this.pFirstNode->pBranch->pPrev : Else : pTemp3=this.pFirstNode->pBranch : End If
        If pTemp3->Tag(0)=LIST_RES Then
            If pNode=pLastNode Then : this.pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : pLastNode=pFirstNode->pBranchLastNode : End If
            pTemp3=this.pFirstNode->pBranch
        End If
        this.pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount ' This.UpLevel         
        pContextRetour.pNode = pTemp3 : pContextRetour.pFirstNode = This.pFirstNode : pContextRetour.pLastNode = This.pLastNode : pContextRetour.uCount=This.uCount
        This.pNode=pContext.pNode : This.pFirstNode=pContext.pFirstNode : This.pLastNode=pContext.pLastNode : this.uCount=pContext.uCount                 
    End If
    If this.pNode->pNext=0 And this.pNode->pPrev->Tag(0)=LIST_RES Then
        pLocalRoot=this.pNode->pPrev : IsLastNode=1 :  pLocalRoot->Tag(1)="" :
        If this.pFirstNode->pBranchLastNode=0 Then : pLocalRoot = this.pFirstNode : pLocalRoot->pBranch->pBranch=0 :  pLocalRoot->Tag(1)="" : pLocalRoot->Tag(0)=LIST_DEL : End If
    ElseIf this.pNode=this.pFirstNode->pBranchLastNode Then       
        If this.pNode->pPrev->Tag(0)=LIST_RES Then : pLocalRoot=this.pNode->pPrev : IsLastNode=1 : pLocalRoot->Tag(1)="" :  pLocalRoot->Tag(0)=LIST_DEL
        Else : this.pLastNode=this.pNode->pPrev : pFirstNode->pBranchLastNode=pLastNode : IsLastNode=1
        End If
    End If
   ' pFirstNode->Tag(1)=""
  ' Swapping / MAJ des pointeurs - depend de IsLastNode                        --------------------------------------------------------------------------     
  ' Envoi d'un ancien node parent déjà swappé vers le garbage collector OU envoi d'un node non parent vers le GarbageCollector (si NFmethod=-1)
    If (pTemp2->Tag(1)=LIST_DEL Or this.bNFmethod=-1) And pTemp2->pBranch=0   Then ' And bNFmethod<>3
        If IsLastNode=0 Then : pTemp2->pNext->pPrev=pTemp2->pPrev : pTemp2->pPrev->pNext=pTemp2->pNext : End If
        pFlatRoot->pNext->pPrev=pTemp2 : pTemp2->pPrev=pFlatRoot : pTemp2->pNext=pFlatRoot->pNext : pFlatRoot->pNext=pTemp2
        pTemp2->Tag(0)=LIST_DEL : pTemp2->Tag(1)="" : uGarbCt+=1 : pTemp2->pBranchLastNode=0
        If pTemp2->ListData<>0 Then : pTemp2->ListData->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pTemp2->ListData : pTemp2->ListData=0 : uContainerGarbCt+=1 : End If
        This.pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount
        If IsLastNode=0 And  bHashStepRev=1 Then : If this.Up=0 Then : If pNode=pNode->pNext <>0 Then : pNode=pNode->pNext  : End If : End If
        ElseIf IsLastNode=1 Then
            'If pTemp5->pPrev=0 Then : pTemp1=pNode : this.BlindTag(" ") : pNode->pNext=0 : pNode=pTemp1: return 0 : End If
            this.pNode=pTemp5->pBranch : this.uCount=pTemp5->pPrev->BranchCount : pLastNode=pTemp5->pPrev->pBranchLastNode : this.pFirstNode = pTemp5->pPrev           
            If bTracking=1 Or bPickReduce=1 Then : If pNode->Tag(1)="" Or pNode->Tag(1)=LIST_DEL Then : this.NodeFlat : this.NodeRecycle2 : End If
            ElseIf bHashStepRev=1 Then : If this.Up=0 Then : this.Last : End If : this.NodeRecycle2 : Return 1
            Else : If pFirstNode<>pFirstFIRSTNode Then : this.UpLevel : Else : pNode=pGarbage : End If  : this.NodeRecycle2 : Return 1 : End If : '  this.NodeFlat : this.NodeRecycle2 ' RECURSIF
        End If
    Else ' Envoi vers la Flat list - Optimisation, à voir                                      --------------------------------------------------------------------------                 
        pFlatRoot->pBranch->BranchCount+=1         
        pNode=pFirstNode->pNext : this.UpLevel
        this.pFirstNode = this.pFirstFIRSTNode : this.pLastNode = this.pFirstNode->pBranchLastNode : this.uCount=this.pFirstNode->BranchCount
        this.pNode=this.pFlatRoot : this.Branch ' this.FlatStack
        If pFlatRoot->pBranch->BranchCount=0 Then : pFlatRoot->pBranch->BranchCount=1 : this.uCount=1 :  End If
        pTemp1 = this.pLastNode
        If IsLastNode=0 Then
            If pTemp2->pNext<>0 Then : pTemp2->pNext->pPrev=pTemp2->pPrev : End If
            If pTemp2->pPrev<>0 And pTemp2->Tag(0)<>LIST_RES Then : pTemp2->pPrev->pNext=pTemp2->pNext : End If
            pTemp2->pPrev= this.pLastNode : pTemp1->pNext = pTemp2 : this.pLastNode=pTemp2
            this.pFirstNode->pBranchLastNode = pTemp2 : pTemp2->Tag(uTag) = Str_tmp : pTemp2->pPrev=pTemp1 : pTemp2->pNext=0
            this.pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount     
            If bHashStepRev=1 Then : If this.Up=0 Then : this.BlindStep : End If : If pNode=pNode->pNext <>0 Then : pNode=pNode->pNext : End If : Return 1 :  End If             
        Else
            pTemp1->pNext=pTemp2  : pTemp2->pNext=0 : this.pLastNode=pTemp2
            this.pFirstNode->pBranchLastNode = pTemp2  : pTemp2->Tag(uTag)=Str_tmp : pTemp2->pPrev=pTemp1  '
            this.pNode=pTemp5->pBranch : this.pFirstNode = pTemp5->pPrev : pLastNode=pTemp5->pPrev->pBranchLastNode : this.uCount=pTemp5->pPrev->BranchCount 
            If bTracking=1 Or bPickReduce=1 Then :  If pNode->Tag(1)="" Or pNode->Tag(1)=LIST_DEL  Then : this.NodeFlat : this.NodeRecycle2 : End If
            ElseIf bHashStepRev=1 Then : If this.Up=0 Then : this.Last : End If : this.NodeRecycle2 : If pNode=pNode->pNext <>0 Then : pNode=pNode->pNext : End If  : Return 1
            Else : If pFirstNode<>pFirstFIRSTNode Then : this.UpLevel : Else : pNode=pGarbage : End If  : this.NodeRecycle2 : Return 1 : End If ' this.NodeFlat : this.NodeRecycle2 ' RECURSIF
        End If
    End If
    If bTracking=1 And pTemp6<>0 Then : this.NodeRecycle : pNode=AllowCake : pNode->pBranchLastNode=pTemp6 : pLocalMove=pNode : pLocalMove->Tag(0)=LIST_DEL : Return 1 : End If
    Return 1
End Property

Property List.RestoreHash As Byte
    Dim As ListNode Ptr pTemp,  pTmpPrev, pTmpNext, pMove
    Dim str_tmp as string=this.Tag : Dim bTagExists As Byte : Dim uTagTmp As Byte=uTag
'    If pNode=pEndFlat then : this.Root : Return 0 : End If
    pTemp=this.pnode : str_tmp=this.Tag(uTag) : If str_tmp="" Then : Return 0 : End If : pTmpPrev=this.pnode->pPrev : pTmpNext=this.pnode->pNext
    'Vérification du contexte
    this.NodeRecycle
    If this.pNode=this.pEndFlat Or pFirstNode->pBranch<>pFlatRoot  Then : Return 0 : End If
    'HashTagging
    uTag=0 : bRHByPass=1 : bTagExists=this.HashTag(str_tmp) : bRHByPass=0     
    If bHashKeyUnique=0 Then 'Multikeys=>1 seul mode possible car pas de conflit possible
        pTemp->Tag(0)= this.pnode->Tag(uTag)  : pMove=this.pnode : pMove->Tag(0)=str_tmp : bTagExists=2 ' swap
    ElseIf bTagExists=1 And pNode->Tag(1)<>""  Then ' tag deja existant et "vraie" clef
        'Gestion des modes (RHmethod)
        If bRHmethod=-1 Then : pTemp->Tag(0)= this.pnode->Tag(uTag)  : pLocalMove=this.pnode : pLocalMove->Tag(0)=LIST_DEL : this.pFlatRoot->pBranch->BranchCount-=1 ':  pLocalMove->pBranch=0  :'envoi garbage
        ElseIf bRHmethod=1 Then : pTemp->Tag(0)= this.pnode->Tag(uTag)  : pMove=this.pnode : pMove->Tag(0)=str_tmp : bTagExists=2 ' swap
        Else : If pNode->Tag(1)=LIST_DEL Then : pNode->Tag(1)=" " : End If : this.RootPrivate : this.pNode=this.pFlatRoot : this.Branch : pNode=pTemp : Return 0  ' bypass
        End If       
    Else : pTemp->Tag(0)= this.pnode->Tag(uTag) : pLocalMove=this.pnode : pLocalMove->Tag(0)=LIST_DEL : this.pFlatRoot->pBranch->BranchCount-=1 ':  pLocalMove->pBranch=0  :
    End If
    uTag=uTagTmp
    'Swapping mémoire
    pTemp->pPrev->pNext=pTemp->pNext : pTemp->pNext->pPrev=pTemp->pPrev
    pTemp->pPrev=this.pnode->pPrev : pTemp->pNext=this.pnode->pNext
  '  If bNFmethod<>3 Then : pTemp->pBranch=this.pnode->pBranch : End If  ' Deprecated : "flat" list is not designed to support a hierarchy - would be too complex to manage - use snatch instead
    this.pnode->pPrev->pNext=pTemp
    If this.pnode->pNext<>0 Then : If this.pnode->pNext->pPrev=this.pnode Then : this.pnode->pNext->pPrev=pTemp :  End If : End If
    If this.pnode=this.pLastNode Then : this.pLastNode=pTemp : End If : If this.pnode=this.pFirstNode Then : this.pFirstNode=pTemp : End If     
    If this.pnode->pBranch<>0 Then  '  pFirstNode->Tag(1)=""  '  pnode->pBranch->Tag(1)=""
        If this.pnode=this.pFirstNode->pBranchLastNode Then : this.pFirstNode->pBranchLastNode=pTemp : End If
        If this.pnode->pBranch->pBranch=this.pnode Then : this.pnode->pBranch->pBranch=pTemp : End If       
        pTemp->pBranch=this.pnode->pBranch : pTemp->pBranchLastNode=this.pnode->pBranchLastNode : pTemp->BranchCount=this.pnode->BranchCount
    End If
    'Reprise ds Flat List
    this.FlatStack(1)
    If bTagExists<>2 Then : this.pnode=pLocalMove : this.pnode->pPrev=pTmpPrev : this.pnode->pNext=pTmpNext :  pLocalMove->pBranch=0  : pLocalMove->Tag(1)="" : pLocalMove->Tag(0)=LIST_DEL :
    Else : pNode=pMove : pTmpPrev->pNext=pNode : pTmpNext->pPrev=pNode : pNode->pPrev=pTmpPrev : pNode->pNext=pTmpNext :
    End If
    Return 1
End Property

'==========================================================================================TYPE LIST PUBLIC PROPERTIES - PROPERTIES PARAMETERS
Property List.AutoCursor(b As Byte) As Byte : If 0<=b<=3 Then : bAutoCursor=b : Return 1 : End If : Return 0 : End Property
Property List.BranchCountDown(i as Byte) As Byte
    If i<>0 And i<>1 Then : Print "BranchCountDown : invalid parameter" : Return 0 : ElseIf i=0 Or (i=1 And bColBcountLocked=0) Then : bBranchCountDown=i : bColBcountLocked=i : Return 1 : Else : Print "Branch count vector already booked" : Return 0 : End If
End Property
Property List.CopyCatMethod(i As Byte) As Byte : If i=0 Or i=1 Then : bCopyCatMethod=i : Return 1 : Else : Print "CopyCatMethod : invalid parameter" : Return 0 : End If : End Property
Property List.HashKeyUnique(ub as Byte) As Byte : If ub=0 Or ub=1 Then : bHashKeyUnique=ub : bSeekMethod=ub : Return 1 : Else : Print "HashKeyUnique : invalid parameter" :  Return 0 : End If : End Property
Property List.HashLen(bHashLen As uByte) As Byte : If bHashLen>0 And bHashLen<255 Then : this.bHashLen = bHashLen : Return 1 : Else : Print "HashLen : invalid parameter" :  Return 0 : End If : End Property
Property List.KeysRegister(ub As uByte) As Byte :  If ub=0 Or ub=1 Then : ubKeysRegister=ub : Return 1 : Else : Print "KeysRegister : invalid parameter" :  Return 0 : End If : End Property
Property List.NFmethod(i As Byte) As Byte : If i=-1 Or i=0 Or i=1 Then : this.bNFmethod=i : Return 1 : Else : Print "NFmethod : invalid parameter" : Return 0 : End If : End Property
Property List.NFrecursive(i As Byte) As Byte : If i=1 Then : this.bPickReduce=1 : Else : this.bPickReduce=0 : End If : Return 1 : End Property
Property List.PVSmethod(ub As Byte) As Byte :
    If ub=-1 Then : bPVSmethod=ub : Return 1
    ElseIf bColBcountLocked=0 and ub<2 Then : bPVSmethod=ub : bColBcountLocked=1 : Return 1
    Else : Print "PVSmethod : Branch count vector already booked or invalid parameter" : Beep : sleep : Return 0 : End If
End Property
Property List.PVSratio(ub As uByte) As Byte : If ub>1 Then : PVS_ratio=ub : Return 1 : Else : Return 0 : End If : End Property
Property List.RHmethod(i As Byte) As Byte : If -2<i<2 Then : this.bRHmethod=i : Return 1 : Else : this.bRHmethod=-1 : Return 0 : End If : End Property
Property List.SeekMethod(i as Byte) As Byte : If i=0 Or i=1 Or i=2 Then : this.bSeekMethod=i : Return 1 : Else : Return 0 : End If : End Property
Property List.SnatchBLmethod(i As Byte) As Byte : If i=0 Or i=1 Then : bSnatchBLMethod=i : Return 1 : Else : Print "SnatchBeMethod : invalid parameter" : Return 0 : End If : End Property
Property List.TrackMethod(by As Byte) As Byte : If by=0 Or by=1 Then : bTrackingMethod=by : Return 1 : Else : Return 0 : End If: End Property
Property List.TrackMultiKeys(uB as uByte) As Byte : If -1<=uB<=MAX_COLS Then : bTrackMultiKeys=uB : Return 1 : End If : Return 0 : End Property
Property List.VectorUnlock As Byte : bColBcountLocked=0 : bColTrackLocked=0 : Return 1 : End Property
Property List.VectorClear As Byte
    Dim As ListNode Ptr Ptemp1=pNode, pTemp2 : Dim As Byte IsUp=0
    pTemp2=pTemp1->pNext
    If pTemp2=0 Or pNode->Tag(0)=LIST_RES  Or pNode->Tag(0)=LIST_DEL Then : Return 0 : End If
    If bColBcountLocked=1 Or bPVSmethod=1 Then : While this.HashStepTrace And pNode<>pTemp2 :  If bHStepTrace=-1 Then : pFirstNode->Tag(1)="" : End If : pNode->BranchCount=0 : Wend
    Else : While this.HashStepTrace And pNode<>pTemp2 :  If bHStepTrace=-1 Then : pFirstNode->Tag(1)="" : End If : Wend
    End If : pNode=pTemp1 : Return 1
End Property

'==========================================================================================TYPE LIST PUBLIC PROPERTIES - FLOW CONTROL
Property List.Up As Byte : If pFirstNode=pFirstFIRSTnode Then : Return 0 : Else :  this.UpLevel : Return 1: End If : End Property
Property List.Down As Byte
    If pnode->pBranch=0 Or pNode->Tag(0)=LIST_RES Then  : Return 0 : End If
    If pnode->pBranch->pPrev<>pFirstNode Then : Return 0 :
    Else : pFirstNode->BranchCount=uCount : pFirstNode->pBranchLastNode=pLastNode : pFirstNode=pNode->pBranch : uCount=pFirstNode->BranchCount : pLastNode=pNode->pBranch->pBranchLastNode : pNode=pNode->pBranch : Return 1
    End If
End Property
Property List.HoldBack As Byte : Return this.HoldBack(0) : End Property
Property List.HoldBack(by As Byte) As Byte   
    If pNode->Tag(0)=LIST_RES Or bColTrackLocked=1 Then : Return 0
    ElseIf TrackTrace(by)<>0 Then : TrackTrace(by)->pBranchLastNode=pNode : TrackTrace(by)=this.pNode : Return 1
    Else : this.TrackSet(by) : pNode->pBranchLastNode=0 : TrackTrace(by)=pNode : Return 1
    End If
End Property
Property List.TrackStep As Byte
    Dim As ListNode Ptr pTemp1 : bAlrdyTracked=0
    If pNode->pBranchLastNode->Tag(0)=LIST_DEL Or bColTrackLocked=1 Then : this.Root : bTracking=0 : Return 0 : End If ' Or pNode->pBranchLastNode->Tag(0)=LIST_RES
    If pNode->pBranchLastNode<>0  And pNode->pBranchLastNode->Tag(0)<>LIST_RES Then           
        pNode=pNode->pBranchLastNode : bTracking=1
        If bTrackingMethod=1 Then : this.TrackCompute ': pLastNode->pNext=0
        End If : Return 1
    End If : this.TrackCompute : bTracking=0 : Return 0
End Property
Property List.Track As Byte : Return this.Track(0) : End Property
Property List.Track(by As Byte) As Byte
    this.Root : If bColTrackLocked=1 Then : Print "Tracking vector already in use (internal) by CopyCat/Follow" & chr(10) & "Use HashStep or other iterator" & chr(10) & "Attempt to use incompatible vectors may lead to crash" : Return 0 : End If : bAlrdyTracked=0
    If pNode->Tag(0)<>LIST_DEL And pNode->Tag(0)<>LIST_RES And pNode<>pLocalMove Then : This.TrackCompute : End If : bTracking=1 : this.Root ': This.TrackMethod(1)
    If this.Tracks(by).pNode=0 Then : this.TrackSet(by)  : Return 0
    Else
        pFirstNode->BranchCount=this.uCount : pFirstNode->pBranchLastNode=pLastNode : this.NodeRecycle : pNode=AllowCake : pLocalMove=pNode : pLocalMove->Tag(0)=LIST_DEL
        If this.Tracks(by).pNode->Tag(0)=LIST_DEL Then : pNode->pBranchLastNode=this.Tracks(by).pNode->pBranchLastNode
        Else : pNode->pBranchLastNode=this.Tracks(by).pNode
        End If
        pFirstNode=this.Tracks(by).pFirstNode : pLastNode=pFirstNode->pBranchLastNode : bHashLen=this.Tracks(by).bLcHashLen
        pNode->pBranch=0 : pNode->pPrev=0 : pNode->Tag(0)=""
        Return 1
    End If
End Property
Property List.TrackSet As Byte : Return this.TrackSet(0) : End Property
Property List.TrackSet(by As Byte) As Byte
    this.NodeRecycle : If pNode->pBranchLastNode<>0 Then : this.Tracks(by).pNode=pNode->pBranchLastNode  : Else : this.Tracks(by).pNode=pNode : End If
    this.Tracks(by).pFirstNode=pFirstNode : this.Tracks(by).bLcHashLen=bHashLen : TrackTrace(by)=0 : Return 1
End Property
Property List.TrackClear As Byte : Return this.TrackClear(0) : End Property
Property List.TrackClear(by As Byte) As Byte : TrackTrace(by)=0 : Return 1  : End Property
Property List.IsTracked As Byte : Dim i As Byte : If pNode->pBranchLastNode<>0 And pNode->Tag(0)<>LIST_RES Then : Return 1 : Else : For i=0 To MAX_COLS-1 : If TrackTrace(i)=pNode Then : Return 1 : End If : Next i : Return 0 : End If  : End Property

Property List.Aside As Byte : Return this.Aside(1) : End Property
Property List.Aside(by As Byte) As Byte
    If by > MAX_COLS-1 Or By < 1 Then : Return 0 : End If : If bTrackingMethod=1 Then : This.TrackCompute : End If
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    Lcontext(by).pNode=pNode : Lcontext(by).pFirstNode=pFirstNode : Lcontext(by).pLastNode=pLastNode : Lcontext(by).uCount=this.uCount : Lcontext(by).LcHashTag=pNode->Tag(0) : Lcontext(by).bLcHashLen=this.bHashLen
    Return 1
End Property
Property List.Recover As Byte : Return this.Recover(1) : End Property
Property List.Recover(by As Byte) As Byte
    If by > MAX_COLS-1 Or By < 1 Then : Return 0 : End If : If bTrackingMethod=1 Then : This.TrackCompute : End If
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    pNode=Lcontext(by).pNode : pFirstNode=Lcontext(by).pFirstNode : this.bHashLen=Lcontext(by).bLcHashLen
    pLastNode=pFirstNode->pBranchLastNode : this.uCount= this.pFirstNode->BranchCount : this.bHashLen=Lcontext(by).bLcHashLen
    Return 1
End Property
Property List.Follow(pList As List) As Byte
    Dim As ListNode Ptr pTemp1=pList.Relation : bAlrdyTracked=0
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode : bTracking=1
    If pTemp1<>0 Then : this.pNode=pTemp1 : Else : Return 0 : End If
    this.pLastNode=pFirstNode->pBranchLastNode : this.uCount=this.pFirstNode->BranchCount
    Return 1
End Property

'==========================================================================================MEMORY MANAGEMENT
Property List.FlatCount As uInteger : Return this.pFlatRoot->pBranch->BranchCount : End Property
Property List.GarbageCount As uInteger : Return this.uGarbCt : End Property
Property List.ContainerCount As uInteger : Return this.uContainerGarbCt : End Property
Property List.NodeCount As uInteger : Return this.uNodeCOUNT : End Property

Property List.GarbageFlat As Byte
    Dim L_Context As ListContext : Dim As ListNode Ptr pTemp1, pTemp2, pTemp3 : Dim i as Byte
    If pFlatRoot->pBranch=0 Then : Return 0 : End If
    If pFlatRoot->pBranch->pNext=pFlatRoot->pBranch Then : pLocalMove=pFlatRoot->pBranch : pLocalMove->pBranch=0 : pLocalMove->Tag(1)="" : pLocalMove->Tag(0)=LIST_DEL : this.NodeRecycle : Return 0 : End If
    If pFlatRoot->pBranch->pNext=pFlatRoot->pBranch->pBranchLastNode Then : Return 0 : End If
    pTemp1=pFlatRoot->pBranch->pNext : pTemp2=pEndFlat->pPrev
    If pTemp2=0 Then
        L_Context.pNode=pNode : L_Context.pFirstNode=pFirstNode : L_Context.pLastNode=pLastNode : L_Context.uCount=this.uCount
        this.FlatStack : pTemp2=pEndFlat->pPrev
        pNode=L_Context.pNode : pFirstNode=L_Context.pFirstNode : pLastNode=L_Context.pLastNode : this.uCount=L_Context.uCount
    End If :  If pTemp1=pTemp2 Then : Return 0 : End If
    pFlatRoot->pNext->pPrev=pTemp2 : pTemp2->pNext=pFlatRoot->pNext
    pFlatRoot->pNext=pTemp1 : pTemp1->pPrev=pFlatRoot
    Do
        pTemp1->Tag(0)=LIST_DEL : For i=1 to RUP_COLS : pTemp1->Tag(i)="" : Next i : pTemp1->pBranchLastNode=0 : pTemp1->BranchCount=0 ' : pTemp1->ListData.sData=""
        pTemp3=pNode : pNode=pTemp1 : this.Val("") :
        If pTemp1->ListData<>0 Then : pTemp1->ListData->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pTemp1->ListData : pTemp1->ListData=0 : uContainerGarbCt+=1 : End If
        pNode=pTemp3
        pTemp1=pTemp1->pNext
    Loop Until pTemp1=pTemp2
    pTemp1->Tag(0)=LIST_DEL : For i=1 to RUP_COLS : pTemp1->Tag(i)="" : Next i : pTemp1->pBranchLastNode=0 : pTemp1->BranchCount=0 ': pTemp1->ListData.sData=""
    pTemp3=pNode : pNode=pTemp1 : this.Val("") : pNode=pTemp3
    uGarbCt+=pFlatRoot->pBranch->BranchCount
    pFlatRoot->pBranch->pNext=pFlatRoot->pBranchLastNode : pFlatRoot->pBranchLastNode->pPrev=pFlatRoot->pBranch : pFlatRoot->pBranch->BranchCount=0
    If pFirstNode=pFlatRoot->pBranch Then : uCount=0 : this.RootPrivate : End If
    Return 1
End Property

Property List.Recycle As uInteger : Dim As ListNode Ptr pTemp=pNode : this.BlindTag(" ") : pNode=pTemp : this.Up : this.Root : this.AllOf :  Return this.AllRecycle : End Property  '

Property List.DropAll As uInteger  'pRoot principal + pFlatRoot + pFlatRoot->pBranch + pGarbage + pLastLAST/pWhyte = 5 nodes déalloues ds destructor     
    If this.IsDestroyed=1 Then : Return 0 : End If : this.NodeRecycle : this.NodeRecycle2
    Dim As ListNode Ptr pTemp=pNode : this.BlindTag(" ") : pNode=pTemp : this.Up : this.Root : this.GarbageFlat :  this.AllOf : this.AllRecycle : this.NodeRecycle : this.NodeRecycle2
    pTemp=pFlatRoot->pNext  : Dim iLong As uInteger=0   
    While pTemp<>pGarbage And pTemp<>0 And pTemp<>pFlatRoot
        If pFlatRoot->pNext->ListData<>0 Then : _Deallocate(pFlatRoot->pNext->ListData) : End If
        _Deallocate(AllowCake) : pTemp=pFlatRoot->pNext : this.uNodeCOUNT-=1 : iLong+=1
    Wend   
    Dim pPanTemp As ListContainer Ptr =pPanCakeGarbage->pNextContainer : Dim SeekMt As Byte=this.bSeekMethod
    While pPanTemp<>pPanCakeGarbage : _Deallocate(AllowPanCake) : pPanTemp=pPanCakeGarbage->pNextContainer : Wend  ' pPanCakeGarbage->pNextContainer=pPanCakeGarbage           
    this.bSeekMethod=SeekMt : uCount=0 : this.pFirstNode->BranchCount=0   
    If pFlatRoot->pBranch->pNext=pFlatRoot->pBranch Then :  _Deallocate(pFlatRoot->pBranch) : pFlatRoot->pBranch=0 : this.uNodeCOUNT-=1 : iLong+=1 : End If
    this.AllOfPrivate
    Return iLong   
End Property
Last edited by Lost Zergling on Jul 08, 2019 23:10, edited 25 times in total.
PaulSquires
Posts: 747
Joined: Jul 14, 2005 23:41
Contact:

Re: LZLE List Engine with user friendly powerfull syntax

Postby PaulSquires » Mar 26, 2018 16:52

I'm sure this is a great library and I'll try it out and provide feedback. I am curious as to your coding style. Why have the code so compact with all of the colon : line continuations? It makes the code incredibly cumbersome to read. It's not like the old days of tokenized BASIC where you might gain a slight speed advantage by placing as much on one line as possible. Today, whitespace is needed and valued for longer term code maintenance and understanding.

Not trying to be overly critical, I'm just curious.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 26, 2018 17:00

Code PART 3/3 :

Code: Select all



Property List.Destroy As Byte
    If bPVSmethod<>-1 Then : Print "PVS_Count=" & PVS_Count  : End If '& " (the bigger, the most the optimization algo was used)" : End If
    If ubKeysRegister=1 Then : Print "KR_Count=" & KR_Count  : End If
    If this.IsDestroyed=1 Then : Return 0 : End If
    this.Root : this.DropAll : IsDestroyed=1
    If pPanCakeGarbage<>0 Then _Deallocate(pPanCakeGarbage) : pPanCakeGarbage=0 :  End If  :
    If this.pFlatRoot<>0 Then
        If this.pFlatRoot->ListData<>0 Then : _Deallocate this.pFlatRoot->ListData : this.pFlatRoot->ListData=0 :  End If
        If this.pFlatRoot->pBranch<>0 Then
            If this.pFlatRoot->pBranch->pNext<>0 And pFlatRoot->pBranch->pNext<>pEndFlat Then               
                _Deallocate(this.pFlatRoot->pBranch->pNext) : pFlatRoot->pBranch->pNext=0 :   this.uNodeCOUNT-=1
            End If
            _Deallocate(this.pFlatRoot->pBranch) : pFlatRoot->pBranch=0 :  this.uNodeCOUNT-=1
        End If
        _Deallocate(this.pFlatRoot) : pFlatRoot=0 :  this.uNodeCOUNT-=1
    End If
    If this.pEndFlat->ListData<>0 Then : _Deallocate this.pEndFlat->ListData : this.pEndFlat->ListData=0 :  End If
    If this.pLastLASTNode->ListData<>0 Then : _Deallocate this.pLastLASTNode->ListData : this.pLastLASTNode->ListData=0 :  End If
    If this.pGarbage->ListData<>0 Then : _Deallocate this.pGarbage->ListData : this.pGarbage->ListData=0 :  End If
    If this.pWhyteMove->ListData<>0 Then : _Deallocate this.pWhyteMove->ListData : this.pWhyteMove->ListData=0 :  End If
    If this.pFirstFIRSTNode->ListData<>0 Then : _Deallocate this.pFirstFIRSTNode->ListData : this.pFirstFIRSTNode->ListData=0 :  End If
    If this.pNode->ListData<>0 Then : _Deallocate this.pNode->ListData : this.pNode->ListData=0 :  End If
    If this.pEndFlat<>0 Then : _Deallocate(this.pEndFlat) : pEndFlat=0 : This.uNodeCOUNT-=1 :  End If   
    If this.pLastLASTNode<>0 And pLastLASTNode<>pWhyteMove And pLastLASTNode<>pFirstFIRSTNode Then : _Deallocate(this.pLastLASTNode) : pLastLASTNode=0 : this.uNodeCOUNT-=1 :  End If
    If this.pGarbage<>0 And pGarbage<>pNode Then : _Deallocate(this.pGarbage) : pGarbage=0 : This.uNodeCOUNT-=1 :  End If
    If this.pWhyteMove<>0 Then : _Deallocate(this.pWhyteMove) : pWhyteMove=0 : This.uNodeCOUNT-=1 :  End If
    If this.pFirstFIRSTNode<>0 Then : _Deallocate(this.pFirstFIRSTNode) : pFirstFIRSTNode=0 :  this.uNodeCOUNT-=1 :  End If
    If this.pNode<>0 Then : _Deallocate(this.pNode) : pNode=0 : this.uNodeCOUNT-=1 :  End If
    If Listptemp<>0 Then : _Deallocate(Listptemp) : Listptemp=0 :  End If : If Listptemp2<>0 Then : _Deallocate(Listptemp2) : Listptemp2=0 :  End If : If zp3<>0 Then :  _Deallocate(zp3) : zp3=0 :  End If
   ' If this.uNodeCount>2 Then : Print "Erreur a reporter : " & Str(this.uNodeCount-2) & " non dealloues !" : sleep : End If   '_Deallocate( New(@this) List )   
    Return 0
End Property

'==========================================================================================DATA EXCHANGE
Property List.SnatchBelow(pList As List) As Byte
  Dim As ListNode Ptr pTemp1, pTemp2
    If pNode->Tag(0)=LIST_RES Or pNode->Tag(0)=LIST_DEL Or pNode=pWhyteMove Or pNode=pFlatRoot Or pNode=pLocalMove Or pNode=pLocalRoot Or pNode=pEndFlat Then : Return 0 : End If
    this.NodeRecycle : this.NodeRecycle2
    If bSnatchBLMethod=0 Then       
        If pNode->pBranch=0 Then
            this.Branch : this.BlindTag("") : pTemp1=pNode : pLocalMove=pNode : pLocalMove->pBranch=0 : pLocalMove->Tag(1)="" : pLocalMove->Tag(0)=LIST_DEL
            If this.Snatch(pList) <> 1 Then : this.NodeRecycle : pLocalMove=pFirstNode : pFirstNode->pBranch->pBranch=0 : pFirstNode->pBranch=0 :  pLocalMove->Tag(1)="" : pLocalMove->Tag(0)=LIST_DEL : this.NodeRecycle : Return 0
            Else : pTemp1->pPrev->pNext=pTemp1->pNext : pTemp1->pNext->pPrev=pTemp1->pPrev                 
            End If : this.uCount-=1 : pFirstNode->BranchCount-=1 : this.NodeRecycle
        Else : this.Branch : pNode=pFirstNode->pNext : If this.Snatch(pList) <> 1 Then : Return 0 : End If
        End If
 '       pTemp1=pFirstNode ' MAJ des pointeur pFirstNode->pPrev
 '       While pTemp1->pNext<>0 And pTemp1<>pFirstNode->pBranchLastNode : pTemp1=pTemp1->pNext : If pTemp1->pBranch<>0 Then : pTemp1->pBranch->pPrev=pFirstNode : End If : Wend 
    Else       
        If pNode->pBranch=0 Then
            pTemp2=pList.GiveBranchDown : If pTemp2=0 Then : Return 0 : End If
            pTemp2->pBranch=pNode : pTemp2->pPrev=pFirstNode
            pNode->pBranch=pTemp2
            pLastNode=pTemp2->pBranchLastNode : pFirstNode=pTemp2 : pNode=pFirstNode->pNext : Return 1
        Else
            pTemp2=pList.GiveBranchDown : If pTemp2=0 Then : Return 0 : End If
            this.Branch :
            pTemp2->pPrev=pFirstNode->pPrev : pTemp2->pBranch=pFirstNode->pBranch : pTemp2->pBranch->pBranch=pTemp2
            pFirstNode->pNext->pPrev=pTemp2->pBranchLastNode : pTemp2->pBranchLastNode->pNext=pFirstNode->pNext
            pTemp2->pBranchLastNode=pFirstNode->pBranchLastNode
            pTemp1=pFirstNode ' MAJ des pointeur pFirstNode->pPrev
            While pTemp1->pNext<>0 And pTemp1<>pFirstNode->pBranchLastNode : pTemp1=pTemp1->pNext : If pTemp1->pBranch<>0 Then : pTemp1->pBranch->pPrev=pTemp2 : End If : Wend         
            pLocalMove=pFirstNode : pLocalMove->pBranch=0 : pLocalMove->Tag(1)="" : pLocalMove->Tag(0)=LIST_DEL : pFirstNode=pTemp2
        End If
    End If
    this.UpLevel : Return 1
End Property

Property List.Snatch(pList As List) As Byte
    Dim As ListNode Ptr pTemp1, pTemp2
    this.NodeRecycle : this.NodeRecycle2
    If pNode->Tag(0)=LIST_DEL Then : If pFirstNode->pBranch=0 Then : pNode=pGarbage->pNext : Else : Return -1 : End If
    ElseIf pNode->Tag(0)=LIST_RES Then : pNode=pNode->pNext : Return 0 : End If
   ' If pNode=pWhyteMove Then : Return 0 : End If
    pTemp1=pList.GiveBranch : If pTemp1=0 Then : Return 0 : End If
   ' If pFirstNode=pFirstFIRSTNode Then : pTemp2= : End If
    If bBranchCountDown=1 Then : this.BCountDown(pTemp1->BranchCount) : End If : uCount+=1 : pFirstNode->BranchCount+=1
    If pNode<>pLastNode Then : pNode->pNext->pPrev=pTemp1 : Else : pLastNode=pTemp1 : pFirstNode->pBranchLastNode=pTemp1 : End If
    If pTemp1->pBranch<>0 Then : pTemp1->pBranch->pPrev=pFirstNode  : End If
    pTemp1->pNext=pNode->pNext : pNode->pNext=pTemp1 : pTemp1->pPrev=pNode
    If pNode->pBranch<>0 Then : pNode->pBranch->pBranch=pNode : End If
    pList.AllOfPrivate : pNode=pTemp1 : this.VectorClear : Return 1
End Property

Property List.FlatSnatch(pList As List) As Byte   
    Dim pTemp1 As ListNode Ptr : Dim pTemp2 As ListNode Ptr
    pTemp1=pList.GiveFlat : If pTemp1=0 Then : Return 0 : End If   
    pFlatRoot->pBranch->BranchCount+=pTemp1->BranchCount : uNodeCOUNT+=pTemp1->BranchCount : pTemp1->BranchCount=0
    pTemp2=pTemp1->pBranch : pTemp1->pBranch=0 : pFlatRoot->pBranch->pNext->pPrev=pTemp2 : pTemp2->pNext=pFlatRoot->pBranch->pNext
    pFlatRoot->pBranch->pNext=pTemp1 : pTemp1->pPrev=pFlatRoot->pBranch : Return 1
End Property

Property List.GarbageSnatch(pList As List) As Byte   
    Dim As ListContainer Ptr pPanTemp1, pPanTemp2 : Dim As ListNode Ptr pTemp1, pTemp2
    pTemp1=pList.GiveGarbage : If pTemp1=0 Then : Return 0 : End If : uNodeCOUNT+=pTemp1->BranchCount : uGarbCt+=pTemp1->BranchCount
    pTemp2=pTemp1->pBranch : pFlatRoot->pNext->pPrev=pTemp2 : pTemp2->pNext=pFlatRoot->pNext : pTemp1->pBranch=0 : pFlatRoot->pNext=pTemp1 : pTemp1->pPrev=pFlatRoot   
    pPanTemp1=pPanCakeGarbage->pNextContainer
    pPanTemp2=pList.GivePanCake : If pPanTemp2=0 Then : Return 0 : End If :  pPanCakeGarbage->pNextContainer=pPanTemp2
    pPanTemp2=pList.GiveLastPanCake : uContainerGarbCt+=pList.GivePanCakeCount : pPanTemp2->pNextContainer=pPanTemp1 : Return 1
End Property

Property List.CopyCat(pList As List) As Byte
    Dim As ListNode Ptr pTmp1, pTmp2=pNode : Dim as byte by=1 : this.NodeRecycle
    pTmp1=pNode->pNext : pList.HashKeyUnique(0) : pList.HashSort(1) : pList.fSortMethod(1)
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode
    pList.SetRelation(bCopyCatMethod)
    If this.uTag=0 Then
        If this.bCopyCatMethod=1 Then : While pNode<>pTmp1 and by=1 : pList.HashTag(this.HashTag) : pList.RwTag1(this.Tag(1)) : pList.SetRelation1(this.pNode) : by=this.HashStep : Wend
        Else : pList.BranchCountDown(0) : While pNode<>pTmp1 and by=1 : pList.HashTag(this.HashTag) : pList.RwTag1(this.Tag(1)) : pList.SetRelation2(this.pNode) : by=this.HashStep : Wend   
        End If
    Else
        If this.bCopyCatMethod=1 Then : While pNode<>pTmp1 and by=1 : pList.HashTag(this.Tag(uTag)) : pList.SetRelation1(this.pNode) : by=this.HashStep : Wend
        Else : pList.BranchCountDown(0) : While pNode<>pTmp1 and by=1 : pList.HashTag(this.Tag(uTag)) : pList.SetRelation2(this.pNode) : by=this.HashStep : Wend
        End If
    End If
    pNode=pTmp2 : pList.HashKeyUnique(1) : Return 1
End Property



I'm using FbIDE and I have set the editor to be very close to old Lotus Notes designer interface. This the reason.
Second one : I prefer a condensed script to see same time a maximum lines of code, I thought it easier to code.
As I'd want to obfuscate this code this was possible, anyway. It is already a bit "naturally" obfuscate, but because it is complex in some matter, because of optimizations attempts and because of coding style, not because I did want to.

ps : Thank you Paul Squire for your appreciation and feedback
Here are some exemples to show how it is intended to work. I do not create a new post to get this exemples on first page near the library.
Exemple 1

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"
Dim MaListe As List
MaListe.BranchCountDown(1)

Dim u as ulongint : Dim i as ulongint
MaListe.HashTag("a") : MaListe.Val("2")

Print "1"
For u=1100000000 To 1100000030
    MaListe.HashTag(str(u)) : MaListe.Val(str(u-1100000000))
Next u
For u=20 To 28
    MaListe.HashTag(str(u)) : MaListe.Val(str(u))
Next u


 ' MaListe.NFmethod(0)
 ' MaListe.NFmethod(-1)

Print "node count=" & Str(MaListe.Nodecount) & " count=" & Str(MaListe.count)
Print "++"


MaListe.HashTag("8")  : MaListe.Val("55")
'MaListe.Root
MaListe.RootNode
Print "* " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) 
'While MaListe.KeyStep=1
While MaListe.HashStep=1
    Print "* " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) 
Wend
Print "---------------------"
sleep

Print "*Count=" & MaListe.Count

MaListe.Root

Print "#Count=" & MaListe.Count
While MaListe.HashStep=1
    If  (Cint(MaListe.Val) > 22  And Cint(MaListe.Val) <25)  Or Cint(MaListe.Val) =30  Then :   '  And Cint(MaListe.Val) <30   Cint(MaListe.Val) < 17 or  Cint(MaListe.Val) < 17 or Cint(MaListe.Val) < 17 or  Or Cint(MaListe.Val) =0 Or Cint(MaListe.Val) =0 Or Cint(MaListe.Val) =0
      '  Print "Flat -> " & MaListe.HashTag : sleep           
       MaListe.NodeFlat         
    ElseIf Cint(MaListe.Val) =0 Then       
     '   Print "0->Flat -> " & MaListe.HashTag ': sleep
       MaListe.NodeFlat         
    Else
      '  Print "Recycle -> " & MaListe.HashTag : sleep
    End If   
Wend
'MaListe.RootNode
MaListe.Root
Print "Count=" & MaListe.Count
sleep

MaListe.Root
MaListe.RootNode
While MaListe.HashStep=1
    Print "% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) '& " suivant=" & MaListe.NextNode  ': sleep
Wend
Print "F 01"
sleep
MaListe.Root
For i=1 To MaListe.AllOf : MaListe.BlindStep
    Print "+ " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count)     
Next i
Print "F 02"
sleep

MaListe.Root
While MaListe.HashStep=1
    Print "% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count)  '& " suivant=" & MaListe.NextNode ': sleep
Wend
Print "F 03"
sleep

MaListe.Root
MaListe.EndNode
Print "# EndNode=" & MaListe.Tag
Print "root1"
For i=1 To MaListe.AllOf : MaListe.BlindStep
   ' Print "**" & MaListe.Tag ': sleep
  '  MaListe.RestoreHash
Next i
' MaListe.NodeRecycle
Print "--------------------"

sleep

MaListe.Root
While MaListe.HashStep=1
    Print "~ " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode
Wend


Print "--"


MaListe.Last
Print MaListe.HashTag & " =Last ?"
'MaListe.BlindStep : Print MaListe.Tag & " - " & MaListe.BranchCount
sleep

MaListe.Root
For u=1100000040 To 1100000050
    MaListe.HashTag(str(u)) : MaListe.Val(str(u-1100000000))
Next u
MaListe.Root
While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
     Print "$ " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode
Wend

MaListe.HashTag("52000067") : MaListe.Val("9")

sleep
MaListe.Root
MaListe.HashTag("32000067") : MaListe.Val("98")
MaListe.HashTag("62000067") : MaListe.Val("5")
'MaListe.HashTag("TEST") : MaListe.Val("5")

MaListe.Root

While MaListe.HashStep=1     
    Print "# " & MaListe.HashTag & " - " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode
Wend

MaListe.EndNode
Print MaListe.HashTag & " =EndNode ? "  & MaListe.Tag
MaListe.Last
Print MaListe.HashTag & " =Last ? " & MaListe.Tag :
sleep

MaListe.Root
MaListe.EndNode : 'MaListe.Val("??") 
Print MaListe.HashTag & " =EndNode ?" :
MaListe.Last
Print MaListe.HashTag & " =Last ?" : sleep

MaListe.HashTag("9876") : MaListe.Val("9")

MaListe.Root

While MaListe.HashStep=1
    Print "##? " & MaListe.HashTag & " - " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode
Wend

Print "Fin 1"
sleep

MaListe.Root

While MaListe.HashStep=1
    If Cint(MaListe.Val) < 18 Or ( Cint(MaListe.Val)<49 And Cint(MaListe.Val)>40 )  Then  ' Or ( Cint(MaListe.Val)<50 And Cint(MaListe.Val)>40 )
    '    Print "Flating " & MaListe.HashTag ': sleep
        MaListe.NodeFlat
    Else
      '  Print "Parsing " & MaListe.HashTag ': sleep
    End If
Wend
print "FIN"
sleep

MaListe.HashTag("1100000030")
MaListe.BlindStep(-1) : Print "30->" & MaListe.Tag
MaListe.BlindStep(1) : Print "30->" & MaListe.HashTag
MaListe.Last : Print "30 Last->" & MaListe.HashTag
MaListe.HashTag("110000004") : Print "110000004 is branch=" & MaListe.BranchCount
MaListe.HashTag("1100000040")
MaListe.BlindStep(-1) : Print "40->" & MaListe.Tag
MaListe.BlindStep(1) : Print "40->" & MaListe.HashTag
MaListe.Last : Print "40 Last->" & MaListe.HashTag
sleep

MaListe.HashTag("1100000041")
MaListe.Root : MaListe.First
Print "++**++"
While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
    Print "%% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode
Wend
Print "Pt A01" : sleep
'MaListe.Root
MaListe.HashTag("110000001")
For i=1 To MaListe.AllOf : MaListe.BlindStep
'    Print "Tag =" & MaListe.Tag
Next i

Print "%" & MaListe.HashTag & "%"
Print "Pt A02" : sleep


Print "~01"
MaListe.HashTag("1100000010")
MaListe.Root
Print "++**++"
While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
    Print "%-% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count)  ' & " suivant=" & MaListe.NextNode
Wend

Print "~02"

sleep
'MaListe.Root
'Print "++**++"
'While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
'    Print "%1 " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count)
'Wend

sleep
'Print "Count=" & MaListe.Count ' & " AllOf=" & MaListe.AllOf
'For i=1 To MaListe.Count : MaListe.BlindStep(-1)
'    Print "+ " & MaListe.Tag   
'Next i

'sleep : system

Print "===================="
MaListe.Root
MaListe.FlatStack ': MaListe.Branch
Print "Count=" & MaListe.Count & " AllOf=" & MaListe.AllOf
Print "~03"

For i=1 To MaListe.AllOf : MaListe.BlindStep
    Print "restoring " & MaListe.Tag ': sleep
   ' Print  MaListe.Tag
 '  If  Cint(MaListe.Val) <30   Then   
        MaListe.RestoreHash
  '  Else
  '      MaListe.NodeRecycle
  '  End If   
Next i
Print "--------------------"

Print "Restored "
sleep


MaListe.Root
MaListe.RootNode
 MaListe.Val ("totor")
Print "*** " & MaListe.HashTag & " tag=" & MaListe.Tag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode

While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
    Print "** " & MaListe.HashTag & " tag=" & MaListe.Tag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ' & " suivant=" & MaListe.NextNode '  : sleep
Wend
Print "--------------------"
sleep
Print "* flating"
MaListe.Root
'While MaListe.HashStep=1
'     Print "* flating -> " & MaListe.HashTag ' : sleep
'        MaListe.NodeFlat
'Wend
'sleep
i=0
'dim i as integer=0
MaListe.Root
Print "count=" & MaListe.Count  : sleep
'MaListe.FlatStack : MaListe.Branch : Print "Flat count=" & MaListe.Count
'MaListe.UpLevel
Print "count=" & MaListe.Count  : sleep
Print MaListe.Tag
'For u=1 To MaListe.Count :
'    Print MaListe.Tag : i+=1
 '   MaListe.BlindStep
'Next u

MaListe.Root
Print "# " & MaListe.Tag : MaListe.BlindStep
Print "# " & MaListe.Tag : MaListe.BlindStep
Print "# " & MaListe.Tag : MaListe.BlindStep
Print "# " & MaListe.Tag : MaListe.BlindStep
'Print "**********"
'MaListe.BlindStep : Print MaListe.Tag
Print "**********"
Print "value=" & str(u) & " / " & str(i)

Print "FlatCount=" & MaListe.Count
Print "GarbageCount=" & MaListe.GarbageCount
Print "NodeCount=" & MaListe.NodeCount
Print "**********"
sleep
u=1
MaListe.Root
MaListe.RootNode
Print "% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ': sleep
While MaListe.HashStep=1
  '   Print "% " & MaListe.Tag & " = " & MaListe.Val
    Print "% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ': sleep
    u+=1
Wend
sleep
Print "% " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ': sleep
Print "Node visibles parcourables = " & str(u) &  " Garbage=" & MaListe.GarbageCount '& " Flat=" & MaListe.FlatCount
Sleep
 
' Print "Node visibles parcourables = " & str(u) & " Garbage=" & MaListe.GarbageCount '& " Flat=" & MaListe.FlatCount
MaListe.First 'GarbagePtr
 Print "?? " & MaListe.HashTag & " = " & MaListe.Val & " branch " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count) ': sleep
 sleep
Print str(MaListe.NodeCount) & " totaux"
sleep
MaListe.EndNode
Print "*? " & MaListe.hashTag & " / " & MaListe.Tag
'u=0 : MaListe.Root : While MaListe.HashStep=1 : u+=1 : Wend
Print MaListe.DropAll & " / " & MaListe.NodeCount & " / Total parse=" & u
 print "destroy"
MaListe.Destroy
Print "Fin **********"
sleep : system

Exemple 2

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"

Dim MaListe As List
dim str_tmp as string
Dim i as Integer
MaListe.Root
Print "Flat=" & MaListe.FlatCount
Print "Garbage=" & MaListe.GarbageCount

MaListe.HashLen(1)
'MaListe.BranchCountDown(1)
MaListe.HashTag("99")
MaListe.HashTag("72") : Maliste.Val("-12*-")
MaListe.HashTag("78")
For i=720 To 728
    MaListe.HashTag(str(i)) : Maliste.Val("-" & str(i) & "-" )
Next i
MaListe.Root
MaListe.HashTag("7210")
MaListe.HashTag("7211")
MaListe.HashTag("7212")

'MaListe.Root
'MaListe.HashTag("7211")
'MaListe.NFmethod(-1)
'MaListe.NodeFlat
MaListe.RootNode
MaListe.Root ': MaListe.Last
'MaListe.EndNode
While MaListe.HashStepRev=1
    Print MaListe.HashTag & " = " & MaListe.Val    & " BranchCount=" & MaListe.BranchCount
Wend
Print "??"
sleep
MaListe.Root
Print "?=" & MaListe.HasHashTag("728")
MaListe.AllOf

While MaListe.fStepRev=1
    Print MaListe.HashTag & " = " & MaListe.Val    & " BranchCount=" & MaListe.BranchCount
Wend
Print "???"
sleep

' MaListe.NFmethod(-1)

MaListe.Root
'MaListe.EndNode
'While MaListe.HashStepRev=1
'    Print "TestRev => " & MaListe.HashTag & " = " & MaListe.Val & " tag1=" & str_tmp & " BranchCount=" & MaListe.BranchCount  & " count=" & MaListe.Count ''
'Wend

MaListe.Root ': MaListe.Last
'MaListe.EndNode
While MaListe.HashStep=1
  '  Print "? " & MaListe.HashTag & "%" 
    If Val( Right(MaListe.HashTag,1) )<6 Then
 '   If Val( Right(MaListe.HashTag,1) )>4 And Val( Right(MaListe.HashTag,1) )<8 Then

'   If Val( Right(MaListe.HashTag,1) )<9 Then
        MaListe.ColTags(1) : str_tmp=MaListe.Tag : MaListe.ColTags(0)
        Print "Flat => " & MaListe.HashTag & " = " & MaListe.Val & " tag1=" & str_tmp & " BranchCount=" & MaListe.BranchCount  & " count=" & MaListe.Count '
       '  If MaListe.NodeFlat=1 Then : : End If
        MaListe.NodeFlat
    End If   
    'Print MaListe.HashTag & " = " & MaListe.Val
   
Wend
sleep

Print "Garbage Count= " & MaListe.GarbageCount
MaListe.Root : MaListe.RootNode
While MaListe.HashStep=1
    Print MaListe.HashTag & " = " & MaListe.Val & " tag="  & MaListe.Tag & " count=" & MaListe.Count
Wend
Print "--------------------------------------------"
'Sleep

If MaListe.FlatCount>0 Then
    MaListe.FlatStack ': MaListe.Branch
    For i=1 To MaListe.AllOf+1 : MaListe.BlindStep
        Print MaListe.HashTag & " == " & MaListe.Val & " Tag=" &  MaListe.Tag & " count=" & MaListe.Count
    Next i
End If
sleep
Print "____"
Print "nb nodes=" & MaListe.NodeCount
'sleep
Print "*Liste 1 garb count=" & MaListe.GarbageCount
Dim MaListe2 As List
Print "*Liste 2 garb count=" & MaListe2.GarbageCount
MaListe2.GarbageSnatch(MaListe)
Print "Liste 2 garb count=" & MaListe2.GarbageCount
Print "*Liste 1 garb count=" & MaListe.GarbageCount
MaListe2.RootNode
Print  "## count=" & MaListe2.Count
While MaListe2.HashStep=1   
    Print MaListe2.HashTag & " tag=" & MaListe2.Tag & " = " & MaListe2.Val & " count=" & MaListe2.Count
Wend

MaListe.RootNode
Print  "##### count=" & MaListe.Count
While MaListe.HashStep=1   
    Print MaListe.HashTag & " tag=" & MaListe.Tag & " = " & MaListe.Val & " count=" & MaListe.Count
Wend
Print "NodeCount=" & MaListe.NodeCount

Print "Fin" : sleep
'system


Print "dealloues" & MaListe.DropAll


Print  "## count=" & MaListe.Count
MaListe.Root
MaListe.Root
MaListe.Root
Print  "## count=" & MaListe.Count
sleep
MaListe.BlindTag("*")
MaListe.Root
Print  "## count=" & MaListe.Count
'print "02"
MaListe.HashTag("72") : Maliste.Val("-12*-")
MaListe.HashTag("78")
'print "03"

MaListe.Root
Print  "## count=" & MaListe.Count
While MaListe.HashStep=1
    Print MaListe.HashTag & " tag=" & MaListe.Tag & " = " & MaListe.Val & " count=" & MaListe.Count
Wend
MaListe.Root



'MaListe.Root
'While MaListe.HashStep=1
'    Print MaListe.HashTag & " tag=" & MaListe.Tag & " = " & MaListe.Val & " count=" & MaListe.Count
'Wend
Print "a"
Print MaListe.DropAll & " / " & MaListe.NodeCount
Print MaListe2.DropAll & " / " & MaListe2.NodeCount
MaListe.Destroy : MaListe2.Destroy
Print "Fin"
sleep
system



Exemple 3

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"
Dim MaListe1 As List
Dim MaListe2 As List

Dim i as Integer


For i=500 To 560 Step 10
   ' Print "i=" & str(i)
    MaListe1.HashTag(str(i))
   ' i+=9
Next
' MaListe1.Root
For i=10 to 20
'    Print "i=" & str(i)
    MaListe1.HashTag("520" & str(i) )   
Next i

MaListe1.Root
While MaListe1.KeyStep
    Print MaListe1.HashTag
Wend
sleep

MaListe1.HashTag("520")

'MaListe2.HashTag("a")
MaListe2.Root
MaListe2.Snatch(MaListe1)

Print "-----------------------------------"
MaListe2.Root
While MaListe2.HashStep
    Print MaListe2.HashTag & "  " & MaListe2.Count
Wend

Print "************"
MaListe1.Root
While MaListe1.HashStep
    Print MaListe1.HashTag & "  " & MaListe1.Count
Wend

'MaListe1.HashTag("52") : '
'MaListe1.Root
MaListe2.HashTag("0") : MaListe1.HashTag("52") :' MaListe1.Root : MaListe1.HashTag("52")
Print "???= " & MaListe1.SnatchBelow(MaListe2)

Print "#####################"
MaListe1.Root
While MaListe1.HashStepRev
    Print MaListe1.HashTag & "  " & MaListe1.Count
Wend

Print "-----------------------------------"
MaListe2.Root
While MaListe2.HashStep
    Print MaListe2.HashTag & "  " & MaListe2.Count
Wend
Print MaListe2.DropAll & " / " & MaListe2.NodeCount
MaListe2.Destroy
sleep
system

Exemple 4

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"
Dim MaListe As List
Dim i As Integer
For i=30 to 50
    MaListe.HashTag(str(i))
    If Right(str(i),1)="0" Or Right(str(i),1)="9" Then
 '   If str(i)<>"50" Then
        Print "* " & MaListe.HashTag ' &  "  = " & MaListe.NextNode
     MaListe.HoldBack
    End If   
Next i

MaListe.RootNode
While MaListe.HashStep=1
    Print "# " & MaListe.HashTag & " - " & MaListe.Val & " tag=" & MaListe.Tag '& " - " & MaListe.NextNode ' & " BranchCount " & str(MaListe.BranchCount) & " count=" & str(MaListe.Count)
Wend


MaListe.NFmethod(1)
MaListe.Root 'Node
While MaListe.HashStepRev
   
   'Print MaListe.HashTag & "* ->"  & MaListe.Tag(0) & "<-" : sleep ' &  "  = " & MaListe.NextNode
   ' If Right(MaListe.HashTag,1)="0" Or Right(MaListe.HashTag,1)="9"  Then '
    If Right(MaListe.HashTag,1)<>"0" And Right(MaListe.HashTag,1)<>"9"  Then '
  '  If MaListe.HashTag<>"50" Then   
  'Print "**" & MaListe.Tag
  'Print "hashtag=" & MaListe.HashTag & "+"  :sleep
       MaListe.NodeFlat
    End If   
Wend
Print "---"
sleep
MaListe.RootNode
'MaListe.FlatStack
'MaListe.AllOf
While MaListe.fStep 'Rev
'While MaListe.HashStep
'For i=1 to MaListe.AllOf : MaListe.BlindStep(-1
    Print  "? " & MaListe.HashTag   & " tag="   & MaListe.Tag  '&  "  " & MaListe.NextNode    'MaListe.PrevNode &
Wend
sleep
Print "1"
sleep' : system
'MaListe.Root
MaListe.Track
'Print  "== " & MaListe.HashTag
Print  MaListe.HashTag  & " -- " & MaListe.Tag
Print "2"
' MaListe.TrackMethod(0)
'MaListe.NFmethod(0)
While MaListe.TrackStep
    Print  MaListe.HashTag  & " - "      & MaListe.Tag '  & MaListe.PrevNode & "  "    & MaListe.NextNode
   MaListe.NodeFlat
   ' sleep
Wend
' MaListe.Track ': MaListe.AllOf
Print "*" : sleep

MaListe.RootNode
While MaListe.HashStep
    Print MaListe.HashTag
Wend

Print "Fin"
Print MaListe.DropAll & " / " & MaListe.NodeCount
Print "??"
sleep
MaListe.Destroy
system

Exemple 5

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"
Dim MaListe1 As List
Dim MaListe2 As List
Dim i as Integer

For i=1 to 20
    MaListe1.HashTag(str(i))
Next i

MaListe1.Root
Print "##1" & MaListe1.Tag : sleep
While MaListe1.HashStep'Rev
    Print MaListe1.HashTag
Wend
MaListe1.Root
Print "##2" & MaListe1.Tag : sleep


'MaListe2.HashTag("+")
MaListe1.Tag("1") : MaListe1.Down
MaListe1.AllOf
'MaListe1.Root
For i=1 to MaListe1.AllOf : MaListe1.BlindStep
'While MaListe1.fStep
    Print "? " & MaListe1.HashTag
    Print  " success=" & MaListe2.Snatch(MaListe1)
'Wend
Next i


Print "snatched" : sleep ': system

MaListe2.Root
MaListe2.AllOf
'MaListe2.blindTag("#")

'For i=1 To MaListe2.AllOf : MaListe2.BlindStep(-1)
While MaListe2.HashStepRev
'While MaListe2.fStepRev
    Print MaListe2.HashTag ': sleep
   
Wend
'Next i
Print "Fin"
Print MaListe1.DropAll & " / " & MaListe1.NodeCount
Print MaListe2.DropAll & " / " & MaListe2.NodeCount
MaListe1.Destroy : MaListe2.Destroy
sleep : System

Exemple 6

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"

Dim MaListe As List : Dim MaListe2 As List
Dim i as integer

For i=1000 To 1050
    MaListe.HashTag("ABCDEFG" & str(i)) : MaListe.Val("#" & str(i))
Next i
MaListe.Root'Node
While MaListe.HashStepRev
    Print MaListe.HashTag & " = " & MaListe.Val   
Wend
Print "Liste Chargee"
MaListe.Recycle
Print "Liste recycle & garbage=" & MaListe.GarbageCount & " container=" & MaListe.ContainerCount
For i=1000 To 1040
    MaListe.HashTag("*" & str(i)) : MaListe.Val("+" & str(i))
Next i
Print "Liste recycle & garbage=" & MaListe.GarbageCount & " container=" & MaListe.ContainerCount
MaListe.RootNode
While MaListe.HashStep
    Print MaListe.HashTag & " = " & MaListe.Val   
Wend
Print "##############"
MaListe2.GarbageSnatch(MaListe)
sleep
MaListe.RootNode
While MaListe.HashStep
    Print MaListe.HashTag & " = " & MaListe.Val   
Wend
Print "--------------------------------------"
Print "Liste 1 recycle & garbage=" & MaListe.GarbageCount & " container=" & MaListe.ContainerCount
Print MaListe.DropAll & " / " & MaListe.NodeCount

sleep
MaListe2.RootNode
While MaListe2.HashStep
    Print MaListe2.HashTag & " = " & MaListe2.Val   
Wend
Print "*************************"
Print "Liste 2 recycle & garbage=" & MaListe2.GarbageCount & " container=" & MaListe2.ContainerCount
Print MaListe2.DropAll & " / " & MaListe2.NodeCount
MaListe.Destroy : MaListe2.Destroy
Print "Fin"
sleep
system

Exemple 7

Code: Select all

#Include once "D:\Basic\LZListsEngine.bi"

Dim MaListe As List ': MaListe.Root
Dim str_tmp As String="ABCDEFGHIJKLMNOPKRSTUVWXYZ"
Dim i as integer : Dim t as integer :  Dim k as string
Print time
For t=1 To 3
    Print "Do you have a long Key ?"
    For i=1000000 To 2000000
        MaListe.HashTag( str_tmp & str(i)) : MaListe.ColTags(1) : MaListe.RwTag("#" & str(i))  : MaListe.ColTags(0) ' MaListe.HashTag( str_tmp & str(i)) : MaListe.Val("#" & str(i))
    '    MaListe.HashTag( str_tmp & str(i)) : MaListe.RwTag1("#" & str(i)) 
    Next i           
    If str_tmp<>"" Then : Print "SIR YES SIR !" : Else : Print "sir no sir." : End If
    MaListe.Recycle
    Print "Recycle : garbage=" & MaListe.GarbageCount & " container=" & MaListe.ContainerCount
    If str_tmp="" Then : str_tmp="ABCDEFGHIJKLMNOPKRSTUVWXYZ" : Else : str_tmp="" : End If
Next t
Print time
Print "Fin"
MaListe.Destroy
sleep
system
Last edited by Lost Zergling on Jul 08, 2019 23:11, edited 12 times in total.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Postby sancho3 » Mar 26, 2018 19:03

I probably should have waited until you showed us how to use it but...
It is reporting an error when I try to create a List variable, Dim as List L.
On Ubuntu (64 bit) and using FBC 64 bit,
*** Error in `./1522090711': malloc(): memory corruption (fast): 0x000000000185a730

I have narrowed it down to this line in Destroy:

Code: Select all

    If this.pNode<>0 Then : Deallocate(this.pNode) :  If this.uNodeCOUNT>0 Then :  this.uNodeCOUNT-=1 : End If : End If '  If this.pGhost<>0 Then : Deallocate(this.pGhost) : End If   

Without knowing how to use your list, I can't say for sure there really is a problem.
EDIT:
This line destroys the pNode pointer. For whatever reason this.pGarbage points to the same memory location. So after this line pNode is already deallocated.

Code: Select all

    If this.pGarbage<>0 Then : Deallocate(this.pGarbage) :  If this.uNodeCOUNT>0 Then :  This.uNodeCOUNT-=1 : End If : End If

I find that pGarbage is assigned pNode in the DropAll (method) property.
END EDIT

A second question is why are obvious methods, like Destroy, declared as properties? In modeling a list object don't you think that Destroy is a method?

One other thing: What is this line doing? I don't understand why you are deallocating newly created memory and why that memory is allocated to the size determined by the physical address of the current instance. Surely that instance will be at a different address on different machines giving very strange inconsistent results. (new(size) data type)

Code: Select all

Deallocate( New(@this) List )

The list looks incredibly thorough. I have been working on one as well but no where near as all encompassing.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 26, 2018 19:49

Hi,
Well I'll post some exemples tomorrow. About the bug you encoutered : I developed and tested it onto W7 with a 32 bit fbc (0.24).
I had some bugs in deallocation. It looks like the destructor method is not called automatically or systematically or just looking like, so I made a destroy method as a property : before exiting all lists may call something like "MyList.Destroy". When running on a system where destructor is effectively called (it is called a second time : Destructor List : this.Destroy : End Destructor ) and pNode is deallocated twice, so the bug you encoutered perhaps. Just comment the line you report or the destructor call.
Otherwise it might be strange you get corruption from destructor when instanciating. (?)
So the obvious destructor is called as a method because my tests I had doubt it was effectively called or always properly done, so I used a property to enforce it. There is no methods because it is a deliberate choice to be compatible with older fbc versions.
Deallocate( New(@this) List ) => don't know if it works, purpose is to send a deallocation flag on current instance adress wich is same size of object used when instanciating for forcing freeing memory. The List object instance is fixed size or should be. Just the allocated pNode and Container are dynamic and are deallocated with DropAll and Destroy.
"The list looks incredibly thorough." => yes there are some advanced features and most of them tested & working fine and some others I didn't had time to code yet, and a "light version" could make sens just consumming less memory (so far a thick faster), but there are implementations issues.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Postby sancho3 » Mar 26, 2018 20:41

I have been doing some more scouring of the code.
Memory allocations can be a real task to debug so in my list (only uses new/delete and not allocate/deallocate) I created a log to write to a file the address of any new memory being allocated and write any address being deallocated. Then I just look and see that for each pointer there must be a deallocation occurring.
So I did that with your list. Here is the result:

Code: Select all

(A)LIST.constructor 213 callocate 96 memory at: 17314224 variable: pFlatRoot
(B)LIST.constructor 214 callocate 96 memory at: 17314368 variable: pNode
(C)LIST.constructor 219 callocate 104 memory at: 17314864 variable: pPanCakeGarbage
LIST.ALLOWCAKE.property.get 234 callocate 96 memory at: 17315120 variable: pTemp
LIST.ALLOWPANCAKE.property.get 243 callocate 104 memory at: 17316336 variable: pPanTemp
LIST.ALLOWCAKE.property.get 234 callocate 96 memory at: 17316496 variable: pTemp
LIST.ALLOWCAKE.property.get 234 callocate 96 memory at: 17316608 variable: pTemp
LIST.ALLOWCAKE.property.get 234 callocate 96 memory at: 17314608 variable: pTemp
LIST.ALLOWCAKE.property.get 234 callocate 96 memory at: 17316720 variable: pTemp
LIST.DROPALL.property.get 983 deallocate memory at: 17316496 Variable: pNode
LIST.DROPALL.property.get 983 deallocate memory at: 17316720 Variable: pNode
LIST.DROPALL.property.get 983 deallocate memory at: 17315120 Variable: pNode
LIST.DROPALL.property.get 991 deallocate memory at: 17314608 Variable: pTemp
LIST.ALLOWPANCAKE.property.get 243 callocate 104 memory at: 17315120 variable: pPanTemp
LIST.ALLOWPANCAKE.property.get 243 callocate 104 memory at: 17316496 variable: pPanTemp
LIST.DROPALL.property.get 1010 callocate 96 memory at: 17316880 Variable: pTemp-pNext
(/A)LIST.DESTROY.property.get 1036 deallocate memory at: 17314224 Variable: pFlatRoot
LIST.DESTROY.property.get 1046 deallocate memory at: 17316880 Variable: this.pGarbage
(/B)LIST.DESTROY.property.get 1058 deallocate memory at: 17314368 Variable: pFirstFIRSTNode
This is with only the code Dim L as list.
Right away you can see that memory at: 17314864 variable: pPanCakeGarbage, does not have a deallocation.
Same for LIST.ALLOWPANCAKE.property.get 243 callocate 104 memory at: 17316336 variable: pPanTemp.
This memory is reserved but never deallocated.
I find that pPanCakeGarbage is never deallocated because the code errors out before it gets to that line in Destroy. However I don't yet see why no deallocation for pPanTemp/17316336.

There is another anomaly in that List.AllowCake is allocating memory at 17316608 twice in succession. I can't figure that one out.

This is the logging code I use. Very simple for debugging.

Code: Select all

#Define CRLF Chr(13) & Chr(10)

Namespace _Log
   Const Log_FILE = "xxLOG.txt"
   Declare Sub clear_file()
   Declare Function post(Byref txt As String) As Boolean

   Sub clear_file()
      '
      Dim As Ulong f
      f = Freefile()
      Open Log_FILE For Output As f
      Close f
   End Sub

   Function post(Byref txt As String)  As Boolean
      '
      Dim As Ulong f
      f = Freefile()
      If Open(Log_FILE , For Binary, As f)<>0 Then Return False
         Seek f, Lof(f)
         Print #f, txt & CRLF
      Close f
   End Function
   
End Namespace


Here is an example of of how it is used:

Code: Select all

   this.pPanCakeGarbage=cAllocate(Len(ListContainer)) : :_log.post(__Function__ & " " & __Line__  & " callocate " & Len(ListContainer) &  " memory at: " & This.pPanCakeGarbage & " variable: pPanCakeGarbage") ' Moment angulaire(petite masse)

I recommend that you log allocations and deletions and track down why they aren't matching up.

As for that last line in Destroy, you can be certain that it is in error.
MrSwiss
Posts: 3194
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: LZLE List Engine with user friendly powerfull syntax

Postby MrSwiss » Mar 26, 2018 20:45

Lost Zergling wrote:I developed and tested it onto W7 with a 32 bit fbc (0.24).

It is imho, the wrong approach, when developing something new, to target *old FBC versions*.

Reasons are, among others:
  • no 64 bit compiler, in the old versions, which is a requirement, if you want people to use it!
  • plenty of fixes have been implemented, since then: ver. 0.24.0 vs. 1.05.0
  • those might the be of use, in the implementation (especially, to OOP stuff).
  • and more, along those lines ...
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Postby sancho3 » Mar 26, 2018 20:55

Code: Select all

Deallocate( New(@this) List )

I wanted to log what exactly was happening with that line so I separated it out. This is the same code on two lines.

Code: Select all

   Dim As List Ptr __p = New(@this) List
   Deallocate(__p)

Here is the log post of the memory you are creating with new (on my machine):

Code: Select all

LIST.DESTROY.property.get 1077 create New memory at: 140736082517232 size: 140736082517232

And again my computer errors on the attempt to deallocate at that memory location (and look at the size of memory).
purpose is to send a deallocation flag on current instance adress wich is same size of object used when instanciating for forcing freeing memory

I don't understand what this means. The current instance is a List object and doesn't need to be freed. Its memory allocated members do for sure but the instance can be left to run out of scope at the end of its destructor.
I think that if the other holes are patched, then this line can just be eliminated.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 26, 2018 22:04

Mr Swiss : you're right. Developping such a software for older version is looking like an error,.. anyway, this constraint was in the spirit of what I wanted to do. It is working on old version and I hope it may just need some few adjustments to work fine on newer ones, this an issue you're right. I'll fix it soon with 64 bits versions.
Sancho3 : "Deallocate( New(@this) List )" can be removed.
"The current instance is a List object and doesn't need to be freed." : you're right of course, I add a patch because I had a doubt.
"There is another anomaly in that List.AllowCake is allocating memory at 17316608 twice in succession. I can't figure that one out. " : so do I. Need some more investigation because there should be no deallocate during instanciation, will check.
"I think that if the other holes are patched, then this line can just be eliminated." : I'm not sure there is so many mem leaks, this may depend on the fbc version and and seems to be circumscribed to a few (statics) pointers.
"I recommend that you log allocations and deletions and track down why they aren't matching up." : Meters are implemented. The number of allocations/deallocations can be tracked by print MyList.DropAll & " - " & MyList.NodeCount
Only 3 listnode should remains after any DropAll and they shall be deallocated by MyList.Destroy
The spirit is to deallocate only when list instance has become useless : node are never deallocated : they're reused.
There is also a listcontainer count to track the PanCakes,...
Anyway, I thank you for your remarks, it helps me to find out issues.
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 28, 2018 19:37

Thanks to Paul Squires and Sancho3. I think I'd appreciate some more returns, tests, remarks, questions and so on. Every subjects open. May be I was a little bit too optimistic.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Postby sancho3 » Mar 29, 2018 3:58

I'll keep digging at it. I don't think you are far off from where you want to be.
I would like some usage info though please. It doesn't have to be the full tutorial. Maybe just a small example of a list to start with.
And just to be clear, I am not criticizing. I want to be encouraging.

I googled and I can't find any data structures that use Cake and PanCake. Can you tell me what AllowCake and the like are about?
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 29, 2018 6:18

Some short exemples are posted above. I see "AllowCake" as a node re-dispatcher wich short-circuit deallocate then ulterior allocate working as very very minimalist v-mem driver using as a priority garbaged node when available. Cake & PanCake just for the fun of the name.
MrSwiss
Posts: 3194
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: LZLE List Engine with user friendly powerfull syntax

Postby MrSwiss » Mar 29, 2018 9:19

Lost Zergling wrote:I think I'd appreciate some more returns, tests, remarks, questions and so on. Maybe I was a little bit too optimistic.

It may have something to do, with the reasons I've already stated.
I for one, am not touching 'anything' (not even for testing), if it isn't for 64-bits also ...
( just a hint, nothing more )
Lost Zergling
Posts: 238
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Postby Lost Zergling » Mar 29, 2018 12:28

I take note of this. The 64 bits issue is probably due to a bug because compiler is now more rigorous and not because program is not set for 64 bits also. I'm going to investigate this point.
Problem solved on FB 1.05.0 W7 64bits - Sancho3 was right about Destroy Property : pGarbage=pNode => double deallocation & Deallocate( New(@this) List ) probably useless. I modified source of Destroy Property directly in my second post. This Destroy Property may be of little interest. Perhaps for Linux Destructor should call this.DropAll instead of this.Destroy.
I know there might be some other issues,.. code should be usable, not bug free, some of the code is ok but some is weak.
Thus, I didn't implemented yet all the features I wanted to.
Most of main features seriously tested. Possible issues on Rev parsing in combination with NodeFlat. Tracking and Snatching few tested.

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 5 guests