Code archives/Miscellaneous/listClass
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This is a group of list management functions for managing dynamic amounts of data. Each list item can consist of a Key value and a handle to a data object for additional information. Very flexible and allows you to add, delete, move, search, and sort items in lists. P.S. Look in general forum for code example using listClass. | |||||
; listClass.BB ; ; Makakoman - 11/22/2002 ; ; ; Thanks to skn3[ac] for the gettok$ function! ; listClass.BB - A set of list management functions. You can use freely ; in any programs you wish, but do not sell, redistribute, package with ; another product, etc, etc, without the authors expressed written permission. ; ; BLAH, BLAH, BLAH... ; ; Key Type constants - what kind of value stored in key Const KEYTYPE_INTEGER = 1 Const KEYTYPE_FLOAT = 2 Const KEYTYPE_STRING = 3 Const KEYTYPE_DATE = 4 Const KEYTYPE_TIME = 5 Const KEYTYPE_SPEED = 6; NOTE: KEYTYPE_SPEED bypasses the call to listCompare() ; and does a straight string compare a$=b$. Therefore, ; all SORTS, SEARCHES, and ADD/INSERTS will be affected. ; "Hello" and "hello" are not the same and can appear ; far from each other in sort order. Don't get confused. ; Allowdups set to FALSE will still allow these two keys. ; KEYTYPE_SPEED is ALWAYS CASE SENSITIVE! ; Compare Type Constants Const COMPARE_GT = 1 Const COMPARE_LT = -1 Const COMPARE_EQ = 0 ; Compare Type Constants Const LIST_CASESENSITIVE = True Const LIST_ALLOWDUPS = True ; List Errors Const LISTERR_NONE = 0 Const LISTERR_NOTFOUND = -1 Const LISTERR_DUPLICATE = -2 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;TYPE ITEMTYPE - used to store list item information ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type itemType ;``````````````````````````````````````````````````` Field key$ ; lookup/search key - can be string,integer,float(date,time, wildcard coming soon!) Field objecthandle ; generic data pointer End Type ; itemType ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;TYPE LISTTYPE - The list object contains any number ; of ITEMTYPE objects and supports adding, ; deleting, moving, sorting, searching, ; in many combinations. ; NOTE: Lists are 0 based (index starts at 0) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type listType ;``````````````````````````````````````````````````` Field indexes ; bank containing all list item handles in sequential(index) order. Field count% ; current number of items in list. (indexes -> 0 .. count-1) Field sizeincrement% ; how many 4 byte chunks to allocate when the list needs to grow. Field keytype ; how to cast the data in the key$ of each item Field index% ; index of most recently found or added item. Field sort ; Should the list be kept sorted? True/False Field error% ; most recent error raised while executing list function Field case_sensitive ; Should keys use case sensitivity? True/False (only works on KEYTYPE_STRING) Field allowdups ; Are duplicate keys allowed? True/False (only works on sorted list) End Type ; listType ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Create a new list ; ; size: Initial size of list ; sizeincrement : how many items to increase list to when allocating more space ; keytype : what kind of data is stored in key field ; sort : True to sort the list ; case_sensitive : True to enforce case sensativity in comparisons ; allowdups : True allows duplicate keys, False fails on insert. ;................................................................................ Function listNew.listType(size, sizeincrement = 5, keytype = KEYTYPE_SPEED, sort=True, case_sensitive=True, allowdups=True) ;``````````````````````````````````````````````````````````````````````````````` l.listType = New listType l\indexes = CreateBank(size * 4) ; create storage area for handles to list items. l\keytype = keytype l\count% = 0 l\sizeincrement = sizeincrement l\sort = sort l\allowdups = allowdups l\case_sensitive = case_sensitive l\error% = LISTERR_NONE l\index% = LISTERR_NOTFOUND ; no current list item Return(l) End Function ; listNew ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Return number of items in list ;............................................................................... Function listCount%(l.listType) ;``````````````````````````````````````````````````````````````````````````````` Return(l\count%) End Function ; listCount() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Deletes all of the items from the list and resizes index bank ; NOTE: This will not FREE any objects you have attached to a list item. Use ; listitemDelete() to delete listitem and return object handle to user. ;............................................................................... Function listDeleteAll(l.listType) ;``````````````````````````````````````````````````````````````````````````````` Local item.itemType ; delete all data objects For i = 0 To l\count-1 item = Object.itemType(PeekInt(l\indexes, offset)) Delete item Next ; resize bank to initial size ResizeBank(l\indexes, l\sizeincrement * 4) ; destroy data pointers l\count = 0 ; list is empty l\index% = LISTERR_NOTFOUND ; no current list item End Function ; listDeleteAll() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Deletes all of the items from the list and then destroys list ; NOTE: This will not FREE any objects you have attached to a list item. Use ; listitemDelete() to delete listitem and return object handle to user. ;............................................................................... Function listDelete(l.listType) ;``````````````````````````````````````````````````````````````````````````````` listDeleteAll(l) ; call delete all nodes. FreeBank(l\indexes) ; free the memory for indexes Delete l ; destroy list object End Function ; listDelete() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Sequential Search for a listitem in an UNSORTED list with the specified key value. ; Returns the index of the list item if found. ;............................................................................... Function listFind.itemType(l.listType, key$) ;``````````````````````````````````````````````````````````````````````````````` listRaiseError(l, LISTERR_NONE) ; search list sequentially for specified item. For i = 0 To listCount(l) - 1 item.itemType = listItem(l, i) ; if keys are equal, return list index If l\keytype = KEYTYPE_SPEED Then ; don't call compare function, sloooow... If key$ = item\key$ = COMPARE_EQ Then l\index% = i ; save current item index Return(item) End If Else If listCompare(key$, item\key$, l\keytype, l\case_sensitive) = COMPARE_EQ Then l\index% = i ; save current item index Return(item) End If End If Next listRaiseError(l, LISTERR_NOTFOUND) Return Null ; not found End Function ; listFind() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Returns the index of the most recently found list item. ;............................................................................... Function listIndex%(l.listType) ;``````````````````````````````````````````````````````````````````````````````` Return(l\index%) End Function ; listIndex() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Sort a list using key$. Algorythm uses Selection Sort. ;............................................................................... Function listSort(l.listType) ;``````````````````````````````````````````````````````````````````````````````` Local item.itemType ; This function implements a SELECTION SORT count = listCount(l)-1 If count < 2 Then Return ; no need to sort 1 item list ; sort list shortening it by 1 each loop iteration For effectiveSize = count To 1 Step -1 ; initialize max base comparison values to first item item = listItem(l, 0) maxkey$ = item\key$ maxpos% = 0 ; check each item in remaining list to find highest value (maxkey$) For i = 0 To effectiveSize ; find maximum value in list item = listItem(l, i) ; get current item ; check if this item is a higher value than current maxkey$ If l\keytype = KEYTYPE_SPEED Then ; don't call compare function, sloooow... newmaxkey% = item\key$ > maxkey$ Else newmaxkey% = listCompare(item\key$, maxkey$, l\keytype, l\case_sensitive) = COMPARE_GT End If ; if current key$ > max key$ then we have a new max key$ If newmaxkey% Then maxpos% = i maxkey$ = item\key$ End If Next ; i ; swap the max value with the highest unsorted value listItemSwap(l, maxpos%, effectiveSize) Next ; j End Function ; listSort() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Set list sort flag. It true, then listSort() is called. ;............................................................................... Function listSetSort(l.listType, sort) ;``````````````````````````````````````````````````````````````````````````````` ; don't want to sort again if it is already sorted If l\sort Then If sort Then Return ; if list is not sorted and sort is set to TRUE, then sort list. If Not l\sort Then If sort Then listSort(l) l\sort = sort ; assign value End Function ; listSetSort() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Set Allow Duplicates flag to True or False. ; This will affect listItemAdd() for a SORTED list. ; allowdups has NO EFFECT on an unsorted list! ;............................................................................... Function listSetAllowDups(l.listType, allowdups%) ;``````````````````````````````````````````````````````````````````````````````` l\allowdups = allowdups% ; assign value End Function ; listSetAllowDups() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Set Case Sensitive flag to True or False. ; This will affect listItemAdd(), listFind(), listSearch() and listSort() ; This flag will affect the way the item is sorted an searches. Also, ; allowdups will act differently depending on case_sensitive ;............................................................................... Function listSetCaseSensitive(l.listType, case_sensitive%) ;``````````````````````````````````````````````````````````````````````````````` l\case_sensitive = case_sensitive% ; assign value End Function ; listSetCaseSensitive() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Set KEYTYPE for list. This tells the Comparison function how to treat your ; key$ data. Strings of number sort different than actual numeric values, so ; It is important to choose the right keytype. ; NOTE: KEYTYPE_SPEED does not use the compare function. It just does a standard ; string compare (a$=b$), so it IS ALWAYS CASE SENSITIVE. ; NOTE: KEYTYPE can be changed anytime, but you should probably call ; listSort() after changing it, if you are working with sorted list. ;............................................................................... Function listItemSetKey(l.listType, index%, key$) ;``````````````````````````````````````````````````````````````````````````````` item.itemType = listItem(l, index%) If item = Null Then RuntimeError("listItemSetKey : Index out of bounds - "+index%) item\key$ = key$ End Function ; listItemSetKey() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Set KEYTYPE for list. This tells the Comparison function how to treat your ; key$ data. Strings of number sort different than actual numeric values, so ; It is important to choose the right keytype. ; NOTE: KEYTYPE_SPEED does not use the compare function. It just does a standard ; string compare (a$=b$), so it IS ALWAYS CASE SENSITIVE. ; NOTE: KEYTYPE can be changed anytime, but you should probably call ; listSort() after changing it, if you are working with sorted list. ;............................................................................... Function listSetKeyType(l.listType, keytype%) ;``````````````````````````````````````````````````````````````````````````````` l\keytype = keytype ; assign value End Function ; listSetKeyType() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Use a Binary Search to find a key in a SORTED list. Do not use on UNSORTED list! ; Returns the item if it is found, else NULL if not found. ;............................................................................... Function listSearch.itemType(l.listType, value$) ;``````````````````````````````````````````````````````````````````````````````` listRaiseError(l, LISTERR_NONE) ; Perform Binary Search on entire list index% = listBinarySearch(l, 0, listCount(l)-1, value$) If index% = LISTERR_NOTFOUND Then listRaiseError(l, LISTERR_NOTFOUND) Return Null ; return NULL if not found... End If ; Get item from list and return handle item.itemType = listItem(l, index%) ; get list item l\index% = index% ; save current item index Return item End Function ; listSearch() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; This is a PRIVATE recursive function that should not be called directly. ;............................................................................... Function listBinarySearch%(l.listType, low%, high%, value$) ;``````````````````````````````````````````````````````````````````````````````` Local middle%; ; Termination check if (low% > high%) Return LISTERR_NOTFOUND; ; calculate the middle point between low% and high% middle% = (high%+low%)/2; item.itemType = listItem(l, middle%) ; get list item ; compare to key we are searching for in list If l\keytype = KEYTYPE_SPEED Then ; If item\key$ = value$ Then Return middle% If item\key$ > value$ Then Return listBinarySearch(l, low%, middle%-1, value$) If item\key$ < value$ Then Return listBinarySearch(l, middle%+1, high%, value$) Else ; use listCompare function, a little slow... If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_EQ Then Return middle% If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_GT Then Return listBinarySearch(l, low%, middle%-1, value$) If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_LT Then Return listBinarySearch(l, middle%+1, high%, value$) End If Return LISTERR_NOTFOUND ; returns error if value not found. End Function ; listBinarySearch() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; This is a PRIVATE recursive function used by listItemAdd(). Should not be ; called directly. ;............................................................................... Function listInsertionSearch%(l.listType, low%, high%, value$) ;``````````````````````````````````````````````````````````````````````````````` Local middle%; ; Termination check If listCount(l) < 1 Then Return 0 ; list is empty, append item! ; This is where item shold be inserted... If (low% >= high%) ; check if it goes before or after current node item.itemType = listItem(l, low%) ; get list item If l\keytype = KEYTYPE_SPEED Then ; If item\key$ < value$ Then low% = low%+1 If (item\key$ = value$) And (Not l\allowdups) Then listRaiseError(l, LISTERR_DUPLICATE) Else If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_LT Then low% = low%+1 If (listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_EQ) And (Not l\allowdups) Then listRaiseError(l, LISTERR_DUPLICATE) End If Return low% ; insertion position End If ; calculate the middle point between low% and high% middle% = (high%+low%)/2; item.itemType = listItem(l, middle%) ; get list item ; DebugLog "low="+low%+" high="+high%+" middle="+middle%+" id$="+item\id$+" value$="+value$ ; compare to key we are searching for in list If l\keytype = KEYTYPE_SPEED Then ; If item\key$ = value$ Then If Not l\allowdups Then listRaiseError(l, LISTERR_DUPLICATE) Return middle% End If If item\key$ > value$ Then Return listInsertionSearch(l, low%, middle%-1, value$) If item\key$ < value$ Then Return listInsertionSearch(l, middle%+1, high%, value$) Else ; use listCompare function, a little slow... If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_EQ Then If Not l\allowdups Then listRaiseError(l, LISTERR_DUPLICATE) Return middle% End If If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_GT Then Return listInsertionSearch(l, low%, middle%-1, value$) If listCompare(item\key$, value$, l\keytype, l\case_sensitive) = COMPARE_LT Then Return listInsertionSearch(l, middle%+1, high%, value$) End If End Function ; listInsertionSearch() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Creates a new list item. ; Returns handle to listItem. ;............................................................................... Function itemNew.itemType(key$, objecthandle=0) ;`````````````````````````````````````````````````````````````` ````````````````` ; Create & initialize new itemType object item.itemType = New itemType item\key$ = key$ item\objecthandle = objecthandle Return(item) ; return pointer to item just added End Function ; itemNew() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Creates a new list item and inserts it in the list. If list is sorted, it ; inserts it at the correct location, else it appends it to the list. ; ; Returns handle to listItem just added to list. ;............................................................................... Function listItemAdd.itemType(l.listType, key$, objecthandle=0) ;`````````````````````````````````````````````````````````````` ````````````````` ; if list is to be sorted, use insertion for order If l\sort Then ;...................................................... ; List is Sorted ;...................................................... ; find index to insert listRaiseError(l, LISTERR_NONE) ; reset error flags index% = listInsertionSearch(l, 0, listCount(l)-1, key$) ; Insert item into list If listError(l) = LISTERR_NONE Then item.itemType = listItemInsert(l, index%, key$, objecthandle) Return(item) ; return handle of list item. Else listRaiseError(l, LISTERR_DUPLICATE) ; reset error flags Return(Null) End If End If ;...................................................... ; List is NOT sorted ;...................................................... ; Create & initialize new itemType object item.itemType = itemNew(key$, objecthandle) ; Calculate position of handle in bank offset = l\count * 4 If offset >= BankSize(l\indexes) Then ResizeBank(l\indexes, offset+l\sizeincrement * 4) ; store handle in bank PokeInt(l\indexes, offset, Handle(item)) l\index% = l\count% ; set current item point l\count = l\count + 1 ; increment list count Return(item) ; return pointer to item just added End Function ; listItemAdd() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Return handle of list item at specific index ;............................................................................... Function listItem.itemType(l.listType, index) ;``````````````````````````````````````````````````````````````````````````````` If index >= l\count Or index < 0 Then RuntimeError("listItem: Item out of bounds: "+index) ; calculate index position offset = index * 4 item.itemType = Object.itemType(PeekInt(l\indexes, offset)) Return(item) End Function ; listItem() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Return object handle for a list item at a specific index ;............................................................................... Function listItemObject(l.listType, index) ;``````````````````````````````````````````````````````````````````````````````` If index >= l\count Then RuntimeError("listItemObject: Item out of bounds: "+index) ; calculate index position offset = index * 4 item.itemType = Object.itemType(PeekInt(l\indexes, offset)) Return(item\objecthandle) End Function ; listItemObject() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Return Key value for list item at specific index ;............................................................................... Function listItemKey$(l.listType, index) ;``````````````````````````````````````````````````````````````````````````````` If index >= l\count Then RuntimeError("listItemkey$: Item out of bounds: "+index) offset = index * 4 item.itemType = Object.itemType(PeekInt(l\indexes, offset)) Return(item\key$) End Function ; listItemkey$ ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Deletes list item at specific index and returns handle to object data ; so user can dispose of apprpriatly. ;............................................................................... Function listItemDelete%(l.listType, index) ;``````````````````````````````````````````````````````````````````````````````` If index >= l\count Then RuntimeError("listItemDelete: Item out of bounds: "+index) ; Delete item for itemlist offset = index * 4 item.itemType = Object.itemType(PeekInt(l\indexes, offset)) objecthandle = item\objecthandle ; save handle to data object. Delete item ; update bank of pointers l\count = l\count - 1 ; reduce counter ; copybank(src, src offset, dest, dest offset, count bytes) CopyBank(l\indexes, offset+4, l\indexes, offset, (l\count - index) * 4) Return(objecthandle) ; return object handle so user can call destructor. End Function ; listItemDelete() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Moves a list item from one position to another. ; NOTE: This function should not be used on a SORTED list, unless you call ; listSort() afterwards. ;............................................................................... Function listItemMove(l.listType, srcidx, destidx) ;``````````````````````````````````````````````````````````````````````````````` ; adjust bounds to make sure src and dest are within list size. If srcidx > l\count-1 Then srcidx = l\count-1 If srcidx < 0 Then srcidx = 0 If destidx > l\count-1 Then destidx = l\count-1 If destidx < 0 Then destidx = 0 If srcidx = destidx Then Return ; no need to move to same spot. ; calculate offset in bank from item indexes. soffset = srcidx * 4 doffset = destidx * 4 ; save item handle so we can move it to new position. itemHandle% = PeekInt(l\indexes, soffset) ; if src is before dest, shift list down. If soffset < doffset Then ; copybank(src, src offset, dest, dest offset, count bytes) CopyBank(l\indexes, soffset+4, l\indexes, soffset, doffset - soffset) PokeInt(l\indexes, doffset, itemHandle%) Else ; else src is after dest, shift list up. ; copybank(src, src offset, dest, dest offset, count bytes) CopyBank(l\indexes, doffset, l\indexes, doffset+4, soffset - doffset) PokeInt(l\indexes, doffset, itemHandle%) End If End Function ; listItemMove() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Creates and inserts a new list item before specified index. ; ; NOTE: This function should not be used on a SORTED list, unless you call ; listSort() afterwards. ;............................................................................... Function listItemInsert.itemType(l.listType, index, key$, objecthandle=0) ;``````````````````````````````````````````````````````````````````````````````` ; make room if list is too small If (l\count * 4) >= BankSize(l\indexes) Then ResizeBank(l\indexes, (l\count+l\sizeincrement) * 4) ; if index > list count, then add to end of list. If index > l\count Then Return(listItemAdd(l, key$, objecthandle)) End If ; Create New item instance item.itemType = itemNew(key$, objecthandle) offset = index * 4 ; calculate place to insert ; shift all of the indexes to make room for item to insert ; copybank(src, src offset, dest, dest offset, count bytes) CopyBank(l\indexes, offset, l\indexes, offset+4, (l\count - index) * 4) ; insert item in list PokeInt(l\indexes, offset, Handle(item)) l\index% = l\count ; set current index to item l\count = l\count + 1 ; increment size of list Return(item) End Function ; listItemInsert() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Swaps the index position of two list items. ; NOTE: This function should not be used on a SORTED list, unless you call ; listSort() afterwards. ;............................................................................... Function listItemSwap(l.listType, srcidx, destidx) ;``````````````````````````````````````````````````````````````````````````````` If srcidx > l\count-1 Or srcidx < 0 Then Return ; if src index is out of bounds If destidx > l\count-1 Or destidx < 0 Then Return ; if dest index is out of bounds If srcidx = destidx Then Return ; if src and dest are same item ; calculate offset of index soffset = srcidx * 4 doffset = destidx * 4 ; get handles of each item from bank. srctemp% = PeekInt(l\indexes, soffset) desttemp% = PeekInt(l\indexes, doffset) ; swap handles back into bank PokeInt(l\indexes, soffset, desttemp%) PokeInt(l\indexes, doffset, srctemp%) End Function ; listItemSwaps() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Populates a list from a string with items delimited by sep$. This function ; adds items in string to existing items in list. ;............................................................................... Function listFromString(l.listType, src$, sep$="|") ;``````````````````````````````````````````````````````````````````````````````` idx = 1 tok$ = gettok$(src$, idx, sep$) While tok$ <> "" listItemAdd(l, tok$, 0) idx = idx+1 tok$ = gettok$(src$, idx, sep$) Wend End Function ; listFromString() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Function listFromDir(l.listType, folder$) ;``````````````````````````````````````````````````````````````````````````````` count = 0 dir = ReadDir(folder$) Repeat file$ = NextFile$(dir) If file$ = "" Then Exit ; Use FileType to determine if it is a folder (value 2) or a file If FileType(folder$+"\"+file$) = 2 Then ; this is a folder file$ = "<"+file$+">" End If listItemAdd(l, file$, 0) count = count + 1 ; keep count of dir entries Forever CloseDir(dir) Return count End Function ; listFromDir() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Function listFromFile(l.listType, file$) ;``````````````````````````````````````````````````````````````````````````````` fh = ReadFile(file$) If fh = 0 Then Return False count = 0 While Not Eof(fh) listItemAdd(l, ReadLine$(fh)) count = count + 1 Wend CloseFile(fh) Return count End Function ; listFromFile() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Function listCompare%(key1$,key2$, keytype, case_sensitive) ;`````````````````````````````````````````````````````````````````````` Select keytype Case KEYTYPE_INTEGER If Int(key1$) > Int(key2$) Then Return COMPARE_GT If Int(key1$) < Int(key2$) Then Return COMPARE_LT If Int(key1$) = Int(key2$) Then Return COMPARE_EQ Case KEYTYPE_FLOAT If Float(key1$) > Float(key2$) Then Return COMPARE_GT If Float(key1$) < Float(key2$) Then Return COMPARE_LT If Float(key1$) = Float(key2$) Then Return COMPARE_EQ Case KEYTYPE_STRING If Not case_sensitive Then key1$ = Upper(key1$) key2$ = Upper(key2$) DebugLog key1$+" "+key2$+" "+Str(key1$ = key2$) If key1$ > key2$ Then Return COMPARE_GT If key1$ < key2$ Then Return COMPARE_LT If key1$ = key2$ Then Return COMPARE_EQ Case KEYTYPE_DATE Case KEYTYPE_TIME Default RuntimeError "listCompare: Unknown Keytype "+keytype End Select End Function ; listCompare() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Function listRaiseError(l.listType, errnum) ;`````````````````````````````````````````````````````````````````````` l\error = errnum Select errnum Case LISTERR_NOTFOUND ; reset current if search fails l\index% = errnum End Select End Function ; listRaiseError() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Function listError%(l.listType) ;`````````````````````````````````````````````````````````````````````` error% = l\error ; save current error l\error = LISTERR_NONE ; reset error flag Return(error%) End Function ; listError() ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ; Thanks to skn3[ac] for this function. ;...................................................................... Function gettok$(from$,which,space$=" ") ;`````````````````````````````````````````````````````````````````````` Local foundword=False Local mode=False Local current=0 Local maketok$="" Local getchar$="" For i=1 To Len(from$) getchar$=Mid$(from$,i,1) If foundword=False Then If mode=False Then If getchar$<>space$ Then mode=True current=current+1 End If If current=which Then foundword=True maketok$=maketok$+getchar$ End If Else If getchar$=space$ Then mode=False End If End If Else If getchar$=space$ Then Exit Else maketok$=maketok$+getchar$ End If End If Next Return maketok$ End Function ; gettok$ |
Comments
None.
Code Archives Forum