| // © 2019 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| |
| // localeprioritylist.h |
| // created: 2019jul11 Markus W. Scherer |
| |
| #ifndef __LOCALEPRIORITYLIST_H__ |
| #define __LOCALEPRIORITYLIST_H__ |
| |
| #include "unicode/utypes.h" |
| #include "unicode/locid.h" |
| #include "unicode/stringpiece.h" |
| #include "unicode/uobject.h" |
| |
| struct UHashtable; |
| |
| U_NAMESPACE_BEGIN |
| |
| struct LocaleAndWeightArray; |
| |
| /** |
| * Parses a list of locales from an accept-language string. |
| * We are a bit more lenient than the spec: |
| * We accept extra whitespace in more places, empty range fields, |
| * and any number of qvalue fraction digits. |
| * |
| * https://tools.ietf.org/html/rfc2616#section-14.4 |
| * 14.4 Accept-Language |
| * |
| * Accept-Language = "Accept-Language" ":" |
| * 1#( language-range [ ";" "q" "=" qvalue ] ) |
| * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) |
| * |
| * Each language-range MAY be given an associated quality value which |
| * represents an estimate of the user's preference for the languages |
| * specified by that range. The quality value defaults to "q=1". For |
| * example, |
| * |
| * Accept-Language: da, en-gb;q=0.8, en;q=0.7 |
| * |
| * https://tools.ietf.org/html/rfc2616#section-3.9 |
| * 3.9 Quality Values |
| * |
| * HTTP content negotiation (section 12) uses short "floating point" |
| * numbers to indicate the relative importance ("weight") of various |
| * negotiable parameters. A weight is normalized to a real number in |
| * the range 0 through 1, where 0 is the minimum and 1 the maximum |
| * value. If a parameter has a quality value of 0, then content with |
| * this parameter is `not acceptable' for the client. HTTP/1.1 |
| * applications MUST NOT generate more than three digits after the |
| * decimal point. User configuration of these values SHOULD also be |
| * limited in this fashion. |
| * |
| * qvalue = ( "0" [ "." 0*3DIGIT ] ) |
| * | ( "1" [ "." 0*3("0") ] ) |
| */ |
| class U_COMMON_API LocalePriorityList : public UMemory { |
| public: |
| class Iterator : public Locale::Iterator { |
| public: |
| UBool hasNext() const override { return count < length; } |
| |
| const Locale &next() override { |
| for(;;) { |
| const Locale *locale = list.localeAt(index++); |
| if (locale != nullptr) { |
| ++count; |
| return *locale; |
| } |
| } |
| } |
| |
| private: |
| friend class LocalePriorityList; |
| |
| Iterator(const LocalePriorityList &list) : list(list), length(list.getLength()) {} |
| |
| const LocalePriorityList &list; |
| int32_t index = 0; |
| int32_t count = 0; |
| const int32_t length; |
| }; |
| |
| LocalePriorityList(StringPiece s, UErrorCode &errorCode); |
| |
| ~LocalePriorityList(); |
| |
| int32_t getLength() const { return listLength - numRemoved; } |
| |
| int32_t getLengthIncludingRemoved() const { return listLength; } |
| |
| Iterator iterator() const { return Iterator(*this); } |
| |
| const Locale *localeAt(int32_t i) const; |
| |
| Locale *orphanLocaleAt(int32_t i); |
| |
| private: |
| LocalePriorityList(const LocalePriorityList &) = delete; |
| LocalePriorityList &operator=(const LocalePriorityList &) = delete; |
| |
| bool add(const Locale &locale, int32_t weight, UErrorCode &errorCode); |
| |
| void sort(UErrorCode &errorCode); |
| |
| LocaleAndWeightArray *list = nullptr; |
| int32_t listLength = 0; |
| int32_t numRemoved = 0; |
| bool hasWeights = false; // other than 1.0 |
| UHashtable *map = nullptr; |
| }; |
| |
| U_NAMESPACE_END |
| |
| #endif // __LOCALEPRIORITYLIST_H__ |