in HAP/HAPTLV.c [127:307]
bool HAPTLVFormatIsValid(const HAPTLVFormat* format_) {
HAPPrecondition(format_);
const HAPBaseTLVFormat* format = format_;
switch (format->type) {
case kHAPTLVFormatType_None: {
const HAPSeparatorTLVFormat* fmt HAP_UNUSED = format_;
}
return true;
case kHAPTLVFormatType_Enum: {
const HAPEnumTLVFormat* fmt = format_;
if (!fmt->callbacks.isValid) {
return false;
}
if (!fmt->callbacks.getDescription) {
return false;
}
}
return true;
#define PROCESS_INTEGER_FORMAT(formatName, typeName, printfFormat, printfTypeName) \
do { \
const formatName* fmt = format_; \
if (fmt->constraints.maximumValue < fmt->constraints.minimumValue) { \
return false; \
} \
} while (0)
case kHAPTLVFormatType_UInt8: {
PROCESS_INTEGER_FORMAT(HAPUInt8TLVFormat, uint8_t, "u", unsigned int);
}
return true;
case kHAPTLVFormatType_UInt16: {
PROCESS_INTEGER_FORMAT(HAPUInt16TLVFormat, uint16_t, "u", unsigned int);
}
return true;
case kHAPTLVFormatType_UInt32: {
PROCESS_INTEGER_FORMAT(HAPUInt32TLVFormat, uint32_t, "lu", unsigned long);
}
return true;
case kHAPTLVFormatType_UInt64: {
PROCESS_INTEGER_FORMAT(HAPUInt64TLVFormat, uint64_t, "llu", unsigned long long);
}
return true;
case kHAPTLVFormatType_Int8: {
PROCESS_INTEGER_FORMAT(HAPInt8TLVFormat, int8_t, "d", int);
}
return true;
case kHAPTLVFormatType_Int16: {
PROCESS_INTEGER_FORMAT(HAPInt16TLVFormat, int16_t, "d", int);
}
return true;
case kHAPTLVFormatType_Int32: {
PROCESS_INTEGER_FORMAT(HAPInt32TLVFormat, int32_t, "ld", long);
}
return true;
case kHAPTLVFormatType_Int64: {
PROCESS_INTEGER_FORMAT(HAPInt64TLVFormat, int64_t, "lld", long long);
}
return true;
#undef PROCESS_INTEGER_FORMAT
case kHAPTLVFormatType_Data: {
const HAPDataTLVFormat* fmt = format_;
if (fmt->constraints.maxLength < fmt->constraints.minLength) {
return false;
}
}
return true;
case kHAPTLVFormatType_String: {
const HAPStringTLVFormat* fmt = format_;
if (fmt->constraints.maxLength < fmt->constraints.minLength) {
return false;
}
}
return true;
case kHAPTLVFormatType_Value: {
const HAPValueTLVFormat* fmt = format_;
if (!fmt->callbacks.decode) {
return false;
}
if (!fmt->callbacks.encode) {
return false;
}
if (!fmt->callbacks.getDescription) {
return false;
}
}
return true;
case kHAPTLVFormatType_Sequence: {
const HAPSequenceTLVFormat* fmt = format_;
if (!fmt->item.format) {
return false;
}
if (!HAPTLVFormatIsValid(fmt->item.format)) {
return false;
}
if (!fmt->separator.format) {
return false;
}
if (fmt->item.isFlat) {
if (!HAPTLVFormatIsAggregate(fmt->item.format)) {
return false;
}
if (((const HAPBaseTLVFormat*) fmt->item.format)->type != kHAPTLVFormatType_Union) {
return false;
}
if (HAPTLVFormatUsesType(fmt->item.format, fmt->separator.tlvType)) {
return false;
}
} else if (fmt->item.tlvType == fmt->separator.tlvType) {
return false;
}
}
return true;
case kHAPTLVFormatType_Struct: {
const HAPStructTLVFormat* fmt = format_;
if (fmt->members) {
for (size_t i = 0; fmt->members[i]; i++) {
const HAPStructTLVMember* member = fmt->members[i];
if (!member->format) {
return false;
}
if (!HAPTLVFormatIsValid(member->format)) {
return false;
}
for (size_t j = 0; j < i; j++) {
const HAPStructTLVMember* otherMember = fmt->members[j];
if (member->isFlat) {
if (!HAPTLVFormatIsAggregate(member->format)) {
return false;
}
if (member->isOptional) {
return false;
}
if (otherMember->isFlat) {
if (HAPTLVFormatHaveConflictingTypes(member->format, otherMember->format)) {
return false;
}
} else {
if (HAPTLVFormatUsesType(member->format, otherMember->tlvType)) {
return false;
}
}
} else {
if (otherMember->isFlat) {
if (HAPTLVFormatUsesType(otherMember->format, member->tlvType)) {
return false;
}
} else {
if (member->tlvType == otherMember->tlvType) {
return false;
}
}
}
}
}
}
}
return true;
case kHAPTLVFormatType_Union: {
const HAPUnionTLVFormat* fmt = format_;
if (fmt->variants) {
for (size_t i = 0; fmt->variants[i]; i++) {
const HAPUnionTLVVariant* variant = fmt->variants[i];
if (!variant->format) {
return false;
}
if (!HAPTLVFormatIsValid(variant->format)) {
return false;
}
for (size_t j = 0; j < i; j++) {
const HAPUnionTLVVariant* otherVariant = fmt->variants[j];
if (variant->tlvType == otherVariant->tlvType) {
return false;
}
}
}
}
}
return true;
}
return false;
}