1 /* 2 * Copyright (c) 2022-2023, Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 //! 23 //! \file media_debug_serializer.h 24 //! 25 26 #pragma once 27 28 #if USE_MEDIA_DEBUG_TOOL 29 30 #include <cstring> 31 #include <iomanip> 32 #include <ostream> 33 #include <sstream> 34 #include <string> 35 #include <typeinfo> 36 #include <type_traits> 37 #include <stdint.h> 38 #include "media_class_trace.h" 39 40 template <typename T, typename = void> 41 class MediaDebugSerializer 42 { 43 public: operator()44 void operator()(std::ostream &os, const void *data, size_t size) 45 { 46 const size_t num = size / sizeof(T); 47 size_t idx = 0; 48 49 if (num > 1) 50 { 51 os << "Total Num: " << num << std::endl; 52 os << std::endl; 53 } 54 55 while (idx < num) 56 { 57 if (num > 1) 58 { 59 os << "---------" 60 << "Index = " << idx << "---------" << std::endl; 61 } 62 63 os << reinterpret_cast<const T *>(data)[idx++] << std::endl; 64 } 65 66 size_t numTrailingBytes = size - num * sizeof(T); 67 if (numTrailingBytes) 68 { 69 os << numTrailingBytes << " trailing bytes cannot be reinterpreted as " 70 << typeid(T).name() << " whose size is " << sizeof(T) << ":" 71 << std::endl; 72 for (size_t i = size - numTrailingBytes; i < size; ++i) 73 { 74 os << std::setfill('0') << std::setw(2) << std::hex << std::nouppercase 75 << static_cast<uint32_t>(reinterpret_cast<const uint8_t *>(data)[i]) 76 << std::endl; 77 } 78 } 79 } 80 81 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 82 }; 83 84 template <typename T> 85 class MediaDebugSerializer< 86 T, 87 #if __cplusplus < 201703L 88 typename std::enable_if<std::is_fundamental<T>::value && !std::is_unsigned<T>::value>::type> 89 #else 90 std::enable_if_t<std::is_fundamental_v<T> && !std::is_unsigned_v<T> > > 91 #endif 92 { 93 public: operator()94 void operator()(std::ostream &os, const void *data, size_t size) 95 { 96 const size_t num = size / sizeof(T); 97 size_t idx = 0; 98 99 while (idx < num) 100 { 101 os << reinterpret_cast<const T *>(data)[idx++] << std::endl; 102 } 103 104 size_t numTrailingBytes = size - num * sizeof(T); 105 if (numTrailingBytes) 106 { 107 os << numTrailingBytes << " trailing bytes cannot be reinterpreted as " 108 << typeid(T).name() << " whose size is " << sizeof(T) << ":" 109 << std::endl; 110 for (size_t i = size - numTrailingBytes; i < size; ++i) 111 { 112 os << std::setfill('0') << std::setw(2) << std::hex << std::nouppercase 113 << static_cast<uint32_t>(reinterpret_cast<const uint8_t *>(data)[i]) 114 << std::endl; 115 } 116 } 117 } 118 119 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 120 }; 121 122 template <typename T> 123 class MediaDebugSerializer< 124 T, 125 #if __cplusplus < 201703L 126 typename std::enable_if<std::is_unsigned<T>::value>::type> 127 #else 128 std::enable_if_t<std::is_unsigned_v<T> > > 129 #endif 130 { 131 public: operator()132 void operator()(std::ostream &os, const void *data, size_t size) 133 { 134 constexpr size_t LINE_WIDTH = 16 / sizeof(T); 135 constexpr size_t ELEM_WIDTH = sizeof(T) << 1; 136 137 const size_t num = size / sizeof(T); 138 size_t idx = 0; 139 while (idx < num) 140 { 141 os << std::setfill('0') << std::setw(ELEM_WIDTH) << std::hex 142 << std::nouppercase << reinterpret_cast<const T *>(data)[idx] 143 << ((idx + 1) % LINE_WIDTH == 0 ? "\n" : " "); 144 ++idx; 145 } 146 147 size_t numTrailingBytes = size - num * sizeof(T); 148 if (numTrailingBytes) 149 { 150 T last = 0; 151 std::memcpy( 152 &last, 153 static_cast<const char *>(data) + size - numTrailingBytes, 154 numTrailingBytes); 155 156 std::stringstream ss; 157 ss << std::setfill('?') << std::setw(ELEM_WIDTH) << std::hex 158 << std::nouppercase << last; 159 160 std::string str(ss.str()); 161 if (str[0] == '?') // little endian 162 { 163 for (auto it = str.rbegin(); it != str.rbegin() + numTrailingBytes * 2; ++it) 164 { 165 *it = *it == '?' ? '0' : *it; 166 } 167 } 168 else // big endian 169 { 170 for (auto it = str.begin(); it != str.begin() + numTrailingBytes * 2; ++it) 171 { 172 *it = *it == '?' ? '0' : *it; 173 } 174 } 175 176 os << str << ((idx + 1) % LINE_WIDTH == 0 ? "\n" : " "); 177 } 178 } 179 180 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 181 }; 182 183 template <> 184 class MediaDebugSerializer<uint8_t> 185 { 186 public: operator()187 void operator()(std::ostream &os, const void *data, size_t size) 188 { 189 size_t idx = 0; 190 while (idx < size) 191 { 192 os << std::setfill('0') << std::setw(2) << std::hex << std::nouppercase 193 << static_cast<uint32_t>(reinterpret_cast<const uint8_t *>(data)[idx]) 194 << ((idx + 1) % 32 == 0 ? "\n" : " "); 195 ++idx; 196 } 197 } 198 199 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 200 }; 201 202 template <> 203 class MediaDebugSerializer<int8_t> 204 { 205 public: operator()206 void operator()(std::ostream &os, const void *data, size_t size) 207 { 208 size_t idx = 0; 209 while (idx < size) 210 { 211 os << static_cast<int32_t>(reinterpret_cast<const int8_t *>(data)[idx++]) 212 << std::endl; 213 } 214 } 215 216 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 217 }; 218 219 template <> 220 class MediaDebugSerializer<void> 221 { 222 public: operator()223 void operator()(std::ostream &os, const void *data, size_t size) 224 { 225 size_t idx = 0; 226 while (idx < size) 227 { 228 os << std::setfill('0') << std::setw(2) << std::hex << std::nouppercase 229 << static_cast<uint32_t>(reinterpret_cast<const uint8_t *>(data)[idx]) 230 << ((idx + 1) % 32 == 0 ? "\n" : " "); 231 ++idx; 232 } 233 } 234 235 MEDIA_CLASS_DEFINE_END(MediaDebugSerializer) 236 }; 237 238 #endif // USE_MEDIA_DEBUG_TOOL 239