diff options
-rw-r--r-- | lib/pure/parsecfg.nim | 157 | ||||
-rw-r--r-- | tests/stdlib/tparscfg.nim | 46 |
2 files changed, 124 insertions, 79 deletions
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index 47670cc19..28681a11f 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -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. diff --git a/tests/stdlib/tparscfg.nim b/tests/stdlib/tparscfg.nim index 7022d071b..fc735f3eb 100644 --- a/tests/stdlib/tparscfg.nim +++ b/tests/stdlib/tparscfg.nim @@ -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) |