perkeep/pkg/index/util.go

128 lines
3.0 KiB
Go

/*
Copyright 2011 The Perkeep Authors
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 index
import (
"net/url"
"time"
"perkeep.org/pkg/schema"
"perkeep.org/pkg/types/camtypes"
)
var urle = url.QueryEscape
func urld(s string) string {
d, _ := url.QueryUnescape(s)
return d
}
type dupSkipper struct {
m map[string]bool
}
// not thread safe.
func (s *dupSkipper) Dup(v string) bool {
if s.m == nil {
s.m = make(map[string]bool)
}
if s.m[v] {
return true
}
s.m[v] = true
return false
}
// claimPtrsAttrValue returns the value of attr from claims,
// or the empty string if not found.
// Claims should be sorted by claim.Date.
func claimPtrsAttrValue(claims []*camtypes.Claim, attr string, at time.Time, signerFilter SignerRefSet) string {
return claimsIntfAttrValue(claimPtrSlice(claims), attr, at, signerFilter)
}
type claimsIntf interface {
Len() int
Claim(i int) *camtypes.Claim
}
type claimSlice []camtypes.Claim
func (s claimSlice) Len() int { return len(s) }
func (s claimSlice) Claim(i int) *camtypes.Claim { return &s[i] }
type claimPtrSlice []*camtypes.Claim
func (s claimPtrSlice) Len() int { return len(s) }
func (s claimPtrSlice) Claim(i int) *camtypes.Claim { return s[i] }
// claimsIntfAttrValue finds the value of an attribute in a list of claims
// or empty string if not found. claims must be non-nil.
// If signerFilter contains any refs, a claim is only taken into account if it
// has been signed by one of the given signer refs.
func claimsIntfAttrValue(claims claimsIntf, attr string, at time.Time, signerFilter SignerRefSet) string {
if claims == nil {
panic("nil claims argument in claimsIntfAttrValue")
}
if at.IsZero() {
at = time.Now()
}
// use a small static buffer as it speeds up
// search.BenchmarkQueryPermanodeLocation by 6-7%
// with go 1.7.1
var buf [8]string
v := buf[:][:0]
for i := 0; i < claims.Len(); i++ {
cl := claims.Claim(i)
if cl.Attr != attr || cl.Date.After(at) {
continue
}
if len(signerFilter) > 0 {
if !signerFilter.blobMatches(cl.Signer) {
continue
}
}
switch cl.Type {
case string(schema.DelAttributeClaim):
if cl.Value == "" {
v = v[:0]
} else {
i := 0
for _, w := range v {
if w != cl.Value {
v[i] = w
i++
}
}
v = v[:i]
}
case string(schema.SetAttributeClaim):
v = append(v[:0], cl.Value)
case string(schema.AddAttributeClaim):
v = append(v, cl.Value)
}
}
if len(v) != 0 {
return v[0]
}
return ""
}