Here is
"xList.pb"
Code: Select all
Structure xList
ElementCount.l
*First.xElement
*Last.xElement
DataSize.l
UserData.l
Mutex.l
ConstructorProc.l
DestructorProc.l
AutoSortProc.l
SortReversed.l
ListMemoryIsManual.l
ElementMemoryIsManual.l
EndStructure
Structure xElement
*Parent.xList
*Forward.xElement
*Backward.xElement
EndStructure
Procedure _xNewList(DataSize.l,Buffer.l)
Protected *List.xList
If Buffer
*List=Buffer
*List\ListMemoryIsManual=#True
Else
*List=AllocateMemory(SizeOf(xList))
EndIf
*List\DataSize=DataSize
*List\Mutex=CreateMutex_(#Null,#Null,"")
ProcedureReturn *List
EndProcedure
Procedure xNewList(DataSize.l)
ProcedureReturn _xNewList(DataSize,#Null)
EndProcedure
Procedure xLockList(*List.xList)
WaitForSingleObject_(*List\Mutex,#INFINITE);/
EndProcedure
Procedure xUnlockList(*List.xList)
ReleaseMutex_(*List\Mutex)
EndProcedure
Procedure xEnumElements(*List.xList,CallbackProc.l,Param.l)
Protected *Element.xElement,*NextElement.xElement
*Element=*List\first
While *Element
*NextElement=*Element\Forward
If CallFunctionFast(CallbackProc,*Element+SizeOf(xElement),Param)=#Null
ProcedureReturn #True
EndIf
*Element=*NextElement
Wend
ProcedureReturn #False
EndProcedure
Procedure xEnumElements_Reversed(*List.xList,CallbackProc.l,Param.l)
Protected *Element.xElement
*Element=*List\Last
While *Element
CallFunctionFast(CallbackProc,*Element+SizeOf(xElement),Param)
*Element=*Element\Backward
Wend
EndProcedure
Procedure xQuickSwapElement(*BaseElement.xElement)
Protected *List.xList,*TopElement.xElement
*List=*BaseElement\Parent
*TopElement=*BaseElement\Forward
If *TopElement
If *BaseElement\Backward
*BaseElement\Backward\Forward=*TopElement
EndIf
If *TopElement\Forward
*TopElement\Forward\Backward=*BaseElement
EndIf
*BaseElement\Forward=*TopElement\Forward
*TopElement\Backward=*BaseElement\Backward
*BaseElement\Backward=*TopElement
*TopElement\Forward=*BaseElement
;/List Cleanup:
If *List\first=*BaseElement
*List\first=*TopElement
EndIf
If *List\Last=*TopElement
*List\Last=*BaseElement
EndIf
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure xSortList(*List.xList,SortProc.l)
Protected *Element.xElement
Protected I.l,MaxCount.l,Modified.l
xLockList(*List)
MaxCount=*List\ElementCount-1
For I=1 To MaxCount
Modified=#False
*Element=*List\first
While *Element And *Element\Forward
If CallFunctionFast(SortProc,*Element+SizeOf(xElement),*Element\Forward+SizeOf(xElement))<>*List\SortReversed
xQuickSwapElement(*Element)
Modified=#True
Else
*Element=*Element\Forward
EndIf
Wend
If Modified=#False
Break
EndIf
Next
xUnlockList(*List)
ProcedureReturn #True
EndProcedure
Procedure xSortElement(*Element.xElement,SortProc.l)
Protected *List.xList
*Element-SizeOf(xElement)
*List=*Element\Parent
xLockList(*List)
While *Element And *Element\Forward
If CallFunctionFast(SortProc,*Element+SizeOf(xElement),*Element\Forward+SizeOf(xElement))<>*List\SortReversed
xQuickSwapElement(*Element)
Modified=#True
Else
*Element=*Element\Forward
EndIf
If Modified=#False
Break
EndIf
Wend
While *Element And *Element\Backward
If CallFunctionFast(SortProc,*Element\Backward+SizeOf(xElement),*Element+SizeOf(xElement))<>*List\SortReversed
xQuickSwapElement(*Element\Backward)
Modified=#True
Else
*Element=*Element\Backward
EndIf
If Modified=#False
Break
EndIf
Wend
xUnlockList(*List)
EndProcedure
Procedure xGetList(*Element.xElement)
*Element-SizeOf(xElement)
ProcedureReturn *Element\Parent
EndProcedure
Procedure xFirstElement(*List.xList)
If *List\first
ProcedureReturn *List\first+SizeOf(xElement)
EndIf
ProcedureReturn #Null
EndProcedure
Procedure xLastElement(*List.xList)
If *List\Last
ProcedureReturn *List\Last+SizeOf(xElement)
EndIf
ProcedureReturn #Null
EndProcedure
Procedure xNextElement(*Element.xElement)
*Element-SizeOf(xElement)
If *Element\Forward
ProcedureReturn *Element\Forward+SizeOf(xElement)
EndIf
ProcedureReturn #Null
EndProcedure
Procedure xPreviousElement(*Element.xElement)
*Element-SizeOf(xElement)
If *Element\Backward
ProcedureReturn *Element\Backward+SizeOf(xElement)
EndIf
ProcedureReturn #Null
EndProcedure
Enumeration
#FindByte
#FindWord
#FindLong
#FindString
EndEnumeration
Structure FindElementStruct
TypeOfData.l
StructureOffset.l
FindData.l
*ElementMatch.xElement
EndStructure
Procedure _xFindElement(*Element.xElement,*FindElement.FindElementStruct)
Protected ElementFound.l,FindDataPtr.l
ElementFound=#False
FindDataPtr=*Element+*FindElement\StructureOffset
Select *FindElement\TypeOfData
Case #FindByte
If PeekB(FindDataPtr)=*FindElement\FindData
ElementFound=#True
EndIf
Case #FindWord
If PeekW(FindDataPtr)=*FindElement\FindData
ElementFound=#True
EndIf
Case #FindLong
If PeekL(FindDataPtr)=*FindElement\FindData
ElementFound=#True
EndIf
Case #FindString
If PeekS(FindDataPtr)=PeekS(*FindElement\FindData)
ElementFound=#True
EndIf
EndSelect
If ElementFound
*FindElement\ElementMatch=*Element
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure xFindElement(*List.xList,TypeOfData.l,StructureOffset.l,FindData.l)
Protected FindElement.FindElementStruct
FindElement\TypeOfData=TypeOfData
FindElement\StructureOffset=StructureOffset
FindElement\FindData=FindData
FindElement\ElementMatch=#Null
xEnumElements(*List,@_xFindElement(),@FindElement)
ProcedureReturn FindElement\ElementMatch
EndProcedure
Procedure xCountList(*List.xList)
ProcedureReturn *List\ElementCount
EndProcedure
Procedure xGetListUserData(*List.xList)
ProcedureReturn *List\UserData
EndProcedure
Procedure xSetListUserData(*List.xList,UserData.l)
xLockList(*List)
*List\UserData=UserData
xUnlockList(*List)
EndProcedure
Procedure xSetElementConstructor(*List.xList,ConstructorProc.l)
xLockList(*List)
*List\ConstructorProc=ConstructorProc
xUnlockList(*List)
EndProcedure
Procedure xSetElementDestructor(*List.xList,DestructorProc.l)
xLockList(*List)
*List\DestructorProc=DestructorProc
xUnlockList(*List)
EndProcedure
Procedure xSetElementAutoSortProc(*List.xList,SortProc.l)
xLockList(*List)
*List\AutoSortProc=SortProc
xUnlockList(*List)
EndProcedure
Procedure xSetElementSortReversed(*List.xList,TrueFalse.l)
xLockList(*List)
*List\SortReversed=TrueFalse
xUnlockList(*List)
EndProcedure
Procedure __xAddElement(*List.xList,Param.l,Buffer.l)
Protected *Element.xElement,*NewIndexTable
xLockList(*List)
If Buffer
*List\ElementMemoryIsManual=#True
*Element=Buffer
Else
*Element=AllocateMemory(SizeOf(xElement)+*List\DataSize)
EndIf
*Element\Parent=*List
*Element\Forward=#Null;/Safety First
*Element\Backward=#Null;/Safety First
If *List\ElementCount=#Null;/First Element
*List\first=*Element
*List\Last=*Element
Else
*List\Last\Forward=*Element
*Element\Backward=*List\Last
*List\Last=*Element
EndIf
*List\ElementCount+1
If *List\ConstructorProc
CallFunctionFast(*List\ConstructorProc,*Element+SizeOf(xElement),Param)
EndIf
If *List\AutoSortProc
xSortElement(*Element+SizeOf(xElement),*List\AutoSortProc)
;xSortList(*List,*List\AutoSortProc)
EndIf
xUnlockList(*List)
ProcedureReturn *Element+SizeOf(xElement)
EndProcedure
Procedure _xAddElement(*List.xList,Param.l)
ProcedureReturn __xAddElement(*List,Param,#Null)
EndProcedure
Procedure xAddElement(*List.xList)
ProcedureReturn _xAddElement(*List,#Null)
EndProcedure
Procedure _xDeleteElement(*Element.xElement,QuickDelete.l)
Protected *List.xList
*List=*Element\Parent
xLockList(*List)
If *Element
If QuickDelete=#False
If *Element\Forward
*Element\Forward\Backward=*Element\Backward
Else
*List\Last=*Element\Backward
EndIf
If *Element\Backward
*Element\Backward\Forward=*Element\Forward
Else
*List\first=*Element\Forward
EndIf
EndIf
If *List\DestructorProc
CallFunctionFast(*List\DestructorProc,*Element+SizeOf(xElement))
EndIf
If *List\ElementMemoryIsManual=#False
FreeMemory(*Element)
EndIf
*List\ElementCount-1
EndIf
xUnlockList(*List)
EndProcedure
Procedure xDeleteElement(*Element.xElement)
If *Element
*Element-SizeOf(xElement)
_xDeleteElement(*Element,#False)
EndIf
EndProcedure
Procedure _xDeleteList_Enum(*Element.xElement,Param.l)
*Element-SizeOf(xElement)
_xDeleteElement(*Element,#True)
ProcedureReturn #True
EndProcedure
Procedure xDeleteList(*List.xList)
xEnumElements(*List,@_xDeleteList_Enum(),0)
*List\ElementCount=#Null
*List\first=#Null
*List\Last=#Null
If *List\ListMemoryIsManual=#False
xUnlockList(*List)
CloseHandle_(*List\Mutex)
FreeMemory(*List)
EndIf
EndProcedure
###########################################################
You'll need the updated
"xHash.pb"
Code: Select all
XIncludeFile "xList.pb"
#MaxHashStringLength=255;/The longest a Hash String can be...
Structure xConversion
left.l
right.l
EndStructure
Procedure xNewConverter()
Protected Converter.l
Converter=xNewList(SizeOf(xConversion))
ProcedureReturn Converter
EndProcedure
Procedure xFindConversionFromLeft(Converter.l,left.l)
ProcedureReturn xFindElement(Converter,#FindLong,OffsetOf(xConversion\left),left)
EndProcedure
Procedure xFindConversionFromRight(Converter.l,right.l)
ProcedureReturn xFindElement(Converter,#FindLong,OffsetOf(xConversion\right),right)
EndProcedure
Procedure xAddConversion(Converter.l,left.l,right.l)
Protected *Conversion.xConversion
*Conversion=xFindConversionFromLeft(Converter,left);/Keeps All Left Values Unique
If *Conversion=#Null
;*Conversion=xFindConversionFromRight(Converter,right);/Keeps All Right Values Unique
;If *Conversion=#Null
*Conversion=xAddElement(Converter)
;EndIf
EndIf
If *Conversion
xLockList(Converter)
*Conversion\left=left
*Conversion\right=right
xUnlockList(Converter)
EndIf
EndProcedure
Procedure xDelConversionFromLeft(Converter.l,left.l)
Protected *Conversion.xConversion
*Conversion=xFindConversionFromLeft(Converter,left)
If *Conversion
xDeleteElement(*Conversion)
EndIf
EndProcedure
Procedure xDelConversionFromRight(Converter.l,right.l)
Protected *Conversion.xConversion
*Conversion=xFindConversionFromRight(Converter,right)
If *Conversion
xDeleteElement(*Conversion)
EndIf
EndProcedure
Procedure xDelConverter(Converter.l)
xDeleteList(Converter)
EndProcedure
Procedure _xCopyConverter(*Conversion.xConversion,NewConverter.l)
xAddConversion(NewConverter,*Conversion\left,*Conversion\right)
ProcedureReturn #True
EndProcedure
Procedure xCopyConverter(Converter.l)
Protected NewConverter.l
NewConverter=xNewList(SizeOf(xConversion))
xEnumElements(Converter,@_xCopyConverter(),NewConverter)
ProcedureReturn NewConverter
EndProcedure
Procedure xConvertFromLeft(Converter.l,left.l)
Protected *Conversion.xConversion
*Conversion=xFindConversionFromLeft(Converter,left)
If *Conversion
ProcedureReturn *Conversion\right
EndIf
ProcedureReturn #Null
EndProcedure
Procedure xConvertFromRight(Converter.l,right.l)
Protected *Conversion.xConversion
*Conversion=xFindConversionFromRight(Converter,right)
If *Conversion
ProcedureReturn *Conversion\left
EndIf
ProcedureReturn #Null
EndProcedure
;-------
Structure xHashConversion
left.b[#MaxHashStringLength]
right.b[#MaxHashStringLength]
EndStructure
Procedure xNewHashConverter()
Protected HashConverter.l
HashConverter=xNewList(SizeOf(xHashConversion))
ProcedureReturn HashConverter
EndProcedure
Procedure xFindHashConversionFromLeft(HashConverter.l,left$)
ProcedureReturn xFindElement(HashConverter,#FindString,OffsetOf(xHashConversion\left),@left$)
EndProcedure
Procedure xFindHashConversionFromRight(HashConverter.l,right$)
ProcedureReturn xFindElement(HashConverter,#FindString,OffsetOf(xHashConversion\right),@right$)
EndProcedure
Procedure xAddHashConversion(HashConverter.l,left$,right$)
Protected *HashConversion.xHashConversion
*HashConversion=xFindHashConversionFromLeft(HashConverter,left$);/Keeps All Left Values Unique
If *HashConversion=#Null
;*HashConversion=xFindHashConversionFromRight(HashConverter,right$);/Keeps All Right Values Unique
;If *HashConversion=#Null
*HashConversion=xAddElement(HashConverter)
;EndIf
EndIf
If *HashConversion
xLockList(HashConverter)
PokeS(@*HashConversion\left,Left(left$,#MaxHashStringLength))
PokeS(@*HashConversion\right,Left(right$,#MaxHashStringLength))
xUnlockList(HashConverter)
EndIf
EndProcedure
Procedure xDelHashConversionFromLeft(HashConverter.l,left$)
Protected *HashConversion.xHashConversion
*HashConversion=xFindHashConversionFromLeft(HashConverter,left$)
If *HashConversion
xDeleteElement(*HashConversion)
EndIf
EndProcedure
Procedure xDelHashConversionFromRight(HashConverter.l,right$)
Protected *HashConversion.xHashConversion
*HashConversion=xFindHashConversionFromRight(HashConverter,right$)
If *HashConversion
xDeleteElement(*HashConversion)
EndIf
EndProcedure
Procedure xDelHashConverter(HashConverter.l)
xDelConverter(HashConverter)
EndProcedure
Procedure _xCopyHashConverter(*HashConversion.xHashConversion,NewHashConverter.l)
xAddHashConversion(NewHashConverter,PeekS(@*HashConversion\left),PeekS(@*HashConversion\right))
ProcedureReturn #True
EndProcedure
Procedure xCopyHashConverter(HashConverter.l)
Protected NewHashConverter.l
NewHashConverter=xNewList(SizeOf(xHashConversion))
xEnumElements(HashConverter,@_xCopyHashConverter(),NewHashConverter)
ProcedureReturn NewHashConverter
EndProcedure
Procedure.s xHashConvertFromLeft(HashConverter.l,left$)
Protected *HashConversion.xHashConversion
*HashConversion=xFindHashConversionFromLeft(HashConverter,left$)
If *HashConversion
ProcedureReturn PeekS(@*HashConversion\right)
EndIf
ProcedureReturn ""
EndProcedure
Procedure.s xHashConvertFromRight(HashConverter.l,right$)
Protected *HashConversion.xHashConversion
*HashConversion=xFindHashConversionFromRight(HashConverter,right$)
If *HashConversion
ProcedureReturn PeekS(@*HashConversion\left)
EndIf
ProcedureReturn ""
EndProcedure
;-main--------------------
; XIncludeFile "xHash.pb"
Debug "********* NUMERIC *********"
Converter=xNewConverter()
xAddConversion(Converter,1,123)
xAddConversion(Converter,2,246)
xAddConversion(Converter,3,369)
Debug xConvertFromLeft(Converter,1);/Output: 123
Debug xConvertFromLeft(Converter,2);/Output: 246
Debug xConvertFromLeft(Converter,3);/Output: 369
Debug xConvertFromRight(Converter,123);/Output: 1
Debug xConvertFromRight(Converter,246);/Output: 2
Debug xConvertFromRight(Converter,369);/Output: 3
xDelConverter(Converter)
Debug "********* STRINGS *********"
HashConverter=xNewHashConverter()
xAddHashConversion(HashConverter,"a","apple")
xAddHashConversion(HashConverter,"b","bananna")
xAddHashConversion(HashConverter,"c","carrot")
Debug xHashConvertFromLeft(HashConverter,"a");/Output: "apple"
Debug xHashConvertFromLeft(HashConverter,"b");/Output: "bananna"
Debug xHashConvertFromLeft(HashConverter,"c");/Output: "carrot"
Debug xHashConvertFromRight(HashConverter,"apple");/Output: "a"
Debug xHashConvertFromRight(HashConverter,"bananna");/Output: "b"
Debug xHashConvertFromRight(HashConverter,"carrot");/Output: "c"
xDelHashConverter(HashConverter)