Add Sections as mustache for arrays
This commit is contained in:
105
decode.odin
105
decode.odin
@@ -1,20 +1,18 @@
|
|||||||
package mustache
|
package mustache
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:reflect"
|
import "core:reflect"
|
||||||
import "core:strconv"
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
import "core:fmt"
|
||||||
|
|
||||||
decode :: proc( v: any, key: string ) -> string {
|
decode :: proc( v: any, key: string ) -> any {
|
||||||
if v == nil do return ""
|
if v == nil do return ""
|
||||||
|
|
||||||
ti := runtime.type_info_base(type_info_of(v.id))
|
v := reflect.any_base(v)
|
||||||
a := any{v.data, ti.id}
|
ti := type_info_of(v.id)
|
||||||
|
|
||||||
#partial switch info in ti.variant {
|
switch {
|
||||||
|
case reflect.is_struct(ti):
|
||||||
case runtime.Type_Info_Struct:
|
|
||||||
newkey, err := strings.split_after_n(key, ".", 2)
|
newkey, err := strings.split_after_n(key, ".", 2)
|
||||||
|
|
||||||
if len(newkey) != 2 || err != nil {
|
if len(newkey) != 2 || err != nil {
|
||||||
@@ -22,67 +20,50 @@ decode :: proc( v: any, key: string ) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return decode( reflect.struct_field_value_by_name(v, newkey[0][:len(newkey[0])-1]), newkey[1] )
|
return decode( reflect.struct_field_value_by_name(v, newkey[0][:len(newkey[0])-1]), newkey[1] )
|
||||||
|
case reflect.is_string(ti):
|
||||||
case runtime.Type_Info_String:
|
|
||||||
if key != "." do return ""
|
if key != "." do return ""
|
||||||
|
return v
|
||||||
switch t in a {
|
case reflect.is_integer(ti):
|
||||||
case string:
|
|
||||||
return t
|
|
||||||
case cstring:
|
|
||||||
return string(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
case runtime.Type_Info_Integer:
|
|
||||||
if key != "." do return ""
|
if key != "." do return ""
|
||||||
|
return v
|
||||||
buf: [40]byte
|
case reflect.is_enum(ti):
|
||||||
u := cast_any_int_to_u128(a)
|
return decode(any{v.data, ti.id}, key)
|
||||||
|
case reflect.is_slice(ti):
|
||||||
return strconv.append_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil)
|
if key != "." do return ""
|
||||||
case runtime.Type_Info_Enum:
|
return v
|
||||||
return decode(any{v.data, info.base.id}, key)
|
case:
|
||||||
|
log.warnf("%v", ti)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decode_string :: proc( v: any, key: string ) -> string {
|
||||||
// Stealed from core:endoding/json
|
return fmt.tprintf("%v", decode(v, key))
|
||||||
@(private)
|
|
||||||
cast_any_int_to_u128 :: proc(any_int_value: any) -> u128 {
|
|
||||||
u: u128 = 0
|
|
||||||
|
|
||||||
switch i in any_int_value {
|
|
||||||
case i8: u = u128(i)
|
|
||||||
case i16: u = u128(i)
|
|
||||||
case i32: u = u128(i)
|
|
||||||
case i64: u = u128(i)
|
|
||||||
case i128: u = u128(i)
|
|
||||||
case int: u = u128(i)
|
|
||||||
case u8: u = u128(i)
|
|
||||||
case u16: u = u128(i)
|
|
||||||
case u32: u = u128(i)
|
|
||||||
case u64: u = u128(i)
|
|
||||||
case u128: u = u128(i)
|
|
||||||
case uint: u = u128(i)
|
|
||||||
case uintptr: u = u128(i)
|
|
||||||
|
|
||||||
case i16le: u = u128(i)
|
|
||||||
case i32le: u = u128(i)
|
|
||||||
case i64le: u = u128(i)
|
|
||||||
case u16le: u = u128(i)
|
|
||||||
case u32le: u = u128(i)
|
|
||||||
case u64le: u = u128(i)
|
|
||||||
case u128le: u = u128(i)
|
|
||||||
case i16be: u = u128(i)
|
|
||||||
case i32be: u = u128(i)
|
|
||||||
case i64be: u = u128(i)
|
|
||||||
case u16be: u = u128(i)
|
|
||||||
case u32be: u = u128(i)
|
|
||||||
case u64be: u = u128(i)
|
|
||||||
case u128be: u = u128(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return u;
|
preprocess :: proc( r: ^strings.Reader, v: any, key: string ) -> string {
|
||||||
|
if v == nil do return ""
|
||||||
|
|
||||||
|
save := r.i
|
||||||
|
|
||||||
|
t := reflect.any_base(decode(v, key))
|
||||||
|
ti := type_info_of(t.id)
|
||||||
|
|
||||||
|
ret : string
|
||||||
|
switch {
|
||||||
|
case reflect.is_slice(ti):
|
||||||
|
for i in 0..<reflect.length(t) {
|
||||||
|
elem :=reflect.index(t, i);
|
||||||
|
|
||||||
|
strings.reader_seek(r, save, .Start)
|
||||||
|
tmp := mustache(r, elem, key)
|
||||||
|
defer delete(tmp)
|
||||||
|
|
||||||
|
ret = strings.concatenate({ret, tmp})
|
||||||
|
log.infof(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package mustache
|
package mustache
|
||||||
|
|
||||||
|
import "core:log"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
@private
|
|
||||||
state :: enum {
|
state :: enum {
|
||||||
writing,
|
writing,
|
||||||
reading_key,
|
reading_key,
|
||||||
@@ -10,6 +10,7 @@ state :: enum {
|
|||||||
close_bracket,
|
close_bracket,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mustache :: proc{mustache_reader, mustache_string}
|
||||||
/*
|
/*
|
||||||
Input:
|
Input:
|
||||||
- fmt: A string with placeholders in the form `{{key}}`.
|
- fmt: A string with placeholders in the form `{{key}}`.
|
||||||
@@ -20,7 +21,13 @@ A new string with all placeholders replaced by their corresponding values from
|
|||||||
the dictionary. If a key is missing in the dictionary, the placeholder is
|
the dictionary. If a key is missing in the dictionary, the placeholder is
|
||||||
replaces with an empty string.
|
replaces with an empty string.
|
||||||
*/
|
*/
|
||||||
mustache :: proc(fmt: string, v: any ) -> string {
|
mustache_string :: proc(fmt: string, v: any ) -> string {
|
||||||
|
r : strings.Reader
|
||||||
|
strings.reader_init(&r, fmt)
|
||||||
|
return mustache(&r, v, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string ) -> string {
|
||||||
/*
|
/*
|
||||||
template works as a state machine, it manipulates `b` (returned string)
|
template works as a state machine, it manipulates `b` (returned string)
|
||||||
and `key` (placeholder string), according to the states. No error
|
and `key` (placeholder string), according to the states. No error
|
||||||
@@ -33,7 +40,14 @@ mustache :: proc(fmt: string, v: any ) -> string {
|
|||||||
|
|
||||||
s:= state.writing
|
s:= state.writing
|
||||||
|
|
||||||
for c in fmt do switch c {
|
for {
|
||||||
|
c, _, err := strings.reader_read_rune(r);
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
case '{':
|
case '{':
|
||||||
switch s {
|
switch s {
|
||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
@@ -52,9 +66,25 @@ mustache :: proc(fmt: string, v: any ) -> string {
|
|||||||
strings.write_string(&b, "{}" )
|
strings.write_string(&b, "{}" )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .close_bracket:
|
case .close_bracket:
|
||||||
strings.write_string(&b, decode(v, strings.to_string(key) ))
|
// Work with key
|
||||||
|
skey := strings.to_string(key)
|
||||||
strings.builder_reset(&key)
|
strings.builder_reset(&key)
|
||||||
s=.writing
|
s=.writing
|
||||||
|
|
||||||
|
if len(skey) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch skey[0] {
|
||||||
|
case '/':
|
||||||
|
if skey[1:] == end_block {
|
||||||
|
return strings.to_string(b)
|
||||||
|
}
|
||||||
|
case '#':
|
||||||
|
strings.write_string(&b, preprocess(r, v, skey[1:]) )
|
||||||
|
case:
|
||||||
|
strings.write_string(&b, decode_string(v, skey) )
|
||||||
|
}
|
||||||
case .writing:
|
case .writing:
|
||||||
strings.write_rune(&b, '}' )
|
strings.write_rune(&b, '}' )
|
||||||
s=.writing
|
s=.writing
|
||||||
@@ -78,6 +108,7 @@ mustache :: proc(fmt: string, v: any ) -> string {
|
|||||||
strings.write_rune(&key, c )
|
strings.write_rune(&key, c )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch s {
|
switch s {
|
||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
|
|||||||
Reference in New Issue
Block a user