OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / currency / query.go
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package currency
6
7 import (
8         "sort"
9         "time"
10
11         "golang.org/x/text/language"
12 )
13
14 // QueryIter represents a set of Units. The default set includes all Units that
15 // are currently in use as legal tender in any Region.
16 type QueryIter interface {
17         // Next returns true if there is a next element available.
18         // It must be called before any of the other methods are called.
19         Next() bool
20
21         // Unit returns the unit of the current iteration.
22         Unit() Unit
23
24         // Region returns the Region for the current iteration.
25         Region() language.Region
26
27         // From returns the date from which the unit was used in the region.
28         // It returns false if this date is unknown.
29         From() (time.Time, bool)
30
31         // To returns the date up till which the unit was used in the region.
32         // It returns false if this date is unknown or if the unit is still in use.
33         To() (time.Time, bool)
34
35         // IsTender reports whether the unit is a legal tender in the region during
36         // the specified date range.
37         IsTender() bool
38 }
39
40 // Query represents a set of Units. The default set includes all Units that are
41 // currently in use as legal tender in any Region.
42 func Query(options ...QueryOption) QueryIter {
43         it := &iter{
44                 end:  len(regionData),
45                 date: 0xFFFFFFFF,
46         }
47         for _, fn := range options {
48                 fn(it)
49         }
50         return it
51 }
52
53 // NonTender returns a new query that also includes matching Units that are not
54 // legal tender.
55 var NonTender QueryOption = nonTender
56
57 func nonTender(i *iter) {
58         i.nonTender = true
59 }
60
61 // Historical selects the units for all dates.
62 var Historical QueryOption = historical
63
64 func historical(i *iter) {
65         i.date = hist
66 }
67
68 // A QueryOption can be used to change the set of unit information returned by
69 // a query.
70 type QueryOption func(*iter)
71
72 // Date queries the units that were in use at the given point in history.
73 func Date(t time.Time) QueryOption {
74         d := toDate(t)
75         return func(i *iter) {
76                 i.date = d
77         }
78 }
79
80 // Region limits the query to only return entries for the given region.
81 func Region(r language.Region) QueryOption {
82         p, end := len(regionData), len(regionData)
83         x := regionToCode(r)
84         i := sort.Search(len(regionData), func(i int) bool {
85                 return regionData[i].region >= x
86         })
87         if i < len(regionData) && regionData[i].region == x {
88                 p = i
89                 for i++; i < len(regionData) && regionData[i].region == x; i++ {
90                 }
91                 end = i
92         }
93         return func(i *iter) {
94                 i.p, i.end = p, end
95         }
96 }
97
98 const (
99         hist = 0x00
100         now  = 0xFFFFFFFF
101 )
102
103 type iter struct {
104         *regionInfo
105         p, end    int
106         date      uint32
107         nonTender bool
108 }
109
110 func (i *iter) Next() bool {
111         for ; i.p < i.end; i.p++ {
112                 i.regionInfo = &regionData[i.p]
113                 if !i.nonTender && !i.IsTender() {
114                         continue
115                 }
116                 if i.date == hist || (i.from <= i.date && (i.to == 0 || i.date <= i.to)) {
117                         i.p++
118                         return true
119                 }
120         }
121         return false
122 }
123
124 func (r *regionInfo) Region() language.Region {
125         // TODO: this could be much faster.
126         var buf [2]byte
127         buf[0] = uint8(r.region >> 8)
128         buf[1] = uint8(r.region)
129         return language.MustParseRegion(string(buf[:]))
130 }
131
132 func (r *regionInfo) Unit() Unit {
133         return Unit{r.code &^ nonTenderBit}
134 }
135
136 func (r *regionInfo) IsTender() bool {
137         return r.code&nonTenderBit == 0
138 }
139
140 func (r *regionInfo) From() (time.Time, bool) {
141         if r.from == 0 {
142                 return time.Time{}, false
143         }
144         return fromDate(r.from), true
145 }
146
147 func (r *regionInfo) To() (time.Time, bool) {
148         if r.to == 0 {
149                 return time.Time{}, false
150         }
151         return fromDate(r.to), true
152 }