LZLE List Engine with user friendly powerfull syntax - BETA 0.997a

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

LZLE List Engine with user friendly powerfull syntax - BETA 0.997a

Post by Lost Zergling »

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 & 4 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, features requests welcomes here : https://freebasic.net/forum/viewtopic.php?f=2&t=26637

New version Beta 0.996a : (20/04/2020)
New version 0.996 (20/04/2020): continuation of work to optimize memory load. After the evolution of the implementation logic (0.995), the tests were able to demonstrate that there is no optimal generic solution. It is proposed (#Define) three memory management modes to best cover use cases: an optimized generic mode, a tuning mode, and a mode close to the functioning of previous versions. The two new modes generally offer an equivalent or higher speed, additional functionalities, lower peak memory consumption, more efficient memory deallocation and being able to choose and specify the mode best suited to data and processing.
Looking at the new features: 1) new 'TagLenRedim' & 'TagLenDefault' allows you to limit or not the size of the columns and 2) new 'Check' property enable user-define "marked as key" feature which can be taken into account by iterators without additional memory load or speed loss.
New release Beta 0.996b : (13/05/2020) : BugFix on HasHashTag, (and so on HasKey) & slight speed improvement, HasTag better supports transparently Flat and Tree structure, HasTagTree & HasTagFlat additionnal dedicated coding options.
New release Beta 0.996c : (26/12/2020) : major bugs fixes & new features on Holback/Tracking now better supports when mixed with NodeFlat, dynamic otimization, support for easy syntax on indexed buffers - Holdback/Tracking faster and far better consistency
NFrecursive : NFrecursive efficient on Tracking
exemple here : viewtopic.php?f=7&p=278635#p278635
0.966c : Bugs found, use tracking carefully a new release coming
New release Beta 0.997a : (04/01/2021) : Serious Bug Fixes on tracking, new powerfull feature HoldBackRev, new powerfull features on NFRecursive and NFMethod, New powerfull feature 'CopyTrack', Keyword kinematic is more intuitive & robust on tracking. some more documentation (viewtopic.php?f=9&t=26551&p=278811#p278811).
Important : LZLE now splitted into 4 posts
Code PART 1/4 :

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) &_
"  PARIS 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) & "  https://users.freebasic-portal.de/stw/builds/) or " & chr(10) & " http://users.freebasic-portal.de/sarg/fbcgas64.zip)"&_
" >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/ ou " & chr(10) & " http://users.freebasic-portal.de/sarg/fbcgas64.zip)" & 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

/' ?todo        :
   ' Tag1 is uByte instead string, reserved values : 0,1, 255 previous versions <0.995=> Tag1 0="", Tag1 1=" " , Tag1 255=LIST_DEL -  Meaning : 0=hashtag, not a key, 1=entry is a key, 255=hashtag or key that became a hashtag, key marked as transfered, hashtag to be deleted till no childs
   ' New to 0.996c : major bugs fixes & new features on Holback/Tracking now better supports when mixed with NodeFlat, dynamic otimization, support for easy syntax on indexed buffers - Holdback/Tracking faster and far better consistency
   ' New to 0.996c : NFrecursive : NFrecursive efficient on Tracking 
   ' New 0.996c : HoldBackRev for LIFO indexed buffers
   ' New to 0.996c : MAX_ASIDE is distinct, Inside(=Insert)
   'todo : ++ tests trackings avancés? tests CopyTrack
   'todo : FastTrackStep, FastFollow, Check Snatch & Snatch Below /
   'todo : documentation + détail  check TrackMultiKeys, Check, NFRecursive(2), Check Tag1=255 or-1
    CHECK LISTDATA % NodeFlat !!!  
   '/

'-------- PREPROC OPTIMIZATION OPTIONS --------
' # Define TagMode 0    zString Ptr    =>  Tags len (MIN_COLS to MAX_COLS) are Dynamic (zstring Ptr) from DEF_TAGLEN
' # Define TagMode 1    zString         =>  STATIC (consecutive) TAGS LEN (zstring*MAX_TAGLEN) means more speed (10%-30%)(1) and less memory load (20%-80%)(2) but implies :
'                                                               a) maximum len shall not be exceeded (except if it is desired feature) and b) all Tags len shall be as close as possible each others / c) efficient if 'MAX_TAGLEN' can be tuned to fit dataset structure
'                                                               (1) : No need to check len on each tag while setting      (2) : No need to store intermediate array pointer adress and len accessing datas
'' # Define TagMode 2   String           =>  Tags len (MIN_COLS to MAX_COLS) are Dynamic, managed by standard String Datatype

'--------------- SPEED, LOAD & FEATURES ---------------
' TagMode 0 and DEF_TAGLEN=0 VS TagMode 2 with Dim str_tag_C(MIN_COLS to MAX_COLS) As String : TagMode 0 is up to 20% slower, but requiring 20-60% less memory and is more robust at deallocation
' TagMode 0 with uB_RedimTagLen=0  and DEF_TAGLEN choosen VS TagMode 2 with Dim str_tag_C(MIN_COLS to MAX_COLS) As String : TagMode 0 requires 20-60% less memory, speed 15% faster BUT tags len truncated when exceed DEF_TAGLEN
' TagMode 0 with uB_RedimTagLen=1  and DEF_TAGLEN choosen VS TagMode 2 with Dim str_tag_C(MIN_COLS to MAX_COLS) As String : TagMode 0 requires 20-60% less memory, speed 15% faster BUT slowdown when tags len exceed DEF_TAGLEN
' => Using the string type on str_tag_C with TagMode 2 (ie versus TagMode 0)  may only be relevant  if the data you want to enter in Tags arrays  (MIN_COLS To MAX_COLS) are very large and variable in size.
' TagMode 0 VS TagMode 1 with Dim str_tag_C(MIN_COLS to MAX_COLS) As zString*MAX_TAGLEN : TagMode 0 is 10%-30% slower (depending on algo) and is requiring 20%-80% more memory (depending on dataset) BUT tags len are not truncated (or slow) when exceed MAX_TAGLEN
' TagMode 0 with uB_RedimTagLen=0  and DEF_TAGLEN choosen VS TagMode 1 with Dim str_tag_C(MIN_COLS to MAX_COLS) As zString*MAX_TAGLEN : TagMode 0 is 10%-30% slower and requiring 20%-80% more memory BUT Tags truncation can be customizable
' TagMode 0 with uB_RedimTagLen=1  and DEF_TAGLEN choosen VS TagMode 1 with Dim str_tag_C(MIN_COLS to MAX_COLS) As zString*MAX_TAGLEN : TagMode 0 is 10%-30% slower and requiring 20%-80% more memory BUT Tags len can oversize DEF_TAGLEN
' => Using the Zstring type on str_tag_C with TagMode 1 (ie versus TagMode 0)  may only be relevant if the max size of the data is known in advance and varies little
' Important : All given percentages are only as an indication (on tree), you may find out important variations depending on several conditions - 'use of Flat' lists may be slower.

'-------------------------- CONCLUSION  --------------------------
' => Use # Define TagMode 0 to handle "easily" all common datasets & most situations, eventually use DEF_TAGLEN to optimize speed. The most versatile with manual & automatic optimization options.
' => Use # Define TagMode 1 to gain significant speed & memory load (fine tuning) only efficient for fixed (or little variable size data) to store in Tags(MIN_COLS to MAX_COLS), shall not often oversize MAX_TAGLEN (otherwise serious slowdown & possible bugs or compatibility break)
' => Use # Define TagMode 2 to handle large & variable dataset to store in Tag(MIN_COLS to MAX_COLS) or maybe backward compatibility (big size), can sometimes speed faster than TagMode 0, may consumes much more memory, less good deallocation.


'----------------------- PREPROCESSOR -----------------------  ' * 'Standard' setting = # Define TagMode 0 & CONST DEF_TAGLEN=0   ' * 'Fast' setting = # Define TagMode 1 with MAX_TAGLEN as small as possible & no or few oversize
# Define TagMode 0
'------------------ END PREPROCESSOR -------------------  ' * 'BigBuffer' setting is # Define TagMode 2 efficient on flat lists/big strings
'SHARED 1/2
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
Dim Shared As uInteger TrackCompCounter=0

'CONSTANTS
# IF TagMode=0
    CONST DEF_TAGLEN=0
# ELSEIF TagMode=1
    CONST MAX_TAGLEN=14 'must be>0, the max len to store to zstring tags
# ENDIF
CONST MIN_COLS=1 : CONST MAX_COLS=6 : CONST MAX_HASHLEN=1 : CONST DEF_KEYLEN=200 : CONST MAX_ASIDE=20
CONST LIST_RES=Chr(18) : CONST LIST_DEL=Chr(3)  : CONST LIST_ROOT=Chr(4) : CONST MAX_TRACKS=20 ' MAX_TRACKS = all tracks are on a same single track cros-tracking not managed

'DATA IMPLEMENTATION
Type ListContainer 'Data Segment Level   
    # IF TagMode=0
        Dim As zString Ptr str_tag_C(MIN_COLS to MAX_COLS)
        Dim As uByte TagC_Len(MIN_COLS to MAX_COLS)
    # ELSEIF TagMode=1
        Dim str_tag_C(MIN_COLS to MAX_COLS) As zString*(MAX_TAGLEN+1)
    # ELSE
        Dim str_tag_C(MIN_COLS to MAX_COLS) As String
    # ENDIF
    Dim As zString Ptr str_item, str_flat_tag
    Dim As uShort int_tag_len=0 : Dim As uInteger int_val_len=0
    Dim pNextContainer as ListContainer Ptr
End Type
Type ListNode 'ListNode Level
    Dim Tag0 As zString*(MAX_HASHLEN+1) : Dim Tag1 As uByte=0
    Dim  As ListNode Ptr pNext, pPrev, pBranch, pBranchLastNode
    Dim As ListContainer Ptr ListData : Dim As uInteger BranchCount=0
End Type

'TREE PARSING CONTEXT
Type ListContext 'Branch context Level
    Dim  As ListNode Ptr pNode, pFirstNode, pLastNode : Dim As String LcHashTag : Dim  As uInteger  uCount : Dim As uByte bLcHashLen, uBIsTracked=0
End Type

Type List
    Declare Constructor() : Declare Destructor()   
   
    Private:
    Dim As zString Ptr Listptemp=_Callocate(DEF_KEYLEN), Listptemp2=_Callocate(DEF_KEYLEN), zp3=_Callocate(1)
    Dim  As ListContext Lcontext(0 to MAX_ASIDE), Tracks(0 to MAX_TRACKS)
    Dim As ListNode Ptr pNode, pFirstNode, pLastNode, pFirstFIRSTNode, pLastLASTNode, pGarbage, pEndFlat, pLocalRoot, pLocalMove, pWhyteMove, pFlatRoot, pSearchNode, pValTmp, TrackTrace(0 to MAX_TRACKS), pLatestHTag,_
                                    pTrackTmp , pFirstNodeTMP, pLastNodeTMP, pTrackPrevTmp, pLastHoldBackRev(0 to MAX_TRACKS)
    Dim As ListContainer Ptr pPanCakeGarbage, pLastPanCake, pCurrentPanCakeTMP
    Dim As uInteger uNodeCOUNT, uGarbCt, uCount, uContainerGarbCt,  uContainerGivenCt, PVS_Count=0
    Dim As Byte uTag=0, bSearchRes=0, bRHByPass=0, bHashStepRev=0, bfStepZero=0, bTrackingMethod=0, bTracking=0, bHTMethod=1, bHashKeyUnique=1, uSortTag=-1,_
                        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, bRecur=0, bFullRecursive=0
    Dim As uByte    bHashLen=1, IsDestroyed=0, PVS_ratio=3, uB_CurLevel=1, uB_Level=1, uB_KeyStepCumul=1, uB_MaxLevel=1, uB_BottomLevel=255, uB_BottomByPass=0, uB_tmp, uB_IsTree=0,_
                            uB_ind, uB_RedimTagLen=1, uB_TagC_Len(MIN_COLS to MAX_COLS), ubTrackTarget=0, uBHoldBackRev=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 FlatTagSet(Str_Tag As String) As Byte
    Declare Property ValSet(Str_Tag As String) As Byte
    Declare Property TagC_Set(Str_Tag As String) As Byte
    # IF TagMode=1
    Declare Property TagC_Get As String
    # ENDIF
    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 TrackSecure As Byte
    Declare Property HashStepTrace As Byte                              ' Required by Sort (for optimization)   
   
    Public:
    Declare Property TrackComputeTest As Byte
    '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 HasTagFlat(str_Tag As String) As Byte     ' HasTag alternative (slightly faster) for Flat lists
    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 Insert(str_Tag As String) As Byte
    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
    'Tree 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 KeyStep(ub as uByte) As Byte                 ' FOR EACH - show only Keys previously manually tagged by user using Check(uByte) matching uByte
    Declare Property KeyStepRev(ub as uByte) As Byte          ' FOR EACH - show only Keys previously manually tagged by user using Check(uByte) matching uByte
    Declare Property nCurLevel As Byte
    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 HasTagTree(str_Tag As String) As Byte  ' HasTag alternative (faster) for tree ("Hash") lists
    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)
    Declare Property Check(ub As uByte) As Byte                       ' Set current node IsKey status : 0=not a key, 1=a key (internal, autoset), everything but 0 or 255 : a key, 255 reserved for flag delete
    Declare Property Check As Byte                                            ' return IsKey status
    '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   ' 1/2 DEPRECATED (Dynamic=>Static) !! - Longueur des clefs en cascade
    Declare Property KeysRegister(ub As uByte) As Byte         ' DEPRECATED !! - 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 (restent en hashtag si enfants), NFmethod=2 ou 3 : avec NFrecursive pour usage avec TrackStep : 2 send only HashTag to garbage and keys to flat, 3 : send first key to flat, all parents to garbage 
    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          ' DEPRECATED 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 uB<>0 multikeys will be automatically tracked (Track & TrackStep) on specified track each HashTag : working with CopyCat and RestoreHash as well
    Declare Property TrackTarget(uB As uByte) As Byte         ' If TrackMultiKeys enabled, specify a track number for multi-values auto-tracking, default is Track1
    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 HoldBackRev As Byte 
    Declare Property HoldBackRev(i As Byte) As Byte
    Declare Property TrackStep As Byte                              ' -SELECTIVE- FOR EACH - While MyList.TrackStep=1 : ... : Wend : selective PARSE only Keys marked for tracking by HoldBack, set tracking context to 1
    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/replace a new point for tracking : next List.Track+TrackStep will iterate from next tracked node from tracking point / does not break track list
    Declare Property TrackSet(i As Byte) As Byte                ' Manage several tracking point
    Declare Property IsTracked As Byte                              ' Return 1 If current Tracking context is inside a TrackStep Loop otherwise return 0 - Should be automatic
    Declare Property IsTracked(uB As uByte) As Byte         ' Automatically managed, should be useless, nevertheless.. can force context (List.Root restore tracking context to 0)
    Declare Property IsTagFree 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 (ex 'IsTracked')
    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 TagLenRedim(ub as uByte) as Byte   ' # Define TagMode 0 or # Define TagMode 1 ONLY : MyList.TagLenRedim(0) forces fixed size TagLen (TagLenDefault on TagMode 0 or MAX_TAGLEN on TagMode 1, wich means automatic truncation on oversize
    Declare Property TagLenDefault(ub as uByte) as Byte  ' # Define TagMode 0 ONLY : MyList.ColTags(4) : MyList.TagLenDefault(4) : MyList.ColTags(0) => All NEWLY created node will instanciated with zString*4 by default on Tag4, wheras others tags still instanciated DEF_TAGLEN by default
    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)  
    Declare Property CopyTrack(pList As List) As Byte           'Create an index (linked to source)  from current track cession (if previously opened by 'Track(i)'), element by element (auto support multivalues), take into account 'CopyCat' Method
End Type

'SHARED 2/2
Dim Shared gCollector As List

'==========================================================================================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
    pFirstNode = pNode : pLastNode = pNode : bSeekMethod = 1 : uCount = 0 : uTag = 0 :     
    pFirstFIRSTNode = pNode : pLastLASTNode = pNode  : this.pFirstNode->BranchCount=0 : pNode->Tag0 = LIST_RES     
    pFirstFIRSTNode->pNext=pFlatRoot : pFlatRoot->pPrev=pFirstFIRSTNode : pFlatRoot->Tag0=LIST_ROOT
    # IF TagMode=0
        For ub as uByte=MIN_COLS To MAX_COLS : uB_TagC_Len( ub ) = DEF_TAGLEN : Next ub
    # ENDIF
    this.Root : this.AllOf : uSortTag=0
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
    If pTemp<>pGarbage Then : pFlatRoot->pNext=pTemp->pNext : pTemp->pNext->pPrev=pFlatRoot : This.uGarbCt-=1 : pTemp->pBranchLastNode=0
    Else : pTemp=_Callocate(Len(ListNode)) : this.uNodeCOUNT+=1 ' Moment Angulaire(petite masse)         
End If : pTemp->Tag1=0 : 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="" : *pPanTemp->str_flat_tag=""
        For uB=MIN_COLS To MAX_COLS
            # IF TagMode=0
                *pPanTemp->str_tag_C(uB)=""
            # ELSE
                pPanTemp->str_tag_C(uB)=""
            # ENDIF
        Next uB
        pPanCakeGarbage->pNextContainer=pPanCakeGarbage->pNextContainer->pNextContainer : uContainerGarbCt-=1 : pPanTemp->pNextContainer=0
    Else
        pPanTemp=_Callocate(Len(ListContainer))
        # IF TagMode=0
            If DEF_TAGLEN>0 Then : For uB=MIN_COLS To MAX_COLS : pPanTemp->str_tag_C(uB)=_Callocate(uB_TagC_Len( ub ) ) : pPanTemp->TagC_Len(uB)=uB_TagC_Len( ub )  : Next uB : End If
        # ENDIF
    End If : Return pPanTemp
End Property

Property List.FlatTagSet(Str_Tag As String) As Byte
    Dim As uInteger iLen=Len(Str_Tag)+1
    If iLen >= pCurrentPanCakeTMP->int_tag_len Then
        If pCurrentPanCakeTMP->str_flat_tag<>0 Then : _Deallocate(pCurrentPanCakeTMP->str_flat_tag) : End If       
        pCurrentPanCakeTMP->str_flat_tag=_Callocate(iLen)
        pCurrentPanCakeTMP->int_tag_len=iLen
    End If
    *pCurrentPanCakeTMP->str_flat_tag = str_Tag
    Return 1
End Property

Property List.ValSet(Str_Tag As String) As Byte
    Dim As uInteger iLen=Len(Str_Tag)+1
    If iLen >= pCurrentPanCakeTMP->int_val_len Then       
        If pCurrentPanCakeTMP->str_item<>0 Then : _Deallocate(pCurrentPanCakeTMP->str_item) : End If       
        pCurrentPanCakeTMP->str_item=_Callocate(iLen)     
        pCurrentPanCakeTMP->int_val_len=iLen
    End If
    *pCurrentPanCakeTMP->str_item = str_Tag
    Return 1
End Property

Property List.TagC_Set(Str_Tag As String) As Byte
    # IF TagMode=0
        Dim As uShort iLen : Dim As zString Ptr pz=pCurrentPanCakeTMP->str_tag_C(uB_ind)
        If uB_RedimTagLen=1 Or pz=0 Then
            iLen=Len(Str_Tag)+1
            If iLen >= pCurrentPanCakeTMP->TagC_Len(uB_ind) Then
                If pz<>0 Then : _Deallocate(pz) : End If       
                pCurrentPanCakeTMP->str_tag_C(uB_ind)=_Callocate(iLen)
                pCurrentPanCakeTMP->TagC_Len(uB_ind)=iLen
            End If
        End If
        *pCurrentPanCakeTMP->str_tag_C(uB_ind) = str_Tag
    # ELSEIF TagMode=1
        If uB_RedimTagLen=1 Then
            Dim As uShort iLen ': Dim As uByte Ptr PuB : Dim As zString Ptr PzS
            iLen=Len(Str_Tag)
            If iLen > MAX_TAGLEN Then
                Dim As uShort uNbLoops
                Dim As zString Ptr Pz1=StrPtr(Str_Tag), Pz2=Pz1
                Pz1+=MAX_TAGLEN
                (*zp3)[0]=(*Pz1)[0] : Pz1[0]=0
                pCurrentPanCakeTMP->str_tag_C(uB_ind) = *Pz2               
                (*Pz1)[0]=(*zp3)[0]               
                uNbLoops=-Int(-iLen/MAX_TAGLEN)-1
                For i as uShort=1 To uNbLoops                   
                    Pz2+=MAX_TAGLEN
                    Pz1+=MAX_TAGLEN
                    (*zp3)[0]=(*Pz1)[0] : Pz1[0]=0
                    If pCurrentPanCakeTMP->pNextContainer=0 Then
                        pCurrentPanCakeTMP->pNextContainer=AllowPanCake
                    End If
                    pCurrentPanCakeTMP->pNextContainer->str_tag_C(uB_ind) = *Pz2
                    (*Pz1)[0]=(*zp3)[0]
                    pCurrentPanCakeTMP=pCurrentPanCakeTMP->pNextContainer
                Next i
            Else
                If iLen = MAX_TAGLEN And pCurrentPanCakeTMP->pNextContainer<>0 Then : pCurrentPanCakeTMP->pNextContainer->str_tag_C(uB_ind) = "" : End If
                pCurrentPanCakeTMP->str_tag_C(uB_ind) = str_Tag
            End If
        Else
            pCurrentPanCakeTMP->str_tag_C(uB_ind) = str_Tag
        End If       
    # ELSE
        pCurrentPanCakeTMP->str_tag_C(uB_ind) = str_Tag
    # ENDIF
    Return 1
End Property

# IF TagMode=1
    Property List.TagC_Get As String
        If uB_RedimTagLen=1 Then
            Dim As ListContainer Ptr pPanTmp=pCurrentPanCakeTMP->pNextContainer
            sMV_Tag=pCurrentPanCakeTMP->str_tag_C(uB_ind)
            If Len(sMV_Tag)=MAX_TAGLEN Then
                uB_tmp=1
                While pPanTmp<>0 And uB_tmp=1
                    If pPanTmp->str_tag_C(uB_ind)<>"" Then : sMV_Tag+= pPanTmp->str_tag_C(uB_ind) : Else : uB_tmp=0 : End If
                    pPanTmp=pPanTmp->pNextContainer
                Wend
            End If
            Return sMV_Tag
        Else
            Return pCurrentPanCakeTMP->str_tag_C(uB_ind)
        End If   
    End Property
# ENDIF

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->Tag0<>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
            Else 'ListData->str_flat_tag
                If this.pNode->pNext<>0 Then
                    pNode->Tag0 = LIST_DEL : pNode->BranchCount=0 : NbCollected +=1 ':  pNode->pBranchLastNode=0 ': iLong+=1  For ub1=1 To RUP_COLS : pNode->Tag1(ub1)="" : Next ub1 :
                    If pNode->ListData<>0 Then
                        # IF TagMode=0
                            For ub1=MIN_COLS To MAX_COLS : *pNode->ListData->str_tag_C(ub1)="" : Next ub1
                        # ELSEIF TagMode=1
                            Dim As ListContainer Ptr pPanTemp=pNode->ListData->pNextContainer, PNextContTMP=pPanTemp'->pNextContainer
                           ' If pPanTemp<>0 Then : PNextContTMP=pPanTemp->pNextContainer : End If
                            While PNextContTMP<>0             
                                pPanTemp=PNextContTMP
                                For ub1=MIN_COLS To MAX_COLS : pPanTemp->str_tag_C(ub1)="" : Next ub1
                                PNextContTMP=PNextContTMP->pNextContainer
                                pPanTemp->pNextContainer=pPanCakeGarbage->pNextContainer : pPanCakeGarbage->pNextContainer=pPanTemp :  uContainerGarbCt+=1                               
                            Wend
                            For ub1=MIN_COLS To MAX_COLS : pNode->ListData->str_tag_C(ub1)="" : Next ub1
                        # ELSE
                            For ub1=MIN_COLS To MAX_COLS : pNode->ListData->str_tag_C(ub1)="" : Next ub1
                        # ENDIF
                        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->Tag0 = 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->Tag0 = LIST_RES  ' 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
        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->Tag1="" : 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->Tag0=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 : 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 : pCurrentPanCakeTMP=this.pValTmp->ListData : this.ValSet(str_value) : Return 1 : End Property 'this.pValTmp->ListData->str_item=str_value :
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 : bfStepZero=0
    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
        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 ': TrackCompCounter+=1 ': ? "Track Compute on " & this.pNode->Tag0 
    While pTemp1->Tag0<>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 : pFirstNodeTMP=pTemp1 : pLastNodeTMP=pLastNode : Return 1
End Property

Property List.TrackSecure As Byte
    If pNode->pPrev->Tag0=LIST_RES Then
    ElseIf pNode->pPrev=pTrackTmp Then  : bAlrdyTracked=1
    ElseIf pNode=pTrackTmp Then
        pFirstNode=pFirstNodeTMP : pLastNode=pLastNodeTMP : this.uCount=pFirstNode->BranchCount 
        If pLastNode<>pFirstNode->pNext Then : bAlrdyTracked=1 : End If 
    End If
    this.TrackCompute
    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

Last edited by Lost Zergling on Mar 05, 2021 11:47, edited 122 times in total.
Lost Zergling
Posts: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

Code PART 2/4 :

Code: Select all


Property List.GiveBranchDown As ListNode Ptr
    Dim As ListNode Ptr pTemp1, pTemp2   
    If pNode->pBranch=0 Or pNode->Tag0=LIST_RES Or pNode->Tag0=LIST_DEL Or pNode=pWhyteMove Or pNode=pFlatRoot Or pNode->Tag0="" Then : Return 0
    ElseIf pNode->pBranch->Tag0<>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->Tag0=LIST_RES Or pNode->Tag0=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
        If pLocalRoot->ListData<>0 Then
            # IF TagMode=0
                *pLocalRoot->ListData->str_tag_C(1)=""
            # ELSE
                pLocalRoot->ListData->str_tag_C(1)=""
            # ENDIF
        End If
        pLocalRoot->Tag0=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
            If pLocalRoot->ListData<>0 Then
                # IF TagMode=0
                    *pLocalRoot->ListData->str_tag_C(1)=""
                # ELSE
                    pLocalRoot->ListData->str_tag_C(1)=""
                # ENDIF
            End If
            pLocalRoot->Tag0=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->Tag0=LIST_DEL Then : this.FlatStack(0) : End If
    If pFirstNode->pNext->Tag0=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.pFlatRoot->pBranch->BranchCount=0 : If pFirstNode->pBranch=pFlatRoot Then : uCount=0 : End If 
    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
    If this.HasTag(str_Tag) Then : this.pNode = this.pSearchNode : uB_tmp=1
    Else
        pNode = this.pLastNode : this.uCount+=1 : pNode->pNext = this.AllowCake 'And eat it
        pNode->pNext->pPrev = pNode : pNode->pNext->Tag0 = str_Tag  : uB_tmp=0
        pNode = pNode->pNext : this.pLastNode = pNode : 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
    End If       
    If  (uTag=0 And uB_IsTree=1) Or str_Tag=""  Then
    ElseIf this.uB_tmp=0 Then
        If pNode->ListData=0 Then : pNode->ListData=AllowPanCake : End If
        If uTag=0 Then : pCurrentPanCakeTMP=pNode->ListData : this.FlatTagSet(Str_Tag)
        Else : pCurrentPanCakeTMP=pNode->ListData : uB_ind=uTag : this.TagC_Set(Str_Tag)  '   pNode->ListData->str_tag_C(uTag) = str_Tag
        End If       
    End If
    Return uB_tmp
End Property

Property List.Tag As String : Return This.Tag(uTag) : End Property
Property List.Tag(i As Integer) As String ' La propriété devient multicontextuelle (flat & tree) suite chgt implémentation   "@" + Val(pz)
    If i=0 And uB_IsTree=1 Then : Return this.pNode->Tag0  ' Tree context specified by user
    ElseIf pNode->ListData=0 Then : Return this.pNode->Tag0  ' Tree context mandatory
    ElseIf i=0 Then :  If *pNode->ListData->str_flat_tag="" Then : Return this.pNode->Tag0 : Else : Return *pNode->ListData->str_flat_tag : End If
    Else
        # IF TagMode=0
            Return *pNode->ListData->str_tag_C(i)
        # ELSEIF TagMode=1
            If uB_RedimTagLen=1 Then
                Dim As ListContainer Ptr pPanTmp=pNode->ListData->pNextContainer
                sMV_Tag=pNode->ListData->str_tag_C(i)
                If Len(sMV_Tag)=MAX_TAGLEN Then
                    uB_tmp=1
                    While pPanTmp<>0 And uB_tmp=1
                        If pPanTmp->str_tag_C(i)<>"" Then : sMV_Tag+= pPanTmp->str_tag_C(i) : Else : uB_tmp=0 : End If
                        pPanTmp=pPanTmp->pNextContainer
                    Wend
                End If
                Return sMV_Tag
            Else
                Return pNode->ListData->str_tag_C(i)
            End If           
        # ELSE
            Return pNode->ListData->str_tag_C(i)
        # ENDIF
    End If
End Property

Property List.HasTagFlat(str_Tag As String) As Byte
    If uTag<>0 Then : Return this.HasTagFlat(str_Tag) : End If
    Dim As ListNode Ptr pTemp : uB_tmp=0   
    If bSeekMethod=1 Then
        pTemp=pFirstNode : If this.pFirstNode=this.pFirstFIRSTNode Then : pTemp = this.pGarbage  : End If
        While (pTemp->pNext <> 0 And  uB_tmp=0  AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : End If : Wend
    ElseIf bSeekMethod=2 Then
        pTemp=pLastNode : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : End If
        While (pTemp->pPrev <> 0 And  uB_tmp=0  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : End If : Wend 
    Else
        pTemp=pNode : If pTemp=0 Then : pTemp = this.pFirstNode : End If ': If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : End If
        While (pTemp->pNext <> 0 And  uB_tmp=0  AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : End If : Wend
    End If   
    If uB_tmp=1  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.HasTag(str_Tag As String) As Byte
    Dim pTemp As ListNode Ptr
    this.sSearchTag = str_Tag : uB_tmp=0
    If this.bSeekMethod=1 Then
        pTemp = this.pFirstNode : If this.pGarbage<>0 And this.pFirstNode=this.pFirstFIRSTNode Then : pTemp = this.pGarbage  : End If           
        If uTag=0 Then
            While (pTemp->pNext <> 0 And uB_tmp=0 AND pTemp <> this.pLastNode)
                pTemp = pTemp->pNext :
                If pTemp->ListData<>0 Then : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : ElseIf *pTemp->ListData->str_flat_tag="" And pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If : ElseIf pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If
            Wend               
        Else
            # IF TagMode=0
                If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0) : pTemp = pTemp->pNext :  If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSEIF TagMode=1
                pCurrentPanCakeTMP=pTemp->ListData : uB_ind=uTag
                If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0) : pTemp = pTemp->pNext : pCurrentPanCakeTMP=pTemp->ListData : If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSE
                If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0) : pTemp = pTemp->pNext :  If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ENDIF
        End If     
    ElseIf this.bSeekMethod=2 Then
        pTemp = this.pLastNode
        If uTag=0 Then               
            If pTemp->ListData<>0 Then : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : ElseIf *pTemp->ListData->str_flat_tag="" And pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If : ElseIf pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If
            While (pTemp->pPrev <> 0 And  uB_tmp=0  AND pTemp <> this.pGarbage )
                pTemp = pTemp->pPrev
                If pTemp->ListData<>0 Then : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : ElseIf *pTemp->ListData->str_flat_tag="" And pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If : ElseIf pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If
            Wend               
        Else
            # IF TagMode=0
                uB_tmp=0 : If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pPrev <> 0 And  uB_tmp=0  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSEIF TagMode=1
                pCurrentPanCakeTMP=pTemp->ListData : uB_ind=uTag
                uB_tmp=0 : If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pPrev <> 0 And uB_tmp=0 AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : pCurrentPanCakeTMP=pTemp->ListData : If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSE
                uB_tmp=0 : If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pPrev <> 0 And  uB_tmp=0  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ENDIF
        End If   
    Else
        pTemp = this.pNode : If pTemp=0 Then : pTemp = this.pFirstNode : End If
        If uTag=0 Then
            If pTemp->ListData<>0 Then : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : ElseIf *pTemp->ListData->str_flat_tag="" And pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If : ElseIf pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If
            While (pTemp->pNext <> 0 And uB_tmp=0 AND pTemp <> this.pLastNode )
                pTemp = pTemp->pNext
                If pTemp->ListData<>0 Then : If *pTemp->ListData->str_flat_tag=str_Tag Then : uB_tmp=1 : ElseIf *pTemp->ListData->str_flat_tag="" And pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If : ElseIf pTemp->Tag0=str_Tag Then : uB_tmp=1 : End If
            Wend               
        Else
            # IF TagMode=0
                If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0 AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSEIF TagMode=1
                pCurrentPanCakeTMP=pTemp->ListData : uB_ind=uTag
                uB_tmp=0 : If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0 AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : pCurrentPanCakeTMP=pTemp->ListData : If pCurrentPanCakeTMP<>0 Then : If this.TagC_Get = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ELSE
                If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If
                While (pTemp->pNext <> 0 And uB_tmp=0 AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uTag) = str_Tag Then : uB_tmp=1 : End If : End If : Wend
            # ENDIF
        End If     
    End If   
    If uB_tmp=1  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 :
    If uTag=0 And uB_IsTree=1 Then : pTemp->pNext->Tag0 = str_Tag
    Else
        pTemp->pNext->Tag0=str_Tag : If pTemp->pNext->ListData=0 Then : pTemp->pNext->ListData=AllowPanCake() : End If : pCurrentPanCakeTMP=pTemp->pNext->ListData
        If uTag=0 Then : this.FlatTagSet(Str_Tag)
        ElseIf uSortTag<>-1 Then : uB_ind=uTag : this.TagC_Set(Str_Tag)  ' pTemp->pNext->ListData->str_tag_C(uTag)=str_Tag
        End If
    End If
    pTemp = pTemp->pNext : this.pLastNode = pTemp : this.pNode = pTemp
    If bBranchCountDown=1 Then : this.BCountDown(1) : End If : Return 1
End Property

Property List.Insert(str_Tag As String) As Byte
    Dim pTemp As ListNode Ptr : Dim item As ListContainer
    pTemp = this.pNode : this.uCount+=1 : pTemp->pNext = this.AllowCake 'And eat it
    pTemp->pNext->pPrev = this.pNode :
    If uTag=0 And uB_IsTree=1 Then : pTemp->pNext->Tag0 = str_Tag
    Else
        pTemp->pNext->Tag0=str_Tag : If pTemp->pNext->ListData=0 Then : pTemp->pNext->ListData=AllowPanCake() : End If : pCurrentPanCakeTMP=pTemp->pNext->ListData
        If uTag=0 Then : this.FlatTagSet(Str_Tag)
        ElseIf uSortTag<>-1 Then : uB_ind=uTag : this.TagC_Set(Str_Tag)  ' pTemp->pNext->ListData->str_tag_C(uTag)=str_Tag
        End If
    End If : If pLastNode=pTemp Then : pLastNode = pTemp->pNext : End If
    this.pNode = pTemp->pNext : If bBranchCountDown=1 Then : this.BCountDown(1) : End If : Return 1
End Property

Property List.RwTag(s_Tag As String) As Byte
    If  uTag<>0  Then : If pNode->ListData=0 Then : this.pNode->ListData=AllowPanCake() : End If : pCurrentPanCakeTMP=pNode->ListData : uB_ind=uTag : this.TagC_Set(s_Tag) : Return 1 ' pNode->ListData->str_tag_C(uTag)=s_Tag
    Else
        this.pNode->Tag0=s_Tag ': If uB_IsTree=1 Then : Return 1 : End If
        If pNode->ListData=0 Then : Return 1 : End If : pCurrentPanCakeTMP=pNode->ListData : uB_ind=uTag : this.FlatTagSet(s_Tag) : Return 1
    End If
End Property
Property List.RwTag0(s_Tag As String) As Byte : uB_tmp=uTag : uTag=0 : this.RwTag(s_Tag ) : uTag=uB_tmp : Return 1 : End Property
Property List.RwTag1(s_Tag As String) As Byte : uB_tmp=uTag : uTag=1 : this.RwTag(s_Tag ) : uTag=uB_tmp : 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 then : this.uTag=MAX_COLS : 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 : this list instance cannot be re-used" : Return 0 : End If :
    Dim  As ListNode Ptr pTemp, pTemp2 : If bTracking=1 Then : this.TrackCompute : End If '  bTracking=0 : 
    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(uTag) 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 ' Or pNode->pNext=pEndFlat
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
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->Tag0=LIST_DEL Or pNode->Tag0=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

'==========================================================================================TYPE LIST PUBLIC PROPERTIES - SORTING
Property List.ColSort(i as Byte) As Byte : If i > MAX_COLS then : this.uTag=MAX_COLS : 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 : Dim As uByte tmpIsTree=this.uB_IsTree : this.uB_IsTree=0
    If pFirstNode=pFirstFIRSTnode Then : pTemp1=pGarbage : End If
    'Trie+Insert Sort - non recursive   
    gCollector.SetRelation(1) : gCollector.HashKeyUnique(1) : gCollector.HashSort(1) : gCollector.fSortMethod(this.bSortMT) : 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
        If gCollector.HashTag( this.Tag(this.uSortTag) )=1 Then : gCollector.HashKeyUnique(0) : gCollector.SeekMethod(1) : gCollector.HashTag( this.Tag(this.uSortTag) ) : gCollector.HashKeyUnique(1) : : End If
        gCollector.SetRelation1(this.pNode) : by=this.fStep
    Wend
    If pFirstNode<>pFirstFIRSTnode Then
        If gCollector.HashTag( this.Tag(this.uSortTag) )=1 Then : gCollector.HashKeyUnique(0) : gCollector.SeekMethod(1) : gCollector.HashTag( this.Tag(this.uSortTag) ) : gCollector.HashKeyUnique(1) : End If
        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) :  this.uB_IsTree=tmpIsTree
    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 : Dim as Byte bHashSort=this.bSortMT : this.bSortMT=0
    If this.Up Then : this.Down : End If : If bSortMth=-1 Then : this.fSortMethod(-1) : Else : this.fSortMethod(1) : End If  : this.HashSort(0) :
    this.Root : this.fSort :  this.Root : 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 : bSortMT=bHashSort
    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

Last edited by Lost Zergling on Jan 04, 2021 13:11, edited 34 times in total.
PaulSquires
Posts: 999
Joined: Jul 14, 2005 23:41

Re: LZLE List Engine with user friendly powerfull syntax

Post by PaulSquires »

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: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

Code PART 3/4 : => PART 4 BELOW

Code: Select all


'==========================================================================================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 pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : End If 
    If bTracking=1 And pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : this.TrackSecure : End If :  bTracking=0 
    If this.IsDestroyed=1 Then : Print "LZLE error - List.Root : Error List destroyed : instance can't be re-used" : Sleep : Return 0 : End If
    this.RootPrivate
    If pLocalMove<>0 Then
        If pLocalMove->ListData<>0 Then
            # IF TagMode=0
            *pLocalMove->ListData->str_tag_C(1)=""
            # ELSE
            pLocalMove->ListData->str_tag_C(1)=""
            # ENDIF
        End If
        pLocalMove->pBranch=0 :  pLocalMove->Tag0=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->Tag0=""
        If this.pWhyteMove->pNext<>0 And pWhyteMove->pNext->Tag0<>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 pGarbage=0 Then  ' This.Tag(LIST_DEL) :
        This.BlindTag(LIST_DEL) : pGarbage=this.pNode : pGarbage->pPrev=pFlatRoot : this.Val(LIST_DEL) :
        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->Tag0<>"" 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->Tag0=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.NodeRecycle : this.pNode=AllowCake : pNode->Tag0="" : pLocalMove=pNode : pNode->pNext=pGarbage->pNext
    # IF TagMode=0
        If pLocalMove->ListData<>0 Then : *pLocalMove->ListData->str_tag_C(1)="" : End If
    # ELSE
        If pLocalMove->ListData<>0 Then : pLocalMove->ListData->str_tag_C(1)="" : End If
    # ENDIF
    pLocalMove->pBranch=0 :  pLocalMove->Tag0=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 : bfStepZero=0
    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
    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
    Wend : this.bHashStepRev=0 : Return 0
End Property

Property List.KeyStep As Byte : While this.HashStep=1 : If pNode->Tag1<>0 And pNode->Tag1<>255 Then : Return 1 : End If : Wend : End Property
Property List.KeyStepRev As Byte : While this.HashStepRev=1 : If pNode->Tag1<>0 And pNode->Tag1<>255 Then : Return 1 : End If : Wend : End Property
Property List.KeyStep(ub as uByte) As Byte : While this.HashStep=1 : If pNode->Tag1=ub Then : Return 1 : End If : Wend : End Property
Property List.KeyStepRev(ub as uByte) As Byte : While this.HashStepRev=1 : If pNode->Tag1=ub Then : Return 1 : End If : Wend : End Property

'Numeric parse optimization
Property List.nCurLevel As Byte : Return uB_CurLevel  : End Property
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->Tag1<>0 And pNode->Tag1<>255 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->Tag1<>0 And pNode->Tag1<>255 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>DEF_KEYLEN Then : Listptemp2_b=_CAllocate(iLen+1) : Swap Listptemp2,Listptemp2_b : IsPt2Swp=1 : End If
    str_testTMP=str_Tag  ': If bNFTrackedOut=1 Then : bAlrdyTracked=0 : This.TrackCompute : bNFTrackedOut=0 : 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 : Str_tmp=this.HashTag ' If pFirstNode->Tag1<>"" Then : Str_tmp=pFirstNode->Tag1 & pNode->Tag0 : Else : Str_tmp=this.HashTag  : End If ': If ubKeysRegister=1 Then : pFirstNode->Tag1=Left(Str_tmp, Len(Str_tmp)-istep) : End If
        End If
        iLenStrTmp=Len(Str_tmp)
        If iLenStrTmp>DEF_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
            If MAX_HASHLEN=1 Then : iLenpNode=1 : Else : iLenpNode=Len(pNode->Tag0) : End If
            While iLen<iLenStrTmp : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenStrTmp=Len(Str_tmp)-iLenpNode :  Str_tmp=Left(Str_tmp, iLenStrTmp) : If MAX_HASHLEN=1 Then : iLenpNode=1 : Else : iLenpNode=Len(pNode->Tag0) : End If :  Wend   
            pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
            iLenStrTmp=Len(Str_tmp) ': While iLen<Len(Str_tmp) : this.UpLevel : Str_tmp=this.HashTag :  Wend  '  pNode=pFirstNode->pNext : 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
                *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
                If MAX_HASHLEN=1 Then : iLenpNode=1 : Else : iLenpNode=Len(pNode->Tag0) : End If
                While iLen<iLenStrTmp : pNode=pFirstNode->pBranch : pFirstNode=pFirstNode->pPrev : iLenStrTmp=Len(Str_tmp)-iLenpNode :  Str_tmp=Left(Str_tmp, iLenStrTmp) : If MAX_HASHLEN=1 Then : iLenpNode=1 : Else : iLenpNode=Len(pNode->Tag0) : End If :  Wend   
                pLastNode=pFirstNode->pBranchLastNode : uCount=pFirstNode->BranchCount
                iLenStrTmp=Len(Str_tmp) ' 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- >Tag0<>Str_tmp  AndAlso pTemp<>pTemp02 ) : pTemp = pTemp->pPrev : Wend
        Else : pTemp = pTemp02 : While ( pTemp- >Tag0<>Str_tmp  AndAlso pTemp<>pLastNode ) : pTemp = pTemp->pNext : Wend
        End If
            
        Else : uB_tmp=0
            If bSeekMethod_TMP=2 Then
                pTemp = this.pLastNode : If pTemp=pWhyteMove Then : pTemp = pTemp->pPrev : End If
                If uSortTag=0 Then : While ( pTemp->Tag0>Str_tmp  And pTemp<>pTemp02 ) : pTemp = pTemp->pPrev : Wend
                Else  '  While ( pTemp->ListData->str_tag_C(uSortTag)>Str_tmp  And pTemp<>pTemp02 ) : pTemp = pTemp->pPrev : Wend
                    # IF TagMode=0
                        If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uSortTag)>Str_tmp  Then : uB_tmp=1 : End If : End If
                        While (uB_tmp=1 AndAlso pTemp<>pTemp02) : pTemp = pTemp->pPrev : If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uSortTag)>Str_tmp Then : uB_tmp=1 : End If : End If : Wend
                    # ELSE                   
                        If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uSortTag)>Str_tmp  Then : uB_tmp=1 : End If : End If
                        While (uB_tmp=1 AndAlso pTemp<>pTemp02) : pTemp = pTemp->pPrev : If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uSortTag)>Str_tmp Then : uB_tmp=1 : End If : End If : Wend
                    # ENDIF
                End If
                If pTemp=pLastNode Then : IsLast=1 : End If : If pTemp=pFirstNode Then : pTemp=pTemp->pNext : End If
            Else                 
                If uSortTag=0 Then : pTemp=pTemp02 : While (pTemp->Tag0<Str_tmp  AndAlso pTemp<>pLastNode) : pTemp=pTemp->pNext : Wend : If pTemp->Tag0<Str_tmp  AndAlso pTemp=pLastNode Then : IsLast=1 : End If ': Print "**1" : sleep
                Else  'While (pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  AndAlso pTemp<>pLastNode) : pTemp=pTemp->pNext : Wend : If pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  AndAlso pTemp=pLastNode Then : IsLast=1 : End If
                    pTemp=pTemp02
                    # IF TagMode=0
                        If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  Then : uB_tmp=1 : End If : End If
                        While (uB_tmp=1 AndAlso pTemp<>pLastNode) : pTemp = pTemp->pNext : If pTemp->ListData<>0 Then : If *pTemp->ListData->str_tag_C(uSortTag)<Str_tmp Then : uB_tmp=1 : End If : End If : Wend
                        If *pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  AndAlso pTemp=pLastNode Then : IsLast=1 : End If
                    # ELSE                   
                        If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  Then : uB_tmp=1 : End If : End If
                        While (uB_tmp=1 AndAlso pTemp<>pLastNode) : pTemp = pTemp->pNext : If pTemp->ListData<>0 Then : If pTemp->ListData->str_tag_C(uSortTag)<Str_tmp Then : uB_tmp=1 : End If : End If : Wend
                        If pTemp->ListData->str_tag_C(uSortTag)<Str_tmp  AndAlso pTemp=pLastNode Then : IsLast=1 : End If
                    # ENDIF
                End If
            End If
        End If
        Str_tmp2=pTemp- >Tag0  ':  Print "**2" : sleep If uTag=0..
        If Str_tmp2=Str_tmp And bHashKeyUnique=1 Then : this.pNode = pTemp
        ElseIf Str_tmp2=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->Tag0 = Str_tmp  '  If uTag=0..
            HadHashTag=0 : pFirstNode->BranchCount+=1 : pNode = pTemp03
            If bTrackMultiKeys>0 And bCopyCatRelation=0 Then                 
                If Str_tmp2=Str_tmp Then : If pNode->pNext->pBranchLastNode=0 Then : pNode=pNode->pNext : this.HoldBack(uBTrackTarget) : pNode=pTemp03 : End If : this.HoldBack(uBTrackTarget) : End If
            End If
        Else
            pTemp03 = this.pLastNode : this.uCount+=1 : pTemp03->pNext = this.AllowCake 'And eat it
            pTemp03->pNext->pPrev = this.pLastNode
            pTemp03->pNext->Tag0 = Str_tmp  '  If uTag=0..
            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 Str_tmp2=Str_tmp Then : this.HoldBack(uBTrackTarget) : End If
            End If
     '  Else : Print "LZLE error - attempt to clean process and aborting."  : Print this.DropAll & " / " & this.NodeCount : sleep : system               If bSeekMethod_TMP=2 Then : Print "Pt 9" : sleep :  End If
        End If
       
        If iLenCumul<iLen Then
            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->Tag0 = LIST_RES ' : Else : pTemp03->pNext->Tag1 = 3 : End If ' pTemp03->pNext- >Tag0 = 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 : this.pFirstNode=pTemp->pBranch : this.pNode = this.pFirstNode
            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 : str_Tag=str_testTMP
    this.pFirstNode->pBranchLastNode = this.pLastNode
    If this.pNode->Tag1=0 Then :  If HadHashTag=1 Then : HadHashTag=2 : End If : If bRHByPass=0 Then : this.pNode->Tag1=1 : End If : 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     
    Return HadHashTag
End Property

Property List.HashTag As String
    Dim As ListNode Ptr pTemp01= this.pFirstNode, pTemp02=this.pNode    
    pTemp01 = this.pFirstNode : pTemp02 = this.pNode
    If pFirstNode->pBranch<>pFlatRoot Then : Str_tmp = this.pnode->Tag0 'si pas ds contexte flat root on prends la clef Tag0
    ElseIf bTracking=1 And this.pnode->ListData=0 Then : Str_tmp = this.pnode->Tag0 ': bAlrdyTracked=0 : This.TrackCompute : pTemp01 = this.pFirstNode : pTemp02 = this.pNode
    Else : Str_tmp = *this.pnode->ListData->str_flat_tag  : End If
    While pTemp01->pPrev<>0
        pTemp02 = pTemp01->pBranch
        Str_tmp = pTemp02->Tag0  + Str_tmp                 
        pTemp01 = pTemp01->pPrev
    Wend   
    Return Str_tmp
End Property

Property List.HasTagTree(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->Tag0 <> str_Tag  AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : Wend
    ElseIf this.bSeekMethod=2 Then
        pTemp = this.pLastNode
        While (pTemp->pPrev <> 0 And pTemp->Tag0 <> str_Tag  AND pTemp <> this.pGarbage ) : pTemp = pTemp->pPrev : Wend
    Else
        pTemp = this.pNode : If pTemp=0 Then :  pTemp = this.pFirstNode : End If
        If pTemp->pNext <> 0 Then : pTemp = pTemp->pNext : End If
        While (pTemp->pNext <> 0 And pTemp->Tag0 <> str_Tag  AND pTemp <> this.pLastNode ) : pTemp = pTemp->pNext : Wend
    End If   
    If pTemp->Tag0 = 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.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 : pNode=pGarbage '   
    this.uCount = this.pFirstNode->BranchCount : pLastNode=this.pFirstNode->pBranchLastNode :' uB_tmp=uB_IsTree : uB_IsTree=1
    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.HasTagTree(Str_tmp)=1 Then           
            this.pNode = this.pSearchNode
            # IF TagMode=0
                If pNode->ListData<>0 Then : str_testTMP=*this.pNode->ListData->str_tag_C(1) : Else : str_testTMP="" :  End If
            # ELSE
                If pNode->ListData<>0 Then : str_testTMP=this.pNode->ListData->str_tag_C(1) : Else : str_testTMP="" :  End If
            # ENDIF
            If str_testTMP="*" Then : HadHashTag=1 : IsEtoile=1 : i=t
            ElseIf str_testTMP="!*" Then : HadHashTag=0 : i=t
            ElseIf str_testTMP="!" 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 : uB_IsTree=uB_tmp : Return 1 : Else : uB_IsTree=uB_tmp : If bHashStepRev=1 Then : Return this.KeyStepRev : Else : Return this.KeyStep :  End If  : End If      KO !           
            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 ': uB_IsTree=uB_tmp
    If HadHashTag=1 Then : bSearchRes=1 : pSearchNode=pNode
        If bAutoCursor=1 Then : Return 1
        ElseIf bAutoCursor=2 Then : If pNode->Tag1=0 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
    Dim pContextRetour As ListContext
    pContextRetour.pNode=pNode : pContextRetour.pFirstNode=This.pFirstNode : pContextRetour.pLastNode=This.pLastNode : pContextRetour.uCount=This.uCount
    this.Root : If this.HasHashTag(str_Tag)=1 Then : If pNode->Tag1<>0 And pNode->Tag1<>255 Then : Return 1 : Else : Return 0 : End If : Else : Return 0 : End If
    pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount
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 , ubtest=0
    this.NodeRecycle : NodeRecycle2
    'Contrôle multimode en entrée + contrôle du Token de fin de liste + gestion continuité des ptr
    If pNode->Tag0=LIST_RES Or pNode->Tag0=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 pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : this.TrackCompute : End If  ' If bTracking=1 Then : bAlrdyTracked=0 : tthis.TrackCompute : End If 
        pTemp6=pNode->pBranchLastNode
    ElseIf pFirstNode->pPrev=0 And pNode->pNext=0 Then : pTemp1=pNode : this.AllOf : pNode=pTemp1
    End If  
    If bRecur=2 And pNode->Tag1<>0 And pNode->Tag1<>255 Then : this.bNFmethod=1
    ElseIf bRecur=3 Then : If pNode->Tag1<>0 And pNode->Tag1<>255 Then : If bFullRecursive=0 Then : Return 0  : End If : this.bNFmethod=1 : Else : this.bNFmethod=-1  : End If
    ElseIf bRecur=4 Then : this.bNFmethod=-1 : End If ' If bTracking=1 Then : bAlrdyTracked=0 : this.TrackCompute : End If : Return 0 : End If  bRecur=0 :
    pTemp5=pFirstNode : pTemp2 = this.pNode : Str_tmp=this.HashTag : 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é  bNFflag
        If this.bNFmethod<>1 Then : If bTracking=1 Then : this.TrackCompute : End If : Return 0 : ElseIf this.pNode->Tag1=255 Then : Return 0 : ElseIf bHashStepRev=1 And pNode->pNext->Tag0=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->Tag0=this.pNode->Tag0 : pTemp1->Tag1=255
        pTemp1->pBranchLastNode=this.pNode->pBranchLastNode
        If pTemp2=pLastNode Then : pLastNode=pTemp1 : End If
        this.pNode->pBranch->pBranch=pTemp1 : this.pNode->pBranch=0
        If this.pNode->ListData=0 Then : this.pNode->ListData=this.AllowPanCake : End If : pCurrentPanCakeTMP=pNode->ListData : this.FlatTagSet(Str_tmp)  ' *this.pNode->ListData->str_flat_tag = 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->Tag0=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->Tag0=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->Tag0=LIST_RES Then
        pLocalRoot=this.pNode->pPrev : IsLastNode=1 :  pLocalRoot->Tag1=0 :
        If this.pFirstNode->pBranchLastNode=0 Then : pLocalRoot = this.pFirstNode : pLocalRoot->pBranch->pBranch=0 :  pLocalRoot->Tag1=0 : pLocalRoot->Tag0=LIST_DEL : End If
    ElseIf this.pNode=this.pFirstNode->pBranchLastNode Then       
        If this.pNode->pPrev->Tag0=LIST_RES Then : pLocalRoot=this.pNode->pPrev : IsLastNode=1 : pLocalRoot->Tag1=0 :  pLocalRoot->Tag0=LIST_DEL
        Else : this.pLastNode=this.pNode->pPrev : pFirstNode->pBranchLastNode=pLastNode : IsLastNode=1
        End If
    End If
   
  ' 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->Tag1=255 Or this.bNFmethod=-1Or this.bNFmethod=4) And pTemp2->pBranch=0   Then
        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->Tag0=LIST_DEL : pTemp2->Tag1=0 : 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 ': bNFmethod=bRecur 
            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 bNFmethod=-1 Then : this.NodeRecycle2 : ElseIf bNFmethod>1 Then : bRecur=bNFmethod : bNFmethod=-1 : End If : If pNode->Tag1=0 Or pNode->Tag1=255 Or bRecur>1 Then : this.NodeFlat : this.NodeRecycle2 : If bRecur>1 Then : bNFmethod=bRecur : End If : End If ' RECURSIF
            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
        End If
        If bFullRecursive=1 Then : this.up : this.NodeFlat : this.NodeRecycle2 : End If '                   *********** FULL REC
    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
        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->Tag0<>LIST_RES Then : pTemp2->pPrev->pNext=pTemp2->pNext : End If
            If pTemp2->ListData=0 Then : pTemp2->ListData=this.AllowPanCake : End If : pCurrentPanCakeTMP=pTemp2->ListData : this.FlatTagSet(Str_tmp)
            pTemp1->pNext = pTemp2 : this.pLastNode=pTemp2 : this.pFirstNode->pBranchLastNode=pTemp2 : pTemp2->pPrev=pTemp1 : pTemp2->pNext=0            
            this.pNode=pContextRetour.pNode : This.pFirstNode=pContextRetour.pFirstNode : This.pLastNode=pContextRetour.pLastNode : This.uCount=pContextRetour.uCount
            If bFullRecursive=1 Then : this.up : this.NodeFlat : this.NodeRecycle2 : End If '                   *********** FULL REC
            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
            If pTemp2->ListData=0 Then : pTemp2->ListData=this.AllowPanCake : End If : pCurrentPanCakeTMP=pTemp2->ListData : this.FlatTagSet(Str_tmp)
            pTemp1->pNext=pTemp2 : this.pLastNode=pTemp2 : this.pFirstNode->pBranchLastNode = pTemp2 : pTemp2->pPrev=pTemp1 : pTemp2->pNext=0
            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 bNFmethod<2 Then : this.NodeRecycle2 : ElseIf bNFmethod>1 Then : bRecur=bNFmethod : bNFmethod=-1 : End If : If pNode->Tag1=0 Or pNode->Tag1=255 Or bRecur>1 Then :  this.NodeFlat :  this.NodeRecycle2  :  If bRecur>1 Then : bNFmethod=bRecur : End If : End If  ' RECURSIF
            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
        End If
    End If
    If bTracking=1 And pTemp6<>0 Then 
        If pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : this.TrackCompute : End If
        this.NodeRecycle : pNode=AllowCake : pNode->pBranchLastNode=pTemp6 : pLocalMove=pNode : pLocalMove->Tag0=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 : Dim bTagExists As Byte : Dim As Byte uTagTmp=uTag, IsLastOne=0
    If this.pNode->ListData=0 Then : Return 0 : End If ' If pNode=pLocalMove Then : Return 0 : Else  Print "LZLE : RestoreHash : failure or non-value" :
    pTemp=this.pnode
    # IF TagMode=0
        If uTag=0 Then : str_tmp=*this.pNode->ListData->str_flat_tag : Else : str_tmp=*this.pNode->ListData->str_tag_C(uTag) : End If
    # ELSE
        If uTag=0 Then : str_tmp=*this.pNode->ListData->str_flat_tag : Else : str_tmp=this.pNode->ListData->str_tag_C(uTag) : End If
    # ENDIF
    If str_tmp="" Then : Return 0 : End If : pTmpPrev=this.pnode->pPrev : pTmpNext=this.pnode->pNext
    'Vérification du contexte
    If pNode->pNext=pEndFlat And pNode->pPrev=pFirstNode Then : IsLastOne=1 : End If
    this.NodeRecycle
    If this.pNode=this.pEndFlat Or pFirstNode->pBranch<>pFlatRoot  Then : this.Up : 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
        If uTag=0 Then : pTemp->Tag0= this.pnode->Tag0  : Else : pTemp->Tag0= Str(this.pnode->Tag1)  : End If
        pMove=this.pnode : pCurrentPanCakeTMP=pMove->ListData : this.FlatTagSet(str_tmp) ' *pMove->ListData->str_flat_tag=str_tmp :
        bTagExists=3 ' swap
    ElseIf bTagExists<>0 And pNode->Tag1<>0  Then ' tag deja existant et "vraie" clef
        'Gestion des modes (RHmethod)
        If uTag=0 Then
            If bRHmethod=-1 Then : pTemp->Tag0= this.pnode->Tag0 : pLocalMove=this.pnode : pLocalMove->Tag0=LIST_DEL : this.pFlatRoot->pBranch->BranchCount-=1 ':  pLocalMove->pBranch=0  :'envoi garbage
            ElseIf bRHmethod=1 Then : pTemp->Tag0= this.pnode->Tag0  : pMove=this.pnode :  pCurrentPanCakeTMP=pMove->ListData : this.FlatTagSet(str_tmp) : bTagExists=2 ' swap *pMove->ListData->str_flat_tag=str_tmp
            Else : If pNode->Tag1=255 Then : pNode->Tag1=1 : End If : this.RootPrivate : this.pNode=this.pFlatRoot : this.Branch : pNode=pTemp : Return 0  ' bypass
            End If   
        Else
            If bRHmethod=-1 Then : pTemp->Tag0= Str(this.pnode->Tag1)  : pLocalMove=this.pnode : pLocalMove->Tag0=LIST_DEL : this.pFlatRoot->pBranch->BranchCount-=1 ':  pLocalMove->pBranch=0  :'envoi garbage
            ElseIf bRHmethod=1 Then : pTemp->Tag0= Str(this.pnode->Tag1)  : pMove=this.pnode : pCurrentPanCakeTMP=pMove->ListData : this.FlatTagSet(str_tmp) : bTagExists=2 ' swap *pMove->ListData->str_flat_tag=str_tmp :
            Else : If pNode->Tag1=255 Then : pNode->Tag1=1 : End If : this.RootPrivate : this.pNode=this.pFlatRoot : this.Branch : pNode=pTemp : Return 0  ' bypass
            End If   
        End If
    Else
        If uTag=0 Then : pTemp->Tag0= this.pnode->Tag0 : Else : pTemp->Tag0=Str(this.pnode->Tag1) : End If
        pLocalMove=this.pnode : pLocalMove->Tag0=LIST_DEL : this.pFlatRoot->pBranch->BranchCount-=1 ':  pLocalMove->pBranch=0  :
    End If
    uTag=uTagTmp
    'Swapping mémoire
    pNode->Tag1=pTemp->Tag1
    pTemp->pPrev->pNext=pTemp->pNext : pTemp->pNext->pPrev=pTemp->pPrev
    pTemp->pPrev=this.pnode->pPrev : pTemp->pNext=this.pnode->pNext  : *pTemp->ListData->str_flat_tag=""
  '  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->Tag1=""  '  pnode->pBranch->Tag1=""
        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<>3 Then : this.pnode=pLocalMove : this.pnode->pPrev=pTmpPrev : this.pnode->pNext=pTmpNext :  pLocalMove->pBranch=0  : pLocalMove->Tag1=0 : pLocalMove->Tag0=LIST_DEL :
    Else : pNode=pMove : pTmpPrev->pNext=pNode : pTmpNext->pPrev=pNode : pNode->pPrev=pTmpPrev : pNode->pNext=pTmpNext :
    End If : If IsLastOne=1 Then : this.Up : bfStepZero=1 : pNode=pLastNode : End If '
    Return 1
End Property

Property List.Check(ub As uByte) As Byte : this.pNode->Tag1=ub : Return 1 : End Property
Property List.Check As Byte : Return this.pNode->Tag1 : 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 - use 'VectorUnlock' property before" : 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>MAX_HASHLEN Then : Print "LZLE warning : HashLen Property ignored (deprecated), or must be =< MAX_HASHLEN (constant)" : End If : this.bHashLen=1 : Return 1 : End Property
Property List.KeysRegister(ub As uByte) As Byte : Print "LZLE warning : KeysRegister Property ignored (deprecated)" :  Return 0 : End Property
Property List.NFmethod(i As Byte) As Byte : If i=-1 Or i=0 Or i=1 Or i=2 Or i=3 Or i=4 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 : bFullRecursive=0 :  If i=2 Then :  this.bPickReduce=1 : this.bFullRecursive=1 : ElseIf i=1 Then : this.bPickReduce=1 : Else : this.bPickReduce=0 : If i<>0 Then :  ? "LZLE warning : NFrecursive : invalid parameter - autoset to 0" : End If : End If : Return 1 : End Property
'Property List.NFFullRecursive(i As Byte) As Byte : If i=1 Then : this.bFullRecursive=1 : Else : this.bFullRecursive=0 : If i<>0 Then :  ? "LZLE warning : NFFullRecursive : invalid parameter - autoset to 0" : End If : 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 : ? "LZLE warning : SeekMethod : invalid parameter" : 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 "LZLE warning : SnatchBLMethod : invalid parameter" : Return 0 : End If : End Property
Property List.TrackMethod(by As Byte) As Byte : ? "LZLE warning : TrackMethod Property deprecated (ignored, autoset)" : Return 0 : End Property ' If by=0 Or by=1 Then : bTrackingMethod=by : Return 1 : Else : Return 0 : End If
Property List.TrackMultiKeys(uB as uByte) As Byte : If -1<=uB<=MAX_COLS+1 Then : bTrackMultiKeys=uB : Return 1 : End If : ? "LZLE warning : TrackMultiKeys : invalid parameter" : Return 0 : End Property
Property List.TrackTarget(uB As uByte) As Byte : If 0<=uB<=MAX_TRACKS Then : uBTrackTarget=uB : Return 1 : End If : ? "LZLE warning : TrackTarget : invalid parameter" : 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->Tag0=LIST_RES  Or pNode->Tag0=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->Tag1=0 : End If : pNode->BranchCount=0 : Wend
    Else : While this.HashStepTrace And pNode<>pTemp2 :  If bHStepTrace=-1 Then : pFirstNode->Tag1=0 : 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->Tag0=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
    uBHoldBackRev=0
    If pNode->Tag0=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) :TrackTrace(by)=pNode : Return 1 '  pNode->pBranchLastNode=0 : 
    End If
End Property
Property List.HoldBackRev As Byte : Return this.HoldBackRev(0) : End Property
Property List.HoldBackRev(by As Byte) As Byte
    uBHoldBackRev=1
    If pNode->Tag0=LIST_RES Or bColTrackLocked=1 Then : Return 0
    ElseIf TrackTrace(by)<>0 Then : pNode->pBranchLastNode=TrackTrace(by) : TrackTrace(by)=this.pNode : pLastHoldBackRev(by)=pNode : Return 1
    Else : this.TrackSet(by) : TrackTrace(by)=pNode ': pNode->pBranchLastNode=pFirstNode :
    Return 1
    End If
End Property

Property List.TrackStep As Byte
    bAlrdyTracked=0    
    If pNode->pBranchLastNode->Tag0=LIST_DEL Or bColTrackLocked=1 Or pNode->pBranchLastNode=0 Then : this.Root : bTracking=0 :  Return 0 : End If
    If pTrackTmp=pNode Then  ' If pNode->pBranchLastNode=0 Then : this.Root : bTracking=0 : Return 0  : End If
        pFirstNode=pFirstNodeTMP : pLastNode=pLastNodeTMP : this.uCount=pFirstNode->BranchCount 
    End If    
    If pNode->pBranchLastNode<>0  And pNode->pBranchLastNode->Tag0<>LIST_RES Then 
        pTrackTmp=pNode : pNode=pNode->pBranchLastNode : bTracking=1 
        pFirstNodeTMP=pFirstNode : pLastNodeTMP=pLastNode : pTrackPrevTmp=pTrackTmp->pPrev ': pTrackNextTmp=pTrackTmp->pNext 
        If pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : this.TrackCompute ' bTrackingMethod=1 Or 
        ElseIf pNode->pNext=pTrackTmp Or pNode=pTrackPrevTmp  Then : bAlrdyTracked=1: End If ' Or pNode->pNext=pTrackNextTmp Ko
        If pNode=pEndFlat Then : this.Root : bTracking=0 :  Return 0 : End If : this.TrackSecure
        Return 1
    End If : bAlrdyTracked=0 : this.TrackCompute : bTracking=0 : Return 0
End Property

Property List.Track As Byte : Return this.Track(0) : End Property  'ubTrackTarget
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->Tag0<>LIST_DEL And pNode->Tag0<>LIST_RES And pNode<>pLocalMove Then : This.TrackSecure : End If : this.Root : bTracking=1 ': 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->Tag0=LIST_DEL
        If this.Tracks(by).pNode->Tag0=LIST_DEL Then 
            If uBHoldBackRev=0 Then : pNode->pBranchLastNode=this.Tracks(by).pNode->pBranchLastNode
            Else : pNode->pBranchLastNode=TrackTrace(by)->pBranchLastNode : End If
        Else 
            If uBHoldBackRev=0 Then : pNode->pBranchLastNode=this.Tracks(by).pNode
            Else : pNode->pBranchLastNode=TrackTrace(by) : End If
        End If
        If uBHoldBackRev=0 Then : pFirstNode=this.Tracks(by).pFirstNode : pLastNode=pFirstNode->pBranchLastNode : bHashLen=this.Tracks(by).bLcHashLen
        Else : bAlrdyTracked=0 : this.TrackCompute : End If
        pNode->pBranch=0 : pNode->pPrev=0 : pNode->Tag0="" : bAlrdyTracked=0  ': bTracking=1 
        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 
    Dim pTemp As ListNode Ptr
    If uBHoldBackRev=0 Then : pTemp=this.Tracks(by).pNode : Else : pTemp=TrackTrace(by) : End If
    If pNode->Tag0=LIST_RES Or pNode->Tag0=LIST_DEL Or pNode->Tag0=LIST_RES Or pNode->Tag0="" Then
        If this.Tracks(by).pFirstNode=0 Then : Return 0 : Else : ? "LZLE error : Invalid TrackSet Context" : Return 0 : End If
    End If
    this.NodeRecycle :  this.Tracks(by).pNode=pNode 
    pTrackTmp=0 : bAlrdyTracked=0 : this.TrackSecure : bTracking=1
    this.Tracks(by).pFirstNode=pFirstNode : this.Tracks(by).bLcHashLen=bHashLen : TrackTrace(by)=pNode : 
    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
Last edited by Lost Zergling on Jan 04, 2021 13:13, edited 22 times in total.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Post by sancho3 »

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: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

Code PART 4/4 :

Code: Select all

Property List.IsTracked As Byte : If  bTracking=1 Then : Return 1 : Else :  Return 0 : End If  : End Property
Property List.IsTracked(uB As uByte) As Byte : If  uB=1 Or uB=0 Then : bTracking=uB : Return 1 : Else :  Return 0 : End If  : End Property
Property List.IsTagFree As Byte : Dim i As Byte : If pNode->pBranchLastNode<>0 And pNode->Tag0<>LIST_RES Then : Return 1 : Else : For i=0 To MAX_COLS : 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_ASIDE Or By < 1 Then : Return 0 : End If :' If bNFTrackedOut=1 Then : bAlrdyTracked=0 : This.TrackSecure : bNFTrackedOut=0 : End If  ' If bTracking=1 Then : bAlrdyTracked=0 : tthis.TrackCompute : End If 
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode :  Lcontext(by).uBIsTracked=bTracking
    Lcontext(by).pNode=pNode : Lcontext(by).pFirstNode=pFirstNode : Lcontext(by).pLastNode=pLastNode : Lcontext(by).uCount=this.uCount : Lcontext(by).LcHashTag=pNode->Tag0 : 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_ASIDE Or By < 1 Then : Return 0 : End If ': If bNFTrackedOut=1 Then : bAlrdyTracked=0 : This.TrackSecure : bNFTrackedOut=0 : End If 
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode : bTracking=Lcontext(by).uBIsTracked
    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
    If pTrackTmp=pNode Then : pFirstNode=pFirstNodeTMP : pLastNode=pLastNodeTMP : this.uCount=pFirstNode->BranchCount : End If
    this.pFirstNode->BranchCount = this.uCount : this.pFirstNode->pBranchLastNode = this.pLastNode : bTracking=1
    If pTemp1<>0 And pTemp1->Tag0<>LIST_RES Then 
        pTrackTmp=pNode : this.pNode=pTemp1 : bTracking=1 
        pFirstNodeTMP=pFirstNode : pLastNodeTMP=pLastNode : pTrackPrevTmp=pTrackTmp->pPrev
        If pFirstNode->Tag0<>LIST_RES Then : bAlrdyTracked=0 : this.TrackCompute
        ElseIf pNode->pNext=pTrackTmp Or pNode=pTrackPrevTmp  Then : bAlrdyTracked=1: End If  'Or pNode->pPrev=pTrackTmp
        this.TrackSecure
        Return 1
    End If : Return 0 ' bAlrdyTracked=0 : this.TrackCompute : bTracking=0 : 
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.TagLenRedim(ub as uByte) as Byte
    If ub=1 Then : uB_RedimTagLen=ub : Return 1 : End If
    # IF TagMode=0 Or  TagMode=1
        uB_RedimTagLen=ub : Return 1
    # ELSE
        Print "Lzle warning : ListTagLenRedim(0) - No Redim - is only valid on # Define TagMode 0 and  # Define TagMode 1" : Return 0
    # ENDIF
End Property

Property List.TagLenDefault(ub as uByte) As Byte
    # IF TagMode=0
        uB_TagC_Len(uTag)=ub : Return 1
    # ELSE
        Print "Lzle warning : TagLenDefault (dynamic) is only valid on # Define TagMode=0" : Return 0
    # ENDIF
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->Tag1=0 : pLocalMove->Tag0=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->Tag0=LIST_DEL : pTemp1->pBranchLastNode=0 : pTemp1->BranchCount=0
        pTemp3=pNode : pNode=pTemp1 : this.Val("") :
        If pTemp1->ListData<>0 Then           
            For i=MIN_COLS To MAX_COLS
                # IF TagMode=0
                    *pTemp1->ListData->str_tag_C(i)=""
                # ELSE
                    pTemp1->ListData->str_tag_C(i)=""
                # ENDIF
            Next i
            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->Tag0=LIST_DEL
    If pTemp1->ListData<>0 Then         
        For i=MIN_COLS to MAX_COLS
            # IF TagMode=0
                *pTemp1->ListData->str_tag_C(i)=""
            # ELSE
                pTemp1->ListData->str_tag_C(i)=""
            # ENDIF
        Next i 
    End If
    pTemp1->pBranchLastNode=0 : pTemp1->BranchCount=0
    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     
    Dim As ListContainer Ptr P_tmp : Dim As uInteger i
    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
            If pFlatRoot->pNext->ListData->str_flat_tag<>0 Then : _Deallocate(pFlatRoot->pNext->ListData->str_flat_tag) : End If
            If pFlatRoot->pNext->ListData->str_item<>0 Then : _Deallocate(pFlatRoot->pNext->ListData->str_item) : End If
            # IF TagMode=0
                For i=MIN_COLS To MAX_COLS :  If pFlatRoot->pNext->ListData->str_tag_C(i)<>0 Then : _Deallocate(pFlatRoot->pNext->ListData->str_tag_C(i)) : End If  : Next i
        '    # ELSE
        '        If pFlatRoot->pNext->ListData->str_tag_C<>0 Then : _Deallocate(pFlatRoot->pNext->ListData->str_tag_C) : End If
            # ENDIF
            _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
        P_tmp=AllowPanCake : If P_tmp->str_flat_tag<>0 Then : _Deallocate(P_tmp->str_flat_tag) : End If : If P_tmp->str_item<>0 Then : _Deallocate(P_tmp->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If P_tmp->str_tag_C(i)<>0 Then : _Deallocate(P_tmp->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate(P_tmp) : pPanTemp=pPanCakeGarbage->pNextContainer
    Wend
    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

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
    Dim As uByte i
    If this.IsDestroyed=1 Then : Return 0 : End If
    this.Root : this.DropAll : IsDestroyed=1
    If pPanCakeGarbage<>0 Then
        If pPanCakeGarbage->str_flat_tag<>0 Then : _Deallocate(pPanCakeGarbage->str_flat_tag) : End If
        If pPanCakeGarbage->str_item<>0 Then : _Deallocate(pPanCakeGarbage->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pPanCakeGarbage->str_tag_C(i)<>0 Then : _Deallocate(pPanCakeGarbage->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _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
        If pEndFlat->ListData->str_flat_tag<>0 Then : _Deallocate(pEndFlat->ListData->str_flat_tag) : End If
        If pEndFlat->ListData->str_item<>0 Then : _Deallocate(pEndFlat->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pEndFlat->ListData->str_tag_C(i)<>0 Then : _Deallocate(pEndFlat->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate this.pEndFlat->ListData : this.pEndFlat->ListData=0     
    End If
    If this.pLastLASTNode->ListData<>0 Then
        If pLastLASTNode->ListData->str_flat_tag<>0 Then : _Deallocate(pLastLASTNode->ListData->str_flat_tag) : End If
        If pLastLASTNode->ListData->str_item<>0 Then : _Deallocate(pLastLASTNode->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pLastLASTNode->ListData->str_tag_C(i)<>0 Then : _Deallocate(pLastLASTNode->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate this.pLastLASTNode->ListData : this.pLastLASTNode->ListData=0
    End If
    If this.pGarbage->ListData<>0 Then
        If pGarbage->ListData->str_flat_tag<>0 Then : _Deallocate(pGarbage->ListData->str_flat_tag) : End If
        If pGarbage->ListData->str_item<>0 Then : _Deallocate(pGarbage->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pGarbage->ListData->str_tag_C(i)<>0 Then : _Deallocate(pGarbage->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate this.pGarbage->ListData : this.pGarbage->ListData=0
    End If
    If this.pWhyteMove->ListData<>0 Then
        If pWhyteMove->ListData->str_flat_tag<>0 Then : _Deallocate(pWhyteMove->ListData->str_flat_tag) : End If
        If pWhyteMove->ListData->str_item<>0 Then : _Deallocate(pWhyteMove->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pWhyteMove->ListData->str_tag_C(i)<>0 Then : _Deallocate(pWhyteMove->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate this.pWhyteMove->ListData : this.pWhyteMove->ListData=0
    End If
    If this.pFirstFIRSTNode->ListData<>0 Then
        If pFirstFIRSTNode->ListData->str_flat_tag<>0 Then : _Deallocate(pFirstFIRSTNode->ListData->str_flat_tag) : End If :
        If pFirstFIRSTNode->ListData->str_item<>0 Then : _Deallocate(pFirstFIRSTNode->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pFirstFIRSTNode->ListData->str_tag_C(i)<>0 Then : _Deallocate(pFirstFIRSTNode->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _Deallocate this.pFirstFIRSTNode->ListData : this.pFirstFIRSTNode->ListData=0
    End If
    If this.pNode->ListData<>0 Then
        If pNode->ListData->str_flat_tag<>0 Then : _Deallocate(pNode->ListData->str_flat_tag) : End If : 
        If pNode->ListData->str_item<>0 Then : _Deallocate(pNode->ListData->str_item) : End If
        # IF TagMode=0
            For i=MIN_COLS To MAX_COLS :  If pNode->ListData->str_tag_C(i)<>0 Then : _Deallocate(pNode->ListData->str_tag_C(i)) : End If  : Next i
        # ENDIF
        _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
    Return 0
End Property

'==========================================================================================DATA EXCHANGE
Property List.SnatchBelow(pList As List) As Byte
  Dim As ListNode Ptr pTemp1, pTemp2
    If pNode->Tag0=LIST_RES Or pNode->Tag0=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->Tag1=0 : pLocalMove->Tag0=LIST_DEL
            If this.Snatch(pList) <> 1 Then : this.NodeRecycle : pLocalMove=pFirstNode : pFirstNode->pBranch->pBranch=0 : pFirstNode->pBranch=0 :  pLocalMove->Tag1=0 : pLocalMove->Tag0=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->Tag1=0 : pLocalMove->Tag0=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->Tag0=LIST_DEL Then : If pFirstNode->pBranch=0 Then : pNode=pGarbage->pNext : Else : Return -1 : End If
    ElseIf pNode->Tag0=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 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) : bTracking=0 : bAlrdyTracked=1
    If this.uTag=0 Then
        If this.bCopyCatMethod=1 Then : While pNode<>pTmp1 and by=1 : pList.HashTag(this.HashTag) : pList.Check(this.Check) :: pList.SetRelation1(this.pNode) : by=this.HashStep : Wend
        Else : pList.BranchCountDown(0) : While pNode<>pTmp1 and by=1 : pList.HashTag(this.HashTag) : pList.Check(this.Check) : : 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 ' ?" #1 " & this.Tag(uTag) : 
        End If
    End If 
    pNode=pTmp2 : pList.HashKeyUnique(1) : Return 1
End Property

Property List.CopyTrack(pList As List) As Byte
    Dim as byte by=1 : Dim As ListNode Ptr pTmp1, pFirstTMP, pLastTMP
    If bTracking=0 Then : ? "LZLE warning : can't CopyTrack Track cession not specified" : Return 0 : End If'  bAlrdyTracked=0 : this.TrackSecure : 
    pFirstTMP=pFirstNode : pLastTMP=pLastNode : 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.Check(this.Check) : pList.SetRelation1(this.pNode) : by=this.TrackStep : Wend
        Else : pList.BranchCountDown(0) : While pNode<>pTmp1 and by=1 : pList.HashTag(this.HashTag) : pList.Check(this.Check)  : pList.SetRelation2(this.pNode) : by=this.TrackStep : 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.TrackStep : Wend
        Else : pList.BranchCountDown(0) : While pNode<>pTmp1 and by=1 : pList.HashTag(this.Tag(uTag)) : pList.SetRelation2(this.pNode) : by=this.TrackStep : Wend
        End If
    End If '  If  pList.Tracks(1).pNode=0 Then : ? "$List2 (1)= 0 " : Else : ? "$List2 (1) <> 0 " : End If
    pFirstNode=pFirstTMP : pLastNode=pLastTMP : this.uCount=pFirstNode->BranchCount : pList.HashKeyUnique(1) : Return 1
End Property

Last edited by Lost Zergling on Jan 04, 2021 13:15, edited 9 times in total.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: LZLE List Engine with user friendly powerfull syntax

Post by sancho3 »

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: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: LZLE List Engine with user friendly powerfull syntax

Post by MrSwiss »

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

Post by sancho3 »

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: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

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.


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


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF

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 **********"

gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
sleep : system
Exemple 2

Code: Select all


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF


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=" & MaListe.Tag(1) & " 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 ': sleep 
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
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
Print "Fin"
sleep
system

Exemple 3

Code: Select all


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF

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
MaListe1.Destroy
Print "-----------------------------------"
MaListe2.Root
While MaListe2.HashStep
    Print MaListe2.HashTag & "  " & MaListe2.Count
Wend
Print MaListe2.DropAll & " / " & MaListe2.NodeCount
MaListe2.Destroy
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
sleep
system

Exemple 4

Code: Select all


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF

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
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
Sleep
system

Exemple 5

Code: Select all


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF

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
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
sleep : System

Exemple 6

Code: Select all


# Define IsTEST 0

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF


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
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
Print "Fin"
sleep
system

Exemple 7

Code: Select all


# Define IsTEST 1

# IF (IsTEST=1) 
    Print "Regular release"
    #Include once "F:\Basic\LZLE_TEST.bi"    
# ELSE
    Print "NEW release"
    #Include once "F:\Basic\LZLE_.bi"
# ENDIF

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 9
    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
gCollector.Destroy
Print "%%AllocateDeallocateCounter =" & AllocateDeallocateCounter
sleep
system

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.
Last edited by Lost Zergling on Apr 20, 2020 21:44, edited 1 time in total.
Lost Zergling
Posts: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

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

Post by sancho3 »

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: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

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: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: LZLE List Engine with user friendly powerfull syntax

Post by MrSwiss »

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: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: LZLE List Engine with user friendly powerfull syntax

Post by Lost Zergling »

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.
Post Reply