mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
parsecfg: handle streams and strings when saving or loading configuration (#5554)
This commit is contained in:
committed by
Andreas Rumpf
parent
4ba6f9808e
commit
3374bcb373
@@ -430,40 +430,46 @@ proc newConfig*(): Config =
|
||||
## Useful when wanting to create a configuration file.
|
||||
result = newOrderedTable[string, OrderedTableRef[string, string]]()
|
||||
|
||||
proc loadConfig*(filename: string): Config =
|
||||
## Load the specified configuration file into a new Config instance.
|
||||
proc loadConfig*(stream: Stream, filename: string = "[stream]"): Config =
|
||||
## Load the specified configuration from stream into a new Config instance.
|
||||
## `filename` parameter is only used for nicer error messages.
|
||||
var dict = newOrderedTable[string, OrderedTableRef[string, string]]()
|
||||
var curSection = "" ## Current section,
|
||||
## the default value of the current section is "",
|
||||
## which means that the current section is a common
|
||||
var p: CfgParser
|
||||
var fileStream = newFileStream(filename, fmRead)
|
||||
if fileStream != nil:
|
||||
open(p, fileStream, filename)
|
||||
while true:
|
||||
var e = next(p)
|
||||
case e.kind
|
||||
of cfgEof:
|
||||
break
|
||||
of cfgSectionStart: # Only look for the first time the Section
|
||||
curSection = e.section
|
||||
of cfgKeyValuePair:
|
||||
var t = newOrderedTable[string, string]()
|
||||
if dict.hasKey(curSection):
|
||||
t = dict[curSection]
|
||||
t[e.key] = e.value
|
||||
dict[curSection] = t
|
||||
of cfgOption:
|
||||
var c = newOrderedTable[string, string]()
|
||||
if dict.hasKey(curSection):
|
||||
c = dict[curSection]
|
||||
c["--" & e.key] = e.value
|
||||
dict[curSection] = c
|
||||
of cfgError:
|
||||
break
|
||||
close(p)
|
||||
open(p, stream, filename)
|
||||
while true:
|
||||
var e = next(p)
|
||||
case e.kind
|
||||
of cfgEof:
|
||||
break
|
||||
of cfgSectionStart: # Only look for the first time the Section
|
||||
curSection = e.section
|
||||
of cfgKeyValuePair:
|
||||
var t = newOrderedTable[string, string]()
|
||||
if dict.hasKey(curSection):
|
||||
t = dict[curSection]
|
||||
t[e.key] = e.value
|
||||
dict[curSection] = t
|
||||
of cfgOption:
|
||||
var c = newOrderedTable[string, string]()
|
||||
if dict.hasKey(curSection):
|
||||
c = dict[curSection]
|
||||
c["--" & e.key] = e.value
|
||||
dict[curSection] = c
|
||||
of cfgError:
|
||||
break
|
||||
close(p)
|
||||
result = dict
|
||||
|
||||
proc loadConfig*(filename: string): Config =
|
||||
## Load the specified configuration file into a new Config instance.
|
||||
let file = open(filename, fmRead)
|
||||
let fileStream = newFileStream(file)
|
||||
defer: fileStream.close()
|
||||
result = fileStream.loadConfig(filename)
|
||||
|
||||
proc replace(s: string): string =
|
||||
var d = ""
|
||||
var i = 0
|
||||
@@ -482,54 +488,61 @@ proc replace(s: string): string =
|
||||
inc(i)
|
||||
result = d
|
||||
|
||||
proc writeConfig*(dict: Config, stream: Stream) =
|
||||
## Writes the contents of the table to the specified stream
|
||||
##
|
||||
## **Note:** Comment statement will be ignored.
|
||||
for section, sectionData in dict.pairs():
|
||||
if section != "": ## Not general section
|
||||
if not allCharsInSet(section, SymChars): ## Non system character
|
||||
stream.writeLine("[\"" & section & "\"]")
|
||||
else:
|
||||
stream.writeLine("[" & section & "]")
|
||||
for key, value in sectionData.pairs():
|
||||
var kv, segmentChar: string
|
||||
if key.len > 1 and key[0] == '-' and key[1] == '-': ## If it is a command key
|
||||
segmentChar = ":"
|
||||
if not allCharsInSet(key[2..key.len()-1], SymChars):
|
||||
kv.add("--\"")
|
||||
kv.add(key[2..key.len()-1])
|
||||
kv.add("\"")
|
||||
else:
|
||||
kv = key
|
||||
else:
|
||||
segmentChar = "="
|
||||
kv = key
|
||||
if value != "": ## If the key is not empty
|
||||
if not allCharsInSet(value, SymChars):
|
||||
if find(value, '"') == -1:
|
||||
kv.add(segmentChar)
|
||||
kv.add("\"")
|
||||
kv.add(replace(value))
|
||||
kv.add("\"")
|
||||
else:
|
||||
kv.add(segmentChar)
|
||||
kv.add("\"\"\"")
|
||||
kv.add(replace(value))
|
||||
kv.add("\"\"\"")
|
||||
else:
|
||||
kv.add(segmentChar)
|
||||
kv.add(value)
|
||||
stream.writeLine(kv)
|
||||
|
||||
proc `$`*(dict: Config): string =
|
||||
## Writes the contents of the table to string.
|
||||
## Note: Comment statement will be ignored.
|
||||
let stream = newStringStream()
|
||||
defer: stream.close()
|
||||
dict.writeConfig(stream)
|
||||
result = stream.data
|
||||
|
||||
proc writeConfig*(dict: Config, filename: string) =
|
||||
## Writes the contents of the table to the specified configuration file.
|
||||
## Note: Comment statement will be ignored.
|
||||
var file: File
|
||||
if file.open(filename, fmWrite):
|
||||
try:
|
||||
var section, key, value, kv, segmentChar:string
|
||||
for pair in dict.pairs():
|
||||
section = pair[0]
|
||||
if section != "": ## Not general section
|
||||
if not allCharsInSet(section, SymChars): ## Non system character
|
||||
file.writeLine("[\"" & section & "\"]")
|
||||
else:
|
||||
file.writeLine("[" & section & "]")
|
||||
for pair2 in pair[1].pairs():
|
||||
key = pair2[0]
|
||||
value = pair2[1]
|
||||
if key[0] == '-' and key[1] == '-': ## If it is a command key
|
||||
segmentChar = ":"
|
||||
if not allCharsInSet(key[2..key.len()-1], SymChars):
|
||||
kv.add("--\"")
|
||||
kv.add(key[2..key.len()-1])
|
||||
kv.add("\"")
|
||||
else:
|
||||
kv = key
|
||||
else:
|
||||
segmentChar = "="
|
||||
kv = key
|
||||
if value != "": ## If the key is not empty
|
||||
if not allCharsInSet(value, SymChars):
|
||||
if find(value, '"') == -1:
|
||||
kv.add(segmentChar)
|
||||
kv.add("\"")
|
||||
kv.add(replace(value))
|
||||
kv.add("\"")
|
||||
else:
|
||||
kv.add(segmentChar)
|
||||
kv.add("\"\"\"")
|
||||
kv.add(replace(value))
|
||||
kv.add("\"\"\"")
|
||||
else:
|
||||
kv.add(segmentChar)
|
||||
kv.add(value)
|
||||
file.writeLine(kv)
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
file.close()
|
||||
let file = open(filename, fmWrite)
|
||||
let fileStream = newFileStream(filename)
|
||||
defer: fileStream.close()
|
||||
dict.writeConfig(fileStream)
|
||||
|
||||
proc getSectionValue*(dict: Config, section, key: string): string =
|
||||
## Gets the Key value of the specified Section.
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
import parsecfg
|
||||
discard """
|
||||
output: '''
|
||||
utf-8
|
||||
on
|
||||
hello
|
||||
lihf8515
|
||||
10214028
|
||||
lihaifeng@wxm.com
|
||||
===
|
||||
charset=utf-8
|
||||
[Package]
|
||||
name=hello
|
||||
--threads:on
|
||||
[Author]
|
||||
name=lhf
|
||||
qq=10214028
|
||||
email="lihaifeng@wxm.com"
|
||||
===
|
||||
charset=utf-8
|
||||
[Package]
|
||||
name=hello
|
||||
--threads:on
|
||||
[Author]
|
||||
name=lihf8515
|
||||
qq=10214028
|
||||
'''
|
||||
"""
|
||||
import parsecfg, streams
|
||||
|
||||
## Creating a configuration file.
|
||||
var dict1=newConfig()
|
||||
@@ -8,10 +35,11 @@ dict1.setSectionKey("Package","--threads","on")
|
||||
dict1.setSectionKey("Author","name","lihf8515")
|
||||
dict1.setSectionKey("Author","qq","10214028")
|
||||
dict1.setSectionKey("Author","email","lihaifeng@wxm.com")
|
||||
dict1.writeConfig("config.ini")
|
||||
var ss = newStringStream()
|
||||
dict1.writeConfig(ss)
|
||||
|
||||
## Reading a configuration file.
|
||||
var dict2 = loadConfig("config.ini")
|
||||
var dict2 = loadConfig(newStringStream(ss.data))
|
||||
var charset = dict2.getSectionValue("","charset")
|
||||
var threads = dict2.getSectionValue("Package","--threads")
|
||||
var pname = dict2.getSectionValue("Package","name")
|
||||
@@ -25,13 +53,17 @@ echo name
|
||||
echo qq
|
||||
echo email
|
||||
|
||||
echo "==="
|
||||
|
||||
## Modifying a configuration file.
|
||||
var dict3 = loadConfig("config.ini")
|
||||
var dict3 = loadConfig(newStringStream(ss.data))
|
||||
dict3.setSectionKey("Author","name","lhf")
|
||||
dict3.writeConfig("config.ini")
|
||||
write(stdout, $dict3)
|
||||
|
||||
echo "==="
|
||||
|
||||
## Deleting a section key in a configuration file.
|
||||
var dict4 = loadConfig("config.ini")
|
||||
var dict4 = loadConfig(newStringStream(ss.data))
|
||||
dict4.delSectionKey("Author","email")
|
||||
dict4.writeConfig("config.ini")
|
||||
write(stdout, $dict4)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user