Skip to content

Commit cd04677

Browse files
committed
Update minimal go version to 1.18
Upgrading to 1.18 allows the package to rely on generic implementations of its internal stack and queue data structures.
1 parent 4fe8b8c commit cd04677

File tree

5 files changed

+36
-49
lines changed

5 files changed

+36
-49
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
strategy:
1616
matrix:
17-
go-version: [ '1.16', '1.21', '1.22.x' ]
17+
go-version: [ '1.18', '1.21', '1.22.x' ]
1818

1919
steps:
2020
- uses: actions/checkout@v4

etree.go

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"errors"
1414
"io"
1515
"os"
16-
"sort"
16+
"slices"
1717
"strings"
1818
)
1919

@@ -858,12 +858,12 @@ func (e *Element) RemoveChildAt(index int) Token {
858858

859859
// autoClose analyzes the stack's top element and the current token to decide
860860
// whether the top element should be closed.
861-
func (e *Element) autoClose(stack *stack, t xml.Token, tags []string) {
861+
func (e *Element) autoClose(stack *stack[*Element], t xml.Token, tags []string) {
862862
if stack.empty() {
863863
return
864864
}
865865

866-
top := stack.peek().(*Element)
866+
top := stack.peek()
867867

868868
for _, tag := range tags {
869869
if strings.EqualFold(tag, top.FullTag()) {
@@ -891,7 +891,7 @@ func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err er
891891

892892
dec := newDecoder(r, settings)
893893

894-
var stack stack
894+
var stack stack[*Element]
895895
stack.push(e)
896896
for {
897897
if pr != nil {
@@ -916,7 +916,7 @@ func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err er
916916
return r.Bytes(), ErrXML
917917
}
918918

919-
top := stack.peek().(*Element)
919+
top := stack.peek()
920920

921921
switch t := t.(type) {
922922
case xml.StartElement:
@@ -1411,25 +1411,12 @@ func (e *Element) RemoveAttr(key string) *Attr {
14111411

14121412
// SortAttrs sorts this element's attributes lexicographically by key.
14131413
func (e *Element) SortAttrs() {
1414-
sort.Sort(byAttr(e.Attr))
1415-
}
1416-
1417-
type byAttr []Attr
1418-
1419-
func (a byAttr) Len() int {
1420-
return len(a)
1421-
}
1422-
1423-
func (a byAttr) Swap(i, j int) {
1424-
a[i], a[j] = a[j], a[i]
1425-
}
1426-
1427-
func (a byAttr) Less(i, j int) bool {
1428-
sp := strings.Compare(a[i].Space, a[j].Space)
1429-
if sp == 0 {
1430-
return strings.Compare(a[i].Key, a[j].Key) < 0
1431-
}
1432-
return sp < 0
1414+
slices.SortFunc(e.Attr, func(a, b Attr) int {
1415+
if v := strings.Compare(a.Space, b.Space); v != 0 {
1416+
return v
1417+
}
1418+
return strings.Compare(a.Key, b.Key)
1419+
})
14331420
}
14341421

14351422
// FullKey returns this attribute's complete key, including namespace prefix

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/beevik/etree
22

3-
go 1.16
3+
go 1.18

helpers.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,36 @@ import (
1010
"unicode/utf8"
1111
)
1212

13-
// A simple stack
14-
type stack struct {
15-
data []interface{}
13+
type stack[E any] struct {
14+
data []E
1615
}
1716

18-
func (s *stack) empty() bool {
17+
func (s *stack[E]) empty() bool {
1918
return len(s.data) == 0
2019
}
2120

22-
func (s *stack) push(value interface{}) {
21+
func (s *stack[E]) push(value E) {
2322
s.data = append(s.data, value)
2423
}
2524

26-
func (s *stack) pop() interface{} {
25+
func (s *stack[E]) pop() E {
2726
value := s.data[len(s.data)-1]
28-
s.data[len(s.data)-1] = nil
27+
var empty E
28+
s.data[len(s.data)-1] = empty
2929
s.data = s.data[:len(s.data)-1]
3030
return value
3131
}
3232

33-
func (s *stack) peek() interface{} {
33+
func (s *stack[E]) peek() E {
3434
return s.data[len(s.data)-1]
3535
}
3636

37-
// A fifo is a simple first-in-first-out queue.
38-
type fifo struct {
39-
data []interface{}
37+
type queue[E any] struct {
38+
data []E
4039
head, tail int
4140
}
4241

43-
func (f *fifo) add(value interface{}) {
42+
func (f *queue[E]) add(value E) {
4443
if f.len()+1 >= len(f.data) {
4544
f.grow()
4645
}
@@ -50,33 +49,34 @@ func (f *fifo) add(value interface{}) {
5049
}
5150
}
5251

53-
func (f *fifo) remove() interface{} {
52+
func (f *queue[E]) remove() E {
5453
value := f.data[f.head]
55-
f.data[f.head] = nil
54+
var empty E
55+
f.data[f.head] = empty
5656
if f.head++; f.head == len(f.data) {
5757
f.head = 0
5858
}
5959
return value
6060
}
6161

62-
func (f *fifo) len() int {
62+
func (f *queue[E]) len() int {
6363
if f.tail >= f.head {
6464
return f.tail - f.head
6565
}
6666
return len(f.data) - f.head + f.tail
6767
}
6868

69-
func (f *fifo) grow() {
69+
func (f *queue[E]) grow() {
7070
c := len(f.data) * 2
7171
if c == 0 {
7272
c = 4
7373
}
74-
buf, count := make([]interface{}, c), f.len()
74+
buf, count := make([]E, c), f.len()
7575
if f.tail >= f.head {
76-
copy(buf[0:count], f.data[f.head:f.tail])
76+
copy(buf[:count], f.data[f.head:f.tail])
7777
} else {
7878
hindex := len(f.data) - f.head
79-
copy(buf[0:hindex], f.data[f.head:])
79+
copy(buf[:hindex], f.data[f.head:])
8080
copy(buf[hindex:count], f.data[:f.tail])
8181
}
8282
f.data, f.head, f.tail = buf, 0, count

path.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ type filter interface {
152152
// a Path object. It collects and deduplicates all elements matching
153153
// the path query.
154154
type pather struct {
155-
queue fifo
155+
queue queue[node]
156156
results []*Element
157157
inResults map[*Element]bool
158158
candidates []*Element
@@ -180,7 +180,7 @@ func newPather() *pather {
180180
// and filters.
181181
func (p *pather) traverse(e *Element, path Path) []*Element {
182182
for p.queue.add(node{e, path.segments}); p.queue.len() > 0; {
183-
p.eval(p.queue.remove().(node))
183+
p.eval(p.queue.remove())
184184
}
185185
return p.results
186186
}
@@ -406,9 +406,9 @@ func (s *selectChildren) apply(e *Element, p *pather) {
406406
type selectDescendants struct{}
407407

408408
func (s *selectDescendants) apply(e *Element, p *pather) {
409-
var queue fifo
409+
var queue queue[*Element]
410410
for queue.add(e); queue.len() > 0; {
411-
e := queue.remove().(*Element)
411+
e := queue.remove()
412412
p.candidates = append(p.candidates, e)
413413
for _, c := range e.Child {
414414
if c, ok := c.(*Element); ok {

0 commit comments

Comments
 (0)