gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

codec.go (1978B)


      1 package ini
      2 
      3 import (
      4 	"bytes"
      5 	"sort"
      6 	"strings"
      7 
      8 	"github.com/spf13/cast"
      9 	"gopkg.in/ini.v1"
     10 )
     11 
     12 // LoadOptions contains all customized options used for load data source(s).
     13 // This type is added here for convenience: this way consumers can import a single package called "ini".
     14 type LoadOptions = ini.LoadOptions
     15 
     16 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding.
     17 type Codec struct {
     18 	KeyDelimiter string
     19 	LoadOptions  LoadOptions
     20 }
     21 
     22 func (c Codec) Encode(v map[string]interface{}) ([]byte, error) {
     23 	cfg := ini.Empty()
     24 	ini.PrettyFormat = false
     25 
     26 	flattened := map[string]interface{}{}
     27 
     28 	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
     29 
     30 	keys := make([]string, 0, len(flattened))
     31 
     32 	for key := range flattened {
     33 		keys = append(keys, key)
     34 	}
     35 
     36 	sort.Strings(keys)
     37 
     38 	for _, key := range keys {
     39 		sectionName, keyName := "", key
     40 
     41 		lastSep := strings.LastIndex(key, ".")
     42 		if lastSep != -1 {
     43 			sectionName = key[:(lastSep)]
     44 			keyName = key[(lastSep + 1):]
     45 		}
     46 
     47 		// TODO: is this a good idea?
     48 		if sectionName == "default" {
     49 			sectionName = ""
     50 		}
     51 
     52 		cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
     53 	}
     54 
     55 	var buf bytes.Buffer
     56 
     57 	_, err := cfg.WriteTo(&buf)
     58 	if err != nil {
     59 		return nil, err
     60 	}
     61 
     62 	return buf.Bytes(), nil
     63 }
     64 
     65 func (c Codec) Decode(b []byte, v map[string]interface{}) error {
     66 	cfg := ini.Empty(c.LoadOptions)
     67 
     68 	err := cfg.Append(b)
     69 	if err != nil {
     70 		return err
     71 	}
     72 
     73 	sections := cfg.Sections()
     74 
     75 	for i := 0; i < len(sections); i++ {
     76 		section := sections[i]
     77 		keys := section.Keys()
     78 
     79 		for j := 0; j < len(keys); j++ {
     80 			key := keys[j]
     81 			value := cfg.Section(section.Name()).Key(key.Name()).String()
     82 
     83 			deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
     84 
     85 			// set innermost value
     86 			deepestMap[key.Name()] = value
     87 		}
     88 	}
     89 
     90 	return nil
     91 }
     92 
     93 func (c Codec) keyDelimiter() string {
     94 	if c.KeyDelimiter == "" {
     95 		return "."
     96 	}
     97 
     98 	return c.KeyDelimiter
     99 }