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