CopyStructure - auch mit Strings

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

CopyStructure - auch mit Strings

Beitrag 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:
Zuletzt geändert von mk-soft am 28.03.2009 15:08, insgesamt 3-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag 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:
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Boa Danke :o ! Daran bin ich immer gescheitert!
Ab ins Codearchiv oder gleich nativ in PureBasic
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
inc.
Beiträge: 348
Registriert: 27.10.2004 12:25

Beitrag von inc. »

Toll! :)
Hier gibts die OOP Option für PureBasic.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag 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.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag 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(...)
Zuletzt geändert von mk-soft am 28.03.2009 15:09, insgesamt 2-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag 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:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Update v1.09
- compatible mit X86 und X64

FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag 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
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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:
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten