func (f *File) getSection(name string) (*Section, int) {
	n := f.SectionManipFunc(name)
	if f.sectionNameComp(n, "") {
		return f.sections[0], 0
	}
	for idx, line := range f.lines {
		if s, ok := line.item.(*Section); ok && f.sectionNameComp(n, s.name) {
			return s, idx
		}
	}
	return nil, -1
}
getSection Get a section and its starting line number.
package parser
import (
	"bytes"
	"fmt"
	"os"
)
type File struct {
	lines []*Line
	sections []*Section
	SectionManipFunc func(string) string
	SectionNameFunc func(string) string
	SectionCompFunc func(string, string) bool
	KeyManipFunc func(string) string
	KeyCompFunc func(string, string) bool
	ValueManipFunc func(string) string
	NameSplitFunc func(string) (string, string)
}
func NewFile(lines []*Line) *File {
	ret := &File{
		lines:    lines,
		sections: make([]*Section, 0),
		SectionManipFunc: SectionManipFunc,
		SectionNameFunc:  SectionNameFunc,
		SectionCompFunc:  nil,
		KeyManipFunc:     KeyManipFunc,
		KeyCompFunc:      KeyCompFunc,
		ValueManipFunc:   ValueManipFunc,
		NameSplitFunc:    NameSplitFunc,
	}
	lastSection := NewSection(position{}, "", "", nil)
	lastSection.file = ret
	ret.sections = append(ret.sections, lastSection)
	for _, l := range lines {
		switch l.item.(type) {
		case *Section:
			lastSection, _ = l.item.(*Section)
			lastSection.file = ret
			ret.sections = append(ret.sections, lastSection)
		case *KeyValuePair:
			kvp, _ := l.item.(*KeyValuePair)
			lastSection.keys = append(lastSection.keys, kvp.key)
		}
	}
	return ret
}
func (f File) String() string {
	var buf bytes.Buffer
	for _, l := range f.lines {
		buf.WriteString(l.String())
	}
	return buf.String()
}
func (f *File) Write(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = file.WriteString(f.String())
	return err
}
func (f *File) LineCount() int {
	return len(f.lines)
}
func (f *File) RawSectionNames() []string {
	names := make([]string, len(f.sections))
	for i, s := range f.sections {
		names[i] = s.RawName()
	}
	return names
}
func (f *File) SectionNames() []string {
	names := make([]string, len(f.sections))
	for i, s := range f.sections {
		names[i] = s.Name()
	}
	return names
}
func (f *File) AddSectionRaw(name string) *Section {
	if f.sectionNameComp(name, "") {
		return f.GetSection("")
	}
	s := NewSection(position{}, name, "", nil)
	s.file = f
	f.sections = append(f.sections, s)
	if len(f.lines) > 0 && f.lines[len(f.lines)-1].item == nil {
		f.lines[len(f.lines)-1].item = s
	} else {
		le := DefaultLineEnding
		if len(f.lines) > 0 {
			le = f.lines[0].le
		}
		l := NewLine(position{}, "", s, le)
		f.lines = append(f.lines, l)
	}
	return s
}
func (f *File) AddSection(name string) *Section {
	return f.AddSectionRaw(f.SectionManipFunc(name))
}
func (f *File) sectionNameComp(a, b string) bool {
	if f.SectionCompFunc != nil {
		return f.SectionCompFunc(a, b)
	}
	return f.SectionNameFunc(a) == f.SectionNameFunc(b)
}