diff --git a/extra/ini-file/authors.txt b/extra/ini-file/authors.txt new file mode 100644 index 0000000000..e091bb8164 --- /dev/null +++ b/extra/ini-file/authors.txt @@ -0,0 +1 @@ +John Benediktsson diff --git a/extra/ini-file/ini-file-docs.factor b/extra/ini-file/ini-file-docs.factor new file mode 100644 index 0000000000..c108dff783 --- /dev/null +++ b/extra/ini-file/ini-file-docs.factor @@ -0,0 +1,36 @@ +! Copyright (C) 2010 John Benediktsson +! See http://factorcode.org/license.txt for BSD license + +USING: assocs hashtables help.syntax help.markup io strings ; + +IN: ini-file + +HELP: read-ini +{ $values { "assoc" assoc } } +{ $description + "Reads and parses an INI configuration from the " { $link input-stream } + " and returns the result as a nested " { $link hashtable } + "." +} ; + +HELP: write-ini +{ $values { "assoc" assoc } } +{ $description + "Writes a configuration to the " { $link output-stream } + " in the INI format." +} ; + +HELP: string>ini +{ $values { "str" string } { "assoc" assoc } } +{ $description + "Parses the specified " { $link string } " as an INI configuration" + " and returns the result as a nested " { $link hashtable } + "." +} ; + +HELP: ini>string +{ $values { "assoc" assoc } { "str" string } } +{ $description + "Encodes the specified " { $link hashtable } " as an INI configuration." +} ; + diff --git a/extra/ini-file/ini-file-tests.factor b/extra/ini-file/ini-file-tests.factor new file mode 100644 index 0000000000..072ae6ec5e --- /dev/null +++ b/extra/ini-file/ini-file-tests.factor @@ -0,0 +1,131 @@ +! Copyright (C) 2010 John Benediktsson +! See http://factorcode.org/license.txt for BSD license + +USING: ini-file tools.test ; + +IN: ini-file.tests + +[ H{ } ] [ "" string>ini ] unit-test + +[ H{ { "section" H{ } } } ] [ "[section]" string>ini ] unit-test + +[ H{ { "section" H{ } } } ] [ "[\"section\" ]" string>ini ] unit-test + +[ H{ { " some name with spaces " H{ } } } ] +[ "[ \" some name with spaces \"]" string>ini ] unit-test + +[ H{ { "[]" H{ } } } ] [ "[\\[\\]]" string>ini ] unit-test + +[ H{ { "foo" "bar" } } ] [ "foo=bar" string>ini ] unit-test + +[ H{ { "foo" "bar" } { "baz" "quz" } } ] +[ "foo=bar\nbaz= quz" string>ini ] unit-test + +[ H{ { "section" H{ { "foo" "abc def" } } } } ] +[ + """ + [section] + foo = abc def + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "abc def" } } } } ] +[ + """ + [section] + foo = abc \\ + "def" + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "abc def" } } } } ] +[ + """ + [section] + foo = "abc " \\ + def + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "abc def" } } } } ] +[ + """ + [section] foo = "abc def" + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "abc def" } } } } ] +[ + """ + [section] foo = abc \\ + "def" + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "" } } } } ] +[ + """ + [section] + foo= + """ string>ini +] unit-test + +[ H{ { "section" H{ { "foo" "" } } } } ] +[ + """ + [section] + foo + """ string>ini +] unit-test + +[ H{ { "" H{ { "" "" } } } } ] +[ + """ + [] + = + """ string>ini +] unit-test + +[ H{ { "owner" H{ { "name" "John Doe" } + { "organization" "Acme Widgets Inc." } } } + { "database" H{ { "server" "192.0.2.62" } + { "port" "143" } + { "file" "payroll.dat" } } } } ] +[ + """ + ; last modified 1 April 2001 by John Doe + [owner] + name=John Doe + organization=Acme Widgets Inc. + + [database] + server=192.0.2.62 ; use IP address in case network name resolution is not working + port=143 + file = "payroll.dat" + """ string>ini +] unit-test + +[ H{ { "a long section name" + H{ { "a long key name" "a long value name" } } } } ] +[ + """ + [a long section name ] + a long key name= a long value name + """ string>ini +] unit-test + +[ H{ { "key with \n esc\ape \r codes \"" + "value with \t esc\ape codes" } } ] +[ + """ + key with \\n esc\\ape \\r codes \\\" = value with \\t esc\\ape codes + """ string>ini +] unit-test + + +[ """key with \\n esc\\ape \\r codes \\\"=value with \\t esc\\ape codes\n""" ] +[ + H{ { "key with \n esc\ape \r codes \"" + "value with \t esc\ape codes" } } ini>string +] unit-test + diff --git a/extra/ini-file/ini-file.factor b/extra/ini-file/ini-file.factor new file mode 100644 index 0000000000..1b642f6499 --- /dev/null +++ b/extra/ini-file/ini-file.factor @@ -0,0 +1,149 @@ +! Copyright (C) 2010 John Benediktsson +! See http://factorcode.org/license.txt for BSD license + +USING: arrays assocs combinators combinators.short-circuit +formatting hashtables io io.streams.string kernel make math +namespaces quoting sequences splitting strings strings.parser ; + +IN: ini-file + + ] + [ first CHAR: [ = ] + [ CHAR: ] swap last-index ] + } 1&& ; + +: line-continues? ( line -- ? ) + { [ empty? not ] [ last CHAR: \ = ] } 1&& ; + +: section, ( -- ) + section get [ , ] when* ; + +: option, ( name value -- ) + section get [ second swapd set-at ] [ 2array , ] if* ; + +: [section] ( line -- ) + unwrap cleanup-string H{ } clone 2array section set ; + +: name=value ( line -- ) + option [ + [ swap [ first2 ] dip ] [ + "=" split1 [ cleanup-string "" ] [ "" or ] bi* + ] if* + dup line-continues? [ + dup length 1 - head cleanup-string + dup last space? [ " " append ] unless append 2array + ] [ + cleanup-string append option, f + ] if + ] change ; + +: parse-line ( line -- ) + uncomment unspace dup section? [ + section, 1 + cut [ [section] ] [ unspace ] bi* + ] when* [ name=value ] unless-empty ; + +PRIVATE> + +: read-ini ( -- assoc ) + section off option off + [ [ parse-line ] each-line section, ] { } make + >hashtable ; + +: write-ini ( assoc -- ) + [ + dup string? + [ [ escape-string ] bi@ "%s=%s\n" printf ] + [ + [ escape-string "[%s]\n" printf ] dip + [ [ escape-string ] bi@ "%s=%s\n" printf ] + assoc-each nl + ] if + ] assoc-each ; + +! FIXME: escaped comments "\;" don't work + +: string>ini ( str -- assoc ) + [ read-ini ] with-string-reader ; + +: ini>string ( str -- assoc ) + [ write-ini ] with-string-writer ; + diff --git a/extra/ini-file/summary.txt b/extra/ini-file/summary.txt new file mode 100644 index 0000000000..7566fd39a3 --- /dev/null +++ b/extra/ini-file/summary.txt @@ -0,0 +1 @@ +Parses INI configuration files.