lang.IndexTemplateObject()
(template API)Returns element(s) from a data structure
This is a template API you can use for your custom data types.
It should only be called from ReadIndex()
and ReadNotIndex()
functions.
This function ensures consistency with the index, [
, builtin when used with different Murex data types. Thus making indexing a data type agnostic capability.
Example calling lang.IndexTemplateObject()
function:
package json
import (
"github.com/lmorg/murex/lang"
"github.com/lmorg/murex/utils/json"
)
func index(p *lang.Process, params []string) error {
var jInterface interface{}
b, err := p.Stdin.ReadAll()if err != nil {
return err
}
err = json.Unmarshal(b, &jInterface)if err != nil {
return err
}
func(iface interface{}) ([]byte, error) {
marshaller := return json.Marshal(iface, p.Stdout.IsTTY())
}
return lang.IndexTemplateObject(p, params, &jInterface, marshaller)
}
package lang
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/lmorg/murex/lang/types"
)
type indexValueT interface {
string | ~bool | ~int | ~float64 | any
~
}
// IndexTemplateObject is a handy standard indexer you can use in your custom data types for structured object types.
// The point of this is to minimize code rewriting and standardising the behavior of the indexer.
func IndexTemplateObject(p *Process, params []string, object *any, marshaller func(any) ([]byte, error)) error {
if p.IsNot {
return itoNot(p, params, object, marshaller)
}return itoIndex(p, params, object, marshaller)
}
// itoIndex allow
func itoIndex(p *Process, params []string, object *any, marshaller func(any) ([]byte, error)) error {
switch v := (*object).(type) {
case []any:
return itoIndexArray(p, params, v, marshaller)
case map[string]any:
return itoIndexMap(p, params, v, marshaller)
case map[any]any:
return itoIndexMap(p, params, v, marshaller)
default:
return errors.New("object cannot be indexed")
}
}
func itoIndexArray[V indexValueT](p *Process, params []string, v []V, marshaller func(any) ([]byte, error)) error {
var objArray []V
for _, key := range params {
i, err := strconv.Atoi(key)if err != nil {
return err
}if i < 0 {
len(v)
i +=
}if i >= len(v) {
return fmt.Errorf("key '%s' greater than number of items in array", key)
}
if len(params) > 1 {
append(objArray, v[i])
objArray = continue
}
switch value := any(v[i]).(type) {
case nil:
p.Stdout.SetDataType(types.Null)case bool:
p.Stdout.SetDataType(types.Boolean)if value {
p.Stdout.Write(types.TrueByte)else {
}
p.Stdout.Write(types.FalseByte)
}case int:
p.Stdout.SetDataType(types.Integer)
s := strconv.Itoa(value)byte(s))
p.Stdout.Write([]case float64:
p.Stdout.SetDataType(types.Number)
s := types.FloatToString(value)byte(s))
p.Stdout.Write([]case string:
p.Stdout.SetDataType(types.String)byte(value))
p.Stdout.Write([]default:
b, err := marshaller(value)if err != nil {
return err
}
p.Stdout.Writeln(b)
}
}if len(objArray) > 0 {
b, err := marshaller(objArray)if err != nil {
return err
}
p.Stdout.Writeln(b)
}return nil
}
func itoIndexMap[K comparable, V indexValueT](p *Process, params []string, v map[K]V, marshaller func(any) ([]byte, error)) error {
var (
objArray []any
obj anyerror
err
)
for i := range params {
if len(params[i]) > 2 && params[i][0] == '[' && params[i][len(params[i])-1] == ']' {
1:len(params[i])-1])
obj, err = ElementLookup(v, params[i][if err != nil {
return err
}
else {
} var (
int
iString
key anybool
ok
)
for {
switch iString {
case 0:
key = params[i]case 1:
key = strings.Title(params[i])case 2:
key = strings.ToLower(params[i])case 3:
key = strings.ToUpper(params[i])default:
return fmt.Errorf("key '%s' not found", params[i])
}
obj, ok = v[key.(K)]if ok {
break
}
iString++
}
}
if len(params) > 1 {
append(objArray, obj)
objArray =
else {
} switch obj := obj.(type) {
case nil:
p.Stdout.SetDataType(types.Null)case bool:
p.Stdout.SetDataType(types.Boolean)if obj {
p.Stdout.Write(types.TrueByte)else {
}
p.Stdout.Write(types.FalseByte)
}case int:
p.Stdout.SetDataType(types.Integer)
s := strconv.Itoa(obj)byte(s))
p.Stdout.Write([]case float64:
p.Stdout.SetDataType(types.Number)
s := types.FloatToString(obj)byte(s))
p.Stdout.Write([]case string:
p.Stdout.SetDataType(types.String)byte(obj))
p.Stdout.Write([]default:
b, err := marshaller(obj)if err != nil {
return err
}
p.Stdout.Writeln(b)
}
}
}if len(objArray) > 0 {
b, err := marshaller(objArray)if err != nil {
return err
}
p.Stdout.Writeln(b)
}return nil
}
// itoNot requires the indexes to be explicit
func itoNot(p *Process, params []string, object *any, marshaller func(any) ([]byte, error)) error {
switch v := (*object).(type) {
case []any:
return itoNotArray(p, params, v, marshaller)
case map[string]any:
return itoNotMap(p, params, v, marshaller)
case map[any]any:
return itoNotMap(p, params, v, marshaller)
default:
return errors.New("object cannot be !indexed")
}
}
func itoNotArray[V indexValueT](p *Process, params []string, v []V, marshaller func(any) ([]byte, error)) error {
var objArray []any
make(map[int]bool)
not := for _, key := range params {
i, err := strconv.Atoi(key)if err != nil {
return err
}if i < 0 {
return errors.New("cannot have negative keys in array")
}if i >= len(v) {
return fmt.Errorf("key '%s' greater than number of items in array", key)
}
true
not[i] =
}
for i := range v {
if !not[i] {
append(objArray, v[i])
objArray =
}
}
b, err := marshaller(objArray)if err != nil {
return err
}
_, err = p.Stdout.Writeln(b)
return err
}
func itoNotMap[K comparable, V indexValueT](p *Process, params []string, v map[K]V, marshaller func(any) ([]byte, error)) error {
make(map[K]any)
objMap := make(map[K]bool)
not := var key any
for _, key = range params {
true
not[key.(K)] =
string))
key = strings.Title(key.(true
not[key.(K)] =
string))
key = strings.ToLower(key.(true
not[key.(K)] =
string))
key = strings.ToUpper(key.(true
not[key.(K)] =
}
for s := range v {
if !not[s] {
objMap[s] = v[s]
}
}
b, err := marshaller(objMap)if err != nil {
return err
}
p.Stdout.Writeln(b)
return nil
}
*lang.Process
: Process’s runtime state. Typically expressed as the variable p
[]string
: slice of parameters used in [
/ ![
*interface{}
: a pointer to the data structure being indexedfunc(interface{}) ([]byte, error)
: data type marshaller functionReadArray()
(type): Read from a data type one array element at a timeReadArrayWithType()
(type): Read from a data type one array element at a time and return the elements contents and data typeReadIndex()
(type): Data type handler for the index, [
, builtinReadMap()
(type): Treat data type as a key/value structure and read its contentsReadNotIndex()
(type): Data type handler for the bang-prefixed index, ![
, builtinWriteArray()
(type): Write a data type, one array element at a timelang.IndexTemplateTable()
(template API): Returns element(s) from a tableThis document was generated from lang/stdio/interface_doc.yaml.
This site's content is rebuilt automatically from murex's source code after each merge to the master
branch. Downloadable murex binaries are also built with the website.
Last built on Tue Dec 10 22:56:57 UTC 2024 against commit 60f05a260f05a227caf73dd5b3478e3cb3f4bb24e46745b.
Current version is 6.4.1005 (develop) which has been verified against tests cases.