Using adresses as a key for AddMapElements ???
Using adresses as a key for AddMapElements ???
Hi,
Is there a save and fast way to use adresses as a key for maps like this :
AddMapElement(map(), Str(adres))
Chr(47710280) is faster as Str(47710280) but does only two bytes.
And ... how to convert back ?
Val(MapKey(map())) ;<= Converts a string into a quad numeric value.
Thanks.
Is there a save and fast way to use adresses as a key for maps like this :
AddMapElement(map(), Str(adres))
Chr(47710280) is faster as Str(47710280) but does only two bytes.
And ... how to convert back ?
Val(MapKey(map())) ;<= Converts a string into a quad numeric value.
Thanks.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Re: Using adresses as a key for AddMapElements ???
The only fast and safe way is to use a custom hastable library that accepts numbers as key.
But it depends how fast you need to go, Pb map are pretty good even if str(adress) is somehow slow.
Remark, your adress evolves probably 4 by 4 so you can reduce its key by right shifting it by 2.
But it depends how fast you need to go, Pb map are pretty good even if str(adress) is somehow slow.
Remark, your adress evolves probably 4 by 4 so you can reduce its key by right shifting it by 2.
There are 2 methods to program bugless.
But only the third works fine.
Win10, Pb x64 5.71 LTS
But only the third works fine.
Win10, Pb x64 5.71 LTS
Re: Using adresses as a key for AddMapElements ???
the pb map header suggests there is a numeric map key, this works on linux x64
LINUX x64
LINUX x64
Code: Select all
ImportC ""
PB_AddNumericMapElement(*Map,key.i);
PB_FindNumericMapElement(*Map,Key.i);
EndImport
Global NewMap dummy.i()
Macro _NewMap(var,size=512) ;linux x64
EnableASM
mov rdi,size
!MOV r8,rdi
lea rcx, var ;pointer
!XOr rdx,rdx
!MOV rsi,21
!MOV rdi,8
!SUB rsp,32
!CALL PB_NewMap
!ADD rsp,32
DisableASM
EndMacro
Global *mp
_NewMap(*mp,1024)
Global *el.Integer
;
*el = PB_AddNumericMapElement(*mp,123)
*el\i = 123
;
*el = PB_AddNumericMapElement(*mp,345)
*el\i = 345
;
*el = PB_FindNumericMapElement(*mp,123)
Debug *el\i
*el = PB_FindNumericMapElement(*mp,345)
Debug *el\i
Windows 11, Manjaro, Raspberry Pi OS
Re: Using adresses as a key for AddMapElements ???
What do you mean with this ? I see only strings as map key in the PB-helpfiles.idle wrote:the pb map header suggests there is a numeric map key...
Your code doesn't works on windows, so ... no can do.
Thanks.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Re: Using adresses as a key for AddMapElements ???
The c headers for maps say it allJoris wrote:What do you mean with this ? I see only strings as map key in the PB-helpfiles.idle wrote:the pb map header suggests there is a numeric map key...
Your code doesn't works on windows, so ... no can do.
Thanks.
PB_NewMap(integer ElementSize, int ElementType, integer *StructureMap, PB_Map **Address, int HashSize);
PB_NewNumericMap(integer ElementSize, integer *StructureMap, PB_Map **Address, int HashSize);
I don't know how long it's been like that but it is clearly an option which just isn't exposed.
Hey, I did clearly say it only worked on Linux x64, I ran out of time to look at it, however Wilbert has taken a look and I expect he will post a solution soon!
Windows 11, Manjaro, Raspberry Pi OS
Re: Using adresses as a key for AddMapElements ???
Idle means the procedures are there but they aren't exposed so you won't find them in the help file.Joris wrote:Your code doesn't works on windows, so ... no can do.
Here's an example ...
Code: Select all
;->> Map extension module <<
DeclareModule MapEx
Prototype GetMapPointerI (Map IntegerMap.i())
Prototype GetMapPointerL (Map LongMap.l())
Prototype GetMapPointerQ (Map QuadMap.q())
Prototype GetMapPointerS (Map StringMap.s())
Prototype NumericMapKeyI (Map IntegerMap.i())
Prototype NumericMapKeyL (Map LongMap.l())
Prototype NumericMapKeyQ (Map QuadMap.q())
Prototype NumericMapKeyS (Map StringMap.s())
Global GetMapPointerI.GetMapPointerI
Global GetMapPointerL.GetMapPointerL
Global GetMapPointerQ.GetMapPointerQ
Global GetMapPointerS.GetMapPointerS
Global NumericMapKeyI.NumericMapKeyI
Global NumericMapKeyL.NumericMapKeyL
Global NumericMapKeyQ.NumericMapKeyQ
Global NumericMapKeyS.NumericMapKeyS
EndDeclareModule
Module MapEx
DisableDebugger
;->> Procedures <<
Procedure GetMapPointer(*Map)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Map]
!mov rax, [rdx + 72]
CompilerElse
!mov edx, [p.p_Map]
!mov eax, [edx + 48]
CompilerEndIf
ProcedureReturn
EndProcedure
Procedure NumericMapKey(*Map)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Map]
!mov rdx, [rdx]
!mov rax, [rdx + 8]
CompilerElse
!mov edx, [p.p_Map]
!mov edx, [edx]
!mov eax, [edx + 4]
CompilerEndIf
ProcedureReturn
EndProcedure
;->> Prototype assignments <<
GetMapPointerI = @GetMapPointer()
GetMapPointerL = @GetMapPointer()
GetMapPointerQ = @GetMapPointer()
GetMapPointerS = @GetMapPointer()
NumericMapKeyI = @NumericMapKey()
NumericMapKeyL = @NumericMapKey()
NumericMapKeyQ = @NumericMapKey()
NumericMapKeyS = @NumericMapKey()
EndModule
;->> PB imports for numeric integer maps <<
Import ""
PB_NewNumericMap(ElementSize, *StructureMap, *PtrAddress, HashSize)
PB_AddNumericMapElement2(Map IntegerMap.i(), Key, ElementCheck = #PB_Map_ElementCheck)
PB_FindNumericMapElement(Map IntegerMap.i(), Key)
PB_DeleteNumericMapElement2(Map IntegerMap.i(), Key)
PB_GetNumericMapElement(Map IntegerMap.i(), Key)
EndImport
; Create a dummy map and free it again
; this way we have a variable that is
; marked as a map
NewMap NumericMap.i()
*NumericMap = MapEx::GetMapPointerI(NumericMap())
FreeMap(NumericMap())
; Create a numeric map for the same variable
PB_NewNumericMap(SizeOf(Integer), 0, *NumericMap, 512)
; Work with the numeric map
PB_AddNumericMapElement2(NumericMap(), 12)
NumericMap() = 123
PB_AddNumericMapElement2(NumericMap(), 34)
NumericMap() = 345
PushMapPosition(NumericMap())
PB_AddNumericMapElement2(NumericMap(), 56)
NumericMap() = 765
PB_AddNumericMapElement2(NumericMap(), 56, #PB_Map_NoElementCheck)
NumericMap() = 567
PopMapPosition(NumericMap())
Debug NumericMap()
PB_FindNumericMapElement(NumericMap(), 56)
Debug NumericMap()
*Int.Integer = PB_GetNumericMapElement(NumericMap(), 12)
Debug *Int\i
ForEach NumericMap()
Debug "Key:" + Str(MapEx::NumericMapKeyI(NumericMap())) + " Value: " + Str(NumericMap())
Next
FreeMap(NumericMap())
But is shows the procedures themselves are there.
@Fred, is there a reason this functionality is not exposed ?
It would be very useful to be able to use a numeric value as a key.
Last edited by wilbert on Sat Dec 14, 2019 6:44 am, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Using adresses as a key for AddMapElements ???
Thanks for the efforts people (masters).
@Wilbert I get this (PB 5.71 LTS on XP 32, yeah old hé) :
One value 345 and then :
"The debugged executable quit unexpectedly."
@Wilbert I get this (PB 5.71 LTS on XP 32, yeah old hé) :
One value 345 and then :
"The debugged executable quit unexpectedly."
Indeed.wilbert wrote:It would be very useful to be able to use a numeric value as a key.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Re: Using adresses as a key for AddMapElements ???
Does it make a difference if you change ImportC to Import ?Joris wrote:@Wilbert I get this (PB 5.71 LTS on XP 32, yeah old hé) :
One value 345 and then :
"The debugged executable quit unexpectedly."
An alternative could be to have a faster function to convert a memory pointer to a string.
Or if you don't have to store a lot of values, a tree instead of a map.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Using adresses as a key for AddMapElements ???
Thanks wilbert! Any chance you could get this to work with custom structures?
Code: Select all
Structure window
NewList controls.i()
hWnd.i
value.i
EndStructure
I'd be pretty interested in that, toowilbert wrote:@Fred, is there a reason this functionality is not exposed ?
It would be very useful to be able to use a numeric value as a key.
Et cetera is my worst enemy
Re: Using adresses as a key for AddMapElements ???
It can be used with structures, It just needs the structure address filled out, so for strings or any structure with a PB_Object, you just pass in the addresschi wrote:Thanks wilbert! Any chance you could get this to work with custom structures?Code: Select all
Structure window NewList controls.i() hWnd.i value.i EndStructure
I'd be pretty interested in that, toowilbert wrote:@Fred, is there a reason this functionality is not exposed ?
It would be very useful to be able to use a numeric value as a key.
example tested on linux x64 and Windows x86
Code: Select all
Import ""
PB_NewNumericMap(ElementSize.i,*StructureMap,*Address,HashTabelSize.l);
PB_FreeMap(*Map);
PB_ResetMap(*Map);
PB_ClearMap(*Map);
PB_MapSize(*Map) ;
PB_PushMapPosition(*map);
PB_PopMapPosition(*map);
PB_NextMapElement(*Map);
PB_FindNumericMapElement(*Map,Key.i);
PB_GetNumericMapElement(*Map,Key.i);
PB_AddNumericMapElement(*Map,Key.i);
PB_AddNumericMapElement2(*Map,Key.i,ElementCheck=#PB_Map_ElementCheck);
PB_DeleteNumericMapElement2(*Map,Key.i);
PB_DeleteNumericMapElement(*Map);
PB_CopyMap(*Map,*DestinationMap);
PB_CopyMap2(*Map,*DestinationMap,Clear.l);
;
PB_MapKey(*Map,PreviousPosition.l);
EndImport
Macro NewNumericMap(pmap,mapsize,Type)
Global structadr
EnableASM
CompilerIf TypeOf(Type) = #PB_Structure
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
lea rax,[s_#Type]
mov [v_structadr],rax
CompilerElse
lea eax,[s_#Type]
mov [v_structadr],eax
CompilerEndIf
CompilerElse
structadr = 0
CompilerEndIf
DisableASM
PB_NewNumericMap(SizeOf(Type),structadr,@pmap,mapsize)
EndMacro
Structure mFoo
List controls.i()
i.i
s.s
EndStructure
Global *mp,*el.mFoo
NewNumericMap(*mp,512,mfoo)
*el = PB_AddNumericMapElement2(*mp,123)
AddElement(*el\controls())
*el\controls() = 123
AddElement(*el\controls())
*el\controls() = 345
*el\i = 123
*el\s = "Hello"
;
*el = PB_AddNumericMapElement2(*mp,345)
AddElement(*el\controls())
*el\controls() = 678
AddElement(*el\controls())
*el\controls() = 911
*el\i = 345
*el\s = "World"
;
*el = PB_FindNumericMapElement(*mp,123)
ForEach *el\controls()
Debug *el\controls()
Next
Debug *el\i
Debug *el\s
*el = PB_FindNumericMapElement(*mp,345)
ForEach *el\controls()
Debug *el\controls()
Next
Debug *el\i
Debug *el\s
PB_FreeMap(*mp)
Windows 11, Manjaro, Raspberry Pi OS
Re: Using adresses as a key for AddMapElements ???
This is fantastic! Thank you, idle
Now I can finally get rid of converting the hWnd to a string first...
Now I can finally get rid of converting the hWnd to a string first...
Et cetera is my worst enemy
Re: Using adresses as a key for AddMapElements ???
try this, think I've got it sorted so you can use native types but might not work on osxchi wrote:This is fantastic! Thank you, idle
Now I can finally get rid of converting the hWnd to a string first...
Code: Select all
;NumericMap hack for structured Numeric keyed Maps
;windows linux osx
Import ""
PB_NewNumericMap(ElementSize.i,*StructureMap,*Address,HashTabelSize.l);
PB_FreeMap(*Map) ;
PB_ResetMap(*Map) ;
PB_ClearMap(*Map) ;
PB_MapSize(*Map) ;
PB_PushMapPosition(*map) ;
PB_PopMapPosition(*map) ;
PB_NextMapElement(*Map) ;
PB_FindNumericMapElement(*Map,Key.i) ;
PB_AddNumericMapElement(*Map,Key.i) ;
PB_AddNumericMapElement2(*Map,Key.i,ElementCheck=#PB_Map_ElementCheck);
PB_DeleteNumericMapElement2(*Map,Key.i) ;
PB_DeleteNumericMapElement(*Map) ;
PB_CopyMap(*Map,*DestinationMap) ;
PB_CopyMap2(*Map,*DestinationMap,Clear.l) ;
EndImport
Macro NewNumericMap(pmap,HashTableSize,StructureType,IsStructure=0)
Global structadr=0
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
CompilerIf IsStructure
lea rax,[s_#StructureType]
mov [v_structadr],rax
CompilerEndIf
CompilerElse
CompilerIf IsStructure
lea eax,[s_#StructureType]
mov [v_structadr],eax
CompilerEndIf
CompilerEndIf
DisableASM
PB_NewNumericMap(SizeOf(StructureType),structadr,@pmap,HashTableSize)
EndMacro
Procedure NumericMapkey(*Map)
Protected ele,key
ele = PeekI(*map)
key = PeekI(ele+SizeOf(Integer))
ProcedureReturn key
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
;Note you need to use a structured element pointer even for native types
Structure foo
List controls.i()
i.i
s.s
EndStructure
Procedure test()
Protected mp, *el.foo
NewNumericMap(mp,512,foo,#PB_Structure) ;create the map and pass map variable, number of elements, the name of the structure
*el = PB_AddNumericMapElement(mp,123)
AddElement(*el\controls())
*el\controls() = 111
AddElement(*el\controls())
*el\controls() = 112
*el\i = 123
*el\s = "Hello"
;
*el = PB_AddNumericMapElement2(mp,345)
AddElement(*el\controls())
*el\controls() = 113
AddElement(*el\controls())
*el\controls() = 114
*el\i = 345
*el\s = "World"
;
*el = PB_FindNumericMapElement(mp,123)
ForEach *el\controls()
Debug "list Controls " + *el\controls()
Next
Debug "integer " + *el\i
Debug "string " + *el\s
*el = PB_FindNumericMapElement(mp,345)
ForEach *el\controls()
Debug "list Controls " + *el\controls()
Next
Debug "integer " + *el\i
Debug "string " + *el\s
Debug "+++++++++++"
Debug "walk the map"
Debug "+++++++++++"
PB_ResetMap(mp)
Repeat
*el = PB_NextMapElement(mp)
If *el
Debug "mapkey " + NumericMapkey(mp)
ForEach *el\controls()
Debug "list Controls " + *el\controls()
Next
Debug "integer " + *el\i
Debug "string " + *el\s
EndIf
Until *el=0
Debug "++++++++++++++"
Debug "clear map"
PB_ClearMap(mp);
PB_ResetMap(mp)
Repeat
*el = PB_NextMapElement(mp)
If *el
Debug "mapkey " + NumericMapkey(mp)
ForEach *el\controls()
Debug "list Controls " + *el\controls()
Next
Debug "integer " + *el\i
Debug "string " + *el\s
EndIf
Until *el=0
Debug "should be nothing"
PB_FreeMap(mp)
Debug "++++++++++++"
Debug "test with a native type via pointer"
Protected *elf.float
NewNumericMap(mp,512,float) ;create the map and pass map variable, number of elements, the name of the structure
*elf = PB_AddNumericMapElement(mp,123)
*elf\f = #PI
*elf = PB_AddNumericMapElement(mp,345)
*elf\f = 2*#PI
*elf = PB_FindNumericMapElement(mp,123)
Debug *elf\f
*elf = PB_FindNumericMapElement(mp,345)
If *elf
Debug *elf\f
EndIf
Debug NumericMapkey(mp)
PB_FreeMap(mp)
EndProcedure
test()
CompilerEndIf
Windows 11, Manjaro, Raspberry Pi OS
Re: Using adresses as a key for AddMapElements ???
I tried but no better result.wilbert wrote:Does it make a difference if you change ImportC to Import ?
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Re: Using adresses as a key for AddMapElements ???
Approximately how many items with a numeric key do you need to store ?Joris wrote:I tried but no better result.wilbert wrote:Does it make a difference if you change ImportC to Import ?
Hundreds, thousands ?
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Using adresses as a key for AddMapElements ???
wilbert it can vary by user use of the program, but I suppose it will mostly be less then 100, but yeah, that's my guess...wilbert wrote:... Approximately how many items with a numeric key do you need to store ?
Hundreds, thousands ?
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.