github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/config/serialize.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  )
    11  
    12  // ReadConfigFile reads the config from `filename` into `cfg`.
    13  func ReadConfigFile(filename string, cfg interface{}) error {
    14  	f, err := os.Open(filename)
    15  	if err != nil {
    16  		return err
    17  	}
    18  	defer f.Close()
    19  
    20  	return Decode(f, cfg)
    21  }
    22  
    23  // WriteConfigFile writes the config from `cfg` into `filename`.
    24  func WriteConfigFile(filename string, cfg interface{}) error {
    25  	err := os.MkdirAll(filepath.Dir(filename), 0775)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	f, err := os.Create(filename)
    31  	if err != nil {
    32  		return err
    33  	}
    34  	defer f.Close()
    35  
    36  	return Encode(f, cfg)
    37  }
    38  
    39  // WriteFile writes the buffer at filename
    40  func WriteFile(filename string, buf []byte) error {
    41  	err := os.MkdirAll(filepath.Dir(filename), 0775)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	f, err := os.Create(filename)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	defer f.Close()
    51  
    52  	_, err = f.Write(buf)
    53  	return err
    54  }
    55  
    56  // Encode configuration with JSON
    57  func Encode(w io.Writer, value interface{}) error {
    58  	// need to prettyprint, hence MarshalIndent, instead of Encoder
    59  	buf, err := json.MarshalIndent(value, "", "  ")
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	_, err = w.Write(buf)
    65  	return err
    66  }
    67  
    68  // Decode configuration with JSON
    69  func Decode(r io.Reader, value interface{}) error {
    70  	return json.NewDecoder(r).Decode(value)
    71  }
    72  
    73  // ReadConfigKey retrieves only the value of a particular key
    74  func ReadConfigKey(filename, key string) (interface{}, error) {
    75  	var cfg interface{}
    76  	if err := ReadConfigFile(filename, &cfg); err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	var ok bool
    81  	cursor := cfg
    82  	parts := strings.Split(key, ".")
    83  	for i, part := range parts {
    84  		cursor, ok = cursor.(map[string]interface{})[part]
    85  		if !ok {
    86  			sofar := strings.Join(parts[:i], ".")
    87  			return nil, fmt.Errorf("%s key has no attributes", sofar)
    88  		}
    89  	}
    90  	return cursor, nil
    91  }
    92  
    93  // WriteConfigKey writes the value of a particular key
    94  func WriteConfigKey(filename, key string, value interface{}) error {
    95  	var cfg interface{}
    96  	if err := ReadConfigFile(filename, &cfg); err != nil {
    97  		return err
    98  	}
    99  
   100  	var ok bool
   101  	var mcursor map[string]interface{}
   102  	cursor := cfg
   103  
   104  	parts := strings.Split(key, ".")
   105  	for i, part := range parts {
   106  		mcursor, ok = cursor.(map[string]interface{})
   107  		if !ok {
   108  			sofar := strings.Join(parts[:i], ".")
   109  			return fmt.Errorf("%s key is not a map", sofar)
   110  		}
   111  
   112  		// last part? set here
   113  		if i == (len(parts) - 1) {
   114  			mcursor[part] = value
   115  			break
   116  		}
   117  
   118  		cursor, ok = mcursor[part]
   119  		if !ok { // create map if this is empty
   120  			mcursor[part] = map[string]interface{}{}
   121  			cursor = mcursor[part]
   122  		}
   123  	}
   124  
   125  	return WriteConfigFile(filename, cfg)
   126  }