• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2019 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 // localeprioritylist.h
5 // created: 2019jul11 Markus W. Scherer
6 
7 #ifndef __LOCALEPRIORITYLIST_H__
8 #define __LOCALEPRIORITYLIST_H__
9 
10 #include "unicode/utypes.h"
11 #include "unicode/locid.h"
12 #include "unicode/stringpiece.h"
13 #include "unicode/uobject.h"
14 
15 struct UHashtable;
16 
17 U_NAMESPACE_BEGIN
18 
19 struct LocaleAndWeightArray;
20 
21 /**
22  * Parses a list of locales from an accept-language string.
23  * We are a bit more lenient than the spec:
24  * We accept extra whitespace in more places, empty range fields,
25  * and any number of qvalue fraction digits.
26  *
27  * https://tools.ietf.org/html/rfc2616#section-14.4
28  * 14.4 Accept-Language
29  *
30  *        Accept-Language = "Accept-Language" ":"
31  *                          1#( language-range [ ";" "q" "=" qvalue ] )
32  *        language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
33  *
34  *    Each language-range MAY be given an associated quality value which
35  *    represents an estimate of the user's preference for the languages
36  *    specified by that range. The quality value defaults to "q=1". For
37  *    example,
38  *
39  *        Accept-Language: da, en-gb;q=0.8, en;q=0.7
40  *
41  * https://tools.ietf.org/html/rfc2616#section-3.9
42  * 3.9 Quality Values
43  *
44  *    HTTP content negotiation (section 12) uses short "floating point"
45  *    numbers to indicate the relative importance ("weight") of various
46  *    negotiable parameters.  A weight is normalized to a real number in
47  *    the range 0 through 1, where 0 is the minimum and 1 the maximum
48  *    value. If a parameter has a quality value of 0, then content with
49  *    this parameter is `not acceptable' for the client. HTTP/1.1
50  *    applications MUST NOT generate more than three digits after the
51  *    decimal point. User configuration of these values SHOULD also be
52  *    limited in this fashion.
53  *
54  *        qvalue         = ( "0" [ "." 0*3DIGIT ] )
55  *                       | ( "1" [ "." 0*3("0") ] )
56  */
57 class U_COMMON_API LocalePriorityList : public UMemory {
58 public:
59     class Iterator : public Locale::Iterator {
60     public:
hasNext()61         UBool hasNext() const override { return count < length; }
62 
next()63         const Locale &next() override {
64             for(;;) {
65                 const Locale *locale = list.localeAt(index++);
66                 if (locale != nullptr) {
67                     ++count;
68                     return *locale;
69                 }
70             }
71         }
72 
73     private:
74         friend class LocalePriorityList;
75 
Iterator(const LocalePriorityList & list)76         Iterator(const LocalePriorityList &list) : list(list), length(list.getLength()) {}
77 
78         const LocalePriorityList &list;
79         int32_t index = 0;
80         int32_t count = 0;
81         const int32_t length;
82     };
83 
84     LocalePriorityList(StringPiece s, UErrorCode &errorCode);
85 
86     ~LocalePriorityList();
87 
getLength()88     int32_t getLength() const { return listLength - numRemoved; }
89 
getLengthIncludingRemoved()90     int32_t getLengthIncludingRemoved() const { return listLength; }
91 
iterator()92     Iterator iterator() const { return Iterator(*this); }
93 
94     const Locale *localeAt(int32_t i) const;
95 
96     Locale *orphanLocaleAt(int32_t i);
97 
98 private:
99     LocalePriorityList(const LocalePriorityList &) = delete;
100     LocalePriorityList &operator=(const LocalePriorityList &) = delete;
101 
102     bool add(const Locale &locale, int32_t weight, UErrorCode &errorCode);
103 
104     void sort(UErrorCode &errorCode);
105 
106     LocaleAndWeightArray *list = nullptr;
107     int32_t listLength = 0;
108     int32_t numRemoved = 0;
109     bool hasWeights = false;  // other than 1.0
110     UHashtable *map = nullptr;
111 };
112 
113 U_NAMESPACE_END
114 
115 #endif  // __LOCALEPRIORITYLIST_H__
116