aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffas <dev@jeffas.io>2020-02-29 01:27:31 +0000
committerDrew DeVault <sir@cmpwn.com>2020-02-28 20:54:14 -0500
commite8b7b3bcc16329ab9fe402d6629db775f197b73b (patch)
tree79905088ef2c0e50d75536412a8e8fda30f1cf45
parent583b129c9470a060d17c952b46dbe1bffc4c0c49 (diff)
Cleanup sorting logic
There was an unused error value as well as unnecessary usage of the sort interface. There should now be less copying so a bit better performance in some cases.
-rw-r--r--worker/lib/sort.go210
1 files changed, 55 insertions, 155 deletions
diff --git a/worker/lib/sort.go b/worker/lib/sort.go
index 36c0924..ac8ed07 100644
--- a/worker/lib/sort.go
+++ b/worker/lib/sort.go
@@ -4,7 +4,6 @@ import (
"fmt"
"sort"
"strings"
- "time"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@@ -15,51 +14,44 @@ func Sort(messageInfos []*models.MessageInfo,
// loop through in reverse to ensure we sort by non-primary fields first
for i := len(criteria) - 1; i >= 0; i-- {
criterion := criteria[i]
- var err error
switch criterion.Field {
case types.SortArrival:
- err = sortDate(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) time.Time {
- return msgInfo.InternalDate
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].InternalDate.Before(messageInfos[j].InternalDate)
+ })
case types.SortCc:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.Cc
})
case types.SortDate:
- err = sortDate(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) time.Time {
- return msgInfo.Envelope.Date
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].Envelope.Date.Before(messageInfos[j].Envelope.Date)
+ })
case types.SortFrom:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.From
})
case types.SortRead:
- err = sortFlags(messageInfos, criterion, models.SeenFlag)
+ sortFlags(messageInfos, criterion, models.SeenFlag)
case types.SortSize:
- err = sortInts(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) uint32 {
- return msgInfo.Size
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].Size < messageInfos[j].Size
+ })
case types.SortSubject:
- err = sortStrings(messageInfos, criterion,
+ sortStrings(messageInfos, criterion,
func(msgInfo *models.MessageInfo) string {
subject := strings.ToLower(msgInfo.Envelope.Subject)
subject = strings.TrimPrefix(subject, "re: ")
return strings.TrimPrefix(subject, "fwd: ")
})
case types.SortTo:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.To
})
}
- if err != nil {
- return nil, err
- }
}
var uids []uint32
// copy in reverse as msgList displays backwards
@@ -69,40 +61,38 @@ func Sort(messageInfos []*models.MessageInfo,
return uids, nil
}
-func sortDate(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) time.Time) error {
- var slice []*dateStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &dateStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, dateSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
-}
-
func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) []*models.Address) error {
- var slice []*addressStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &addressStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, addressSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
+ getValue func(*models.MessageInfo) []*models.Address) {
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ addressI, addressJ := getValue(messageInfos[i]), getValue(messageInfos[j])
+ var firstI, firstJ *models.Address
+ if len(addressI) > 0 {
+ firstI = addressI[0]
+ }
+ if len(addressJ) > 0 {
+ firstJ = addressJ[0]
+ }
+ if firstI == nil && firstJ == nil {
+ return false
+ } else if firstI == nil && firstJ != nil {
+ return false
+ } else if firstI != nil && firstJ == nil {
+ return true
+ } else /* firstI != nil && firstJ != nil */ {
+ getName := func(addr *models.Address) string {
+ if addr.Name != "" {
+ return addr.Name
+ } else {
+ return fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)
+ }
+ }
+ return getName(firstI) < getName(firstJ)
+ }
+ })
}
func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- testFlag models.Flag) error {
+ testFlag models.Flag) {
var slice []*boolStore
for _, msgInfo := range messageInfos {
flagPresent := false
@@ -116,31 +106,17 @@ func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterio
MsgInfo: msgInfo,
})
}
- sortSlice(criterion, boolSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
-}
-
-func sortInts(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) uint32) error {
- var slice []*intStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &intStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, intSlice{slice})
+ sortSlice(criterion, slice, func(i, j int) bool {
+ valI, valJ := slice[i].Value, slice[j].Value
+ return valI && !valJ
+ })
for i := 0; i < len(messageInfos); i++ {
messageInfos[i] = slice[i].MsgInfo
}
- return nil
}
func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) string) error {
+ getValue func(*models.MessageInfo) string) {
var slice []*lexiStore
for _, msgInfo := range messageInfos {
slice = append(slice, &lexiStore{
@@ -148,11 +124,12 @@ func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriter
MsgInfo: msgInfo,
})
}
- sortSlice(criterion, lexiSlice{slice})
+ sortSlice(criterion, slice, func(i, j int) bool {
+ return slice[i].Value < slice[j].Value
+ })
for i := 0; i < len(messageInfos); i++ {
messageInfos[i] = slice[i].MsgInfo
}
- return nil
}
type lexiStore struct {
@@ -160,94 +137,17 @@ type lexiStore struct {
MsgInfo *models.MessageInfo
}
-type lexiSlice struct{ Slice []*lexiStore }
-
-func (s lexiSlice) Len() int { return len(s.Slice) }
-func (s lexiSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s lexiSlice) Less(i, j int) bool {
- return s.Slice[i].Value < s.Slice[j].Value
-}
-
-type dateStore struct {
- Value time.Time
- MsgInfo *models.MessageInfo
-}
-
-type dateSlice struct{ Slice []*dateStore }
-
-func (s dateSlice) Len() int { return len(s.Slice) }
-func (s dateSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s dateSlice) Less(i, j int) bool {
- return s.Slice[i].Value.Before(s.Slice[j].Value)
-}
-
-type intStore struct {
- Value uint32
- MsgInfo *models.MessageInfo
-}
-
-type intSlice struct{ Slice []*intStore }
-
-func (s intSlice) Len() int { return len(s.Slice) }
-func (s intSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s intSlice) Less(i, j int) bool {
- return s.Slice[i].Value < s.Slice[j].Value
-}
-
-type addressStore struct {
- Value []*models.Address
- MsgInfo *models.MessageInfo
-}
-
-type addressSlice struct{ Slice []*addressStore }
-
-func (s addressSlice) Len() int { return len(s.Slice) }
-func (s addressSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s addressSlice) Less(i, j int) bool {
- addressI, addressJ := s.Slice[i].Value, s.Slice[j].Value
- var firstI, firstJ *models.Address
- if len(addressI) > 0 {
- firstI = addressI[0]
- }
- if len(addressJ) > 0 {
- firstJ = addressJ[0]
- }
- if firstI == nil && firstJ == nil {
- return false
- } else if firstI == nil && firstJ != nil {
- return false
- } else if firstI != nil && firstJ == nil {
- return true
- } else /* firstI != nil && firstJ != nil */ {
- getName := func(addr *models.Address) string {
- if addr.Name != "" {
- return addr.Name
- } else {
- return fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)
- }
- }
- return getName(firstI) < getName(firstJ)
- }
-}
-
type boolStore struct {
Value bool
MsgInfo *models.MessageInfo
}
-type boolSlice struct{ Slice []*boolStore }
-
-func (s boolSlice) Len() int { return len(s.Slice) }
-func (s boolSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s boolSlice) Less(i, j int) bool {
- valI, valJ := s.Slice[i].Value, s.Slice[j].Value
- return valI && !valJ
-}
-
-func sortSlice(criterion *types.SortCriterion, interfce sort.Interface) {
+func sortSlice(criterion *types.SortCriterion, slice interface{}, less func(i, j int) bool) {
if criterion.Reverse {
- sort.Stable(sort.Reverse(interfce))
+ sort.SliceStable(slice, func(i, j int) bool {
+ return less(j, i)
+ })
} else {
- sort.Stable(interfce)
+ sort.SliceStable(slice, less)
}
}