| 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: | 
|---|
| 61 | UBool hasNext() const override { return count < length; } | 
|---|
| 62 |  | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 88 | int32_t getLength() const { return listLength - numRemoved; } | 
|---|
| 89 |  | 
|---|
| 90 | int32_t getLengthIncludingRemoved() const { return listLength; } | 
|---|
| 91 |  | 
|---|
| 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 |  | 
|---|