mirror of
https://github.com/go-ini/ini.git
synced 2026-06-19 21:46:45 +02:00
Added support for unparseable sections. (#72)
* Added support for unparseable sections. * Add write support for unparseable sections. * Slightly changed test files to make test results clearer with tools/platforms that handle whitespace differently.
This commit is contained in:
@@ -164,6 +164,9 @@ type LoadOptions struct {
|
|||||||
// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
|
// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
|
||||||
// This type of keys are mostly used in my.cnf.
|
// This type of keys are mostly used in my.cnf.
|
||||||
AllowBooleanKeys bool
|
AllowBooleanKeys bool
|
||||||
|
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
|
||||||
|
// conform to key/value pairs. Specify the names of those blocks here.
|
||||||
|
UnparseableSections []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
||||||
@@ -233,6 +236,13 @@ func (f *File) NewSection(name string) (*Section, error) {
|
|||||||
return f.sections[name], nil
|
return f.sections[name], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRawSection creates a new section as an unparseable body.
|
||||||
|
func (f *File) NewRawSection(name string, body string) (*Section, error) {
|
||||||
|
section, err := f.NewSection(name)
|
||||||
|
section.rawBody = body
|
||||||
|
return section, err
|
||||||
|
}
|
||||||
|
|
||||||
// NewSections creates a list of sections.
|
// NewSections creates a list of sections.
|
||||||
func (f *File) NewSections(names ...string) (err error) {
|
func (f *File) NewSections(names ...string) (err error) {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
@@ -386,6 +396,13 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sec.rawBody != "" {
|
||||||
|
if _, err = buf.WriteString(sec.rawBody); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Count and generate alignment length and buffer spaces using the
|
// Count and generate alignment length and buffer spaces using the
|
||||||
// longest key. Keys may be modifed if they contain certain characters so
|
// longest key. Keys may be modifed if they contain certain characters so
|
||||||
// we need to take that into account in our calculation.
|
// we need to take that into account in our calculation.
|
||||||
|
|||||||
+26
@@ -357,6 +357,32 @@ NotFound, State, 50000"""
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_File_WriteTo_SectionRaw(t *testing.T) {
|
||||||
|
Convey("Write a INI with a raw section", t, func() {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
cfg, err := LoadSources(
|
||||||
|
LoadOptions{
|
||||||
|
UnparseableSections: []string{"CORE_LESSON", "COMMENTS"},
|
||||||
|
},
|
||||||
|
"testdata/aicc.ini")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(cfg, ShouldNotBeNil)
|
||||||
|
cfg.WriteToIndent(&buf, "\t")
|
||||||
|
So(buf.String(), ShouldEqual, `[Core]
|
||||||
|
Lesson_Location = 87
|
||||||
|
Lesson_Status = C
|
||||||
|
Score = 3
|
||||||
|
Time = 00:02:30
|
||||||
|
|
||||||
|
[CORE_LESSON]
|
||||||
|
my lesson state data – 1111111111111111111000000000000000001110000
|
||||||
|
111111111111111111100000000000111000000000 – end my lesson state data
|
||||||
|
[COMMENTS]
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Helpers for slice tests.
|
// Helpers for slice tests.
|
||||||
func float64sEqual(values []float64, expected ...float64) {
|
func float64sEqual(values []float64, expected ...float64) {
|
||||||
So(values, ShouldHaveLength, len(expected))
|
So(values, ShouldHaveLength, len(expected))
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
section, _ := f.NewSection(DEFAULT_SECTION)
|
section, _ := f.NewSection(DEFAULT_SECTION)
|
||||||
|
|
||||||
var line []byte
|
var line []byte
|
||||||
|
var inUnparseableSection bool
|
||||||
for !p.isEOF {
|
for !p.isEOF {
|
||||||
line, err = p.readUntil('\n')
|
line, err = p.readUntil('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -295,6 +296,22 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
// Reset aotu-counter and comments
|
// Reset aotu-counter and comments
|
||||||
p.comment.Reset()
|
p.comment.Reset()
|
||||||
p.count = 1
|
p.count = 1
|
||||||
|
|
||||||
|
inUnparseableSection = false
|
||||||
|
if len(f.options.UnparseableSections) > 0 {
|
||||||
|
for _, sectionName := range f.options.UnparseableSections {
|
||||||
|
if sectionName == name ||
|
||||||
|
(f.options.Insensitive && strings.ToLower(sectionName) == strings.ToLower(name)) {
|
||||||
|
inUnparseableSection = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if inUnparseableSection {
|
||||||
|
section.rawBody += string(line)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -28,10 +28,11 @@ type Section struct {
|
|||||||
keys map[string]*Key
|
keys map[string]*Key
|
||||||
keyList []string
|
keyList []string
|
||||||
keysHash map[string]string
|
keysHash map[string]string
|
||||||
|
rawBody string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSection(f *File, name string) *Section {
|
func newSection(f *File, name string) *Section {
|
||||||
return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)}
|
return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string), ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns name of Section.
|
// Name returns name of Section.
|
||||||
@@ -39,6 +40,12 @@ func (s *Section) Name() string {
|
|||||||
return s.name
|
return s.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Body returns rawBody of Section if the section was marked as unparseable.
|
||||||
|
// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
|
||||||
|
func (s *Section) Body() string {
|
||||||
|
return strings.TrimSpace(s.rawBody)
|
||||||
|
}
|
||||||
|
|
||||||
// NewKey creates a new key to given section.
|
// NewKey creates a new key to given section.
|
||||||
func (s *Section) NewKey(name, val string) (*Key, error) {
|
func (s *Section) NewKey(name, val string) (*Key, error) {
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
|
|||||||
@@ -45,3 +45,31 @@ func Test_Section(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_SectionRaw(t *testing.T) {
|
||||||
|
Convey("Test section raw string", t, func() {
|
||||||
|
cfg, err := LoadSources(
|
||||||
|
LoadOptions{
|
||||||
|
Insensitive: true,
|
||||||
|
UnparseableSections: []string{"core_lesson", "comments"},
|
||||||
|
},
|
||||||
|
"testdata/aicc.ini")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(cfg, ShouldNotBeNil)
|
||||||
|
|
||||||
|
Convey("Get section strings", func() {
|
||||||
|
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,core,core_lesson,comments")
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Validate non-raw section", func() {
|
||||||
|
val, err := cfg.Section("core").GetKey("lesson_status")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(val.String(), ShouldEqual, "C")
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Validate raw section", func() {
|
||||||
|
So(cfg.Section("core_lesson").Body(), ShouldEqual, `my lesson state data – 1111111111111111111000000000000000001110000
|
||||||
|
111111111111111111100000000000111000000000 – end my lesson state data`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
[Core]
|
||||||
|
Lesson_Location = 87
|
||||||
|
Lesson_Status = C
|
||||||
|
Score = 3
|
||||||
|
Time = 00:02:30
|
||||||
|
|
||||||
|
[CORE_LESSON]
|
||||||
|
my lesson state data – 1111111111111111111000000000000000001110000
|
||||||
|
111111111111111111100000000000111000000000 – end my lesson state data
|
||||||
|
[COMMENTS]
|
||||||
|
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||||
Reference in New Issue
Block a user