github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/mxjson/structs.go (about)

     1  package mxjson
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  )
     7  
     8  // parser state
     9  
    10  type parserState int
    11  
    12  const (
    13  	stateBeginKey parserState = 0 + iota
    14  	stateEndKey
    15  	stateBeginVal
    16  	stateEndVal
    17  	stateExpectNext
    18  )
    19  
    20  type objectType int
    21  
    22  const (
    23  	objUndefined objectType = 0 + iota
    24  	objBoolean
    25  	objNumber
    26  	objString
    27  	objArrayUndefined
    28  	objArrayBoolean
    29  	objArrayNumber
    30  	objArrayString
    31  	objArrayArray
    32  	objArrayMap
    33  	objMap
    34  )
    35  
    36  // quote pairs
    37  
    38  type quote struct {
    39  	open bool
    40  	pos  int
    41  }
    42  
    43  func (q *quote) IsOpen() bool {
    44  	return q.open
    45  }
    46  
    47  func (q *quote) Open(pos int) {
    48  	q.open = true
    49  	q.pos = pos
    50  }
    51  
    52  func (q *quote) Close() {
    53  	q.open = false
    54  }
    55  
    56  // bracket pairs
    57  
    58  type pair struct {
    59  	pos []int
    60  	len int
    61  }
    62  
    63  func newPair() *pair {
    64  	p := new(pair)
    65  	p.pos = make([]int, 100)
    66  	return p
    67  }
    68  
    69  func (p *pair) IsOpen() bool {
    70  	return p.len != 0
    71  }
    72  
    73  func (p *pair) Open(pos int) {
    74  	if len(p.pos) == p.len {
    75  		p.pos = append(p.pos, pos)
    76  	} else {
    77  		p.pos[p.len] = pos
    78  	}
    79  	p.len++
    80  }
    81  
    82  func (p *pair) Close() error {
    83  	if p.len == 0 {
    84  		return errors.New("close found with no open")
    85  	}
    86  	p.len--
    87  	return nil
    88  }
    89  
    90  // lazy string
    91  
    92  type str struct {
    93  	b   []byte
    94  	len int
    95  }
    96  
    97  func newStr() *str {
    98  	s := new(str)
    99  	s.b = make([]byte, 1024*1024)
   100  	return s
   101  }
   102  
   103  func (s *str) Append(b byte) {
   104  	if len(s.b) == s.len {
   105  		s.b = append(s.b, b)
   106  	} else {
   107  		s.b[s.len] = b
   108  	}
   109  	s.len++
   110  }
   111  
   112  func (s *str) Get() []byte {
   113  	if s.len == 0 {
   114  		return nil
   115  	}
   116  
   117  	b := s.b[:s.len]
   118  	s.len = 0
   119  	return b
   120  }
   121  
   122  func (s *str) String() string {
   123  	if s.len == 0 {
   124  		return ""
   125  	}
   126  
   127  	b := s.b[:s.len]
   128  	s.len = 0
   129  	return string(b)
   130  }
   131  
   132  // object type
   133  
   134  type nestedObject struct {
   135  	nest []item
   136  	len  int
   137  }
   138  type item struct {
   139  	key     *str
   140  	value   interface{}
   141  	objType objectType
   142  }
   143  
   144  func newObjs() (no nestedObject) {
   145  	no.nest = make([]item, 10)
   146  	for i := range no.nest {
   147  		no.nest[i].key = newStr()
   148  	}
   149  	no.len = -1
   150  	return
   151  }
   152  
   153  func (no *nestedObject) New(objType objectType) {
   154  	no.len++
   155  
   156  	var v interface{}
   157  	switch objType {
   158  	case objUndefined:
   159  		panic("Undef object type - We should know what the data type is by now!")
   160  
   161  	case objBoolean:
   162  		v = false
   163  
   164  	case objNumber:
   165  		v = float64(0)
   166  
   167  	case objString:
   168  		v = ""
   169  
   170  	case objArrayUndefined:
   171  		//panic("Undef array - We should know what the array is by now!")
   172  		v = []interface{}{}
   173  
   174  	case objArrayBoolean:
   175  		v = []bool{}
   176  
   177  	case objArrayNumber:
   178  		v = []float64{}
   179  
   180  	case objArrayString:
   181  		v = []string{}
   182  
   183  	case objArrayArray:
   184  		v = [][]interface{}{}
   185  
   186  	case objArrayMap:
   187  		v = []interface{}{}
   188  
   189  	case objMap:
   190  		v = make(map[string]interface{})
   191  
   192  	default:
   193  		panic("This condition shouldn't arise!")
   194  	}
   195  
   196  	if len(no.nest) == no.len {
   197  		no.nest = append(no.nest, item{
   198  			key:     newStr(),
   199  			objType: objType,
   200  			value:   v,
   201  		})
   202  	} else {
   203  		no.nest[no.len].objType = objType
   204  		no.nest[no.len].value = v
   205  	}
   206  }
   207  
   208  func (no *nestedObject) GetKeyPtr() *str {
   209  	return no.nest[no.len].key
   210  }
   211  
   212  func (no *nestedObject) GetObjType() objectType {
   213  	if no.len < 0 || len(no.nest) == 0 || no.len > len(no.nest) {
   214  		return objUndefined
   215  	}
   216  	return no.nest[no.len].objType
   217  }
   218  
   219  func (no *nestedObject) SetObjType(objType objectType) {
   220  	no.nest[no.len].objType = objType
   221  }
   222  
   223  func (no *nestedObject) SetValue(value interface{}) error {
   224  	if no.len < 0 {
   225  		return fmt.Errorf("unable to marshal '%v' into parent structure. This might be due to the an incorrect file", value)
   226  	}
   227  
   228  	switch no.nest[no.len].objType {
   229  	case objUndefined:
   230  		return fmt.Errorf("undef object type. We should know what the data type is by now. Please file a bug at https://github.com/lmorg/murex/issues")
   231  
   232  	case objBoolean:
   233  		no.nest[no.len].value = value.(bool)
   234  
   235  	case objNumber:
   236  		no.nest[no.len].value = value.(float64)
   237  
   238  	case objString:
   239  		no.nest[no.len].value = value.(string)
   240  
   241  	case objArrayUndefined:
   242  		//panic("Undef array - We should know what the array is by now!")
   243  		no.nest[no.len].value = append(no.nest[no.len].value.([]interface{}), value)
   244  
   245  	case objArrayBoolean:
   246  		no.nest[no.len].value = append(no.nest[no.len].value.([]bool), value.(bool))
   247  
   248  	case objArrayNumber:
   249  		no.nest[no.len].value = append(no.nest[no.len].value.([]float64), value.(float64))
   250  
   251  	case objArrayString:
   252  		no.nest[no.len].value = append(no.nest[no.len].value.([]string), value.(string))
   253  
   254  	case objArrayArray:
   255  		no.nest[no.len].value = append(no.nest[no.len].value.([][]interface{}), value.([]interface{}))
   256  
   257  	case objArrayMap:
   258  		no.nest[no.len].value = append(no.nest[no.len].value.([]interface{}), value)
   259  
   260  	case objMap:
   261  		no.nest[no.len].value.(map[string]interface{})[no.nest[no.len].key.String()] = value
   262  
   263  	default:
   264  		return fmt.Errorf("switch statement unexpectedly failed. This condition shouldn't arise, so please file a bug at https://github.com/lmorg/murex/issues")
   265  	}
   266  
   267  	return nil
   268  }
   269  
   270  func (no *nestedObject) MergeDown() {
   271  	switch no.len {
   272  	case -1:
   273  		panic("This condition shouldn't arise!")
   274  
   275  	case 0:
   276  		no.len--
   277  
   278  	default:
   279  		no.len--
   280  		no.SetValue(no.nest[no.len+1].value)
   281  	}
   282  }