localeprioritylist.h 3.5 KB

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