This one is simple but useful to quickly append config/settings support to your app.
It supports both raw XML mode (where user can edit config), and compressed mode (binary file, greatly decreased in size).
Usage is also simple: whole 2 functions for Save and Load
Code: Select all
EnableExplicit
; Assume this is your app configuration ^^
Structure ConfigEx
Value$
EndStructure
Structure Config
SomeStuff$
Another.a
StuffX.ConfigEx
Stuff.a [4]
EndStructure
;{ Config XML v2 }
; *InData a structure of type CONFIG (define it as needed)
; Filename$ path to a config file
; Compress TRUE to compress data (will make config unreadable, but much smaller than raw XML)
; Format TRUE to reformat XML before save
; RETURN: 0 on success
; 1 if XML-related error
; 2 if compression failed
; 3 if file-related error
Procedure SaveCfg (*inData.CONFIG, Filename$, Compress = #False, Format = #False)
Protected Res, TreeXML = CreateXML(#PB_Any, #PB_UTF8)
Protected xSize, *hMem, *hCMem, hFile, fSize
If IsXML(TreeXML) And InsertXMLStructure(RootXMLNode(TreeXML), *inData, CONFIG)
If Format And Not Compress
FormatXML(TreeXML, #PB_XML_ReFormat | #PB_XML_WindowsNewline, 2)
EndIf
If Compress ; pack config to xml, then pack xml to compressed binary, then save to file
xSize = ExportXMLSize(TreeXML, #PB_XML_NoDeclaration)
If xSize < 64 ; using this to avoid "comression failed" on CompressMemory()
xSize = 64
EndIf
*hMem = AllocateMemory(xSize)
*hCMem = AllocateMemory(xSize)
Res = 2
If *hMem And *hCMem And ExportXML(TreeXML, *hMem, MemorySize(*hMem), #PB_XML_NoDeclaration)
FreeXML(TreeXML)
UseZipPacker()
fSize = CompressMemory(*hMem, MemorySize(*hMem), *hCMem, MemorySize(*hCMem), #PB_PackerPlugin_Zip)
If fSize
DeleteFile(Filename$, #PB_FileSystem_Force)
hFile = CreateFile(#PB_Any, Filename$)
If hFile
WriteLong(hFile, xSize) ; uncompressed size [first 8 bytes of file]
WriteData(hFile, *hCMem, fSize) ; at last, save to file compressed data
CloseFile(hFile)
Res = 0
Else
Res = 3
EndIf
Else
Res = 2
EndIf
EndIf
Else ; pack cfg to xml and write to file
If Not SaveXML(TreeXML, Filename$, #PB_XML_NoDeclaration)
Res = 3
EndIf
EndIf
Else
Res = 1
EndIf
;cls
If *hMem : FreeMemory(*hMem) : EndIf
If *hCMem : FreeMemory(*hCMem) : EndIf
If IsXML(TreeXML) : FreeXML(TreeXML) :EndIf
If IsFile(hFile) : CloseFile(hFile) : EndIf
ProcedureReturn Res
EndProcedure
; *OutData a structure of type CONFIG to receive data
; Filename$ path to a config file
; Compressed if file was compressed on saving, set it to TRUE
; RETURN: 0 on success
; 1 if XML-related error
; 2 if decompression failed
; 3 if file-related error
Procedure ReadCfg (*OutData.CONFIG, Filename$, Compressed = #False)
Protected Res, TreeXML
Protected xSize, *hMem, *hCMem, hFile, fSize
If Compressed ; read from file, decompress xml, get map from xml
If FileSize(Filename$) >= SizeOf(Long)
hFile = OpenFile(#PB_Any, Filename$)
EndIf
If hFile
fSize = Lof(hFile) - SizeOf(Long)
xSize = ReadLong(hFile) ; read size of uncompressed data
*hMem = AllocateMemory(fSize)
If *hMem And ReadData(hFile, *hMem, fSize) = fSize ; read compressed binary
UseZipPacker()
*hCMem = AllocateMemory(xSize)
If *hCMem And UncompressMemory(*hMem, MemorySize(*hMem), *hCMem, MemorySize(*hCMem), #PB_PackerPlugin_Zip) = xSize ; decompress
TreeXML = CatchXML(#PB_Any, *hCMem, MemorySize(*hCMem), 0, #PB_UTF8) ; get XML
If IsXML(TreeXML)
ExtractXMLStructure(MainXMLNode(TreeXML), *OutData, CONFIG) ; finally extract data
Else
Res = 1
EndIf
Else
Res = 2
EndIf
Else
Res = 3
EndIf
Else
Res = 3
EndIf
Else
TreeXML = LoadXML(#PB_Any, Filename$, #PB_UTF8)
If IsXML(TreeXML)
ExtractXMLStructure(MainXMLNode(TreeXML), *OutData, CONFIG) ; finally extract data
Else
Res = 1
EndIf
EndIf
;cls
If *hMem : FreeMemory(*hMem) : EndIf
If *hCMem : FreeMemory(*hCMem) : EndIf
If IsXML(TreeXML) : FreeXML(TreeXML) : EndIf
If IsFile(hFile) : CloseFile(hFile) : EndIf
ProcedureReturn Res
EndProcedure
;}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Example
;;;;;;;;;;;;;;;;;
; Set some config values
Define F.Config
F\Another = 1
F\SomeStuff$ = "a"
F\Stuff[2] = 6
F\StuffX\Value$ = "stuffX"
; 1) Writing config file (compressed)
SaveCfg(F, "config.bin", #True)
; 2) Now read it back to an empty structure, like on application startup
Define R.Config
ReadCfg(R, "config.bin", #True)
; Show results
Debug R\Another
Debug R\SomeStuff$
Debug R\Stuff[2]
Debug R\StuffX\Value$