Seite 1 von 1

CopyStructure - auch mit Strings

Verfasst: 09.01.2008 03:10
von mk-soft
Memory Strukturen kopieren mit Strings und Arrays

Update v1.03 -> Update v1.04

Problem mit Unterstrukturen und Arrays gelöst. Beim anlegen der Strukturen jetzt mit "EndStruct(strukturname)" beenden. Bei EndStruct(...) Strukturname immer klein schreiben! Wichtig da der Compiler intern immer alles nach klein umwandelt.

Update v1.09
- compatible mit X86 und X64

Code: Alles auswählen

;-TOP
; Comment       : CopyStructure with Strings and Arrays
; Author        : mk-soft
; Second Author : 
; File          : CopyStructure.pb
; Version       : 1.09
; Create        : 
; Update        : 28.03.2009
; 
; Compilermode  :
;
; ***************************************************************************************

;- Macros EndStruct to create help functions

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  ; X86 Processor  
  Macro EndStruct(StructureName) ; <- name of structure allways lowercase
    EndStructure
      Procedure ___dummy_#StructureName()
        Protected dummy.StructureName
      EndProcedure
      Procedure ___addr_#StructureName()
      !MOV eax, dword s_#StructureName
      ProcedureReturn
    EndProcedure
  EndMacro

CompilerElse
  ; X64 Processor
  Macro EndStruct(StructureName) ; <- name of structure allways lowercase
    EndStructure
      Procedure ___dummy_#StructureName()
        Protected dummy.StructureName
      EndProcedure
      Procedure ___addr_#StructureName()
        !MOV rax, qword s_#StructureName
        ProcedureReturn
      EndProcedure
  EndMacro

CompilerEndIf
    
Macro GetStruct(StructureName)
  ___addr_#StructureName()
EndMacro

; ***************************************************************************************

; Recursive function
Procedure SubCopyStructure(*Scoure, *Desk, StructAdress, Offset)
  
  Protected adress, loop, ofs, size, subStruct, count, *s1.string , *s2.string
  Repeat
    adress = PeekI(StructAdress)
    If adress = -1
      Break
    EndIf
    If adress = -2
      loop = PeekI(StructAdress+SizeOf(adress)) -1
      ofs = PeekI(StructAdress+SizeOf(adress)*2)
      size = PeekI(StructAdress+SizeOf(adress)*3)
      subStruct = PeekI(StructAdress+SizeOf(adress)*4)
      For count = 0 To loop
        SubCopyStructure(*Scoure, *Desk, subStruct, ofs +(count*size))
      Next
      StructAdress + SizeOf(adress)*5
    Else
      *s1 = *Scoure + adress + Offset
      *s2 = *Desk + adress + Offset
      PokeI(*s2, 0)
      *s2\s = *s1\s
      StructAdress + SizeOf(adress)
    EndIf
  ForEver

EndProcedure

; Main function
Procedure CopyStructure(*Scoure, *Desk, Size, StructAdress)
  
  CopyMemory(*Scoure, *Desk, Size)
  SubCopyStructure(*Scoure, *Desk, StructAdress, 0)
  
EndProcedure 

; ***************************************************************************************

; Recursive function
Procedure SubListStructureStrings(*Scoure, List List.i(), StructAdress, Offset)
  
  Protected adress, loop, ofs, size, subStruct, count, *s1.string , *s2.string
  Repeat
    adress = PeekI(StructAdress)
    If adress = -1
      Break
    EndIf
    If adress = -2
      loop = PeekI(StructAdress+SizeOf(adress)) -1
      ofs = PeekI(StructAdress+SizeOf(adress)*2)
      size = PeekI(StructAdress+SizeOf(adress)*3)
      subStruct = PeekI(StructAdress+SizeOf(adress)*4)
      For count = 0 To loop
        SubListStructureStrings(*Scoure, List(), subStruct, ofs +(count*size))
      Next
      StructAdress + SizeOf(adress)*5
    Else
      AddElement(List())
      List() = *Scoure + adress + Offset
      StructAdress + SizeOf(adress)
    EndIf
  ForEver

EndProcedure

; Function Get Strings
Procedure.s GetStructureStrings(*Scoure, StructAdress, Separator.s = ";")
  
  Protected NewList List.i()
  Protected *s1.string, result.s
  
  SubListStructureStrings(*Scoure, List(), StructAdress, 0)
  ForEach List()
    *s1 = List()
    result + *s1\s + Separator
  Next
  ProcedureReturn result

EndProcedure

; Function Set Strings
Procedure SetStructureStrings(*Scoure, StructAdress, Strings.s, Separator.s = ";")
  
  Protected NewList List.i()
  Protected *s1.string, count
  
  SubListStructureStrings(*Scoure, List(), StructAdress, 0)
  count = 1
  ForEach List()
    *s1 = List()
    *s1\s = StringField(Strings, count, Separator)
    count + 1
  Next
  
EndProcedure 

; Function Clear Strings
Procedure ClearStructureStrings(*Scoure, StructAdress)
  
  Protected NewList List.i()
  Protected *s1.string, count
  
  SubListStructureStrings(*Scoure, List(), StructAdress, 0)
  count = 1
  ForEach List()
    *s1 = List()
    *s1\s = ""
    count + 1
  Next
  
EndProcedure 

; ***************************************************************************************

Procedure FreeStructureMemory(*PointerToStructure, StructAdress)
  
  ClearStructureStrings(*PointerToStructure, StructAdress)
  FreeMemory(*PointerToStructure)
EndProcedure

; ***************************************************************************************

;- Test structure
Structure soso
  s1.s
  s2.s
EndStructure

Structure udttest
  w1.w
  w2.w
  l1.l
  l2.l
  s1.s
  s2.s
  d1.d
  d2.d
  s3.soso[2]
EndStruct(udttest) ; <- NEU : Erstellt eine Hilfsfuntion , Strukturname immer klein schreiben


; Test

Global quell.udttest
Global ziel.udttest

With quell
  \s1 = "Hallo Welt"
  \s2 = "Daten 1"
  \s3[0]\s1 = ";)"
  \s3[1]\s2 = ":wink:"
EndWith

Debug "Quelldaten"
With quell
  Debug \s1
  Debug \s2
  Debug \s3[0]\s1
  Debug \s3[1]\s2
EndWith
Debug "-------------------"

CopyStructure(quell, ziel, SizeOf(udttest), GetStruct(udtTest))

Debug "Zieldaten"
With ziel
  Debug \s1
  Debug \s2
  Debug \s3[0]\s1
  Debug \s3[1]\s2
EndWith
Debug "-------------------"

With quell
  \s1 = "Hallo Welt"
  \s2 = "Quelldaten geändert"
  \s3[0]\s1 = ";) ---"
  \s3[1]\s2 = ":evil:"
EndWith

With ziel
  \s1 = "Hallo Welt"
  \s2 = "Zieldaten geändert"
  \s3[0]\s1 = ";) ***"
  \s3[1]\s2 = ":allright:"
EndWith

Debug "Quelldaten neu"
With quell
  Debug \s1
  Debug \s2
  Debug \s3[0]\s1
  Debug \s3[1]\s2
EndWith
Debug "-------------------"

Debug "Zieldaten neu"
With ziel
  Debug \s1
  Debug \s2
  Debug \s3[0]\s1
  Debug \s3[1]\s2
EndWith
Debug "-------------------"

Debug "Get all strings"
temp.s = GetStructureStrings(quell, GetStruct(udtTest), #TAB$)
Debug temp
Debug "Upercase all strings"
temp.s = UCase(temp)
SetStructureStrings(quell, GetStruct(udtTest), temp, #TAB$)
Debug GetStructureStrings(quell, GetStruct(udtTest), #TAB$)
Debug "Delete all strings"
ClearStructureStrings(quell, GetStruct(udtTest))
Debug GetStructureStrings(quell, GetStruct(udtTest), #TAB$)
Debug "-------------------"
Debug "Free structure memory"
*mem.udttest = AllocateMemory(SizeOf(udttest))
FreeStructureMemory(*mem, GetStruct(udtTest))
FF :wink:

Verfasst: 09.01.2008 04:46
von PureLust
Einfach nur ... WOW. :shock:

Konnte es kaum glauben dass Du das nun endlich auch mal mit Strings hinbekommen hast ... bis ich Dein mitgeliefertes Beispiel ausprobiert habe.
Komme aber nicht dahinter was und wie genau Du da machst.
Hättest Du evtl. noch Lust hinzuzufügen wie Du das geschafft hast? :|

Ansonsten: Thanks for this great piece of code. :allright:

Verfasst: 09.01.2008 08:58
von milan1612
Boa Danke :o ! Daran bin ich immer gescheitert!
Ab ins Codearchiv oder gleich nativ in PureBasic

Verfasst: 09.01.2008 11:00
von inc.
Toll! :)

Verfasst: 09.01.2008 14:00
von NicTheQuick
Da wird wohl meine 'CopyStructure' unnötig: Write-, Read- und CopyStructure

Aber was natürlich nicht geht, sind Strings in Unter-Strukturen:

Code: Alles auswählen

Structure soso
  s1.s
  s2.s
EndStructure

Structure udttest
  w1.w
  w2.w
  l1.l
  l2.l
  s1.s
  s2.s
  d1.d
  d2.d
  s3.soso
EndStructure

; Macro gibt den Pointer auf den Strukturtypeliste zurück
; Wichtig: Alles immer klein schreiben
Macro GetStructAdress(adress, struct)
  !MOV dword [v_#adress], s_#struct
EndMacro

Procedure CopyStructure(*Scoure, *Desk, Size.l, struct.l)
  Protected offset, *s1.String , *s2.String
  CopyMemory(*Scoure, *Desk, Size)
  Repeat
    offset = PeekL(struct)
    Debug offset
    If offset < 0
      Break
    EndIf
    *s1 = *Scoure + offset
    *s2 = *Desk + offset
    PokeL(*s2, 0)
    *s2\s = *s1\s
    struct + 4
  ForEver
EndProcedure

; Test

Procedure Dummy()
  dummy.udttest
EndProcedure

Global quell.udttest, ziel.udttest

With quell
  \s1 = "Hallo Welt"
  \s2 = "Quelldaten"
  \s3\s1 = ";)"
  \s3\s2 = ":wink:"
EndWith

Debug "Quelldaten"
With quell
  Debug \s1
  Debug \s2
  Debug \s3\s1
  Debug \s3\s2
EndWith

Global adress = 0
GetStructAdress(adress, udttest) ; <- Immer klein schreiben
CopyStructure(quell, ziel, SizeOf(udttest), adress)

Debug "Zieldaten"
With ziel
  Debug \s1
  Debug \s2
  Debug \s3\s1
  Debug \s3\s2
EndWith

With quell
  \s1 = "Hallo Welt"
  \s2 = "Quelldaten geändert"
  \s3\s1 = ";)"
  \s3\s2 = ":evil:"
EndWith

With ziel
  \s1 = "Hallo Welt"
  \s2 = "Zieldaten geändert"
  \s3\s1 = ";)"
  \s3\s2 = ":allright:"
EndWith

Debug "Quelldaten"
With quell
  Debug \s1
  Debug \s2
  Debug \s3\s1
  Debug \s3\s2
EndWith

Debug "Zieldaten"
With ziel
  Debug \s1
  Debug \s2
  Debug \s3\s1
  Debug \s3\s2
EndWith
Also aufpassen!

@mk-soft:
Ansonsten tolle Herangehensweise. Wenn man weiß, wie PureBasic unter
der Haube funktioniert, ist das natürlich ein leichtes.

Verfasst: 11.01.2008 02:13
von mk-soft
Edit:
Update v1.03 -> Update v1.04

Problem mit Unterstrukturen und Arrays gelöst. Beim anlegen der Strukturen jetzt mit "EndStruct(strukturname)" beenden. Bei EndStruct(...) Strukturname immer klein schreiben! Wichtig da der Compiler intern immer alles nach klein umwandelt.

Code: Alles auswählen

siehe oben
Bitte testen ob alles funktioniert.

FF :allright:

P.S. Edit
Drei neue Funktionen hinzugefügt.
- GetStructureStrings(...)
- SetStructureStrings(...)
- ClearStructureStrings(...)

Verfasst: 12.01.2008 04:25
von mk-soft
Update v1.04

Bei Verwendung von Strukturen mit AllocateMemory(...) und FreeMemory fürt diese zu Speicherlecks, da nur der Pointer auf die Strings freigegeben werden und nicht der Speicher der Strings selber.

Neue Funktion hinzugefügt

FreeStructureMemory(*Scoure, StructAdress)


FF :wink:

Verfasst: 28.03.2009 15:10
von mk-soft
Update v1.09
- compatible mit X86 und X64

FF :wink:

Verfasst: 30.03.2009 18:01
von PMV
Ich muss mich auch mal bei dir herzlich für dieses stückchen Code
bedanken. :allright: Hoffentlich hälst du das auch schön auf dem
laufenden, sonnst werd ich wohl arge Probleme bekommen. :oops:

MFG PMV

Verfasst: 03.04.2009 16:13
von STARGÅTE
Weil ich gerade selber "meine Eigenen" proceduren/Macos schreiben würde ich dir gerne noch eine Verbesserung vorschlagen:

Ich verwende diese Structure:

Code: Alles auswählen

 ; Aufbau der Struktur
 Structure StructureData
  StructureUnion
   Position.i
   Type.i
  EndStructureUnion
  ArraySize.i
  ArrayPosition.i
  SubStructureSize.i
  *SubStructure
 EndStructure
So könntest du dir das Auslesen ersparen:

Code: Alles auswählen

      loop = PeekI(StructAdress+SizeOf(adress)) -1 
      ofs = PeekI(StructAdress+SizeOf(adress)*2) 
      size = PeekI(StructAdress+SizeOf(adress)*3) 
      subStruct = PeekI(StructAdress+SizeOf(adress)*4) 
und stattdessen direkt auf die Daten zugreifen, wenn StructAdress dann zu *StructAdress.StructureData wird:

Code: Alles auswählen

 *StructAdress\ArraySize -1
 *StructAdress\ArrayPosition
 *StructAdress\SubStructureSize
 *StructAdress\SubStructure
Ist nur n Vorschlag :allright: