%PDF- %PDF-
| Direktori : /home/waritko/go/src/github.com/odeke-em/drive/src/ |
| Current File : //home/waritko/go/src/github.com/odeke-em/drive/src/sort.go |
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package drive
import (
"sort"
"strings"
)
const (
AttrUnknown = iota
AttrSize
AttrModTime
AttrLastViewedByMeTime
AttrVersion
AttrIsDir
AttrMd5Checksum
AttrMimeType
AttrName
)
type attr int
type fileList []*File
type lastViewedTimeFlist fileList
type md5Flist fileList
type mimeTypeFlist fileList
type modTimeFlist fileList
type nameFlist fileList
type sizeFlist fileList
type typeFlist fileList
type versionFlist fileList
var (
lastViewedTimeCmpLess = _lessCmper(AttrLastViewedByMeTime)
md5CmpLess = _lessCmper(AttrMd5Checksum)
mimeTypeCmpLess = _lessCmper(AttrMimeType)
modTimeCmpLess = _lessCmper(AttrModTime)
nameCmpLess = _lessCmper(AttrName)
sizeCmpLess = _lessCmper(AttrSize)
versionCmpLess = _lessCmper(AttrVersion)
typeCmpLess = _lessCmper(AttrIsDir)
)
func (fl modTimeFlist) Less(i, j int) bool {
return modTimeCmpLess(fl[i], fl[j])
}
func (fl modTimeFlist) Len() int {
return len(fl)
}
func (fl modTimeFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl typeFlist) Less(i, j int) bool {
return typeCmpLess(fl[i], fl[j])
}
func (fl typeFlist) Len() int {
return len(fl)
}
func (fl typeFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl mimeTypeFlist) Less(i, j int) bool {
return mimeTypeCmpLess(fl[i], fl[j])
}
func (fl mimeTypeFlist) Len() int {
return len(fl)
}
func (fl mimeTypeFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl lastViewedTimeFlist) Less(i, j int) bool {
return lastViewedTimeCmpLess(fl[i], fl[j])
}
func (fl lastViewedTimeFlist) Len() int {
return len(fl)
}
func (fl lastViewedTimeFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl versionFlist) Less(i, j int) bool {
return versionCmpLess(fl[i], fl[j])
}
func (fl versionFlist) Len() int {
return len(fl)
}
func (fl versionFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl nameFlist) Less(i, j int) bool {
return nameCmpLess(fl[i], fl[j])
}
func (fl nameFlist) Len() int {
return len(fl)
}
func (fl nameFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl md5Flist) Less(i, j int) bool {
return md5CmpLess(fl[i], fl[j])
}
func (fl md5Flist) Len() int {
return len(fl)
}
func (fl md5Flist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func (fl sizeFlist) Less(i, j int) bool {
return sizeCmpLess(fl[i], fl[j])
}
func (fl sizeFlist) Len() int {
return len(fl)
}
func (fl sizeFlist) Swap(i, j int) {
fl[i], fl[j] = fl[j], fl[i]
}
func attrAtoiSorter(a string, fl []*File) (attr, sort.Interface, bool) {
aLower := strings.ToLower(a)
if len(aLower) < 1 {
return AttrUnknown, nil, false
}
reverse := hasAnySuffix(aLower, "_r", "-")
if hasAnyPrefix(aLower, Md5Key) {
return AttrMd5Checksum, md5Flist(fl), reverse
}
if hasAnyPrefix(aLower, NameKey) {
return AttrName, nameFlist(fl), reverse
}
if hasAnyPrefix(aLower, SizeKey) {
return AttrSize, sizeFlist(fl), reverse
}
if hasAnyPrefix(aLower, TypeKey) {
return AttrIsDir, typeFlist(fl), reverse
}
if hasAnyPrefix(aLower, ModTimeKey) {
return AttrModTime, modTimeFlist(fl), reverse
}
if hasAnyPrefix(aLower, LastViewedByMeTimeKey) {
return AttrLastViewedByMeTime, lastViewedTimeFlist(fl), reverse
}
if hasAnyPrefix(aLower, VersionKey) {
return AttrVersion, versionFlist(fl), reverse
}
return AttrUnknown, nil, false
}
func nilCmpOrProceed(fallback func(*File, *File) bool) func(*File, *File) bool {
return func(l, r *File) bool {
if l == nil {
return false
}
if r == nil {
return true
}
return fallback(l, r)
}
}
func _lessCmper(_attr attr) func(*File, *File) bool {
switch _attr {
case AttrSize:
return nilCmpOrProceed(func(l, r *File) bool { return l.Size < r.Size })
case AttrVersion:
return nilCmpOrProceed(func(l, r *File) bool { return l.Version < r.Version })
case AttrIsDir:
return nilCmpOrProceed(func(l, r *File) bool { return !l.IsDir })
case AttrMd5Checksum:
return nilCmpOrProceed(func(l, r *File) bool { return l.Md5Checksum < r.Md5Checksum })
case AttrName:
return nilCmpOrProceed(func(l, r *File) bool { return l.Name < r.Name })
case AttrModTime:
return nilCmpOrProceed(func(l, r *File) bool { return l.ModTime.Before(r.ModTime) })
case AttrLastViewedByMeTime:
return nilCmpOrProceed(func(l, r *File) bool { return l.LastViewedByMeTime.Before(r.LastViewedByMeTime) })
}
return nilCmpOrProceed(func(l, r *File) bool { return true })
}
func (g *Commands) sort(fl []*File, attrStrValues ...string) []*File {
for _, attrStr := range attrStrValues {
attrEnum, sortInterface, reverse := attrAtoiSorter(attrStr, fl)
if attrEnum == AttrUnknown {
g.log.LogErrf("%s is an unknown sort attribute\n", attrStr)
continue
}
if reverse {
sortInterface = sort.Reverse(sortInterface)
}
// Stable is needed if more than one sort keyword is used
sort.Stable(sortInterface)
}
return fl
}