void HAPTLVAppendToLog()

in HAP/HAPTLV.c [309:477]


void HAPTLVAppendToLog(
        HAPTLVType tlvType,
        const char* debugDescription,
        const HAPTLVFormat* format_,
        HAPTLVValue* _Nullable value_,
        HAPStringBuilderRef* stringBuilder,
        size_t nestingLevel) {
    HAPPrecondition(debugDescription);
    HAPPrecondition(format_);
    const HAPBaseTLVFormat* format = format_;
    HAPPrecondition(stringBuilder);

    HAPError err;

    HAPStringBuilderAppend(stringBuilder, "\n");
    for (size_t i = 0; i < nestingLevel; i++) {
        HAPStringBuilderAppend(stringBuilder, "  ");
    }
    HAPStringBuilderAppend(stringBuilder, "- [%02X %s] ", tlvType, debugDescription);

    switch (format->type) {
        case kHAPTLVFormatType_None: {
            return;
        }
        case kHAPTLVFormatType_Enum: {
            const HAPEnumTLVFormat* fmt = format_;
            HAPPrecondition(fmt->callbacks.getDescription);
            uint8_t* value = HAPNonnullVoid(value_);
            HAPStringBuilderAppend(stringBuilder, "%s (%u)", fmt->callbacks.getDescription(*value), *value);
            return;
        }
#define PROCESS_INTEGER_FORMAT(formatName, typeName, printfFormat, printfTypeName) \
    do { \
        const formatName* fmt = format_; \
        typeName* value = HAPNonnullVoid(value_); \
        bool appended = false; \
        if (fmt->callbacks.getDescription) { \
            const char* _Nullable description = fmt->callbacks.getDescription(*value); \
            if (description) { \
                HAPStringBuilderAppend(stringBuilder, "%s (%" printfFormat ")", description, (printfTypeName) *value); \
                appended = true; \
            } \
        } \
        if (!appended && fmt->callbacks.getBitDescription) { \
            HAPStringBuilderAppend(stringBuilder, "["); \
            bool needsSeparator = false; \
            for (uint8_t i = 0; i < sizeof(typeName) * CHAR_BIT; i++) { \
                typeName optionValue = (typeName)(1 << i); \
                if (*value & optionValue) { \
                    if (needsSeparator) { \
                        HAPStringBuilderAppend(stringBuilder, ", "); \
                    } \
                    needsSeparator = true; \
                    const char* _Nullable bitDescription = fmt->callbacks.getBitDescription(optionValue); \
                    if (bitDescription) { \
                        HAPStringBuilderAppend(stringBuilder, "%s", bitDescription); \
                    } else { \
                        HAPStringBuilderAppend(stringBuilder, "<Unknown bit>"); \
                    } \
                    HAPStringBuilderAppend(stringBuilder, " (bit %u)", i); \
                } \
            } \
            HAPStringBuilderAppend(stringBuilder, "]"); \
            appended = true; \
        } \
        if (!appended) { \
            HAPStringBuilderAppend(stringBuilder, "%" printfFormat, (printfTypeName) *value); \
        } \
    } while (0)
        case kHAPTLVFormatType_UInt8: {
            PROCESS_INTEGER_FORMAT(HAPUInt8TLVFormat, uint8_t, "u", unsigned int);
            return;
        }
        case kHAPTLVFormatType_UInt16: {
            PROCESS_INTEGER_FORMAT(HAPUInt16TLVFormat, uint16_t, "u", unsigned int);
            return;
        }
        case kHAPTLVFormatType_UInt32: {
            PROCESS_INTEGER_FORMAT(HAPUInt32TLVFormat, uint32_t, "lu", unsigned long);
            return;
        }
        case kHAPTLVFormatType_UInt64: {
            PROCESS_INTEGER_FORMAT(HAPUInt64TLVFormat, uint64_t, "llu", unsigned long long);
            return;
        }
#undef PROCESS_INTEGER_FORMAT
#define PROCESS_INTEGER_FORMAT(formatName, typeName, printfFormat, printfTypeName) \
    do { \
        const formatName* fmt = format_; \
        typeName* value = HAPNonnullVoid(value_); \
        bool appended = false; \
        if (fmt->callbacks.getDescription) { \
            const char* _Nullable description = fmt->callbacks.getDescription(*value); \
            if (description) { \
                HAPStringBuilderAppend(stringBuilder, "%s (%" printfFormat ")", description, (printfTypeName) *value); \
                appended = true; \
            } \
        } \
        if (!appended) { \
            HAPStringBuilderAppend(stringBuilder, "%" printfFormat, (printfTypeName) *value); \
        } \
    } while (0)
        case kHAPTLVFormatType_Int8: {
            PROCESS_INTEGER_FORMAT(HAPInt8TLVFormat, int8_t, "d", int);
            return;
        }
        case kHAPTLVFormatType_Int16: {
            PROCESS_INTEGER_FORMAT(HAPInt16TLVFormat, int16_t, "d", int);
            return;
        }
        case kHAPTLVFormatType_Int32: {
            PROCESS_INTEGER_FORMAT(HAPInt32TLVFormat, int32_t, "ld", long);
            return;
        }
        case kHAPTLVFormatType_Int64: {
            PROCESS_INTEGER_FORMAT(HAPInt64TLVFormat, int64_t, "lld", long long);
            return;
        }
#undef PROCESS_INTEGER_FORMAT
        case kHAPTLVFormatType_Data: {
            const HAPDataTLVFormat* fmt HAP_UNUSED = format_;
            HAPDataTLVValue* value = HAPNonnullVoid(value_);
            HAPStringBuilderAppend(stringBuilder, "<");
            for (size_t i = 0; i < value->numBytes; i++) {
                const uint8_t* b = value->bytes;
                if (i && !(i % 4)) {
                    HAPStringBuilderAppend(stringBuilder, " ");
                }
                HAPStringBuilderAppend(stringBuilder, "%02X", b[i]);
            }
            HAPStringBuilderAppend(stringBuilder, ">");
            return;
        }
        case kHAPTLVFormatType_String: {
            const HAPStringTLVFormat* fmt HAP_UNUSED = format_;
            char** value = HAPNonnullVoid(value_);
            HAPStringBuilderAppend(stringBuilder, "%s", *value);
            return;
        }
        case kHAPTLVFormatType_Value: {
            const HAPValueTLVFormat* fmt = format_;
            HAPPrecondition(fmt->callbacks.getDescription);

            char descriptionBytes[kHAPTLVValue_MaxDescriptionBytes + 1];
            err = fmt->callbacks.getDescription(HAPNonnullVoid(value_), descriptionBytes, sizeof descriptionBytes);
            if (err) {
                HAPAssert(err == kHAPError_OutOfResources);
                HAPStringBuilderAppend(stringBuilder, "<Description too long>");
            } else {
                HAPStringBuilderAppend(stringBuilder, "%s", descriptionBytes);
            }
            return;
        }
        case kHAPTLVFormatType_Sequence: {
            const HAPSequenceTLVFormat* fmt HAP_UNUSED = format_;
            HAPStringBuilderAppend(stringBuilder, "<Sequence>");
            return;
        }
        case kHAPTLVFormatType_Struct: {
            const HAPStructTLVFormat* fmt HAP_UNUSED = format_;
            return;
        }
        case kHAPTLVFormatType_Union: {
            const HAPUnionTLVFormat* fmt HAP_UNUSED = format_;
            return;
        }
    }
    HAPFatalError();
}