diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/ezconf.iml b/.idea/ezconf.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/ezconf.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..72fda76
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..afaf152
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,7 @@
+module ezconf
+
+go 1.20
+
+require gopkg.in/ini.v1 v1.67.0
+
+require github.com/stretchr/testify v1.8.2 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..5c407e4
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,18 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/ini.go b/ini.go
new file mode 100644
index 0000000..73b036b
--- /dev/null
+++ b/ini.go
@@ -0,0 +1,161 @@
+package ezconf
+
+import (
+ "errors"
+ "fmt"
+ "gopkg.in/ini.v1"
+ "os"
+ "strings"
+)
+
+type Configuration struct {
+ fileLocation string
+ file *ini.File
+}
+
+func NewConfiguration(fileLocation string) *Configuration {
+ conf := new(Configuration)
+ conf.fileLocation = fileLocation
+ conf.load()
+ return conf
+}
+
+func (config *Configuration) getSection(sectionName string) *ini.Section {
+ section, err := config.file.GetSection(sectionName)
+ if err != nil {
+ fmt.Printf("Error getting section %v in config: %v", sectionName, err)
+ os.Exit(1)
+ }
+ return section
+}
+
+func getChildSection(section *ini.Section, childSectionName string) (childSection *ini.Section, err error) {
+ childSections := section.ChildSections()
+ for _, childSection := range childSections {
+ if childSection.Name() == childSectionName {
+ return childSection, nil
+ }
+ }
+ return nil, errors.New("subsection " + childSectionName + " not found")
+}
+
+func (config *Configuration) GetKey(path string) *ini.Key {
+ splitPaths := strings.Split(path, ".")
+ if len(splitPaths) == 1 {
+ splitPaths = append([]string{"."}, splitPaths...)
+ }
+ section := config.getSection(splitPaths[0])
+ var key *ini.Key
+ var err error
+ if len(splitPaths) > 2 {
+ tempSection := section
+ for i := 0; i < len(splitPaths)-1; i++ {
+ tempSection, err = getChildSection(tempSection, splitPaths[i])
+ if err != nil {
+ fmt.Printf("Error getting child section %v: %v", splitPaths[i], err)
+ os.Exit(1)
+ }
+ if len(splitPaths) == i+1 {
+ key, err = tempSection.GetKey(splitPaths[i+1])
+ if err != nil {
+ fmt.Printf("Error getting key %v: %v", splitPaths[i+1], err)
+ }
+ }
+ }
+ } else {
+ key, err = section.GetKey(splitPaths[1])
+ if err != nil {
+ fmt.Printf("Error getting key %v: %v", splitPaths[1], err)
+ }
+ }
+ return key
+}
+
+func (config *Configuration) GetString(path string) string {
+ return config.GetKey(path).String()
+}
+
+func (config *Configuration) GetStrings(path string) []string {
+ return config.GetKey(path).Strings(",")
+}
+
+func (config *Configuration) GetInt(path string) int {
+ var i int
+ var err error
+ i, err = config.GetKey(path).Int()
+ if err != nil {
+ fmt.Printf("Error parsing integer: %v", err)
+ os.Exit(1)
+ }
+ return i
+}
+
+func (config *Configuration) GetInts(path string) []int {
+ return config.GetKey(path).Ints(",")
+}
+
+func (config *Configuration) GetUInt(path string) uint {
+ var i uint
+ var err error
+ i, err = config.GetKey(path).Uint()
+ if err != nil {
+ fmt.Printf("Error parsing integer: %v", err)
+ os.Exit(1)
+ }
+ return i
+}
+
+func (config *Configuration) GetUInts(path string) []uint {
+ return config.GetKey(path).Uints(",")
+}
+
+func (config *Configuration) GetFloat(path string) float64 {
+ var f float64
+ var err error
+ f, err = config.GetKey(path).Float64()
+ if err != nil {
+ fmt.Printf("Error parsing float: %v", err)
+ os.Exit(1)
+ }
+ return f
+}
+
+func (config *Configuration) GetFloats(path string) []float64 {
+ return config.GetKey(path).Float64s(",")
+}
+
+func (config *Configuration) GetBoolean(path string) bool {
+ var b bool
+ var err error
+ b, err = config.GetKey(path).Bool()
+ if err != nil {
+ fmt.Printf("Error parsingn bool: %v", err)
+ os.Exit(1)
+ }
+ return b
+}
+
+func (config *Configuration) GetBooleans(path string) []bool {
+ return config.GetKey(path).Bools(",")
+}
+
+func (config *Configuration) load() {
+ var err error = nil
+ config.file, err = ini.Load(config.fileLocation)
+ if err != nil {
+ fmt.Printf("Failed to open configuration file: %v", err)
+ os.Exit(1)
+ }
+}
+
+func (config *Configuration) Reload() {
+ config.load()
+}
+
+func (config *Configuration) Save() {
+ err := config.file.SaveTo(config.fileLocation)
+ if err != nil {
+ fmt.Printf("Failed to save configuration file: %v", err)
+ os.Exit(1)
+ }
+}