field_encodings.h (3954B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #ifndef LIB_JXL_FIELD_ENCODINGS_H_ 7 #define LIB_JXL_FIELD_ENCODINGS_H_ 8 9 // Constants needed to encode/decode fields; avoids including the full fields.h. 10 11 #include <stddef.h> 12 #include <stdint.h> 13 14 #include <hwy/base.h> 15 #include <vector> 16 17 #include "lib/jxl/base/bits.h" 18 #include "lib/jxl/base/status.h" 19 20 namespace jxl { 21 22 // Macro to define the Fields' derived class Name when compiling with debug 23 // names. 24 #if JXL_IS_DEBUG_BUILD 25 #define JXL_FIELDS_NAME(X) \ 26 const char* Name() const override { return #X; } 27 #else 28 #define JXL_FIELDS_NAME(X) 29 #endif // JXL_IS_DEBUG_BUILD 30 31 class Visitor; 32 class Fields { 33 public: 34 virtual ~Fields() = default; 35 #if JXL_IS_DEBUG_BUILD 36 virtual const char* Name() const = 0; 37 #endif // JXL_IS_DEBUG_BUILD 38 virtual Status VisitFields(Visitor* JXL_RESTRICT visitor) = 0; 39 }; 40 41 // Distribution of U32 values for one particular selector. Represents either a 42 // power of two-sized range, or a single value. A separate type ensures this is 43 // only passed to the U32Enc ctor. 44 struct U32Distr { 45 // No need to validate - all `d` are legitimate. 46 constexpr explicit U32Distr(uint32_t d) : d(d) {} 47 48 static constexpr uint32_t kDirect = 0x80000000u; 49 50 constexpr bool IsDirect() const { return (d & kDirect) != 0; } 51 52 // Only call if IsDirect(). 53 constexpr uint32_t Direct() const { return d & (kDirect - 1); } 54 55 // Only call if !IsDirect(). 56 constexpr size_t ExtraBits() const { return (d & 0x1F) + 1; } 57 uint32_t Offset() const { return (d >> 5) & 0x3FFFFFF; } 58 59 uint32_t d; 60 }; 61 62 // A direct-coded 31-bit value occupying 2 bits in the bitstream. 63 constexpr U32Distr Val(uint32_t value) { 64 return U32Distr(value | U32Distr::kDirect); 65 } 66 67 // Value - `offset` will be signaled in `bits` extra bits. 68 constexpr U32Distr BitsOffset(uint32_t bits, uint32_t offset) { 69 return U32Distr(((bits - 1) & 0x1F) + ((offset & 0x3FFFFFF) << 5)); 70 } 71 72 // Value will be signaled in `bits` extra bits. 73 constexpr U32Distr Bits(uint32_t bits) { return BitsOffset(bits, 0); } 74 75 // See U32Coder documentation in fields.h. 76 class U32Enc { 77 public: 78 constexpr U32Enc(const U32Distr d0, const U32Distr d1, const U32Distr d2, 79 const U32Distr d3) 80 : d_{d0, d1, d2, d3} {} 81 82 // Returns the U32Distr at `selector` = 0..3, least-significant first. 83 U32Distr GetDistr(const uint32_t selector) const { 84 JXL_ASSERT(selector < 4); 85 return d_[selector]; 86 } 87 88 private: 89 U32Distr d_[4]; 90 }; 91 92 // Returns bit with the given `index` (0 = least significant). 93 template <typename T> 94 static inline constexpr uint64_t MakeBit(T index) { 95 return 1ULL << static_cast<uint32_t>(index); 96 } 97 98 // Returns vector of all possible values of an Enum type. Relies on each Enum 99 // providing an overload of EnumBits() that returns a bit array of its values, 100 // which implies values must be in [0, 64). 101 template <typename Enum> 102 std::vector<Enum> Values() { 103 uint64_t bits = EnumBits(Enum()); 104 105 std::vector<Enum> values; 106 values.reserve(hwy::PopCount(bits)); 107 108 // For each 1-bit in bits: add its index as value 109 while (bits != 0) { 110 const int index = Num0BitsBelowLS1Bit_Nonzero(bits); 111 values.push_back(static_cast<Enum>(index)); 112 bits &= bits - 1; // clear least-significant bit 113 } 114 return values; 115 } 116 117 // Returns true if value is one of Values<Enum>(). 118 template <class Enum> 119 Status EnumValid(const Enum value) { 120 if (static_cast<uint32_t>(value) >= 64) { 121 return JXL_FAILURE("Value %u too large for %s\n", 122 static_cast<uint32_t>(value), EnumName(Enum())); 123 } 124 const uint64_t bit = MakeBit(value); 125 if ((EnumBits(Enum()) & bit) == 0) { 126 return JXL_FAILURE("Invalid value %u for %s\n", 127 static_cast<uint32_t>(value), EnumName(Enum())); 128 } 129 return true; 130 } 131 132 } // namespace jxl 133 134 #endif // LIB_JXL_FIELD_ENCODINGS_H_