package mw import "git.smesh.lol/moxie/pkg/mxutil" type MW struct { S string I int32 } func New(s string) (m MW) { w := MW{S: s} for w.I < len(s) && s[w.I] != '[' { w.I++ } if w.I < len(s) { w.I++ } return w } func (w *MW) Sep() { // Declared outside the loop: a declaration in the body of a self-mutating // method allocates in the sovereign arena on every iteration. var c byte for w.I < len(w.S) { c = w.S[w.I] if c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != ',' { break } w.I++ } } func (w *MW) Str() (s string) { w.Sep() if w.I >= len(w.S) || w.S[w.I] != '"' { return "" } w.I++ start := w.I for w.I < len(w.S) && w.S[w.I] != '"' { if w.S[w.I] == '\\' { w.I++ } w.I++ } if w.I >= len(w.S) { return "" } result := w.S[start:w.I] w.I++ return result } func (w *MW) Num() (n int64) { w.Sep() neg := false if w.I < len(w.S) && w.S[w.I] == '-' { neg = true w.I++ } var n int64 for w.I < len(w.S) && w.S[w.I] >= '0' && w.S[w.I] <= '9' { n = n*10 + int64(w.S[w.I]-'0') w.I++ } if neg { n = -n } return n } func (w *MW) Raw() (s string) { w.Sep() start := w.I w.I = Skipval(w.S, w.I) if w.I < 0 { w.I = len(w.S) return "" } return w.S[start:w.I] } func (w *MW) Strs() (ss []string) { w.Sep() if w.I >= len(w.S) || w.S[w.I] != '[' { return nil } w.I++ // Declared outside the loop, as above. var out []string var s string for { w.Sep() if w.I >= len(w.S) || w.S[w.I] == ']' { if w.I < len(w.S) { w.I++ } return out } s = w.Str() out = mxutil.Ensure(out, 1) out = push(out, s) } } func Unescape(s string) (sv string) { if len(s) == 0 { return s } i := 0 for i < len(s) { if s[i] == '\\' { break } i++ } if i == len(s) { return s } out := []byte{:0:len(s)} out = out | s[:i] for i < len(s) { if s[i] == '\\' && i+1 < len(s) { c := s[i+1] if c == '"' || c == '\\' || c == '/' { out = push(out, c) } else if c == 'n' { out = out | "\n" } else if c == 'r' { out = out | "\r" } else if c == 't' { out = out | "\t" } else { out = push(out, s[i]) out = push(out, c) } i += 2 } else { out = push(out, s[i]) i++ } } return string(out) } func Skipval(s string, i int32) (n int32) { if i >= len(s) { return -1 } c := s[i] if c == '"' { i++ for i < len(s) && s[i] != '"' { if s[i] == '\\' { i++ } i++ } if i >= len(s) { return -1 } return i + 1 } if c == '{' || c == '[' { open := c closeB := byte('}') if open == '[' { closeB = ']' } depth := 1 i++ for i < len(s) && depth > 0 { if s[i] == '"' { i++ for i < len(s) && s[i] != '"' { if s[i] == '\\' { i++ } i++ } if i >= len(s) { return -1 } i++ continue } if s[i] == open { depth++ } else if s[i] == closeB { depth-- if depth == 0 { return i + 1 } } i++ } return -1 } for i < len(s) { c = s[i] if c == ',' || c == ']' || c == '}' { return i } i++ } return i }