1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
package part
import (
"fmt"
"reflect"
"strings"
)
type Parts []Part
func NewParts(s string) Parts {
var parts []Part
if s == "" {
return parts
}
for _, p := range strings.Split(s, ".") {
parts = append(parts, NewPart(p))
}
return parts
}
func (parts Parts) Normalize() Parts {
ret := make(Parts, len(parts))
copy(ret, parts)
for i := len(ret) - 1; i >= 0; i-- {
lastItem := ret[i]
if lastItem.IsNull() {
ret = ret[:i]
continue
}
break
}
return ret
}
func (parts Parts) Padding(size int, padding Part) Parts {
diff := size - len(parts)
if diff <= 0 {
return parts
}
padded := parts
for i := 0; i < diff; i++ {
padded = append(padded, padding)
}
return padded
}
func (parts Parts) Compare(other Part) int {
if other == nil {
return 1
} else if other.IsAny() {
return 0
}
var o Parts
switch t := other.(type) {
case InfinityType:
return -1
case NegativeInfinityType:
return 1
case Parts:
o = t
default:
return -1
}
if reflect.DeepEqual(parts, o) {
return 0
}
iter := parts.Zip(o)
for tuple := iter(); tuple != nil; tuple = iter() {
var l, r = tuple.Left, tuple.Right
if l == nil {
return -1
}
if r == nil {
return 1
}
if l.IsAny() || r.IsAny() {
return 0
}
if result := l.Compare(r); result != 0 {
return result
}
}
return 0
}
func (parts Parts) IsNull() bool {
return parts.IsAny() || len(parts) == 0
}
func (parts Parts) IsAny() bool {
for _, p := range parts {
if p.IsAny() {
return true
}
}
return false
}
func (parts Parts) IsEmpty() bool {
return false
}
func (parts Parts) String() string {
s := make([]string, len(parts))
for i, p := range parts {
s[i] = fmt.Sprint(p)
}
return strings.Join(s, ".")
}
type ZipTuple struct {
Left Part
Right Part
}
func (parts Parts) Zip(other Parts) func() *ZipTuple {
i := 0
return func() *ZipTuple {
var part1, part2 Part
if i < len(parts) {
part1 = parts[i]
}
if i < len(other) {
part2 = other[i]
}
if part1 == nil && part2 == nil {
return nil
}
i++
return &ZipTuple{Left: part1, Right: part2}
}
}
func Uint64SliceToParts(uint64Parts []Uint64) Parts {
parts := make(Parts, len(uint64Parts))
for i, u := range uint64Parts {
parts[i] = u
}
return parts
}
|