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