bool HAPTLVFormatIsValid()

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;
}