mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	* Update makefile to use dep * Migrate to dep * Fix some deps * Try to find a better version for golang.org/x/net * Try to find a better version for golang.org/x/oauth2
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2013 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package cldr
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"sort"
 | 
						|
)
 | 
						|
 | 
						|
// Slice provides utilities for modifying slices of elements.
 | 
						|
// It can be wrapped around any slice of which the element type implements
 | 
						|
// interface Elem.
 | 
						|
type Slice struct {
 | 
						|
	ptr reflect.Value
 | 
						|
	typ reflect.Type
 | 
						|
}
 | 
						|
 | 
						|
// Value returns the reflect.Value of the underlying slice.
 | 
						|
func (s *Slice) Value() reflect.Value {
 | 
						|
	return s.ptr.Elem()
 | 
						|
}
 | 
						|
 | 
						|
// MakeSlice wraps a pointer to a slice of Elems.
 | 
						|
// It replaces the array pointed to by the slice so that subsequent modifications
 | 
						|
// do not alter the data in a CLDR type.
 | 
						|
// It panics if an incorrect type is passed.
 | 
						|
func MakeSlice(slicePtr interface{}) Slice {
 | 
						|
	ptr := reflect.ValueOf(slicePtr)
 | 
						|
	if ptr.Kind() != reflect.Ptr {
 | 
						|
		panic(fmt.Sprintf("MakeSlice: argument must be pointer to slice, found %v", ptr.Type()))
 | 
						|
	}
 | 
						|
	sl := ptr.Elem()
 | 
						|
	if sl.Kind() != reflect.Slice {
 | 
						|
		panic(fmt.Sprintf("MakeSlice: argument must point to a slice, found %v", sl.Type()))
 | 
						|
	}
 | 
						|
	intf := reflect.TypeOf((*Elem)(nil)).Elem()
 | 
						|
	if !sl.Type().Elem().Implements(intf) {
 | 
						|
		panic(fmt.Sprintf("MakeSlice: element type of slice (%v) does not implement Elem", sl.Type().Elem()))
 | 
						|
	}
 | 
						|
	nsl := reflect.MakeSlice(sl.Type(), sl.Len(), sl.Len())
 | 
						|
	reflect.Copy(nsl, sl)
 | 
						|
	sl.Set(nsl)
 | 
						|
	return Slice{
 | 
						|
		ptr: ptr,
 | 
						|
		typ: sl.Type().Elem().Elem(),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (s Slice) indexForAttr(a string) []int {
 | 
						|
	for i := iter(reflect.Zero(s.typ)); !i.done(); i.next() {
 | 
						|
		if n, _ := xmlName(i.field()); n == a {
 | 
						|
			return i.index
 | 
						|
		}
 | 
						|
	}
 | 
						|
	panic(fmt.Sprintf("MakeSlice: no attribute %q for type %v", a, s.typ))
 | 
						|
}
 | 
						|
 | 
						|
// Filter filters s to only include elements for which fn returns true.
 | 
						|
func (s Slice) Filter(fn func(e Elem) bool) {
 | 
						|
	k := 0
 | 
						|
	sl := s.Value()
 | 
						|
	for i := 0; i < sl.Len(); i++ {
 | 
						|
		vi := sl.Index(i)
 | 
						|
		if fn(vi.Interface().(Elem)) {
 | 
						|
			sl.Index(k).Set(vi)
 | 
						|
			k++
 | 
						|
		}
 | 
						|
	}
 | 
						|
	sl.Set(sl.Slice(0, k))
 | 
						|
}
 | 
						|
 | 
						|
// Group finds elements in s for which fn returns the same value and groups
 | 
						|
// them in a new Slice.
 | 
						|
func (s Slice) Group(fn func(e Elem) string) []Slice {
 | 
						|
	m := make(map[string][]reflect.Value)
 | 
						|
	sl := s.Value()
 | 
						|
	for i := 0; i < sl.Len(); i++ {
 | 
						|
		vi := sl.Index(i)
 | 
						|
		key := fn(vi.Interface().(Elem))
 | 
						|
		m[key] = append(m[key], vi)
 | 
						|
	}
 | 
						|
	keys := []string{}
 | 
						|
	for k, _ := range m {
 | 
						|
		keys = append(keys, k)
 | 
						|
	}
 | 
						|
	sort.Strings(keys)
 | 
						|
	res := []Slice{}
 | 
						|
	for _, k := range keys {
 | 
						|
		nsl := reflect.New(sl.Type())
 | 
						|
		nsl.Elem().Set(reflect.Append(nsl.Elem(), m[k]...))
 | 
						|
		res = append(res, MakeSlice(nsl.Interface()))
 | 
						|
	}
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
// SelectAnyOf filters s to contain only elements for which attr matches
 | 
						|
// any of the values.
 | 
						|
func (s Slice) SelectAnyOf(attr string, values ...string) {
 | 
						|
	index := s.indexForAttr(attr)
 | 
						|
	s.Filter(func(e Elem) bool {
 | 
						|
		vf := reflect.ValueOf(e).Elem().FieldByIndex(index)
 | 
						|
		return in(values, vf.String())
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// SelectOnePerGroup filters s to include at most one element e per group of
 | 
						|
// elements matching Key(attr), where e has an attribute a that matches any
 | 
						|
// the values in v.
 | 
						|
// If more than one element in a group matches a value in v preference
 | 
						|
// is given to the element that matches the first value in v.
 | 
						|
func (s Slice) SelectOnePerGroup(a string, v []string) {
 | 
						|
	index := s.indexForAttr(a)
 | 
						|
	grouped := s.Group(func(e Elem) string { return Key(e, a) })
 | 
						|
	sl := s.Value()
 | 
						|
	sl.Set(sl.Slice(0, 0))
 | 
						|
	for _, g := range grouped {
 | 
						|
		e := reflect.Value{}
 | 
						|
		found := len(v)
 | 
						|
		gsl := g.Value()
 | 
						|
		for i := 0; i < gsl.Len(); i++ {
 | 
						|
			vi := gsl.Index(i).Elem().FieldByIndex(index)
 | 
						|
			j := 0
 | 
						|
			for ; j < len(v) && v[j] != vi.String(); j++ {
 | 
						|
			}
 | 
						|
			if j < found {
 | 
						|
				found = j
 | 
						|
				e = gsl.Index(i)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if found < len(v) {
 | 
						|
			sl.Set(reflect.Append(sl, e))
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// SelectDraft drops all elements from the list with a draft level smaller than d
 | 
						|
// and selects the highest draft level of the remaining.
 | 
						|
// This method assumes that the input CLDR is canonicalized.
 | 
						|
func (s Slice) SelectDraft(d Draft) {
 | 
						|
	s.SelectOnePerGroup("draft", drafts[len(drafts)-2-int(d):])
 | 
						|
}
 |