go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

size.go (3413B)


      1 package render
      2 
      3 import (
      4 	"bytes"
      5 	"fmt"
      6 	"strings"
      7 )
      8 
      9 // Sizer splits dynamic contents into individual segments for browseable pages.
     10 type Sizer struct {
     11 	outputSize uint32 // maximum output for a single page.
     12 //	menuSize uint16 // actual menu size for the dynamic page being sized
     13 	memberSizes map[string]uint16 // individual byte sizes of all content to be rendered by template.
     14 	totalMemberSize uint32 // total byte size of all content to be rendered by template (sum of memberSizes)
     15 	crsrs []uint32 // byte offsets in the sink content for browseable pages indices.
     16 	sink string // sink symbol.
     17 }
     18 
     19 // NewSizer creates a new Sizer object with the given output size constraint.
     20 func NewSizer(outputSize uint32) *Sizer {
     21 	return &Sizer{
     22 		outputSize: outputSize,
     23 		memberSizes: make(map[string]uint16),
     24 	}
     25 }
     26 
     27 // WithMenuSize sets the size of the menu being used in the rendering context.
     28 //func(szr *Sizer) WithMenuSize(menuSize uint16) *Sizer {
     29 //	szr.menuSize = menuSize
     30 //	return szr
     31 //}
     32 
     33 // Set adds a content symbol in the state it will be used by the renderer.
     34 func(szr *Sizer) Set(key string, size uint16) error {
     35 	szr.memberSizes[key] = size
     36 	if size == 0 {
     37 		szr.sink = key
     38 	}
     39 	szr.totalMemberSize += uint32(size)
     40 	return nil
     41 }
     42 
     43 // Check audits whether the rendered string is within the output size constraint of the sizer.
     44 func(szr *Sizer) Check(s string) (uint32, bool) {
     45 	l := uint32(len(s))
     46 	if szr.outputSize > 0 {
     47 		if l > szr.outputSize {
     48 			Logg.Infof("sized check fails", "length", l, "sizer", szr)
     49 			Logg.Tracef("", "sizer contents", s)
     50 			return 0, false
     51 		}
     52 		l = szr.outputSize - l
     53 	}
     54 	return l, true
     55 }
     56 
     57 // String implements the String interface.
     58 func(szr *Sizer) String() string {
     59 //	var diff uint32
     60 //	if szr.outputSize > 0 {
     61 //		diff = szr.outputSize - szr.totalMemberSize - uint32(szr.menuSize)
     62 //	}
     63 //	return fmt.Sprintf("output: %v, member: %v, menu: %v, diff: %v", szr.outputSize, szr.totalMemberSize, szr.menuSize, diff)
     64 	return fmt.Sprintf("output: %v, member: %v", szr.outputSize, szr.totalMemberSize)
     65 }
     66 
     67 // Size gives the byte size of content for a single symbol.
     68 //
     69 // Fails if the symbol has not been registered using Set
     70 func(szr *Sizer) Size(s string) (uint16, error) {
     71 	r, ok := szr.memberSizes[s]
     72 	if !ok {
     73 		return 0, fmt.Errorf("unknown member: %s", s)
     74 	}
     75 	return r, nil
     76 }
     77 
     78 // Menusize returns the currently defined menu size.
     79 //func(szr *Sizer) MenuSize() uint16 {
     80 //	return szr.menuSize
     81 //}
     82 
     83 // AddCursor adds a pagination cursor for the paged sink content.
     84 func(szr *Sizer) AddCursor(c uint32) {
     85 	Logg.Debugf("Added cursor", "offset", c)
     86 	szr.crsrs = append(szr.crsrs, c)
     87 }
     88 
     89 // GetAt the paged symbols for the current page index.
     90 //
     91 // Fails if index requested is out of range.
     92 func(szr *Sizer) GetAt(values map[string]string, idx uint16) (map[string]string, error) {
     93 	if szr.sink == "" {
     94 		return values, nil
     95 	}
     96 	outValues := make(map[string]string)
     97 	for k, v := range values {
     98 		Logg.Tracef("check values", "k", k, "v", v, "idx", idx, "cursors", szr.crsrs)
     99 		if szr.sink == k {
    100 			if idx >= uint16(len(szr.crsrs)) {
    101 				return nil, fmt.Errorf("no more values in index") 
    102 			}
    103 			c := szr.crsrs[idx]
    104 			v = v[c:]
    105 			nl := strings.Index(v, "\n")
    106 			if nl > 0 {
    107 				v = v[:nl]
    108 			}
    109 			b := bytes.ReplaceAll([]byte(v), []byte{0x00}, []byte{0x0a})
    110 			v = string(b)
    111 		}
    112 		outValues[k] = v
    113 	}
    114 	return outValues, nil
    115 }
    116 
    117 func(szr *Sizer) Reset() {
    118 	szr.crsrs = []uint32{}
    119 }