diff options
| author | Shulhan <ms@kilabit.info> | 2019-05-26 03:14:48 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2019-05-26 03:19:07 +0700 |
| commit | 9e0f6248bce30a6517c8d8cf3a08e3e7fa748c2a (patch) | |
| tree | 353bc97a70b7a7239e4a5ab7c8e5095e9a26c002 | |
| parent | c9ceaece557a117b0962710d1523d8dec35811d8 (diff) | |
| download | pakakeh.go-9e0f6248bce30a6517c8d8cf3a08e3e7fa748c2a.tar.xz | |
ini: replace multiple ifs conditions with switch statement
This is the third part of refactoring ini package. The change affect
on how variable value being fetched and formatted.
| -rw-r--r-- | lib/ini/linemode.go | 18 | ||||
| -rw-r--r-- | lib/ini/reader.go | 242 | ||||
| -rw-r--r-- | lib/ini/reader_test.go | 26 | ||||
| -rw-r--r-- | lib/ini/variable.go | 8 |
4 files changed, 152 insertions, 142 deletions
diff --git a/lib/ini/linemode.go b/lib/ini/linemode.go index 68887a19..cecc8b48 100644 --- a/lib/ini/linemode.go +++ b/lib/ini/linemode.go @@ -15,3 +15,21 @@ const ( lineModeValue lineMode = 16 lineModeMulti lineMode = 32 ) + +// +// isLineModeVar will return true if mode is variable, which is either +// lineModeSingle, lineModeValue, or lineModeMulti; otherwise it will return +// false. +// +func isLineModeVar(mode lineMode) bool { + if mode&lineModeSingle > 0 { + return true + } + if mode&lineModeValue > 0 { + return true + } + if mode&lineModeMulti > 0 { + return true + } + return false +} diff --git a/lib/ini/reader.go b/lib/ini/reader.go index 1b7af049..584b88a7 100644 --- a/lib/ini/reader.go +++ b/lib/ini/reader.go @@ -24,7 +24,6 @@ const ( tokHash = '#' tokHyphen = '-' tokNewLine = '\n' - tokPercent = '%' tokSecEnd = ']' tokSecStart = '[' tokSemiColon = ';' @@ -134,9 +133,7 @@ func (reader *reader) Parse(src []byte) (in *Ini, err error) { reader._var.lineNum = reader.lineNum - if reader._var.mode&lineModeSingle == lineModeSingle || - reader._var.mode&lineModeValue == lineModeValue || - reader._var.mode&lineModeMulti == lineModeMulti { + if isLineModeVar(reader._var.mode) { if reader.sec.mode == lineModeEmpty { err = fmt.Errorf(errVarNoSection, reader.lineNum, @@ -189,33 +186,36 @@ func (reader *reader) Parse(src []byte) (in *Ini, err error) { } func (reader *reader) parse() (err error) { + var isNewline bool + reader.bufFormat.Reset() - for { + for !isNewline { reader.b, err = reader.br.ReadByte() if err != nil { return err } - if reader.b == tokNewLine { + switch reader.b { + case tokNewLine: reader.bufFormat.WriteByte(reader.b) reader._var.format = reader.bufFormat.String() - break - } - if reader.b == tokSpace || reader.b == tokTab { + isNewline = true + + case tokSpace, tokTab: reader.bufFormat.WriteByte(reader.b) - continue - } - if reader.b == tokHash || reader.b == tokSemiColon { - _ = reader.br.UnreadByte() + case tokHash, tokSemiColon: + _ = reader.br.UnreadByte() return reader.parseComment() - } - if reader.b == tokSecStart { + + case tokSecStart: _ = reader.br.UnreadByte() return reader.parseSectionHeader() + + default: + _ = reader.br.UnreadByte() + return reader.parseVariable() } - _ = reader.br.UnreadByte() - return reader.parseVariable() } return nil @@ -270,30 +270,31 @@ func (reader *reader) parseSectionHeader() (err error) { return errBadConfig } + var isNewline bool reader.bufFormat.Write([]byte{'%', 's'}) reader.buf.WriteRune(reader.r) - for { + for !isNewline { reader.r, _, err = reader.br.ReadRune() if err != nil { return errBadConfig } - if reader.r == tokSpace || reader.r == tokTab { - break - } - if reader.r == tokSecEnd { - reader.bufFormat.WriteRune(reader.r) + switch { + case reader.r == tokSpace, reader.r == tokTab: + isNewline = true + case reader.r == tokSecEnd: + reader.bufFormat.WriteRune(reader.r) reader._var.secName = reader.buf.String() - return reader.parsePossibleComment() - } - if unicode.IsLetter(reader.r) || unicode.IsDigit(reader.r) || reader.r == tokHyphen || reader.r == tokDot { + + case unicode.IsLetter(reader.r), unicode.IsDigit(reader.r), + reader.r == tokHyphen, reader.r == tokDot: reader.buf.WriteRune(reader.r) - continue - } - return errBadConfig + default: + return errBadConfig + } } reader.bufFormat.WriteRune(reader.r) @@ -302,15 +303,12 @@ func (reader *reader) parseSectionHeader() (err error) { return reader.parseSubsection() } -// -// (0) Skip white-spaces -// func (reader *reader) parseSubsection() (err error) { reader.buf.Reset() reader._var.mode |= lineModeSubsection - // (0) + // Skip white-spaces for { reader.b, err = reader.br.ReadByte() if err != nil { @@ -371,25 +369,26 @@ func (reader *reader) parseSubsection() (err error) { // character. // func (reader *reader) parsePossibleComment() (err error) { - for { + var isNewline bool + + for !isNewline { reader.b, err = reader.br.ReadByte() if err != nil { break } - if reader.b == tokNewLine { + switch reader.b { + case tokNewLine: reader.bufFormat.WriteByte(reader.b) - break - } - if reader.b == tokSpace || reader.b == tokTab { + isNewline = true + case tokSpace, tokTab: reader.bufFormat.WriteByte(reader.b) - continue - } - if reader.b == tokHash || reader.b == tokSemiColon { + case tokHash, tokSemiColon: _ = reader.br.UnreadByte() - err = reader.parseComment() - return + return reader.parseComment() + + default: + return errBadConfig } - return errBadConfig } reader._var.format = reader.bufFormat.String() @@ -409,25 +408,34 @@ func (reader *reader) parseVariable() (err error) { return errVarNameInvalid } + var isNewline bool reader.bufFormat.Write([]byte{'%', 's'}) reader.buf.WriteRune(reader.r) - for { + for !isNewline { reader.r, _, err = reader.br.ReadRune() if err != nil { break } - if reader.r == tokNewLine { + switch { + case reader.r == tokEqual: reader.bufFormat.WriteRune(reader.r) - break - } - if unicode.IsLetter(reader.r) || unicode.IsDigit(reader.r) || - reader.r == tokHyphen || reader.r == tokDot || - reader.r == tokUnderscore { + + reader._var.mode = lineModeSingle + reader._var.key = reader.buf.String() + + return reader.parseVarValue() + + case reader.r == tokNewLine: + reader.bufFormat.WriteRune(reader.r) + isNewline = true + + case unicode.IsLetter(reader.r), unicode.IsDigit(reader.r), + reader.r == tokHyphen, reader.r == tokDot, + reader.r == tokUnderscore: reader.buf.WriteRune(reader.r) - continue - } - if reader.r == tokHash || reader.r == tokSemiColon { + + case reader.r == tokHash, reader.r == tokSemiColon: _ = reader.br.UnreadRune() reader._var.mode = lineModeSingle @@ -435,24 +443,18 @@ func (reader *reader) parseVariable() (err error) { reader._var.value = varValueTrue return reader.parseComment() - } - if unicode.IsSpace(reader.r) { + + case unicode.IsSpace(reader.r): reader.bufFormat.WriteRune(reader.r) reader._var.mode = lineModeSingle reader._var.key = reader.buf.String() return reader.parsePossibleValue() - } - if reader.r == tokEqual { - reader.bufFormat.WriteRune(reader.r) - reader._var.mode = lineModeSingle - reader._var.key = reader.buf.String() - - return reader.parseVarValue() + default: + return errVarNameInvalid } - return errVarNameInvalid } reader._var.mode = lineModeSingle @@ -468,29 +470,30 @@ func (reader *reader) parseVariable() (err error) { // or `=`. // func (reader *reader) parsePossibleValue() (err error) { - for { + var isNewline bool + for !isNewline { reader.b, err = reader.br.ReadByte() if err != nil { break } - if reader.b == tokNewLine { + switch reader.b { + case tokNewLine: reader.bufFormat.WriteByte(reader.b) - break - } - if reader.b == tokSpace || reader.b == tokTab { + isNewline = true + + case tokSpace, tokTab: reader.bufFormat.WriteByte(reader.b) - continue - } - if reader.b == tokHash || reader.b == tokSemiColon { + + case tokHash, tokSemiColon: _ = reader.br.UnreadByte() reader._var.value = varValueTrue return reader.parseComment() - } - if reader.b == tokEqual { + case tokEqual: reader.bufFormat.WriteByte(reader.b) return reader.parseVarValue() + default: + return errVarNameInvalid } - return errVarNameInvalid } reader._var.mode = lineModeSingle @@ -504,13 +507,12 @@ func (reader *reader) parsePossibleValue() (err error) { // At this point we found `=` on source, and we expect the rest of source will // be variable value. // -// (0) Consume leading white-spaces. -// func (reader *reader) parseVarValue() (err error) { reader.buf.Reset() reader.bufSpaces.Reset() - // (0) + // Consume leading white-spaces. +consume_spaces: for { reader.b, err = reader.br.ReadByte() if err != nil { @@ -518,16 +520,17 @@ func (reader *reader) parseVarValue() (err error) { reader._var.value = varValueTrue return err } - if reader.b == tokSpace || reader.b == tokTab { + switch reader.b { + case tokSpace, tokTab: reader.bufFormat.WriteByte(reader.b) - continue - } - if reader.b == tokHash || reader.b == tokSemiColon { + continue consume_spaces + + case tokHash, tokSemiColon: _ = reader.br.UnreadByte() reader._var.value = varValueTrue return reader.parseComment() - } - if reader.b == tokNewLine { + + case tokNewLine: reader.bufFormat.WriteByte(reader.b) reader._var.format = reader.bufFormat.String() reader._var.value = varValueTrue @@ -536,97 +539,91 @@ func (reader *reader) parseVarValue() (err error) { break } + reader.bufFormat.Write([]byte{'%', 's'}) reader._var.mode = lineModeValue _ = reader.br.UnreadByte() var ( - quoted bool - esc bool + quoted bool + esc bool + isNewline bool ) - for { + for !isNewline { reader.b, err = reader.br.ReadByte() if err != nil { break } if esc { - if reader.b == tokNewLine { + switch reader.b { + case tokNewLine: reader._var.mode = lineModeMulti - reader.valueCommit(true) - - reader.bufFormat.WriteByte(tokNewLine) - reader.lineNum++ esc = false continue - } - if reader.b == tokBackslash || reader.b == tokDoubleQuote { + + case tokBackslash, tokDoubleQuote: reader.valueWriteByte(reader.b) esc = false continue - } - if reader.b == 'b' { - reader.bufFormat.WriteByte(reader.b) + + case 'b': reader.buf.WriteByte(tokBackspace) esc = false continue - } - if reader.b == 'n' { - reader.bufFormat.WriteByte(reader.b) + + case 'n': reader.buf.WriteByte(tokNewLine) esc = false continue - } - if reader.b == 't' { - reader.bufFormat.WriteByte(reader.b) + case 't': reader.buf.WriteByte(tokTab) esc = false continue } return errValueInvalid } - if reader.b == tokSpace || reader.b == tokTab { + + switch reader.b { + case tokSpace, tokTab: if quoted { reader.valueWriteByte(reader.b) continue } - reader.bufFormat.WriteByte(reader.b) reader.bufSpaces.WriteByte(reader.b) - continue - } - if reader.b == tokBackslash { - reader.bufFormat.WriteByte(reader.b) + + case tokBackslash: esc = true - continue - } - if reader.b == tokDoubleQuote { - reader.bufFormat.WriteByte(reader.b) + + case tokDoubleQuote: if quoted { quoted = false } else { quoted = true } - continue - } - if reader.b == tokNewLine { + + case tokNewLine: reader.bufFormat.WriteByte(reader.b) - break - } - if reader.b == tokHash || reader.b == tokSemiColon { + isNewline = true + + case tokHash, tokSemiColon: if quoted { reader.valueWriteByte(reader.b) continue } + reader.bufFormat.Write(reader.bufSpaces.Bytes()) reader.valueCommit(false) _ = reader.br.UnreadByte() return reader.parseComment() + + default: + reader.valueWriteByte(reader.b) } - reader.valueWriteByte(reader.b) } if quoted { @@ -659,10 +656,5 @@ func (reader *reader) valueWriteByte(b byte) { reader.bufSpaces.Reset() } - if b == tokPercent { - reader.bufFormat.Write([]byte{'%', '%'}) - } else { - reader.bufFormat.WriteByte(b) - } reader.buf.WriteByte(b) } diff --git a/lib/ini/reader_test.go b/lib/ini/reader_test.go index 43dc5c21..198a2d49 100644 --- a/lib/ini/reader_test.go +++ b/lib/ini/reader_test.go @@ -391,7 +391,7 @@ func TestParseVarValue(t *testing.T) { desc: `Double quoted with spaces`, in: []byte(`" "`), expErr: io.EOF, - expFormat: `" "`, + expFormat: `%s`, expValue: " ", }, { desc: `Double quote at start only`, @@ -405,78 +405,78 @@ func TestParseVarValue(t *testing.T) { desc: `Double quoted at start only`, in: []byte(`"\\" value`), expErr: io.EOF, - expFormat: `"\\" value`, + expFormat: `%s`, expValue: `\ value`, }, { desc: `Double quoted at end only`, in: []byte(`value "\""`), expErr: io.EOF, - expFormat: `value "\""`, + expFormat: `%s`, expValue: `value "`, }, { desc: `Double quoted at start and end`, in: []byte(`"\\" value "\""`), expErr: io.EOF, - expFormat: `"\\" value "\""`, + expFormat: `%s`, expValue: `\ value "`, }, { desc: `With comment #`, in: []byte(`value # comment`), expErr: io.EOF, - expFormat: `value %s`, + expFormat: `%s %s`, expValue: "value", expComment: "# comment", }, { desc: `With comment ;`, in: []byte(`value ; comment`), expErr: io.EOF, - expFormat: "value %s", + expFormat: "%s %s", expValue: "value", expComment: "; comment", }, { desc: `With comment # inside double-quote`, in: []byte(`"value # comment"`), expErr: io.EOF, - expFormat: `"value # comment"`, + expFormat: `%s`, expValue: `value # comment`, }, { desc: `With comment ; inside double-quote`, in: []byte(`"value ; comment"`), expErr: io.EOF, - expFormat: `"value ; comment"`, + expFormat: `%s`, expValue: `value ; comment`, }, { desc: `Double quote and comment #1`, in: []byte(`val" "#ue`), expErr: io.EOF, - expFormat: `val" "%s`, + expFormat: `%s%s`, expValue: `val `, expComment: `#ue`, }, { desc: `Double quote and comment #2`, in: []byte(`val" " #ue`), expErr: io.EOF, - expFormat: `val" " %s`, + expFormat: `%s %s`, expValue: `val `, expComment: `#ue`, }, { desc: `Double quote and comment #3`, in: []byte(`val " " #ue`), expErr: io.EOF, - expFormat: `val " " %s`, + expFormat: `%s %s`, expValue: `val `, expComment: `#ue`, }, { desc: `Escaped chars #1`, in: []byte(`value \"escaped\" here`), expErr: io.EOF, - expFormat: `value \"escaped\" here`, + expFormat: `%s`, expValue: `value "escaped" here`, }, { desc: `Escaped chars #2`, in: []byte(`"value\b\n\t\"escaped\" here"`), expErr: io.EOF, - expFormat: `"value\b\n\t\"escaped\" here"`, + expFormat: `%s`, expValue: "value\b\n\t\"escaped\" here", }, { desc: `Invalid escaped chars`, diff --git a/lib/ini/variable.go b/lib/ini/variable.go index ab85f992..4d49da64 100644 --- a/lib/ini/variable.go +++ b/lib/ini/variable.go @@ -64,25 +64,25 @@ func (v *variable) String() string { } case lineModeValue: if len(v.format) > 0 { - _, _ = fmt.Fprintf(&buf, v.format, v.key) + _, _ = fmt.Fprintf(&buf, v.format, v.key, v.value) } else { _, _ = fmt.Fprintf(&buf, "%s = %s\n", v.key, v.value) } case lineModeValue | lineModeComment: if len(v.format) > 0 { - _, _ = fmt.Fprintf(&buf, v.format, v.key, v.others) + _, _ = fmt.Fprintf(&buf, v.format, v.key, v.value, v.others) } else { _, _ = fmt.Fprintf(&buf, "%s = %s %s\n", v.key, v.value, v.others) } case lineModeMulti: if len(v.format) > 0 { - _, _ = fmt.Fprintf(&buf, v.format, v.key) + _, _ = fmt.Fprintf(&buf, v.format, v.key, v.value) } else { _, _ = fmt.Fprintf(&buf, "%s = %s\n", v.key, v.value) } case lineModeMulti | lineModeComment: if len(v.format) > 0 { - _, _ = fmt.Fprintf(&buf, v.format, v.key, v.others) + _, _ = fmt.Fprintf(&buf, v.format, v.key, v.value, v.others) } else { _, _ = fmt.Fprintf(&buf, "%s = %s %s\n", v.key, v.value, v.others) } |
