3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2015-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements interfaces for debugging and logging
26 #ifndef __STDC_FORMAT_MACROS
27 #define __STDC_FORMAT_MACROS
34 #include <core/CHIPTLV.h>
35 #include <core/CHIPTLVDebug.hpp>
36 #include <core/CHIPTLVUtilities.hpp>
37 #include <support/CodeUtils.h>
38 #include <support/logging/CHIPLogging.h>
47 * Dump the TLV element referenced by @a aReader in human-readable form using
50 * @param[in] aWriter The writer to log the TLV data.
51 * @param[in] aIndent The indentation for logging the current depth into
53 * @param[in] aReader A read-only reference to the TLV reader containing
54 * the TLV data to log.
55 * @param[in] aDepth The current depth into the TLV data.
58 static void DumpHandler(DumpWriter aWriter, const char * aIndent, const TLVReader & aReader, size_t aDepth)
60 const TLVType type = aReader.GetType();
61 const uint64_t tag = aReader.GetTag();
62 const uint32_t len = aReader.GetLength();
63 const uint8_t * strbuf = nullptr;
64 CHIP_ERROR err = CHIP_NO_ERROR;
66 TLVTagControl tagControl;
69 tagControl = static_cast<TLVTagControl>(temp.GetControlByte() & kTLVTagControlMask);
71 aWriter("%zd ", aDepth);
73 for (size_t i = 0; i < aDepth; i++)
74 aWriter("%s", aIndent);
76 aWriter("%p, ", temp.GetReadPoint());
78 if (IsProfileTag(tag))
80 aWriter("tag[%s]: 0x%x::0x%x::0x%x, ", DecodeTagControl(tagControl), VendorIdFromTag(tag), ProfileNumFromTag(tag),
83 else if (IsContextTag(tag))
85 aWriter("tag[%s]: 0x%x, ", DecodeTagControl(tagControl), TagNumFromTag(tag));
87 else if (IsSpecialTag(tag))
90 aWriter("tag[%s]: 0x%x, ", DecodeTagControl(tagControl), tag);
94 aWriter("tag[unknown]: 0x%x, ", tag);
97 aWriter("type: %s (0x%02x), ", DecodeType(type), type);
99 if (TLVTypeIsContainer(type))
101 aWriter("container: ");
105 if (type == kTLVType_UTF8String || type == kTLVType_ByteString)
106 aWriter("length: %" PRIu32 ", ", len);
113 case kTLVType_SignedInteger:
115 err = temp.Get(sVal);
116 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_SignedInteger"));
117 aWriter("%" PRIi64, sVal);
120 case kTLVType_UnsignedInteger:
122 err = temp.Get(uVal);
123 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_UnsignedInteger"));
124 aWriter("%" PRIu64, uVal);
127 case kTLVType_Boolean:
129 err = temp.Get(bVal);
130 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_Boolean"));
131 aWriter("%s", bVal ? "true" : "false");
134 case kTLVType_FloatingPointNumber:
136 err = temp.Get(fpVal);
137 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_FloatingPointNumber"));
138 aWriter("%lf", fpVal);
141 case kTLVType_UTF8String:
142 err = temp.GetDataPtr(strbuf);
143 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_UTF8String"));
144 aWriter("\"%-.*s\"", static_cast<int>(len), strbuf);
147 case kTLVType_ByteString:
148 err = temp.GetDataPtr(strbuf);
149 VerifyOrExit(err == CHIP_NO_ERROR, aWriter("Error in kTLVType_ByteString"));
150 aWriter("%p\n", strbuf);
157 case kTLVType_NotSpecified:
158 aWriter("Not Specified");
162 aWriter("Error: Type is not primitive.");
172 * Decode a TLV tag control with a descriptive string.
174 * @param[in] aTagControl The TLV tag control to decode and for which to return
175 * a descriptive string.
177 * @return A pointer to a NULL-terminated string describing the specified
178 * tag control on success; otherwise, NULL.
181 const char * DecodeTagControl(const TLVTagControl aTagControl)
188 case TLVTagControl::Anonymous:
189 retval = "Anonymous";
192 case TLVTagControl::ContextSpecific:
193 retval = "Context Specific";
196 case TLVTagControl::CommonProfile_2Bytes:
197 retval = "Common Profile (2 Bytes)";
200 case TLVTagControl::CommonProfile_4Bytes:
201 retval = "Common Profile (4 Bytes)";
204 case TLVTagControl::ImplicitProfile_2Bytes:
205 retval = "Implicit Profile (2 Bytes)";
208 case TLVTagControl::ImplicitProfile_4Bytes:
209 retval = "Implicit Profile (4 Bytes)";
212 case TLVTagControl::FullyQualified_6Bytes:
213 retval = "Fully Qualified (6 Bytes)";
216 case TLVTagControl::FullyQualified_8Bytes:
217 retval = "Fully Qualified (8 Bytes)";
229 * Decode a TLV type with a descriptive string.
231 * @param[in] aType The TLV type to decode and for which to return
232 * a descriptive string.
234 * @return A pointer to a NULL-terminated string describing the specified
235 * type on success; otherwise, NULL.
238 const char * DecodeType(const TLVType aType)
245 case kTLVType_NotSpecified:
246 retval = "Not Specified";
249 case kTLVType_SignedInteger:
250 retval = "Signed Fixed Point";
253 case kTLVType_UnsignedInteger:
254 retval = "Unsigned Fixed Point";
257 case kTLVType_Boolean:
261 case kTLVType_FloatingPointNumber:
262 retval = "Floating Point";
265 case kTLVType_UTF8String:
266 retval = "UTF-8 String";
269 case kTLVType_ByteString:
277 case kTLVType_Structure:
278 retval = "Structure";
298 * Log the TLV data within the specified reader in human-readable form to
299 * the specified writer.
301 * @param[in] aWriter The writer to log the TLV data.
302 * @param[in] aReader A read-only reference to the TLV reader containing
303 * the TLV data to log.
305 * @retval #CHIP_NO_ERROR Unconditionally.
308 CHIP_ERROR DumpIterator(DumpWriter aWriter, const TLVReader & aReader)
310 const char * tabs = "";
311 const size_t depth = 0;
312 CHIP_ERROR retval = CHIP_NO_ERROR;
314 DumpHandler(aWriter, tabs, aReader, depth);
320 * Log the TLV data within the specified reader in human-readable form.
322 * @param[in] aReader A read-only reference to the TLV reader containing
323 * the TLV data to log.
324 * @param[in] aDepth The current depth into the TLV data.
325 * @param[in,out] aContext A pointer to the handler-specific context.
327 * @retval #CHIP_NO_ERROR On success.
329 * @retval #CHIP_ERROR_INVALID_ARGUMENT If aContext is NULL or if
330 * aContext->mWriter is NULL.
333 CHIP_ERROR DumpHandler(const TLVReader & aReader, size_t aDepth, void * aContext)
335 static const char indent[] = " ";
336 DumpContext * context;
338 VerifyOrReturnError(aContext != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
340 context = static_cast<DumpContext *>(aContext);
342 VerifyOrReturnError(context->mWriter != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
344 DumpHandler(context->mWriter, indent, aReader, aDepth);
346 return CHIP_NO_ERROR;
350 * Dump the TLV data within the specified reader in human-readable form with
351 * the specified writer.
353 * @param[in] aReader A read-only reference to the TLV reader containing
354 * the TLV data to log.
356 * @param[in] aWriter A dump writer to log the TLV data of the TLV reader.
358 * @retval #CHIP_NO_ERROR On success.
361 CHIP_ERROR Dump(const TLVReader & aReader, DumpWriter aWriter)
363 void * context = nullptr;
364 DumpContext dumpContext = { aWriter, context };
367 retval = Utilities::Iterate(aReader, DumpHandler, &dumpContext);