@@ -77,62 +77,25 @@ bool IsExactlyOneValuePopulated(const AttributeValuePairType & type)
77
77
// / CapAttributeValue
78
78
// / Cap the attribute value based on the attribute's min and max if they are defined,
79
79
// / or based on the attribute's size if they are not.
80
- // / @param[in] aVPair AttributeValuePairType
81
- // / @param[in] metadata EmberAfAttributeMetadata
82
80
// /
83
- template <typename Type>
81
+ // / The TypeForMinMax template parameter determines the type to use for the
82
+ // / min/max computation. The Type template parameter determines how the
83
+ // / resulting value is actually represented, because for booleans we
84
+ // / unfortunately end up using uint8, not an actual boolean.
85
+ // /
86
+ // / @param[in] value The value from the AttributeValuePairType that we were given.
87
+ // / @param[in] metadata The metadata for the attribute the value is for.
88
+ // /
89
+ // /
90
+ // /
91
+ template <typename Type, typename TypeForMinMax = Type>
84
92
void CapAttributeValue (typename app::NumericAttributeTraits<Type>::WorkingType & value, const EmberAfAttributeMetadata * metadata)
85
93
{
86
- using IntType = app::NumericAttributeTraits<Type>;
87
- using WorkingType = typename IntType::WorkingType;
88
-
89
- WorkingType maxValue;
90
- WorkingType minValue;
91
- uint16_t bitWidth = static_cast <uint16_t >(emberAfAttributeSize (metadata) * 8 );
92
-
93
- // TODO Use min/max values from Type to obtain min/max instead of relying on metadata. See:
94
- // https://github.com/project-chip/connectedhomeip/issues/35328
95
-
96
- // Min/Max Value caps for the OddSize integers
97
- if (metadata->IsSignedIntegerAttribute ())
98
- {
99
- // We use emberAfAttributeSize for cases like INT24S, INT40S, INT48S, INT56S where numeric_limits<WorkingType>::max()
100
- // wouldn't work
101
- maxValue = static_cast <WorkingType>((1ULL << (bitWidth - 1 )) - 1 );
102
- minValue = static_cast <WorkingType>(-(1ULL << (bitWidth - 1 )));
103
- }
104
- else
105
- {
106
- // We use emberAfAttributeSize for cases like INT24U, INT40U, INT48U, INT56U where numeric_limits<WorkingType>::max()
107
- // wouldn't work
108
- if (ZCL_INT64U_ATTRIBUTE_TYPE == app::Compatibility::Internal::AttributeBaseType (metadata->attributeType ))
109
- {
110
- maxValue = static_cast <WorkingType>(UINT64_MAX); // Bit shift of 64 is undefined so we use UINT64_MAX
111
- }
112
- else
113
- {
114
- maxValue = static_cast <WorkingType>((1ULL << bitWidth) - 1 );
115
- }
116
- minValue = static_cast <WorkingType>(0 );
117
- }
94
+ using IntType = app::NumericAttributeTraits<TypeForMinMax>;
95
+ using WorkingType = std::remove_reference_t <decltype (value)>;
118
96
119
- // Ensure that the metadata's signedness matches the working type's signedness
120
- VerifyOrDie (metadata->IsSignedIntegerAttribute () == std::is_signed<WorkingType>::value);
121
-
122
- if (metadata->IsBoolean ())
123
- {
124
- if (metadata->IsNullable () && (value != 1 && value != 0 ))
125
- {
126
- // If the attribute is nullable, the value can be set to NULL
127
- app::NumericAttributeTraits<WorkingType>::SetNull (value);
128
- }
129
- else
130
- {
131
- // Caping the value to 1 in case values greater than 1 are set
132
- value = value ? 1 : 0 ;
133
- }
134
- return ;
135
- }
97
+ WorkingType minValue = IntType::MinValue (metadata->IsNullable ());
98
+ WorkingType maxValue = IntType::MaxValue (metadata->IsNullable ());
136
99
137
100
// Check metadata for min and max values
138
101
if (metadata->HasMinMax ())
@@ -142,10 +105,6 @@ void CapAttributeValue(typename app::NumericAttributeTraits<Type>::WorkingType &
142
105
maxValue = ConvertDefaultValueToWorkingValue<Type>(minMaxValue->maxValue );
143
106
}
144
107
145
- // If the attribute is nullable, the min and max values calculated for types will not be valid, however this does not
146
- // change the behavior here as the value will already be NULL if it is out of range. E.g. a nullable INT8U has a minValue of
147
- // -127. The code above determin minValue = -128, so an input value of -128 would not enter the condition block below, but would
148
- // be considered NULL nonetheless.
149
108
if (metadata->IsNullable () && (minValue > value || maxValue < value))
150
109
{
151
110
// If the attribute is nullable, the value can be set to NULL
@@ -187,6 +146,9 @@ CHIP_ERROR ValidateAttributePath(EndpointId endpoint, ClusterId cluster, Attribu
187
146
switch (app::Compatibility::Internal::AttributeBaseType (metadata->attributeType ))
188
147
{
189
148
case ZCL_BOOLEAN_ATTRIBUTE_TYPE:
149
+ VerifyOrReturnError (aVPair.valueUnsigned8 .HasValue (), CHIP_ERROR_INVALID_ARGUMENT);
150
+ CapAttributeValue<uint8_t , bool >(aVPair.valueUnsigned8 .Value (), metadata);
151
+ break ;
190
152
case ZCL_INT8U_ATTRIBUTE_TYPE:
191
153
VerifyOrReturnError (aVPair.valueUnsigned8 .HasValue (), CHIP_ERROR_INVALID_ARGUMENT);
192
154
CapAttributeValue<uint8_t >(aVPair.valueUnsigned8 .Value (), metadata);
0 commit comments