JSON als Ersatz für Preferences-Befehle

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.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

JSON als Ersatz für Preferences-Befehle

Beitrag von GPI »

Es gibt eine Sache, die mich an den Preference-Befehlen immer gestört hat: Sehr viel Schreibarbeit! Man muss die Config-Variablen anlegen, eine ReadPreference*() und eine WritePreference*() schreiben, und überall den Variablennamen gleich angeben etc. Alles sehr Umständlich.

Einfacher geht es eigentlich mit den JSON-Befehlen. Es ist möglich eine Structure in JSON zu übernehmen und wieder zu extrahieren. Man braucht hier nur eine Config-Structure anlegen und diese überall nutzen. Vorteil ist hier: Schon alleine mit config\option kann man in Quellcode schnell lesen, was gespeichert wird. Auch schön ist, das die Key-Namen einfach aus der Structur entnommen, Schreibfehler führen hier zu einen Compilerfehler. Zudem lassen sich so Arrays, LinkedList, Maps und Structuren einfach nutzen, was mit den Preference-Befehlen bedingt und umständlich möglich ist.

Es gibt aber einen Nachteil: ExtractJSONStructure() löscht leider die bestehende Structure, so das man keine Default-Werte mitgeben kann. Meine Include soll diesen Manko ausgleichen.

Die Benutzung ist einfach.
1) Als erstes eine Structure anlegen.

2) JSONConfig::Define(Structure-Name)
Mit diesen Befehl legt man zwei nötige Proceduren an, die man für laden und speichern benötigt.

3) optional eine Default-Werte-Variable von Typ der Strucutre anlegen und füllen.

4) JSONConfig::Load(DateiName.s, StructureName , ConfigVariable [,DefaultVariable])
hiermit lädt man eine Configdatei ein. Die Defaultwerte kann man über die DefaultVariable übergeben. Die Config-Variable von Typ der Structure muss existieren!

5) JSONConfig::Save(DateiName.s, StructureName, ConfigVariable)

In Quellcode ist auch ein Beispiel. Lasst es einmal ausführen und ändert dann mal die TestConfig.JSON (zeilen löschen, ändern, willkürliche reinschreiben) und beobachtet, was dann passiert.

edit: Achja vergessen: Man kann natürlich mehrere Structuren als Config benutzen, so das man unterschiedliche Sachen abspeichern kann.

Code: Alles auswählen

DeclareModule JSONConfig
  EnableExplicit
  Macro _c34
    "
  EndMacro  
  Macro Define(StructureName)
    Runtime Procedure StructureName#__InsertJSONStructure(value,*adr)
      InsertJSONStructure( value, *adr, StructureName)
    EndProcedure
    Runtime Procedure StructureName#__ExtractJSONStructure(value,*adr)
      ExtractJSONStructure(value,*adr,StructureName)
    EndProcedure
  EndMacro  
  Declare CombineJSONMember(Value1,Value2)
  Declare SetActiveJSONMember(ObjectValue,Name.s)
  
  Macro Load(File,StructureName,VariableAdr,DefaultAdr=0)
    JSONConfig::_Load(File,JSONConfig::_c34#StructureName#JSONConfig::_c34,#PB_Compiler_Module,VariableAdr,DefaultAdr)
  EndMacro
  Declare _Load(File.s,StructureName.s,ModuleName.s,*Variable,*Default=0)
  
  Macro Save(File,StructureName,VariableAdr)
    JSONConfig::_Save(File,JSONConfig::_c34#StructureName#JSONConfig::_c34,#PB_Compiler_Module,VariableAdr)
  EndMacro
  Declare _Save(File.s,StructureName.s,ModuleName.s,*Variable)
  
EndDeclareModule 

Module JSONConfig
  Procedure SetActiveJSONMember(ObjectValue,name.s)
    Protected ret
    If ExamineJSONMembers(ObjectValue)
      While NextJSONMember(ObjectValue)
        If JSONMemberKey(ObjectValue)=name
          ret=JSONMemberValue(ObjectValue)
          Break
        EndIf
      Wend
    EndIf
    ProcedureReturn ret
  EndProcedure
  Procedure _InsertArray(newva,jmv2)
    Protected count1,count,i,Element,NewElement
    count1=JSONArraySize(newva)
    count=JSONArraySize(jmv2)
    For i=0 To count-1
      Element=GetJSONElement(jmv2,i)
      If i<count1
        RemoveJSONElement(newva,i)
      EndIf
      NewElement=AddJSONElement(newva,i)
      Select JSONType(element)
        Case #PB_JSON_Null
          SetJSONNull(NewElement)
        Case #PB_JSON_String
          SetJSONString(NewElement,GetJSONString(Element))
        Case #PB_JSON_Number
          SetJSONDouble(NewElement,GetJSONDouble(Element))
        Case #PB_JSON_Boolean
          SetJSONBoolean(NewElement,GetJSONBoolean(Element))
        Case #PB_JSON_Array
          SetJSONArray(NewElement)
          _InsertArray(NewElement,Element)
        Case #PB_JSON_Object
          SetJSONObject(NewElement)
          CombineJSONMember(NewElement,Element)
      EndSelect
    Next     
  EndProcedure
  Procedure CombineJSONMember(Value1,Value2)
    Protected newva
    Protected jmv2
    Protected jmk2.s
    If ExamineJSONMembers(Value2)
      While NextJSONMember(Value2)
        
        jmv2=JSONMemberValue(Value2)
        jmk2.s=JSONMemberKey(Value2)
        
        Select JSONType(jmv2)
          Case #PB_JSON_Null
            newva=AddJSONMember(Value1,jmk2)
            SetJSONNull(newva)
          Case #PB_JSON_String
            newva=AddJSONMember(Value1,jmk2)
            SetJSONString(newva,GetJSONString(jmv2))
          Case #PB_JSON_Number
            newva=AddJSONMember(Value1,jmk2)
            SetJSONDouble(newva,GetJSONDouble(jmv2))
          Case #PB_JSON_Boolean
            newva=AddJSONMember(Value1,jmk2)
            SetJSONBoolean(newva,GetJSONBoolean(jmv2))
          Case #PB_JSON_Array            
            newva=SetActiveJSONMember(Value1,jmk2)
            If newva=0 Or JSONType(newva)<>#PB_JSON_Array
              newva=AddJSONMember(Value1,jmk2)
              SetJSONArray(newva)
            EndIf
            _InsertArray(newva,jmv2)
          Case #PB_JSON_Object
            newva=SetActiveJSONMember(Value1,jmk2)
            If newva=0 Or JSONType(newva)<>#PB_JSON_Object
              newva=AddJSONMember(Value1,jmk2)
              SetJSONObject(newva)
            EndIf
            CombineJSONMember(newva,jmv2)
        EndSelect
      Wend
    EndIf
  EndProcedure  
  Prototype JSONStructure(value,*adr)
  
  Procedure _Load(File.s,StructureName.s,ModuleName.s,*variable,*Default=0)
    Protected Extract.JSONStructure
    Protected Insert.JSONStructure
    Protected JS,ret,JSd
    
    If ModuleName<>"" And FindString(StructureName,"::")=0
      StructureName=ModuleName+"::"+StructureName
    EndIf
    
    Extract=GetRuntimeInteger(StructureName+"__ExtractJSONStructure()")
    Insert =GetRuntimeInteger(StructureName+"__InsertJSONStructure()")
    
    If Extract=0 Or Insert=0
      ProcedureReturn #False
    EndIf
        
    If *Default
      jsD=CreateJSON(#PB_Any)
      Insert(JSONValue(jsD),*Default)
    EndIf
    
    js=LoadJSON(#PB_Any,file)
    
    If js And jsd
      CombineJSONMember(JSONValue(jsD),JSONValue(JS))
      ret=#True
    ElseIf js And jsd=0
      jsD=js
      js=0
    EndIf
    
    If jsd
      Extract(JSONValue(jsD),*variable)
      FreeJSON(jsD)
    EndIf
    
    If js
      FreeJSON(js)
    EndIf
  
    
    ProcedureReturn ret
  EndProcedure
  
  Procedure _Save(File.s,StructureName.s,ModuleName.s,*variable)
    Protected Insert.JSONStructure
    Protected JS,ret
    
    If ModuleName<>"" And FindString(StructureName,"::")=0
      StructureName=ModuleName+"::"+StructureName
    EndIf
    
    Insert =GetRuntimeInteger(StructureName+"__InsertJSONStructure()")
    If Insert=0
      ProcedureReturn #False
    EndIf
    
    js=CreateJSON(#PB_Any)
    If js
      Insert(JSONValue(js),*variable)
      ret=SaveJSON(js,File,#PB_JSON_PrettyPrint)
      FreeJSON(js)
    EndIf
    ProcedureReturn js
  EndProcedure
  
EndModule

;-
;-Example
CompilerIf  #PB_Compiler_IsMainFile
  
  Structure HiScore
    Name.s
    Score.i
  EndStructure
  
  Structure sConfig
    Version.i
    PlayerName.s
    Array HiScore.HiScore(9)
  EndStructure
  
  JSONConfig::Define(sConfig)
  
  Global Config.sConfig
  Global ConfigDefault.sConfig
  ConfigDefault\Version=$101
  ConfigDefault\PlayerName="Dummy"
  For i=0 To 9
    ConfigDefault\HiScore(i)\Name="Randomguy"+i
    ConfigDefault\HiScore(i)\Score=10000-1000*i
  Next
  
  JSONConfig::Load("ConfigTest.json",sConfig,Config,ConfigDefault)
  
  Debug Hex(config\Version)
  Debug config\PlayerName
  For i=0 To 9
    Debug config\HiScore(i)\Name+" "+config\HiScore(i)\Score
  Next
  
  JSONConfig::Save("ConfigTest.json",sConfig,Config)
  
CompilerEndIf
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!