tags.mx raw

   1  package tag
   2  
   3  import (
   4  	"bytes"
   5  
   6  	"smesh.lol/pkg/lol/chk"
   7  	"smesh.lol/pkg/lol/log"
   8  )
   9  
  10  type S []*T
  11  
  12  func NewS(t ...*T) *S {
  13  	s := S(t)
  14  	return &s
  15  }
  16  
  17  func NewSWithCap(c int) *S {
  18  	ss := (make)(S, 0, c)
  19  	return &ss
  20  }
  21  
  22  func (s *S) Len() int {
  23  	if s == nil {
  24  		return 0
  25  	}
  26  	return len(*s)
  27  }
  28  
  29  func (s *S) Less(i, j int) bool {
  30  	return bytes.Compare((*s)[i].T[0], (*s)[j].T[0]) < 0
  31  }
  32  
  33  func (s *S) Swap(i, j int) {
  34  	(*s)[i].T, (*s)[j].T = (*s)[j].T, (*s)[i].T
  35  }
  36  
  37  func (s *S) Append(t ...*T) {
  38  	*s = append(*s, t...)
  39  }
  40  
  41  func (s *S) ContainsAny(tagName []byte, values [][]byte) bool {
  42  	if s == nil || len(tagName) < 1 {
  43  		return false
  44  	}
  45  	isBinaryTag := len(tagName) == 1 && (tagName[0] == 'e' || tagName[0] == 'p')
  46  	for _, v := range *s {
  47  		if v.Len() < 2 {
  48  			continue
  49  		}
  50  		if !bytes.Equal(v.Key(), tagName) {
  51  			continue
  52  		}
  53  		var tagValue []byte
  54  		if isBinaryTag {
  55  			tagValue = v.ValueHex()
  56  		} else {
  57  			tagValue = v.Value()
  58  		}
  59  		for _, candidate := range values {
  60  			if bytes.HasPrefix(tagValue, candidate) {
  61  				return true
  62  			}
  63  		}
  64  	}
  65  	return false
  66  }
  67  
  68  func (s *S) MarshalJSON() ([]byte, error) {
  69  	b := []byte{'['}
  70  	for i, ss := range *s {
  71  		b = ss.Marshal(b)
  72  		if i < len(*s)-1 {
  73  			b = append(b, ',')
  74  		}
  75  	}
  76  	b = append(b, ']')
  77  	return b, nil
  78  }
  79  
  80  func (s *S) Marshal(dst []byte) (b []byte) {
  81  	if s == nil {
  82  		log.I.F([]byte("tags cannot be used without initialization"))
  83  		return
  84  	}
  85  	b = dst
  86  	b = append(b, '[')
  87  	for i, ss := range *s {
  88  		b = ss.Marshal(b)
  89  		if i < len(*s)-1 {
  90  			b = append(b, ',')
  91  		}
  92  	}
  93  	b = append(b, ']')
  94  	return
  95  }
  96  
  97  func (s *S) UnmarshalJSON(b []byte) error {
  98  	_, err := s.Unmarshal(b)
  99  	return err
 100  }
 101  
 102  func (s *S) Unmarshal(b []byte) (r []byte, err error) {
 103  	r = b[:]
 104  	*s = (make)(S, 0, 16)
 105  	for len(r) > 0 {
 106  		switch r[0] {
 107  		case '[':
 108  			r = r[1:]
 109  			goto inTags
 110  		case ',':
 111  			r = r[1:]
 112  		case ']':
 113  			r = r[1:]
 114  			return
 115  		default:
 116  			r = r[1:]
 117  		}
 118  	inTags:
 119  		for len(r) > 0 {
 120  			switch r[0] {
 121  			case '[':
 122  				tt := New()
 123  				if r, err = tt.Unmarshal(r); chk.E(err) {
 124  					return
 125  				}
 126  				*s = append(*s, tt)
 127  			case ',':
 128  				r = r[1:]
 129  			case ']':
 130  				r = r[1:]
 131  				return
 132  			default:
 133  				r = r[1:]
 134  			}
 135  		}
 136  	}
 137  	return
 138  }
 139  
 140  func (s *S) GetFirst(t []byte) *T {
 141  	if s == nil || len(*s) < 1 {
 142  		return nil
 143  	}
 144  	for _, tt := range *s {
 145  		if tt.Len() == 0 {
 146  			continue
 147  		}
 148  		if bytes.Equal(tt.T[0], t) {
 149  			return tt
 150  		}
 151  	}
 152  	return nil
 153  }
 154  
 155  func (s *S) GetAll(t []byte) []*T {
 156  	if s == nil || len(*s) < 1 {
 157  		return nil
 158  	}
 159  	all := []*T{:0:4}
 160  	for _, tt := range *s {
 161  		if len(tt.T) < 1 {
 162  			continue
 163  		}
 164  		if bytes.Equal(tt.T[0], t) {
 165  			all = append(all, tt)
 166  		}
 167  	}
 168  	return all
 169  }
 170  
 171  func (s *S) GetTagElement(i int) *T {
 172  	if s == nil || len(*s) < i {
 173  		return nil
 174  	}
 175  	return (*s)[i]
 176  }
 177