! Copyright (C) 2010 John Benediktsson ! See https://factorcode.org/license.txt for BSD license USING: arrays assocs combinators.short-circuit formatting hashtables io io.streams.string kernel make math namespaces quoting sequences splitting strings strings.parser ; IN: ini-file ! FIXME: support "key: value" ? ! FIXME: support "key value" ? ! FIXME: escaped comments "\;" don't work ! FIXME: \x???? for unicode character escapes ! FIXME: optional value conversion (e.g., 1234, true, etc.)? ] [ first CHAR: [ = ] [ CHAR: ] swap last-index ] } 1&& ; : line-continues? ( line -- ? ) ?last CHAR: \ = ; : 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-quoted ] bi@ "%s=%s\n" printf ] [ [ escape-quoted "[%s]\n" printf ] dip [ [ escape-quoted ] bi@ "%s=%s\n" printf ] assoc-each nl ] if ] assoc-each ; : string>ini ( str -- assoc ) [ read-ini ] with-string-reader ; : ini>string ( assoc -- str ) [ write-ini ] with-string-writer ;