From e82bb45331a0fe1da4fb3a042e031ca62a330ae5 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Tue, 14 Nov 2017 18:30:23 +0100 Subject: [PATCH 1/3] Change internal structure in Property object --- parser.go | 10 ++++++---- properties.go | 35 +++++++++++++++++++++++++++-------- store.go | 1 - 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/parser.go b/parser.go index 92fe5f2..6f7508b 100644 --- a/parser.go +++ b/parser.go @@ -9,10 +9,10 @@ import ( ) // ParseFunction -- type -type ParseFunction func(string, string) (map[string]string, error) +type ParseFunction func(string, string) (map[int]Pair, error) // Default parse method for parsing key - value file -func defaultParse(path, fileName string) (m map[string]string, err error) { +func defaultParse(path, fileName string) (m map[int]Pair, err error) { absolutePathFile, err := filepath.Abs(filepath.Join(path, fileName)) if err != nil { return nil, err @@ -23,8 +23,9 @@ func defaultParse(path, fileName string) (m map[string]string, err error) { } defer file.Close() - m = make(map[string]string) + m = make(map[int]Pair) reader := bufio.NewReader(file) + index := 0 for { line, err := reader.ReadString('\n') @@ -37,7 +38,7 @@ func defaultParse(path, fileName string) (m map[string]string, err error) { value = strings.TrimSpace(strings.Replace(line[equal+1:], "\"", "", -1)) } // assign the values map - m[key] = value + m[index] = Pair{key, value} } } if err == io.EOF { @@ -46,6 +47,7 @@ func defaultParse(path, fileName string) (m map[string]string, err error) { if err != nil { return nil, err } + index++ } return m, nil } diff --git a/properties.go b/properties.go index e875cfb..0d7e163 100644 --- a/properties.go +++ b/properties.go @@ -7,11 +7,16 @@ import ( "strings" ) +type Pair struct { + First string + Second string +} + // Properties -- type type Properties struct { fileName string path string - values map[string]string + values map[int]Pair length int } @@ -20,7 +25,7 @@ func New(path, fileName string) Properties { return Properties{ fileName: fileName, path: filepath.Clean(path), - values: make(map[string]string), + values: make(map[int]Pair), length: 0, } } @@ -51,7 +56,7 @@ func (p Properties) Length() int { } // Values -- Getter values of property file -func (p Properties) Values() map[string]string { +func (p Properties) Values() map[int]Pair { return p.values } @@ -61,7 +66,7 @@ func (p *Properties) Put(key, value string) error { return e.New("Key value is nil") } if p.values != nil { - p.values[key] = value + p.values[p.length+1] = Pair{key, value} p.length++ } else { return e.New("Property values is nil") @@ -74,10 +79,11 @@ func (p Properties) Get(key string) (string, error) { if key == "" || len(strings.TrimSpace(key)) == 0 { return "", e.New("Key value is nil") } - if _, ok := p.values[key]; !ok { + index := p.index(key) + if _, ok := p.values[index]; !ok { return "", e.New("Key not found") } - return p.values[key], nil + return p.values[index].Second, nil } // Remove -- Remove property with key @@ -86,7 +92,8 @@ func (p *Properties) Remove(key string) (string, error) { return "", e.New("Key value is nil") } lenghtBefore := len(p.values) - delete(p.values, key) + index := p.index(key) + delete(p.values, index) if len(p.values) != lenghtBefore { p.length-- } @@ -95,12 +102,24 @@ func (p *Properties) Remove(key string) (string, error) { // GetProperties -- Get all key value in Properties object func (p Properties) GetProperties() (keys []string) { - for key := range p.values { + for i := range p.values { + key := p.values[i].First keys = append(keys, key) } return keys } +func (p Properties) index(key string) int { + index := -1 + for i, item := range p.values { + if item.First == key { + index = i + break + } + } + return index +} + // DefaultLoad -- Load file in Properties object using default parse function func (p *Properties) DefaultLoad() (int, error) { return p.Load(defaultParse) diff --git a/store.go b/store.go index 6c59ff2..1267799 100644 --- a/store.go +++ b/store.go @@ -10,7 +10,6 @@ import ( // StoringFunction -- type type StoringFunction func(Properties) (*os.File, error) -// FIXME when you remove a property it not work fine func defaultStore(p Properties) (*os.File, error) { absolutePathFile, err := filepath.Abs(filepath.Join(p.Path(), p.FileName())) if err != nil { From 1023d728799f9103a300b4870bb5d932dc2dfb51 Mon Sep 17 00:00:00 2001 From: fscotto Date: Tue, 14 Nov 2017 19:58:08 +0100 Subject: [PATCH 2/3] Modify .gitignore file --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ef15dee..275891b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ *.out # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ \ No newline at end of file +.glide/ +.vscode/ From 8ef3bd164344173c2a2be96da4a7eeb2da8f2cb7 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Sun, 26 Nov 2017 14:49:46 +0100 Subject: [PATCH 3/3] Fix store function --- .gitignore | 1 + store.go | 79 ++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 275891b..21a037a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ .vscode/ +.idea/ \ No newline at end of file diff --git a/store.go b/store.go index 1267799..ee3268f 100644 --- a/store.go +++ b/store.go @@ -1,10 +1,13 @@ package properties import ( - "errors" + "bufio" + "bytes" + "fmt" + "log" "os" "path/filepath" - "strings" + "unicode" ) // StoringFunction -- type @@ -15,39 +18,69 @@ func defaultStore(p Properties) (*os.File, error) { if err != nil { return nil, err } - file, err := os.OpenFile(absolutePathFile, os.O_CREATE, 0644) + file, err := os.OpenFile(absolutePathFile, os.O_CREATE|os.O_RDWR, 0644) if err != nil { return nil, err } // Write this file defer file.Close() - for _, key := range p.GetProperties() { - value, err := p.Get(key) - if err != nil { - return nil, err - } - - row, err := buildRow(key, value) - if err != nil { - return nil, err - } - - if _, err := file.Write([]byte(row + "\n")); err != nil { + writer := bufio.NewWriter(file) + for _, pair := range p.values { + line := fmt.Sprintf("%s=%s\n", escape(pair.First, true), escape(pair.Second, false)) + log.Print(line) + if _, err := writer.Write([]byte(line)); err != nil { return nil, err } } + if err := writer.Flush(); err != nil { + return nil, err + } return file, nil } -func buildRow(key, value string) (row string, err error) { - if key == "" || value == "" { - return "", errors.New("Key or Value param is a empty string") - } +// escape returns a string that is safe to use as either a key or value in a +// property file. Whitespace characters, key separators, and comment markers +// should always be escaped. +func escape(s string, key bool) string { - newKey := strings.Replace(key, "\"", "", -1) - newValue := strings.Join([]string{"\"", value, "\""}, "") - row = strings.Join([]string{newKey, newValue}, "=") - return strings.TrimSpace(row), nil + leading := true + var buf bytes.Buffer + for _, ch := range s { + wasSpace := false + if ch == '\t' { + buf.WriteString(`\t`) + } else if ch == '\n' { + buf.WriteString(`\n`) + } else if ch == '\r' { + buf.WriteString(`\r`) + } else if ch == '\f' { + buf.WriteString(`\f`) + } else if ch == ' ' { + if key || leading { + buf.WriteString(`\ `) + wasSpace = true + } else { + buf.WriteRune(ch) + } + } else if ch == ':' { + buf.WriteString(`\:`) + } else if ch == '=' { + buf.WriteString(`\=`) + } else if ch == '#' { + buf.WriteString(`\#`) + } else if ch == '!' { + buf.WriteString(`\!`) + } else if !unicode.IsPrint(ch) || ch > 126 { + buf.WriteString(fmt.Sprintf(`\u%04x`, ch)) + } else { + buf.WriteRune(ch) + } + + if !wasSpace { + leading = false + } + } + return buf.String() }