initial work on auto generated definitions

This commit is contained in:
Roy Olav Purser 2022-09-23 14:44:08 +02:00
parent 27d793492c
commit eef48c1d0a
Signed by: roypur
GPG Key ID: 90142918D5E59AD3
3 changed files with 156 additions and 88 deletions

View File

@ -20,18 +20,18 @@ type cEntry struct {
hasdef bool // Default value is defined hasdef bool // Default value is defined
} }
type keyLookupStruct struct { type keyLookupType struct {
key string key string
end bool 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 { if len(kl.next) == 0 {
kl.next = make(map[string]*keyLookupStruct) kl.next = make(map[string]*keyLookupType)
} }
if len(parts) > 0 { if len(parts) > 0 {
nextLookup := new(keyLookupStruct) nextLookup := new(keyLookupType)
nextLookup.setKey(parts[1:], key) nextLookup.setKey(parts[1:], key)
kl.next[parts[0]] = nextLookup kl.next[parts[0]] = nextLookup
} else { } else {
@ -40,7 +40,7 @@ func (kl *keyLookupStruct) setKey(parts []string, key string) {
} }
} }
func (kl *keyLookupStruct) print() { func (kl *keyLookupType) print() {
if kl.end { if kl.end {
fmt.Println(kl.key) fmt.Println(kl.key)
fmt.Println("-----------------") fmt.Println("-----------------")
@ -52,28 +52,23 @@ func (kl *keyLookupStruct) print() {
} }
} }
type mapEnvType [5]*keyLookupType
type Config struct { type Config struct {
parsed bool parsed bool
env map[string]cEntry env map[string]cEntry
mapEnvTest map[int]*keyLookupStruct mapEnv mapEnvType
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
} }
// NewConfig returns an envconf.Config that is used to read configuration from environment variables. // 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 // The environment variables are stored in envconf.Config, so changes to the environment after NewConfig has been called
// will not be taken into account. // will not be taken into account.
func NewConfig() *Config { func NewConfig() *Config {
levels := 5
config := new(Config) config := new(Config)
config.parsed = false config.parsed = false
config.env = make(map[string]cEntry) config.env = make(map[string]cEntry)
config.mapEnvTest = make(map[int]*keyLookupStruct) for level, _ := range config.mapEnv {
for level := 1; level <= levels; level++ { config.mapEnv[level] = new(keyLookupType)
config.mapEnvTest[level] = new(keyLookupStruct)
} }
for _, v := range os.Environ() { for _, v := range os.Environ() {
@ -81,7 +76,7 @@ func NewConfig() *Config {
if len(splitted) == 2 { if len(splitted) == 2 {
key := cleanKey(splitted[0]) key := cleanKey(splitted[0])
val := splitted[1] 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)) { if unicode.IsLetter(getFirstRune(key)) {
var entry cEntry var entry cEntry
entry.value = val entry.value = val
@ -90,7 +85,7 @@ func NewConfig() *Config {
entry.empty = false entry.empty = false
config.env[key] = entry config.env[key] = entry
if len(splitted) > 1 { if len(splitted) > 1 {
for level := 1; level <= levels; level++ { for level := 1; level <= len(config.mapEnv); level++ {
for count := 0; count < level; count++ { for count := 0; count < level; count++ {
parts := make([]string, level, level) parts := make([]string, level, level)
parts[0] = strings.Trim(strings.Join(splitted[:count+1], "_"), "_") parts[0] = strings.Trim(strings.Join(splitted[:count+1], "_"), "_")
@ -106,69 +101,11 @@ func NewConfig() *Config {
if parts[len(parts)-1] == "" { if parts[len(parts)-1] == "" {
break break
} }
config.mapEnvTest[level].setKey(parts, key) config.mapEnv[level].setKey(parts, key)
} }
config.mapEnvTest[level].print() config.mapEnv[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
}
*/
} }
} }
} }
} }
} }
@ -196,12 +133,12 @@ func (c *Config) Define(key string, dtype DataType) {
// Variables without a defined type will be ignored by Parse. // Variables without a defined type will be ignored by Parse.
func (c *Config) DefineMap(key string, dtype DataType) { func (c *Config) DefineMap(key string, dtype DataType) {
key = cleanKey(key) key = cleanKey(key)
entries, ok := c.mapEnv[key] entries, ok := c.mapEnv[0].next[key]
if ok { if ok {
for _, key = range entries { for _, entry := range entries.next {
entry := c.env[key] defEntry := c.env[entry.key]
entry.dtype = dtype defEntry.dtype = dtype
c.env[key] = entry 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) retval := make(map[string]cValue)
if c.parsed { if c.parsed {
key = cleanKey(key) key = cleanKey(key)
entries, ok := c.mapEnv[key] entries, ok := c.mapEnv[0].next[key]
if ok { if ok {
for k, v := range entries { for k, v := range entries.next {
entry := c.env[v] entry := c.env[v.key]
if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) { if (entry.dtype.baseType() == dtype.baseType()) && (entry.parsed.err == nil) {
retval[k] = entry.parsed retval[k] = entry.parsed
} else { } else {

106
generate.py Normal file
View 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
View 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
}