Wie kann man eine Strukturübergabe variable machen (Makro) ?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Wie kann man eine Strukturübergabe variable machen (Makro) ?

Beitrag von Bisonte »

Hallo.

Strukturen kann man anscheinend nicht als Parameter an eine Prozedur übergeben.
Daher habe ich mir gedacht, mache ich das per Makro. Ist auch kein Problem. Nun
würde ich mir gerne eine "kleine" Sourceverkleinerung gönnen. Dazu müsste ich es
eigentlich nur schaffen (auch über Umwege, völlig egal) den Strukur-Parameter für
ExtractJSONStructure() per variable übergeben zu können.

Ich bastel an einem Parser, der aus einer JSON Zeile die Aktionen ausliest und weiterverarbeitet.
Es sind mehr als 50 dieser möglichen "Events". Diese Events sind auch in der jeweiligen Zeile präsent.

Bsp.:

Code: Alles auswählen

{ "timestamp":"2017-08-16T14:35:44Z", "event":"ReceiveText", .....
Hier nutze ich nun für jedes dieser Events eine Strukur, da die mitgegeben Daten sehr stark abweichen.
Momentan behelfe ich mich mit

Code: Alles auswählen

Structure jsonl_receivetext
  From.s
  From_Localised.s
  Message.s
  Message_Localised.s
  Channel.s
EndStructure
Structure jsonl_rebootrepair
  List Modules.s()
EndStructure

Macro getjsonl(Struktur)
  *Mem = AllocateStructure(Struktur)
  ExtractJSONStructure(jV, *Mem, Struktur)
EndMacro

Procedure.i JL_ReceiveText(*Mem.jsonl_receivetext)
  
  If *Mem
    Debug *Mem\Message
    FreeStructure(*Mem)
  EndIf
  
EndProcedure
Procedure.i JL_RebootRepair(*Mem.jsonl_rebootrepair)
  
  If *Mem
    ForEach *Mem\Modules()
      Debug *Mem\Modules()
    Next
    FreeStructure(*Mem)
  EndIf
  
EndProcedure

Procedure.i ParseString(jString.s)
  
  Protected *Mem, jSon, jV, TimeStamp.s, Event.s
  
  jSon = ParseJSON(#PB_Any, jString, #PB_JSON_NoCase)
  
  If jSon
    
    jV = JSONValue(jSon)
    
    TimeStamp         = GetJSONString(GetJSONMember(jV, "timestamp"))
    Event             = Trim(LCase(GetJSONString(GetJSONMember(jV, "event"))))
    
    Select Event
        
      Case "receivetext"
        getjsonl(jsonl_receivetext)
        JL_ReceiveText(*Mem)
        
      Case "rebootrepair"
        getjsonl(jsonl_rebootrepair)
        JL_RebootRepair(*Mem)
        
    EndSelect
    
    FreeJSON(jSon)
    
  EndIf

EndProcedure
diesem Macro.

Klappt auch wunderbar. Mir schwebt da eine evt. Erleichterung mit Maps vor.
Den Prozeduraufruf kann ich per Prototype proto_Proc(*Mem) variabel gestalten.

Nun müsste ich nur dem Makro per "Variable" mitteilen, dass die bestimmte Struktur
genommen werden soll.

Wie kann ich sowas anstellen ?

Mir schwebt da sowas in der Art vor :

Code: Alles auswählen

Prototype proto_Proc(*Mem)

Structure jsonl_receivetext
  From.s
  From_Localised.s
  Message.s
  Message_Localised.s
  Channel.s
EndStructure
Structure jsonl_rebootrepair
  List Modules.s()
EndStructure

Structure testmap
  ProcAufruf.proto_Proc
  Strukturname.s ; ???
EndStructure

Global NewMap Aufruf.testmap()

Procedure.i JL_ReceiveText(*Mem.jsonl_receivetext)
  
  If *Mem
    Debug *Mem\Message
    FreeStructure(*Mem)
  EndIf
  
EndProcedure
Procedure.i JL_RebootRepair(*Mem.jsonl_rebootrepair)
  
  If *Mem
    ForEach *Mem\Modules()
      Debug *Mem\Modules()
    Next
    FreeStructure(*Mem)
  EndIf
  
EndProcedure

Aufruf("receivetext")\ProcAufruf = @JL_ReceiveText()
Aufruf("receivetext")\Strukturname = "jsonl_receivetext"

Macro getjsonl(Struktur) ; Wie kann ich den Inhalt der Variable Aufruf("receivetext")\Strukturname hier übernehmen ?
  *Mem = AllocateStructure(Struktur)
  ExtractJSONStructure(jV, *Mem, Struktur)
  Aufruf(Event)\ProcAufruf(*Mem)  
EndMacro


Procedure.i ParseString(jString.s)
  
  Protected *Mem, jSon, jV, TimeStamp.s, Event.s
  
  jSon = ParseJSON(#PB_Any, jString, #PB_JSON_NoCase)
  
  If jSon
    
    jV = JSONValue(jSon)
    
    TimeStamp         = GetJSONString(GetJSONMember(jV, "timestamp"))
    Event             = Trim(LCase(GetJSONString(GetJSONMember(jV, "event"))))
    
    getjsonl(????)
        
    FreeJSON(jSon)
    
  EndIf

EndProcedure
Kann mir da jemand weiterhelfen ?
Makrobau oder sonst irgendein Trick ?
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Wie kann man eine Strukturübergabe variable machen (Makr

Beitrag von GPI »

edit lesen hilft ;) -stand mist

Die Frage ist, ob es mit eine Procedure leichter lesbar ist.

Code: Alles auswählen

Structure TestA
  a.a
  b.b
EndStructure
Structure TestB
  c.c
  d.d
EndStructure

Macro DefineJsonProcedure(struc)
  Procedure Json_#struc(jv)
    Protected *mem
    *Mem = AllocateStructure(struc)
    If *mem
      ExtractJSONStructure(jV, *Mem, struc)
    EndIf
    ProcedureReturn *mem
  EndProcedure
EndMacro

DefineJsonProcedure(TestA)
DefineJsonProcedure(TestB)

Macro GetStructure(struc,jv)
  json_#struc(jv)
EndMacro


something( GetStructure(TestA,jv) )
something( GetStructure(TestB,jv) )
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Wie kann man eine Strukturübergabe variable machen (Makr

Beitrag von Bisonte »

GPI hat geschrieben:edit lesen hilft ;) -stand mist
Ok, ich wollt grad sagen das das Problem bestehen bleibt ;) ....

Eigentlich müsste man nur den Inhalt eines Strings dem Makro zugänglich machen können... denke ich.

Denn wenn es heisst

Code: Alles auswählen

Macro foo(struktur)
ExtractJSONStructure(...., struktur) 
EndMacro
Wird es leider zu dem MacroparameterNAMEN den man dort angibt, also würde da wenn man String$ schreibt auch String$ stehen und
nicht der Inhalt von String$...

Code: Alles auswählen

Foo(String$) 

; Expanded Makro =

ExtractJSONStructure(...., String$)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Wie kann man eine Strukturübergabe variable machen (Makr

Beitrag von GPI »

Tja, hier gibts ein Problem, der Parameter "Structur" bei ExtractJSONStructure ist kein normaler Parameter, also keine Variable. Der Befehl ist eigentlich eher ein Compiler-Befehl, als ein klassischer Befehl. Das Macro kann keinen String "expandieren", weil er schlicht beim compilen nicht bekannt ist.

Wenn die Anzahl der Structuren bekannt ist, kannst du mit einer Procedure aushelfen.

Code: Alles auswählen

Procedure ExtractSelect(struc$)
  Select UCase(struc$)
    Case "TESTA": ExtractJSONStructure(...., TestA)
    Case "TESTB": ExtractJSONStructure(..., TestB)
  EndSelect
  ProcedureReturn *mem
EndProcedure
Ansonsten versteh ich dein Problem nicht ganz ;)
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Wie kann man eine Strukturübergabe variable machen (Makr

Beitrag von Bisonte »

GPI hat geschrieben:Ansonsten versteh ich dein Problem nicht ganz ;)
Macht nix.... Ich versteh mich auch oft nicht :D

Nee im Ernst.

Das ist eigentlich schade, das das mit dem Inhalt einer Variablen nicht möglich ist.
Aber ich Dussel hab vielleicht auch an falsche Parameter bei meinem Fall gedacht.

Ich habe für jedes dieser "Events" die in Textform im JSON sind, ja sowieso eine eigene Prozedur zum Auswerten.
Ich dachte mir, den Speicherbereich an die Prozedur zu senden wäre gut. Allerdings kann ich auch "nur"
die beiden JSON Parameter nehmen, die JSonValue() und die JSon PB Nummer, dann halt in jeder der einzelnen Prozeduren
"ExtractJSONStructur".

Jetzt um mal zum Punkt zu kommen sieht es also ungefähr so aus...

Code: Alles auswählen

Prototype proto_Proc(jSon, jV)

Structure jsonl_receivetext
  From.s
  From_Localised.s
  Message.s
  Message_Localised.s
  Channel.s
EndStructure
Structure jsonl_rebootrepair
  List Modules.s()
EndStructure

Structure testmap
  ProcAufruf.proto_Proc
EndStructure

Global NewMap Aufruf.testmap()

Macro GetJSONL(Struktur) ; Wie kann ich den Inhalt der Variable Aufruf("receivetext")\Strukturname hier übernehmen ?
  
  Protected *Mem.Struktur
  
  If IsJSON(jSon) And jV
    *Mem = AllocateStructure(Struktur)
    ExtractJSONStructure(jV, *Mem, Struktur)
    If Not *Mem
      ProcedureReturn #False
    EndIf
  Else
    ProcedureReturn #False
  EndIf  
  
EndMacro

Procedure.i JL_ReceiveText(jSon, jV)

    GetJSONL(jsonl_receivetext)
    
    Debug *Mem\Message
    
    FreeStructure(*Mem)
    
EndProcedure
Procedure.i JL_RebootRepair(jSon, jV)
  
  GetJSONL(jsonl_rebootrepair)  

  ForEach *Mem\Modules()
    Debug *Mem\Modules()
  Next
  
  FreeStructure(*Mem)
  
EndProcedure

Aufruf("receivetext")\ProcAufruf = @JL_ReceiveText()
Aufruf("rebootrepair")\ProcAufruf = @JL_RebootRepair()

Procedure.i ParseString(jString.s)
  
  Protected jSon, jV, Event.s
  
  jSon = ParseJSON(#PB_Any, jString, #PB_JSON_NoCase)
  
  If jSon
    
    jV    = JSONValue(jSon)
    Event = Trim(LCase(GetJSONString(GetJSONMember(jV, "event"))))
    
    If FindMapElement(AufRuf(), Event)
      Aufruf(Event)\ProcAufruf(jSon, jV)
    EndIf
    
    FreeJSON(jSon)
    
  EndIf

EndProcedure
Edit: Heisst also eine ewig lange Kette mit Case und massig anweisungen entfällt. Weil wie gesagt, das sind ne ganze menge Events zum Auswerten ;)

Achja Ich hatte auch probiert, ALLE Strukturen in eine Strukur zu vereinen, weil ExtractJSONStructure ja nur die benötigten Felder befüllt.
Das wäre dann eine Strukture mit der Groesse von 944 Bytes. Klingt nicht viel dachte ich, aber das allerdings vergrösserte die Bearbeitungszeit enorm. Mit der "Einzelstruktur" Extraktion dauern 69 Files ca. 2 Sekunden. Mit einer grossen Strukur dauern 69 Files parsen auf einmal fast 60 Sekunden.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Wie kann man eine Strukturübergabe variable machen (Makr

Beitrag von GPI »

Das Problem mit den Struckturen-parameter ist: Der Compiler muss hier zusätzliche Informationen zur Struktur in der EXE abspeichern. Wäre es variabel, dann müsste der Compiler zu sämtlichen Struckturen was in der EXE abspeichern.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Antworten