initial work on auto generated definitions
This commit is contained in:
parent
27d793492c
commit
eef48c1d0a
113
envconf.go
113
envconf.go
@ -20,18 +20,18 @@ type cEntry struct {
|
||||
hasdef bool // Default value is defined
|
||||
}
|
||||
|
||||
type keyLookupStruct struct {
|
||||
type keyLookupType struct {
|
||||
key string
|
||||
end bool
|
||||
next map[string]*keyLookupStruct
|
||||
next map[string]*keyLookupType
|
||||
}
|
||||
|
||||
func (kl *keyLookupStruct) setKey(parts []string, key string) {
|
||||
func (kl *keyLookupType) setKey(parts []string, key string) {
|
||||
if len(kl.next) == 0 {
|
||||
kl.next = make(map[string]*keyLookupStruct)
|
||||
kl.next = make(map[string]*keyLookupType)
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
nextLookup := new(keyLookupStruct)
|
||||
nextLookup := new(keyLookupType)
|
||||
nextLookup.setKey(parts[1:], key)
|
||||
kl.next[parts[0]] = nextLookup
|
||||
} else {
|
||||
@ -40,7 +40,7 @@ func (kl *keyLookupStruct) setKey(parts []string, key string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (kl *keyLookupStruct) print() {
|
||||
func (kl *keyLookupType) print() {
|
||||
if kl.end {
|
||||
fmt.Println(kl.key)
|
||||
fmt.Println("-----------------")
|
||||
@ -52,28 +52,23 @@ func (kl *keyLookupStruct) print() {
|
||||
}
|
||||
}
|
||||
|
||||
type mapEnvType [5]*keyLookupType
|
||||
|
||||
type Config struct {
|
||||
parsed bool
|
||||
env map[string]cEntry
|
||||
mapEnvTest map[int]*keyLookupStruct
|
||||
mapEnv map[string]map[string]string
|
||||
mapMapEnv map[string]map[string]map[string]string
|
||||
mapMapMapEnv map[string]map[string]map[string]map[string]string
|
||||
mapMapMapMapEnv map[string]map[string]map[string]map[string]map[string]string
|
||||
mapMapMapMapMapEnv map[string]map[string]map[string]map[string]map[string]map[string]string
|
||||
parsed bool
|
||||
env map[string]cEntry
|
||||
mapEnv mapEnvType
|
||||
}
|
||||
|
||||
// NewConfig returns an envconf.Config that is used to read configuration from environment variables.
|
||||
// The environment variables are stored in envconf.Config, so changes to the environment after NewConfig has been called
|
||||
// will not be taken into account.
|
||||
func NewConfig() *Config {
|
||||
levels := 5
|
||||
config := new(Config)
|
||||
config.parsed = false
|
||||
config.env = make(map[string]cEntry)
|
||||
config.mapEnvTest = make(map[int]*keyLookupStruct)
|
||||
for level := 1; level <= levels; level++ {
|
||||
config.mapEnvTest[level] = new(keyLookupStruct)
|
||||
for level, _ := range config.mapEnv {
|
||||
config.mapEnv[level] = new(keyLookupType)
|
||||
}
|
||||
|
||||
for _, v := range os.Environ() {
|
||||
@ -81,7 +76,7 @@ func NewConfig() *Config {
|
||||
if len(splitted) == 2 {
|
||||
key := cleanKey(splitted[0])
|
||||
val := splitted[1]
|
||||
splitted = append(strings.Split(key, "_"), make([]string, levels, levels)...)
|
||||
splitted = append(strings.Split(key, "_"), make([]string, len(config.mapEnv), len(config.mapEnv))...)
|
||||
if unicode.IsLetter(getFirstRune(key)) {
|
||||
var entry cEntry
|
||||
entry.value = val
|
||||
@ -90,7 +85,7 @@ func NewConfig() *Config {
|
||||
entry.empty = false
|
||||
config.env[key] = entry
|
||||
if len(splitted) > 1 {
|
||||
for level := 1; level <= levels; level++ {
|
||||
for level := 1; level <= len(config.mapEnv); level++ {
|
||||
for count := 0; count < level; count++ {
|
||||
parts := make([]string, level, level)
|
||||
parts[0] = strings.Trim(strings.Join(splitted[:count+1], "_"), "_")
|
||||
@ -106,69 +101,11 @@ func NewConfig() *Config {
|
||||
if parts[len(parts)-1] == "" {
|
||||
break
|
||||
}
|
||||
config.mapEnvTest[level].setKey(parts, key)
|
||||
config.mapEnv[level].setKey(parts, key)
|
||||
}
|
||||
config.mapEnvTest[level].print()
|
||||
/*
|
||||
var p0, p1, p2, p3, p4, p5 string
|
||||
p0 = strings.Trim(strings.Join(splitted[:count], "_"), "_")
|
||||
p1 = strings.Trim(strings.Join(splitted[count:], "_"), "_")
|
||||
if len(config.mapEnv[p0]) == 0 {
|
||||
config.mapEnv[p0] = make(map[string]string)
|
||||
config.mapMapEnv[p0] = make(map[string]map[string]string)
|
||||
config.mapMapMapEnv[p0] = make(map[string]map[string]map[string]string)
|
||||
config.mapMapMapMapEnv[p0] = make(map[string]map[string]map[string]map[string]string)
|
||||
config.mapMapMapMapMapEnv[p0] = make(map[string]map[string]map[string]map[string]map[string]string)
|
||||
}
|
||||
if p0 != "" && p1 != "" {
|
||||
config.mapEnv[p0][p1] = key
|
||||
}
|
||||
|
||||
p1 = splitted[count]
|
||||
p2 = strings.Trim(strings.Join(splitted[count+1:], "_"), "_")
|
||||
if len(config.mapMapEnv[p0][p1]) == 0 {
|
||||
config.mapMapEnv[p0][p1] = make(map[string]string)
|
||||
config.mapMapMapEnv[p0][p1] = make(map[string]map[string]string)
|
||||
config.mapMapMapMapEnv[p0][p1] = make(map[string]map[string]map[string]string)
|
||||
config.mapMapMapMapMapEnv[p0][p1] = make(map[string]map[string]map[string]map[string]string)
|
||||
}
|
||||
if p0 != "" && p1 != "" && p2 != "" {
|
||||
config.mapMapEnv[p0][p1][p2] = key
|
||||
}
|
||||
|
||||
p2 = splitted[count+1]
|
||||
p3 = strings.Trim(strings.Join(splitted[count+2:], "_"), "_")
|
||||
if len(config.mapMapMapEnv[p0][p1][p2]) == 0 {
|
||||
config.mapMapMapEnv[p0][p1][p2] = make(map[string]string)
|
||||
config.mapMapMapMapEnv[p0][p1][p2] = make(map[string]map[string]string)
|
||||
config.mapMapMapMapMapEnv[p0][p1][p2] = make(map[string]map[string]map[string]string)
|
||||
}
|
||||
if p0 != "" && p1 != "" && p2 != "" && p3 != "" {
|
||||
config.mapMapMapEnv[p0][p1][p2][p3] = key
|
||||
}
|
||||
|
||||
p3 = splitted[count+2]
|
||||
p4 = strings.Trim(strings.Join(splitted[count+3:], "_"), "_")
|
||||
if len(config.mapMapMapMapEnv[p0][p1][p2][p3]) == 0 {
|
||||
config.mapMapMapMapEnv[p0][p1][p2][p3] = make(map[string]string)
|
||||
config.mapMapMapMapMapEnv[p0][p1][p2][p3] = make(map[string]map[string]string)
|
||||
}
|
||||
if p0 != "" && p1 != "" && p2 != "" && p3 != "" && p4 != "" {
|
||||
config.mapMapMapMapEnv[p0][p1][p2][p3][p4] = key
|
||||
}
|
||||
|
||||
p4 = splitted[count+3]
|
||||
p5 = strings.Trim(strings.Join(splitted[count+4:], "_"), "_")
|
||||
if len(config.mapMapMapMapMapEnv[p0][p1][p2][p3][p4]) == 0 {
|
||||
config.mapMapMapMapMapEnv[p0][p1][p2][p3][p4] = make(map[string]string)
|
||||
}
|
||||
if p0 != "" && p1 != "" && p2 != "" && p3 != "" && p4 != "" && p5 != "" {
|
||||
config.mapMapMapMapMapEnv[p0][p1][p2][p3][p4][p5] = key
|
||||
}
|
||||
*/
|
||||
config.mapEnv[level].print()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -196,12 +133,12 @@ func (c *Config) Define(key string, dtype DataType) {
|
||||
// Variables without a defined type will be ignored by Parse.
|
||||
func (c *Config) DefineMap(key string, dtype DataType) {
|
||||
key = cleanKey(key)
|
||||
entries, ok := c.mapEnv[key]
|
||||
entries, ok := c.mapEnv[0].next[key]
|
||||
if ok {
|
||||
for _, key = range entries {
|
||||
entry := c.env[key]
|
||||
entry.dtype = dtype
|
||||
c.env[key] = entry
|
||||
for _, entry := range entries.next {
|
||||
defEntry := c.env[entry.key]
|
||||
defEntry.dtype = dtype
|
||||
c.env[entry.key] = defEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,11 +334,11 @@ func (c *Config) getRawMap(key string, dtype DataType) (empty map[string]cValue)
|
||||
retval := make(map[string]cValue)
|
||||
if c.parsed {
|
||||
key = cleanKey(key)
|
||||
entries, ok := c.mapEnv[key]
|
||||
entries, ok := c.mapEnv[0].next[key]
|
||||
|
||||
if ok {
|
||||
for k, v := range entries {
|
||||
entry := c.env[v]
|
||||
for k, v := range entries.next {
|
||||
entry := c.env[v.key]
|
||||
if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) {
|
||||
retval[k] = entry.parsed
|
||||
} else {
|
||||
|
106
generate.py
Normal file
106
generate.py
Normal file
@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
import typing
|
||||
|
||||
|
||||
def get_return_type(levels: int, dtype: str) -> str:
|
||||
return ("map[string]" * levels) + dtype
|
||||
|
||||
|
||||
def get_signature(levels: int, sig_dtype: str, dtype: str) -> str:
|
||||
return (
|
||||
"func (c *Config) get"
|
||||
+ ("Map" * levels)
|
||||
+ sig_dtype
|
||||
+ "(key string) (empty "
|
||||
+ get_return_type(levels, dtype)
|
||||
+ ") {"
|
||||
)
|
||||
|
||||
|
||||
def get_empty_def(levels: int, dtype: str) -> str:
|
||||
return "empty = make(" + get_return_type(levels, dtype) + ")"
|
||||
|
||||
|
||||
def get_nested_keys(levels: int) -> str:
|
||||
txt = ""
|
||||
for count in range(levels):
|
||||
txt += "[k" + str(count + 10) + "]"
|
||||
return txt
|
||||
|
||||
|
||||
def get_retval_def(levels: int, current_level: int, dtype: str) -> str:
|
||||
base = "retval := make("
|
||||
if current_level > 0:
|
||||
base = "retval" + get_nested_keys(current_level) + " = make("
|
||||
return base + get_return_type(levels - current_level, dtype) + ")"
|
||||
|
||||
|
||||
def get_entries(levels: int) -> str:
|
||||
return f"v9, ok := c.mapEnv[{levels}].next[key]"
|
||||
|
||||
|
||||
def get_entry(levels: int) -> str:
|
||||
return f"entry := c.env[v{levels}.key]"
|
||||
|
||||
|
||||
def get_loop(levels: int) -> str:
|
||||
return f"for k{levels + 10}, v{levels + 10} := range v{levels + 9}.next {{"
|
||||
|
||||
|
||||
def get_function(file: typing.TextIO, levels: int, sig_dtype: str, dtype: str):
|
||||
print(get_signature(levels, sig_dtype, dtype), file=file)
|
||||
print(get_empty_def(levels, dtype), file=file)
|
||||
print(get_retval_def(levels, 0, dtype), file=file)
|
||||
print("if c.parsed {", file=file)
|
||||
print("key = cleanKey(key)", file=file)
|
||||
print(get_entries(levels), file=file)
|
||||
for level in range(levels):
|
||||
print(get_loop(level), file=file)
|
||||
print(get_retval_def(levels, level, dtype), file=file)
|
||||
print(get_loop(levels), file=file)
|
||||
print(get_entry(levels), file=file)
|
||||
print(
|
||||
"if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) {",
|
||||
file=file,
|
||||
)
|
||||
print("retval[k] = entry.parsed", file=file)
|
||||
print("} else {", file=file)
|
||||
print("return", file=file)
|
||||
print("}", file=file)
|
||||
print("}", file=file)
|
||||
print("return retval", file=file)
|
||||
print("}", file=file)
|
||||
print("}", file=file)
|
||||
print("return", file=file)
|
||||
print("}", file=file)
|
||||
|
||||
|
||||
with open("generated_code.go", mode="w", encoding="utf-8") as f:
|
||||
print("package envconf", file=f)
|
||||
get_function(f, 3, "Int", "int64")
|
||||
|
||||
|
||||
#
|
||||
# func (c *Config) getRawMap(key string, dtype DataType) (empty map[string]cValue) {
|
||||
# empty = make(map[string]cValue)
|
||||
# retval := make(map[string]cValue)
|
||||
# if c.parsed {
|
||||
# key = cleanKey(key)
|
||||
# entries, ok := c.mapEnv[0].next[key]
|
||||
#
|
||||
# if ok {
|
||||
# for k, v := range entries.next {
|
||||
# entry := c.env[v.key]
|
||||
# if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) {
|
||||
# retval[k] = entry.parsed
|
||||
# } else {
|
||||
# return
|
||||
# }
|
||||
# }
|
||||
# return retval
|
||||
# }
|
||||
# }
|
||||
# return
|
||||
# }
|
||||
#
|
||||
#
|
25
generated_code.go
Normal file
25
generated_code.go
Normal file
@ -0,0 +1,25 @@
|
||||
func (c *Config) getMapMapMapInt(key string) (empty map[string]map[string]map[string]int64) {
|
||||
empty = make(map[string]map[string]map[string]int64)
|
||||
retval := make(map[string]map[string]map[string]int64)
|
||||
if c.parsed {
|
||||
key = cleanKey(key)
|
||||
v9, ok := c.mapEnv[3].next[key]
|
||||
for k10, v10 := range v9.next {
|
||||
retval := make(map[string]map[string]map[string]int64)
|
||||
for k11, v11 := range v10.next {
|
||||
retval[k10] = make(map[string]map[string]int64)
|
||||
for k12, v12 := range v11.next {
|
||||
retval[k10][k11] = make(map[string]int64)
|
||||
for k13, v13 := range v12.next {
|
||||
entry := c.env[v3.key]
|
||||
if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) {
|
||||
retval[k] = entry.parsed
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
return retval
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user