MeasureUnit.h (4319B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef intl_components_MeasureUnit_h_ 6 #define intl_components_MeasureUnit_h_ 7 8 #include "mozilla/Assertions.h" 9 #include "mozilla/intl/ICU4CGlue.h" 10 #include "mozilla/intl/ICUError.h" 11 #include "mozilla/Result.h" 12 #include "mozilla/UniquePtr.h" 13 14 #include <iterator> 15 #include <stddef.h> 16 #include <stdint.h> 17 18 struct UResourceBundle; 19 20 namespace mozilla::intl { 21 22 /** 23 * This component is a Mozilla-focused API for working with measurement units in 24 * internationalization code. It is used in coordination with other operations 25 * such as number formatting. 26 */ 27 class MeasureUnit final { 28 class UResourceBundleDeleter { 29 public: 30 void operator()(UResourceBundle* aPtr); 31 }; 32 33 using UniqueUResourceBundle = 34 UniquePtr<UResourceBundle, UResourceBundleDeleter>; 35 36 public: 37 MeasureUnit() = delete; 38 39 class Enumeration final { 40 // Resource bundle for the root locale. 41 UniqueUResourceBundle mRootLocale = nullptr; 42 43 // Resource bundle for the root locale's "units" resource table. 44 UniqueUResourceBundle mUnits = nullptr; 45 46 // The overall amount of available units. 47 int32_t mUnitsSize = 0; 48 49 public: 50 Enumeration(UniqueUResourceBundle aRootLocale, 51 UniqueUResourceBundle aUnits); 52 53 class Iterator { 54 public: 55 // std::iterator traits. 56 using iterator_category = std::input_iterator_tag; 57 using value_type = SpanResult<char>; 58 using difference_type = ptrdiff_t; 59 using pointer = value_type*; 60 using reference = value_type&; 61 62 private: 63 const Enumeration& mEnumeration; 64 65 // Resource bundle to a measurement type within the "units" table. 66 // 67 // Measurement types describe various categories, like "area", "length", 68 // or "mass". 69 UniqueUResourceBundle mType = nullptr; 70 71 // Resource bundle to a specific subtype within the type table. 72 // 73 // Measurement subtypes describe concrete measure units, like "acre", 74 // "meter", or "kilogram". 75 UniqueUResourceBundle mSubtype = nullptr; 76 77 // The next position within the "units" table. 78 int32_t mUnitsPos = 0; 79 80 // The overall amount of types within the |mType| table. 81 int32_t mTypeSize = 0; 82 83 // The next position within the |mType| table. 84 int32_t mTypePos = 0; 85 86 // Flag set when an ICU error has occurred. All further operations on this 87 // iterator will return an error result when this flag is set. 88 bool mHasError = false; 89 90 void advance(); 91 92 public: 93 Iterator(const Enumeration& aEnumeration, int32_t aUnitsPos) 94 : mEnumeration(aEnumeration), mUnitsPos(aUnitsPos) { 95 advance(); 96 } 97 98 Iterator& operator++() { 99 advance(); 100 return *this; 101 } 102 103 // The post-increment operator would return an invalid iterator, so it's 104 // not implemented. 105 Iterator operator++(int) = delete; 106 107 bool operator==(const Iterator& aOther) const { 108 // It's an error to compare an iterator against an iterator from a 109 // different enumeration. 110 MOZ_ASSERT(&mEnumeration == &aOther.mEnumeration); 111 112 return mUnitsPos == aOther.mUnitsPos && mTypeSize == aOther.mTypeSize && 113 mTypePos == aOther.mTypePos && mHasError == aOther.mHasError; 114 } 115 116 bool operator!=(const Iterator& aOther) const { 117 return !(*this == aOther); 118 } 119 120 value_type operator*() const; 121 }; 122 123 friend class Iterator; 124 125 // std::iterator begin() and end() methods. 126 127 /** 128 * Return an iterator pointing to the start of the "units" table. 129 */ 130 Iterator begin() { return Iterator(*this, 0); } 131 132 /** 133 * Return an iterator pointing to the end of the "units" table. 134 */ 135 Iterator end() { return Iterator(*this, mUnitsSize); } 136 137 /** 138 * Create a new measurement unit enumeration. 139 */ 140 static Result<Enumeration, ICUError> TryCreate(); 141 }; 142 143 /** 144 * Return an enumeration over all available measurement units. 145 */ 146 static Result<Enumeration, ICUError> GetAvailable() { 147 return Enumeration::TryCreate(); 148 } 149 }; 150 151 } // namespace mozilla::intl 152 153 #endif