@ -70,6 +70,20 @@ func ParseInto(s string, dest map[string]interface{}) error {
return t . parse ( )
}
// ParseFile parses a set line, but its final value is loaded from the file at the path specified by the original value.
//
// A set line is of the form name1=path1,name2=path2
//
// When the files at path1 and path2 contained "val1" and "val2" respectively, the set line is consumed as
// name1=val1,name2=val2
func ParseFile ( s string , reader RunesValueReader ) ( map [ string ] interface { } , error ) {
vals := map [ string ] interface { } { }
scanner := bytes . NewBufferString ( s )
t := newFileParser ( scanner , vals , reader )
err := t . parse ( )
return vals , err
}
// ParseIntoString parses a strvals line nad merges the result into dest.
//
// This method always returns a string as the value.
@ -79,16 +93,36 @@ func ParseIntoString(s string, dest map[string]interface{}) error {
return t . parse ( )
}
// ParseIntoFile parses a filevals line and merges the result into dest.
//
// This method always returns a string as the value.
func ParseIntoFile ( s string , dest map [ string ] interface { } , reader RunesValueReader ) error {
scanner := bytes . NewBufferString ( s )
t := newFileParser ( scanner , dest , reader )
return t . parse ( )
}
// RunesValueReader is a function that takes the given value (a slice of runes)
// and returns the parsed value
type RunesValueReader func ( [ ] rune ) ( interface { } , error )
// parser is a simple parser that takes a strvals line and parses it into a
// map representation.
type parser struct {
sc * bytes . Buffer
data map [ string ] interface { }
st bool
sc * bytes . Buffer
data map [ string ] interface { }
reader RunesValueReader
}
func newParser ( sc * bytes . Buffer , data map [ string ] interface { } , stringBool bool ) * parser {
return & parser { sc : sc , data : data , st : stringBool }
stringConverter := func ( rs [ ] rune ) ( interface { } , error ) {
return typedVal ( rs , stringBool ) , nil
}
return & parser { sc : sc , data : data , reader : stringConverter }
}
func newFileParser ( sc * bytes . Buffer , data map [ string ] interface { } , reader RunesValueReader ) * parser {
return & parser { sc : sc , data : data , reader : reader }
}
func ( t * parser ) parse ( ) error {
@ -152,8 +186,12 @@ func (t *parser) key(data map[string]interface{}) error {
set ( data , string ( k ) , "" )
return e
case ErrNotList :
v , e := t . val ( )
set ( data , string ( k ) , typedVal ( v , t . st ) )
rs , e := t . val ( )
if e != nil && e != io . EOF {
return e
}
v , e := t . reader ( rs )
set ( data , string ( k ) , v )
return e
default :
return e
@ -225,8 +263,12 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
case io . EOF :
return setIndex ( list , i , "" ) , err
case ErrNotList :
v , e := t . val ( )
return setIndex ( list , i , typedVal ( v , t . st ) ) , e
rs , e := t . val ( )
if e != nil && e != io . EOF {
return list , e
}
v , e := t . reader ( rs )
return setIndex ( list , i , v ) , e
default :
return list , e
}
@ -274,7 +316,7 @@ func (t *parser) valList() ([]interface{}, error) {
list := [ ] interface { } { }
stop := runeSet ( [ ] rune { ',' , '}' } )
for {
switch v , last , err := runesUntil ( t . sc , stop ) ; {
switch rs , last , err := runesUntil ( t . sc , stop ) ; {
case err != nil :
if err == io . EOF {
err = errors . New ( "list must terminate with '}'" )
@ -285,10 +327,15 @@ func (t *parser) valList() ([]interface{}, error) {
if r , _ , e := t . sc . ReadRune ( ) ; e == nil && r != ',' {
t . sc . UnreadRune ( )
}
list = append ( list , typedVal ( v , t . st ) )
return list , nil
v , e := t . reader ( rs )
list = append ( list , v )
return list , e
case last == ',' :
list = append ( list , typedVal ( v , t . st ) )
v , e := t . reader ( rs )
if e != nil {
return list , e
}
list = append ( list , v )
}
}
}