Pass section
This commit is contained in:
73
decode.odin
73
decode.odin
@@ -4,21 +4,48 @@ import "base:runtime"
|
|||||||
import "core:reflect"
|
import "core:reflect"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
||||||
decode :: proc( v: any, key: string ) -> any {
|
@private
|
||||||
v := reflect.any_base(v)
|
_clean_html :: proc(s: string) -> string {
|
||||||
ti := type_info_of(v.id)
|
ret: strings.Builder
|
||||||
|
|
||||||
#partial switch i in runtime.type_info_base(ti).variant {
|
for c in s do switch c {
|
||||||
|
case '<':
|
||||||
|
strings.write_string(&ret, "<")
|
||||||
|
case '>':
|
||||||
|
strings.write_string(&ret, ">")
|
||||||
|
case '&':
|
||||||
|
strings.write_string(&ret, "&")
|
||||||
|
case '"':
|
||||||
|
strings.write_string(&ret, """)
|
||||||
|
case '\'':
|
||||||
|
strings.write_string(&ret, "'")
|
||||||
|
case:
|
||||||
|
strings.write_rune(&ret, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.to_string(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
decode :: proc( v: any, key: string ) -> any {
|
||||||
|
ti := type_info_of(v.id)
|
||||||
|
variant := runtime.type_info_base(ti).variant
|
||||||
|
|
||||||
|
#partial switch i in variant {
|
||||||
case runtime.Type_Info_Enumerated_Array:
|
case runtime.Type_Info_Enumerated_Array:
|
||||||
return decode(any{v.data, ti.id}, key)
|
return decode(any{v.data, ti.id}, key)
|
||||||
|
|
||||||
case runtime.Type_Info_Union:
|
case runtime.Type_Info_Union:
|
||||||
return decode(any{v.data, reflect.union_variant_typeid(v) }, key)
|
return decode(any{v.data, reflect.union_variant_typeid(v) }, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "." {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
#partial switch i in variant {
|
||||||
case runtime.Type_Info_Struct:
|
case runtime.Type_Info_Struct:
|
||||||
newkey, err := strings.split_after_n(key, ".", 2)
|
newkey, err := strings.split_after_n(key, ".", 2)
|
||||||
|
|
||||||
@@ -74,36 +101,31 @@ decode :: proc( v: any, key: string ) -> any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == "." {
|
return nil
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
decode_string :: proc( v: any, key: string ) -> string {
|
|
||||||
return fmt.tprintf("%v", decode(v, key))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@private
|
@private
|
||||||
mustache_section :: proc( r: ^strings.Reader, v: any, key: string, inv: bool = false ) -> string {
|
mustache_section :: proc( r: ^strings.Reader, v, p: any, section_key: string, inv: bool = false ) -> string {
|
||||||
tmp := mustache(r, v, key)
|
tmp := mustache(r, v, section_key)
|
||||||
|
defer delete(tmp)
|
||||||
|
|
||||||
|
tmp2 := mustache(tmp, p, section_key)
|
||||||
|
|
||||||
if inv {
|
if inv {
|
||||||
return tmp
|
return tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
defer delete(tmp)
|
delete(tmp2)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
section :: proc( r: ^strings.Reader, v: any, key: string, inv: bool = false ) -> string {
|
section :: proc( r: ^strings.Reader, v: any, section_key: string, inv: bool = false ) -> string {
|
||||||
save := r.i
|
save := r.i
|
||||||
|
|
||||||
t := reflect.any_base(decode(v, key))
|
t := reflect.any_base(decode(v, section_key))
|
||||||
ti := type_info_of(t.id)
|
ti := type_info_of(t.id)
|
||||||
|
|
||||||
#partial switch i in runtime.type_info_base(ti).variant {
|
#partial switch i in runtime.type_info_base(ti).variant {
|
||||||
@@ -113,7 +135,7 @@ section :: proc( r: ^strings.Reader, v: any, key: string, inv: bool = false ) ->
|
|||||||
elem :=reflect.index(t, i);
|
elem :=reflect.index(t, i);
|
||||||
strings.reader_seek(r, save, .Start)
|
strings.reader_seek(r, save, .Start)
|
||||||
|
|
||||||
tmp := mustache_section(r, elem, key, !inv)
|
tmp := mustache_section(r, elem, v, section_key, !inv)
|
||||||
defer delete(tmp)
|
defer delete(tmp)
|
||||||
|
|
||||||
ret = strings.concatenate({ret, tmp})
|
ret = strings.concatenate({ret, tmp})
|
||||||
@@ -122,13 +144,12 @@ section :: proc( r: ^strings.Reader, v: any, key: string, inv: bool = false ) ->
|
|||||||
case runtime.Type_Info_Boolean:
|
case runtime.Type_Info_Boolean:
|
||||||
b, _ := reflect.as_bool(t)
|
b, _ := reflect.as_bool(t)
|
||||||
|
|
||||||
return mustache_section(r, t, key, b~inv)
|
return mustache_section(r, t, v, section_key, b~inv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return mustache_section(r, t, key, inv)
|
return mustache_section(r, t, v, section_key, inv)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mustache_section(r, t, key, !inv)
|
return mustache_section(r, t, v, section_key, !inv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package mustache
|
package mustache
|
||||||
|
|
||||||
import "core:log"
|
import "core:fmt"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
state :: enum {
|
state :: enum {
|
||||||
@@ -11,31 +11,21 @@ state :: enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mustache :: proc{mustache_reader, mustache_string}
|
mustache :: proc{mustache_reader, mustache_string}
|
||||||
/*
|
|
||||||
Input:
|
|
||||||
- fmt: A string with placeholders in the form `{{key}}`.
|
|
||||||
- dict: A map from string to string, where each key corresponds to a placeholder in the format string.
|
|
||||||
|
|
||||||
Returns:
|
mustache_string :: proc(fmt: string, data: any , section_key: string = "") -> string {
|
||||||
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
|
|
||||||
replaces with an empty string.
|
|
||||||
*/
|
|
||||||
mustache_string :: proc(fmt: string, v: any , end_block: string = "") -> string {
|
|
||||||
r : strings.Reader
|
r : strings.Reader
|
||||||
strings.reader_init(&r, fmt)
|
strings.reader_init(&r, fmt)
|
||||||
return mustache(&r, v, end_block)
|
return mustache(&r, data, section_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) -> string {
|
mustache_reader :: proc(r: ^strings.Reader, data: any, section_key: string = "" ) -> string {
|
||||||
/*
|
/*
|
||||||
template works as a state machine, it manipulates `b` (returned string)
|
This is the main parser for mustache templates, it's a recursive decent parser, that works as a state machine,
|
||||||
and `key` (placeholder string), according to the states. No error
|
it manipulates the processed template with data, `ret`, and the key to element on data `key`, according to the states.
|
||||||
returns are needed because if `key` is not close it writes it as
|
This approach let us process the data as fast as posible.
|
||||||
it's not a placeholder
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
b, key: strings.Builder
|
ret, key: strings.Builder
|
||||||
defer strings.builder_destroy(&key)
|
defer strings.builder_destroy(&key)
|
||||||
|
|
||||||
s:= state.writing
|
s:= state.writing
|
||||||
@@ -53,7 +43,7 @@ mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) ->
|
|||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
s=.reading_key
|
s=.reading_key
|
||||||
case .close_bracket:
|
case .close_bracket:
|
||||||
strings.write_string(&b, "}{" )
|
strings.write_string(&ret, "}{" )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .writing:
|
case .writing:
|
||||||
s=.open_bracket
|
s=.open_bracket
|
||||||
@@ -63,7 +53,7 @@ mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) ->
|
|||||||
case '}':
|
case '}':
|
||||||
switch s {
|
switch s {
|
||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
strings.write_string(&b, "{}" )
|
strings.write_string(&ret, "{}" )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .close_bracket:
|
case .close_bracket:
|
||||||
// Work with key
|
// Work with key
|
||||||
@@ -77,18 +67,33 @@ mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) ->
|
|||||||
|
|
||||||
switch skey[0] {
|
switch skey[0] {
|
||||||
case '/':
|
case '/':
|
||||||
if skey[1:] == end_block {
|
if skey[1:] == section_key {
|
||||||
return strings.to_string(b)
|
return strings.to_string(ret)
|
||||||
}
|
}
|
||||||
case '#':
|
case '#':
|
||||||
strings.write_string(&b, section(r, v, skey[1:]) )
|
strings.write_string(&ret, section(r, data, skey[1:]) )
|
||||||
case '^':
|
case '^':
|
||||||
strings.write_string(&b, section(r, v, skey[1:], true) )
|
strings.write_string(&ret, section(r, data, skey[1:], true) )
|
||||||
|
case '&':
|
||||||
|
strings.write_string(&ret, fmt.tprintf("%v",decode(data, skey[1:])) )
|
||||||
case:
|
case:
|
||||||
strings.write_string(&b, decode_string(v, skey) )
|
dec := decode(data, skey)
|
||||||
|
|
||||||
|
if dec == nil {
|
||||||
|
// If not decoded write as key
|
||||||
|
strings.write_string(&ret, "{{" )
|
||||||
|
strings.write_string(&ret, skey )
|
||||||
|
strings.write_string(&ret, "}}" )
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
clean := _clean_html(fmt.tprintf("%v", dec))
|
||||||
|
defer delete(clean)
|
||||||
|
|
||||||
|
strings.write_string(&ret, clean)
|
||||||
}
|
}
|
||||||
case .writing:
|
case .writing:
|
||||||
strings.write_rune(&b, '}' )
|
strings.write_rune(&ret, '}' )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .reading_key:
|
case .reading_key:
|
||||||
s=.close_bracket
|
s=.close_bracket
|
||||||
@@ -96,15 +101,15 @@ mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) ->
|
|||||||
case:
|
case:
|
||||||
switch s {
|
switch s {
|
||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
strings.write_rune(&b, '{' )
|
strings.write_rune(&ret, '{' )
|
||||||
strings.write_rune(&b, c )
|
strings.write_rune(&ret, c )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .close_bracket:
|
case .close_bracket:
|
||||||
strings.write_rune(&key, '}' )
|
strings.write_rune(&key, '}' )
|
||||||
strings.write_rune(&key, c )
|
strings.write_rune(&key, c )
|
||||||
s=.reading_key
|
s=.reading_key
|
||||||
case .writing:
|
case .writing:
|
||||||
strings.write_rune(&b, c )
|
strings.write_rune(&ret, c )
|
||||||
s=.writing
|
s=.writing
|
||||||
case .reading_key:
|
case .reading_key:
|
||||||
strings.write_rune(&key, c )
|
strings.write_rune(&key, c )
|
||||||
@@ -114,18 +119,18 @@ mustache_reader :: proc(r: ^strings.Reader, v: any, end_block: string = "" ) ->
|
|||||||
|
|
||||||
switch s {
|
switch s {
|
||||||
case .open_bracket:
|
case .open_bracket:
|
||||||
strings.write_rune(&b, '{' )
|
strings.write_rune(&ret, '{' )
|
||||||
case .reading_key:
|
case .reading_key:
|
||||||
strings.write_string(&b,"{{")
|
strings.write_string(&ret,"{{")
|
||||||
strings.write_string(&b,strings.to_string(key))
|
strings.write_string(&ret,strings.to_string(key))
|
||||||
case .close_bracket:
|
case .close_bracket:
|
||||||
strings.write_string(&b,"{{")
|
strings.write_string(&ret,"{{")
|
||||||
strings.write_string(&b,strings.to_string(key))
|
strings.write_string(&ret,strings.to_string(key))
|
||||||
strings.write_rune(&b, '}' )
|
strings.write_rune(&ret, '}' )
|
||||||
case .writing:
|
case .writing:
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.to_string(b)
|
return strings.to_string(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user