parsecfg

The parsecfg module implements a high performance configuration file parser. The configuration file's syntax is similar to the Windows .ini format, but much more powerful, as it is not a line based parser. String literals, raw string literals and triple quoted string literals are supported as in the Nim programming language.

Example of how a configuration file may look like:

# This is a comment.
; this too.

[Common]
cc=gcc     # '=' and ':' are the same
--foo="bar"   # '--cc' and 'cc' are the same, 'bar' and '"bar"' are the same
--verbose

[Windows]
isConsoleApplication=False ; another comment

[Posix]
isConsoleApplication=True

key1: "in this string backslash escapes are interpreted\n"
key2: r"in this string not"
key3: """triple quotes strings
are also supported. They may span
multiple lines."""

--"long option with spaces": r"c:\myfiles\test.txt" 

Here is an example of how to use the configuration file parser:

import os, parsecfg, strutils, streams

var f = newFileStream(paramStr(1), fmRead)
if f != nil:
  var p: CfgParser
  open(p, f, paramStr(1))
  while true:
    var e = next(p)
    case e.kind
    of cfgEof: 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))

Examples

Configuration file example

charset = "utf-8"
[Package]
name = "hello"
--threads:on
[Author]
name = "lihf8515"
qq = "10214028"
email = "lihaifeng@wxm.com"

Creating a configuration file

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

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

import parsecfg
var dict = loadConfig("config.ini")
dict.setSectionKey("Author","name","lhf")
dict.writeConfig("config.ini")

Deleting a section key in a configuration file

import parsecfg
var dict = loadConfig("config.ini")
dict.delSectionKey("Author","email")
dict.writeConfig("config.ini")

CfgEventKind = enum
  cfgEof,                     ## end of file reached
  cfgSectionStart,            ## a ``[section]`` has been parsed
  cfgKeyValuePair,            ## a ``key=value`` pair has been detected
  cfgOption,                  ## a ``--key=value`` command line option
  cfgError                    ## an error occurred during parsing
enumeration of all events that may occur when parsing   Source Edit
CfgEvent = object of RootObj
  case kind*: CfgEventKind      ## the kind of the event
  of cfgEof:
    nil
  of cfgSectionStart:
      section*: string         ## `section` contains the name of the
                     ## parsed section start (syntax: ``[section]``)
    
  of cfgKeyValuePair, cfgOption:
      key*, value*: string      ## contains the (key, value) pair if an option
                        ## of the form ``--key: value`` or an ordinary
                        ## ``key= value`` pair has been parsed.
                        ## ``value==""`` if it was not specified in the
                        ## configuration file.
    
  of cfgError:                 ## the parser encountered an error: `msg`
      msg*: string             ## contains the error message. No exceptions
                 ## are thrown if a parse error occurs.
    
  
describes a parsing event   Source Edit
CfgParser = object of BaseLexer
  tok: Token
  filename: string
the parser object.   ソース 編集
Config = OrderedTableRef[string, OrderedTableRef[string, string]]
  ソース 編集

プロシージャ

proc open(c: var CfgParser; input: Stream; filename: string; lineOffset = 0) {...}{.gcsafe,
    extern: "npc$1", raises: [Defect, IOError, OSError, Exception],
    tags: [ReadIOEffect, RootEffect].}
initializes the parser with an input stream. Filename is only used for nice error messages. lineOffset can be used to influence the line number information in the generated error messages.   ソース 編集
proc close(c: var CfgParser) {...}{.gcsafe, extern: "npc$1",
                           raises: [Exception, IOError, OSError],
                           tags: [WriteIOEffect].}
closes the parser c and its associated input stream.   ソース 編集
proc getColumn(c: CfgParser): int {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}
get the current column the parser has arrived at.   ソース 編集
proc getLine(c: CfgParser): int {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}
get the current line the parser has arrived at.   ソース 編集
proc getFilename(c: CfgParser): string {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}
get the filename of the file that the parser processes.   ソース 編集
proc errorStr(c: CfgParser; msg: string): string {...}{.gcsafe, extern: "npc$1",
    raises: [ValueError], tags: [].}
returns a properly formatted error message containing current line and column information.   ソース 編集
proc warningStr(c: CfgParser; msg: string): string {...}{.gcsafe, extern: "npc$1",
    raises: [ValueError], tags: [].}
returns a properly formatted warning message containing current line and column information.   ソース 編集
proc ignoreMsg(c: CfgParser; e: CfgEvent): string {...}{.gcsafe, extern: "npc$1",
    raises: [ValueError], tags: [].}
returns a properly formatted warning message containing that an entry is ignored.   ソース 編集
proc next(c: var CfgParser): CfgEvent {...}{.gcsafe, extern: "npc$1", raises: [Defect, IOError,
    OSError, ValueError], tags: [ReadIOEffect].}
retrieves the first/next event. This controls the parser.   ソース 編集
proc newConfig(): Config {...}{.raises: [], tags: [].}
Create a new configuration table. Useful when wanting to create a configuration file.   ソース 編集
proc loadConfig(stream: Stream; filename: string = "[stream]"): Config {...}{.
    raises: [Defect, IOError, OSError, Exception, ValueError, KeyError],
    tags: [ReadIOEffect, RootEffect, WriteIOEffect].}
Load the specified configuration from stream into a new Config instance. filename parameter is only used for nicer error messages.   ソース 編集
proc loadConfig(filename: string): Config {...}{.raises: [IOError, Exception, OSError,
    Defect, ValueError, KeyError], tags: [WriteIOEffect, ReadIOEffect, RootEffect].}
Load the specified configuration file into a new Config instance.   ソース 編集
proc writeConfig(dict: Config; stream: Stream) {...}{.raises: [Defect, IOError, OSError],
    tags: [WriteIOEffect].}

Writes the contents of the table to the specified stream

Note: Comment statement will be ignored.

  ソース 編集
proc `$`(dict: Config): string {...}{.raises: [Exception, IOError, OSError, Defect],
                             tags: [WriteIOEffect].}
Writes the contents of the table to string. Note: Comment statement will be ignored.   ソース 編集
proc writeConfig(dict: Config; filename: string) {...}{.
    raises: [IOError, Defect, OSError], tags: [WriteIOEffect].}
Writes the contents of the table to the specified configuration file. Note: Comment statement will be ignored.   ソース 編集
proc getSectionValue(dict: Config; section, key: string): string {...}{.raises: [KeyError],
    tags: [].}
Gets the Key value of the specified Section, returns an empty string if the key does not exist.   ソース 編集
proc setSectionKey(dict: var Config; section, key, value: string) {...}{.raises: [KeyError],
    tags: [].}
Sets the Key value of the specified Section.   ソース 編集
proc delSection(dict: var Config; section: string) {...}{.raises: [], tags: [].}
Deletes the specified section and all of its sub keys.   ソース 編集
proc delSectionKey(dict: var Config; section, key: string) {...}{.raises: [KeyError], tags: [].}
Delete the key of the specified section.   ソース 編集