Merge pull request #4130 from lihf8515/devel

Update parsecfg.nim
This commit is contained in:
Andreas Rumpf
2016-05-26 10:51:10 +02:00
2 changed files with 233 additions and 25 deletions

View File

@@ -22,10 +22,71 @@
##
## .. code-block:: nim
## :file: examples/parsecfgex.nim
##
## Examples
## --------
##
## This is an example of a configuration file.
##
## .. include:: config.ini
##
## charset = "utf-8"
## [Package]
## name = "hello"
## --threads:on
## [Author]
## name = "lihf8515"
## qq = "10214028"
## email = "lihaifeng@wxm.com"
##
## Creating a configuration file.
## ==============================
## .. code-block:: nim
##
## import parsecfg
## var dict=newConfig()
## dict.setSectionKey("","charset","utf-8")
## dict.setSectionKey("Package","name","hello")
## dict.setSectionKey("Package","--threads","on")
## dict.setSectionKey("Author","name","lihf8515")
## dict.setSectionKey("Author","qq","10214028")
## dict.setSectionKey("Author","email","lihaifeng@wxm.com")
## dict.writeConfig("config.ini")
##
## Reading a configuration file.
## =============================
## .. code-block:: nim
##
## import parsecfg
## var dict = loadConfig("config.ini")
## var charset = dict.getSectionValue("","charset")
## var threads = dict.getSectionValue("Package","--threads")
## var pname = dict.getSectionValue("Package","name")
## var name = dict.getSectionValue("Author","name")
## var qq = dict.getSectionValue("Author","qq")
## var email = dict.getSectionValue("Author","email")
## echo pname & "\n" & name & "\n" & qq & "\n" & email
##
## Modifying a configuration file.
## ===============================
## .. code-block:: nim
##
## import parsecfg
## var dict = loadConfig("config.ini")
## dict.setSectionKey("Author","name","lhf")
## dict.writeConfig("config.ini")
##
## Deleting a section key in a configuration file.
## ===============================================
## .. code-block:: nim
##
## import parsecfg
## var dict = loadConfig("config.ini")
## dict.delSectionKey("Author","email")
## dict.writeConfig("config.ini")
import
hashes, strutils, lexbase, streams
hashes, strutils, lexbase, streams, tables
include "system/inclrtl"
@@ -359,3 +420,138 @@ proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} =
result.kind = cfgError
result.msg = errorStr(c, "invalid token: " & c.tok.literal)
rawGetTok(c, c.tok)
# ---------------- Configuration file related operations ----------------
type
Config* = OrderedTableRef[string, OrderedTableRef[string, string]]
proc newConfig*(): Config =
## Create a new configuration table.
## 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.
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)
result = dict
proc replace(s: string): string =
var d = ""
var i = 0
while i < s.len():
if s[i] == '\\':
d.add(r"\\")
elif s[i] == '\c' and s[i+1] == '\L':
d.add(r"\n")
inc(i)
elif s[i] == '\c':
d.add(r"\n")
elif s[i] == '\L':
d.add(r"\n")
else:
d.add(s[i])
inc(i)
result = d
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):
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()
proc getSectionValue*(dict: Config, section, key: string): string =
## Gets the Key value of the specified Section.
if dict.haskey(section):
if dict[section].hasKey(key):
result = dict[section][key]
else:
result = ""
else:
result = ""
proc setSectionKey*(dict: var Config, section, key, value: string) =
## Sets the Key value of the specified Section.
var t = newOrderedTable[string, string]()
if dict.hasKey(section):
t = dict[section]
t[key] = value
dict[section] = t
proc delSection*(dict: var Config, section: string) =
## Deletes the specified section and all of its sub keys.
dict.del(section)
proc delSectionKey*(dict: var Config, section, key: string) =
## Delete the key of the specified section.
if dict.haskey(section):
if dict[section].hasKey(key):
if dict[section].len() == 1:
dict.del(section)
else:
dict[section].del(key)

View File

@@ -1,25 +1,37 @@
import parsecfg
import
os, parsecfg, strutils, streams
## Creating a configuration file.
var dict1=newConfig()
dict1.setSectionKey("","charset","utf-8")
dict1.setSectionKey("Package","name","hello")
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")
## Reading a configuration file.
var dict2 = loadConfig("config.ini")
var charset = dict2.getSectionValue("","charset")
var threads = dict2.getSectionValue("Package","--threads")
var pname = dict2.getSectionValue("Package","name")
var name = dict2.getSectionValue("Author","name")
var qq = dict2.getSectionValue("Author","qq")
var email = dict2.getSectionValue("Author","email")
echo charset
echo threads
echo pname
echo name
echo qq
echo email
## Modifying a configuration file.
var dict3 = loadConfig("config.ini")
dict3.setSectionKey("Author","name","lhf")
dict3.writeConfig("config.ini")
## Deleting a section key in a configuration file.
var dict4 = loadConfig("config.ini")
dict4.delSectionKey("Author","email")
dict4.writeConfig("config.ini")
var f = newFileStream(paramStr(1), fmRead)
if f != nil:
var p: TCfgParser
open(p, f, paramStr(1))
while true:
var e = next(p)
case e.kind
of cfgEof:
echo("EOF!")
break
of cfgSectionStart: ## a ``[section]`` has been parsed
echo("new section: " & e.section)
of cfgKeyValuePair:
echo("key-value-pair: " & e.key & ": " & e.value)
of cfgOption:
echo("command: " & e.key & ": " & e.value)
of cfgError:
echo(e.msg)
close(p)
else:
echo("cannot open: " & paramStr(1))