mw.mx raw

   1  package mw
   2  
   3  import "git.smesh.lol/moxie/pkg/mxutil"
   4  
   5  type MW struct {
   6  	S string
   7  	I int32
   8  }
   9  
  10  func New(s string) (m MW) {
  11  	w := MW{S: s}
  12  	for w.I < len(s) && s[w.I] != '[' {
  13  		w.I++
  14  	}
  15  	if w.I < len(s) {
  16  		w.I++
  17  	}
  18  	return w
  19  }
  20  
  21  func (w *MW) Sep() {
  22  	// Declared outside the loop: a declaration in the body of a self-mutating
  23  	// method allocates in the sovereign arena on every iteration.
  24  	var c byte
  25  	for w.I < len(w.S) {
  26  		c = w.S[w.I]
  27  		if c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != ',' {
  28  			break
  29  		}
  30  		w.I++
  31  	}
  32  }
  33  
  34  func (w *MW) Str() (s string) {
  35  	w.Sep()
  36  	if w.I >= len(w.S) || w.S[w.I] != '"' {
  37  		return ""
  38  	}
  39  	w.I++
  40  	start := w.I
  41  	for w.I < len(w.S) && w.S[w.I] != '"' {
  42  		if w.S[w.I] == '\\' {
  43  			w.I++
  44  		}
  45  		w.I++
  46  	}
  47  	if w.I >= len(w.S) {
  48  		return ""
  49  	}
  50  	result := w.S[start:w.I]
  51  	w.I++
  52  	return result
  53  }
  54  
  55  func (w *MW) Num() (n int64) {
  56  	w.Sep()
  57  	neg := false
  58  	if w.I < len(w.S) && w.S[w.I] == '-' {
  59  		neg = true
  60  		w.I++
  61  	}
  62  	var n int64
  63  	for w.I < len(w.S) && w.S[w.I] >= '0' && w.S[w.I] <= '9' {
  64  		n = n*10 + int64(w.S[w.I]-'0')
  65  		w.I++
  66  	}
  67  	if neg {
  68  		n = -n
  69  	}
  70  	return n
  71  }
  72  
  73  func (w *MW) Raw() (s string) {
  74  	w.Sep()
  75  	start := w.I
  76  	w.I = Skipval(w.S, w.I)
  77  	if w.I < 0 {
  78  		w.I = len(w.S)
  79  		return ""
  80  	}
  81  	return w.S[start:w.I]
  82  }
  83  
  84  func (w *MW) Strs() (ss []string) {
  85  	w.Sep()
  86  	if w.I >= len(w.S) || w.S[w.I] != '[' {
  87  		return nil
  88  	}
  89  	w.I++
  90  	// Declared outside the loop, as above.
  91  	var out []string
  92  	var s string
  93  	for {
  94  		w.Sep()
  95  		if w.I >= len(w.S) || w.S[w.I] == ']' {
  96  			if w.I < len(w.S) {
  97  				w.I++
  98  			}
  99  			return out
 100  		}
 101  		s = w.Str()
 102  		out = mxutil.Ensure(out, 1)
 103  		out = push(out, s)
 104  	}
 105  }
 106  
 107  func Unescape(s string) (sv string) {
 108  	if len(s) == 0 {
 109  		return s
 110  	}
 111  	i := 0
 112  	for i < len(s) {
 113  		if s[i] == '\\' {
 114  			break
 115  		}
 116  		i++
 117  	}
 118  	if i == len(s) {
 119  		return s
 120  	}
 121  	out := []byte{:0:len(s)}
 122  	out = out | s[:i]
 123  	for i < len(s) {
 124  		if s[i] == '\\' && i+1 < len(s) {
 125  			c := s[i+1]
 126  			if c == '"' || c == '\\' || c == '/' {
 127  				out = push(out, c)
 128  			} else if c == 'n' {
 129  				out = out | "\n"
 130  			} else if c == 'r' {
 131  				out = out | "\r"
 132  			} else if c == 't' {
 133  				out = out | "\t"
 134  			} else {
 135  				out = push(out, s[i])
 136  				out = push(out, c)
 137  			}
 138  			i += 2
 139  		} else {
 140  			out = push(out, s[i])
 141  			i++
 142  		}
 143  	}
 144  	return string(out)
 145  }
 146  
 147  func Skipval(s string, i int32) (n int32) {
 148  	if i >= len(s) {
 149  		return -1
 150  	}
 151  	c := s[i]
 152  	if c == '"' {
 153  		i++
 154  		for i < len(s) && s[i] != '"' {
 155  			if s[i] == '\\' {
 156  				i++
 157  			}
 158  			i++
 159  		}
 160  		if i >= len(s) {
 161  			return -1
 162  		}
 163  		return i + 1
 164  	}
 165  	if c == '{' || c == '[' {
 166  		open := c
 167  		closeB := byte('}')
 168  		if open == '[' {
 169  			closeB = ']'
 170  		}
 171  		depth := 1
 172  		i++
 173  		for i < len(s) && depth > 0 {
 174  			if s[i] == '"' {
 175  				i++
 176  				for i < len(s) && s[i] != '"' {
 177  					if s[i] == '\\' {
 178  						i++
 179  					}
 180  					i++
 181  				}
 182  				if i >= len(s) {
 183  					return -1
 184  				}
 185  				i++
 186  				continue
 187  			}
 188  			if s[i] == open {
 189  				depth++
 190  			} else if s[i] == closeB {
 191  				depth--
 192  				if depth == 0 {
 193  					return i + 1
 194  				}
 195  			}
 196  			i++
 197  		}
 198  		return -1
 199  	}
 200  	for i < len(s) {
 201  		c = s[i]
 202  		if c == ',' || c == ']' || c == '}' {
 203  			return i
 204  		}
 205  		i++
 206  	}
 207  	return i
 208  }
 209