PureBasic Forum
http://forums.purebasic.com/english/

Using adresses as a key for AddMapElements ???
http://forums.purebasic.com/english/viewtopic.php?f=35&t=74081
Page 2 of 2

Author:  wilbert [ Thu Dec 19, 2019 5:59 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

Joris wrote:
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...

With that little items, you could probably also do with a simple structured array with key / value fields.
But I'll probably trie to create a simple numeric map myself.

Author:  C87 [ Thu Dec 19, 2019 6:32 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

There are several statements in this Topic that these functions aren't referenced in the HELP file. Can I ask a what may be a stupid question? :
If they aren't in the HELP file, how on earth does anyone know they exist? :?

( an earlier Topic NumericMap by idle made reference to these functions and I just gave up in the end :oops: )

Author:  Tenaja [ Thu Dec 19, 2019 6:44 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

C87 wrote:
If they aren't in the HELP file, how on earth does anyone know they exist? :?

Look at the asm code that is generated when you use Maps. (There are quite a few forum threads on this topic.)

This actually brings up the point that if someone were to rely on the code suggested that the PB version should be listed, as well as assumptions (such as the Map library has not been updated...).

Author:  idle [ Thu Dec 19, 2019 9:06 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

Tenaja wrote:
C87 wrote:
If they aren't in the HELP file, how on earth does anyone know they exist? :?

Look at the asm code that is generated when you use Maps. (There are quite a few forum threads on this topic.)

This actually brings up the point that if someone were to rely on the code suggested that the PB version should be listed, as well as assumptions (such as the Map library has not been updated...).


you can find the headers in the sdk /PureBasic/sdk/c/PureLibraries/

These headers can change with a new version of PB so yes any code using them could break with a new release of PB, so version checking would be the sane thing to do.

Author:  chi [ Tue Jan 14, 2020 7:08 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

idle wrote:
chi wrote:
This is fantastic! Thank you, idle 8)

Now I can finally get rid of converting the hWnd to a string first...


try this, think I've got it sorted so you can use native types but might not work on osx

Code:
;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

@idle: Unfortunately your code only works with the Debugger enabled. With a disabled Debugger or trying to create an executable, I get a bunch of POLINK errors :(

Edit: Btw, it works if you call "NewMap dummy.foo()" somewhere and remove all "PB_FreeMap(mp) " calls...

Author:  idle [ Wed Jan 15, 2020 12:31 am ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

hmmm never thought to try it without the debugger, still need to create dummy map and the PB_FreeNumericMap macro will need some fix up for x86 linux and osx.

Code:
;NumericMap hack for structured Numeric keyed Maps
;windows linux osx
NewMap dummy()
FreeMap(dummy())

Import ""
  PB_InitMap()
  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 PB_FreeNumericMap(pmap)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    PUSH pmap
    POP rdi
    CALL PB_FreeMap
  CompilerElse
    PUSH   pmap
    CALL  _PB_FreeMap@4   ;might need changing for x86 linux osx
  CompilerEndIf
 
  DisableASM
EndMacro 

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
  OpenConsole()   
 
  ;PB_InitMap()
 
  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()
      PrintN( "list Controls " + *el\controls())
    Next   
    PrintN( "integer " + *el\i)
    PrintN( "string "  + *el\s)
   
    *el = PB_FindNumericMapElement(mp,345)
    ForEach *el\controls()
      PrintN( "list Controls " + *el\controls())
    Next   
    PrintN( "integer " + *el\i)
    PrintN( "string "  + *el\s)
   
    PrintN( "+++++++++++")
    PrintN( "walk the map")
    PrintN( "+++++++++++")
   
    PB_ResetMap(mp)
    Repeat
      *el = PB_NextMapElement(mp)
      If *el
        PrintN( "mapkey " + NumericMapkey(mp))
        ForEach *el\controls()
          PrintN( "list Controls " + *el\controls())
        Next   
        PrintN( "integer " + *el\i)
        PrintN( "string "  + *el\s)
      EndIf   
    Until *el=0   
   
    PrintN( "++++++++++++++")
    PrintN( "clear map")
    PB_ClearMap(mp);
    PB_ResetMap(mp)
    Repeat
      *el = PB_NextMapElement(mp)
      If *el
        PrintN( "mapkey " + NumericMapkey(mp))
        ForEach *el\controls()
          PrintN( "list Controls " + *el\controls())
        Next   
        PrintN( "integer " + *el\i)
        PrintN( "string "  + *el\s)
      EndIf   
    Until *el=0   
    PrintN( "should be nothing")
   
    PB_FreeNumericMap(mp)
   
    PrintN( "++++++++++++")
    PrintN( "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)
    PrintN(StrF(*elf\f))
   
    *elf = PB_FindNumericMapElement(mp,345)
    If *elf
      PrintN(StrF(*elf\f))
    EndIf
   
    PrintN(Str(NumericMapkey(mp)))
   
    PB_FreeNumericMap(mp)
   
  EndProcedure
 
  test()
  Input()
 
CompilerEndIf

Author:  chi [ Thu Jan 16, 2020 12:17 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

idle wrote:
hmmm never thought to try it without the debugger...
Neither did I :)
idle wrote:
...and the PB_FreeNumericMap macro will need some fix up for x86 linux and osx
Now I get an IMA on PB_FreeNumericMap (Win7 x64, PB5.71 x64) with the debugger enabled

But don't waste your precious time on this! Who knows in what state Fred left NumericMaps and since he never bothered to answer what's wrong with it and why he didn't finish the implementation, one can only say: "Don't use 'em". I personally switched to wilbert's NKMaps, which are even slightly faster in my tests...

Author:  idle [ Thu Jan 16, 2020 9:14 pm ]
Post subject:  Re: Using adresses as a key for AddMapElements ???

chi wrote:
idle wrote:
hmmm never thought to try it without the debugger...
Neither did I :)
idle wrote:
...and the PB_FreeNumericMap macro will need some fix up for x86 linux and osx
Now I get an IMA on PB_FreeNumericMap (Win7 x64, PB5.71 x64) with the debugger enabled

But don't waste your precious time on this! Who knows in what state Fred left NumericMaps and since he never bothered to answer what's wrong with it and why he didn't finish the implementation, one can only say: "Don't use 'em". I personally switched to wilbert's NKMaps, which are even slightly faster in my tests...


That's the problem with dirty hacks they often fall over. Wilberts NKMap should be fine :)

Page 2 of 2 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/