- Timestamp:
- Sep 15, 2008 6:32:32 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/VBoxDbgStatsQt4.cpp
r12469 r12471 39 39 #include <VBox/log.h> 40 40 #include <iprt/string.h> 41 #include <iprt/mem.h> 41 42 #include <iprt/assert.h> 42 43 … … 57 58 58 59 60 /** 61 * Formats a number into a 64-byte buffer. 62 */ 63 static char *formatNumber(char *psz, uint64_t u64) 64 { 65 static const char s_szDigits[] = "0123456789"; 66 psz += 63; 67 *psz-- = '\0'; 68 unsigned cDigits = 0; 69 for (;;) 70 { 71 const unsigned iDigit = u64 % 10; 72 u64 /= 10; 73 *psz = s_szDigits[iDigit]; 74 if (!u64) 75 break; 76 psz--; 77 if (!(++cDigits % 3)) 78 *psz-- = ','; 79 } 80 return psz; 81 } 82 83 84 /** 85 * Formats a number into a 64-byte buffer. 86 * (18.446.744.073.709.551.615) 87 */ 88 static char *formatNumberSigned(char *psz, int64_t i64) 89 { 90 static const char s_szDigits[] = "0123456789"; 91 psz += 63; 92 *psz-- = '\0'; 93 const bool fNegative = i64 < 0; 94 uint64_t u64 = fNegative ? -i64 : i64; 95 unsigned cDigits = 0; 96 for (;;) 97 { 98 const unsigned iDigit = u64 % 10; 99 u64 /= 10; 100 *psz = s_szDigits[iDigit]; 101 if (!u64) 102 break; 103 psz--; 104 if (!(++cDigits % 3)) 105 *psz-- = ','; 106 } 107 if (fNegative) 108 *--psz = '-'; 109 return psz; 110 } 111 112 113 /** 114 * Formats a unsigned hexadecimal number into a into a 64-byte buffer. 115 */ 116 static char *formatHexNumber(char *psz, uint64_t u64, unsigned cZeros) 117 { 118 static const char s_szDigits[] = "0123456789abcdef"; 119 psz += 63; 120 *psz-- = '\0'; 121 unsigned cDigits = 0; 122 for (;;) 123 { 124 const unsigned iDigit = u64 % 16; 125 u64 /= 16; 126 *psz = s_szDigits[iDigit]; 127 ++cDigits; 128 if (!u64 && cDigits >= cZeros) 129 break; 130 psz--; 131 if (!(cDigits % 8)) 132 *psz-- = '\''; 133 } 134 return psz; 135 } 136 137 138 /** 139 * Formats a sort key number. 140 */ 141 static void formatSortKey(char *psz, uint64_t u64) 142 { 143 static const char s_szDigits[] = "0123456789abcdef"; 144 /* signed */ 145 *psz++ = '+'; 146 147 /* 16 hex digits */ 148 psz[16] = '\0'; 149 unsigned i = 16; 150 while (i-- > 0) 151 { 152 if (u64) 153 { 154 const unsigned iDigit = u64 % 16; 155 u64 /= 16; 156 psz[i] = s_szDigits[iDigit]; 157 } 158 else 159 psz[i] = '0'; 160 } 161 } 162 163 164 #if 0/* unused */ 165 /** 166 * Formats a sort key number. 167 */ 168 static void formatSortKeySigned(char *psz, int64_t i64) 169 { 170 static const char s_szDigits[] = "0123456789abcdef"; 171 172 /* signed */ 173 uint64_t u64; 174 if (i64 >= 0) 175 { 176 *psz++ = '+'; 177 u64 = i64; 178 } 179 else 180 { 181 *psz++ = '-'; 182 u64 = -i64; 183 } 184 185 /* 16 hex digits */ 186 psz[16] = '\0'; 187 unsigned i = 16; 188 while (i-- > 0) 189 { 190 if (u64) 191 { 192 const unsigned iDigit = u64 % 16; 193 u64 /= 16; 194 psz[i] = s_szDigits[iDigit]; 195 } 196 else 197 psz[i] = '0'; 198 } 199 } 200 #endif 201 202 203 204 /** Pointer to a statistics sample. */ 205 typedef struct DBGGUISTATSNODE *PDBGGUISTATSNODE; 206 207 /** 208 * A tree node representing a statistic sample. 209 * 210 * The nodes carry a reference to the parent and to its position among its 211 * siblings. Both of these need updating when the grand parent or parent adds a 212 * new child. This will hopefully not be too expensive but rather pay off when 213 * we need to create a parent index. 214 */ 215 typedef struct DBGGUISTATSNODE 216 { 217 /** Pointer to the parent. */ 218 PDBGGUISTATSNODE pParent; 219 /** Array of children. */ 220 PDBGGUISTATSNODE paChildren; 221 /** The number of children. */ 222 uint32_t cChildren; 223 /** Our index among the parent's children. */ 224 uint32_t iSelf; 225 /** The unit. */ 226 STAMUNIT enmUnit; 227 /** The data type. */ 228 STAMTYPE enmType; 229 /** The data at last update. */ 230 union 231 { 232 /** STAMTYPE_COUNTER. */ 233 STAMCOUNTER Counter; 234 /** STAMTYPE_PROFILE. */ 235 STAMPROFILE Profile; 236 /** STAMTYPE_PROFILE_ADV. */ 237 STAMPROFILEADV ProfileAdv; 238 /** STAMTYPE_RATIO_U32. */ 239 STAMRATIOU32 RatioU32; 240 /** STAMTYPE_U8 & STAMTYPE_U8_RESET. */ 241 uint8_t u8; 242 /** STAMTYPE_U16 & STAMTYPE_U16_RESET. */ 243 uint16_t u16; 244 /** STAMTYPE_U32 & STAMTYPE_U32_RESET. */ 245 uint32_t u32; 246 /** STAMTYPE_U64 & STAMTYPE_U64_RESET. */ 247 uint64_t u64; 248 } Data; 249 /** The description string. */ 250 QString *pDescStr; 251 } DBGGUISTATSNODE; 252 253 254 class VBoxDbgStatsModel : public QAbstractItemModel 255 { 256 private: 257 /** The root of the sample tree. */ 258 PDBGGUISTATSNODE m_pRoot; 259 260 public: 261 /** 262 * Constructor. 263 * 264 * @param a_pParent The parent object. See QAbstractItemModel in the Qt 265 * docs for details. 266 */ 267 VBoxDbgStatsModel(QObject *a_pParent); 268 269 /** 270 * Destructor. 271 * 272 * This will free all the the data the model holds. 273 */ 274 ~VBoxDbgStatsModel(); 275 276 /** 277 * Set the root node. 278 * 279 * This will free all the current data before taking the ownership of the new 280 * root node and its children. 281 * 282 * @param a_pRoot The new root node. 283 */ 284 void setRootNode(PDBGGUISTATSNODE a_pRoot); 285 286 /** 287 * Constructs a new statistics tree by query data from the VM. 288 * 289 * @returns Pointer to the root of the tree we've constructed. This will be NULL 290 * if the STAM API throws an error or we run out of memory. 291 * 292 * @param a_pVM The VM handle. 293 */ 294 static PDBGGUISTATSNODE createNewTree(PVM a_pVM); 295 296 /** 297 * Destroys a statistics tree. 298 * 299 * @param a_pRoot The root of the tree. NULL is fine. 300 */ 301 static void destroyTree(PDBGGUISTATSNODE a_pRoot); 302 303 protected: 304 /** 305 * Destroys a node and all its children. 306 * 307 * @param a_pNode The node to destroy. 308 */ 309 static void destroyNode(PDBGGUISTATSNODE a_pNode); 310 311 /** 312 * Converts an index to a node pointer. 313 * 314 * @returns Pointer to the node, NULL if empty tree. 315 * @param a_rIndex Reference to the index 316 */ 317 inline PDBGGUISTATSNODE nodeFromIndex(const QModelIndex &a_rIndex) const 318 { 319 if (RT_LIKELY(a_rIndex.isValid())) 320 return (PDBGGUISTATSNODE)a_rIndex.internalPointer(); 321 return m_pRoot; 322 } 323 324 public: 325 326 /** @name Methods we override 327 * @{ */ 328 virtual int columnCount(const QModelIndex &parent) const; 329 virtual QVariant data(const QModelIndex &index, int role) const; 330 virtual bool hasChildren(const QModelIndex &parent) const; 331 virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; 332 virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; 333 virtual QModelIndex parent(const QModelIndex &child) const; 334 virtual int rowCount(const QModelIndex &parent) const; 335 /** @} */ 336 }; 337 338 339 VBoxDbgStatsModel::VBoxDbgStatsModel(QObject *a_pParent) 340 : QAbstractItemModel(a_pParent), m_pRoot(NULL) 341 { 342 } 343 344 345 346 VBoxDbgStatsModel::~VBoxDbgStatsModel() 347 { 348 destroyTree(m_pRoot); 349 m_pRoot = NULL; 350 } 351 352 353 /*static*/ void 354 VBoxDbgStatsModel::destroyTree(PDBGGUISTATSNODE a_pRoot) 355 { 356 if (!a_pRoot) 357 return; 358 Assert(!a_pRoot->pParent); 359 Assert(!a_pRoot->iSelf); 360 361 destroyNode(a_pRoot); 362 } 363 364 365 /* static*/ void 366 VBoxDbgStatsModel::destroyNode(PDBGGUISTATSNODE a_pNode) 367 { 368 /* destroy all our children */ 369 uint32_t i = a_pNode->cChildren; 370 while (i-- > 0) 371 destroyNode(&a_pNode->paChildren[i]); 372 373 /* free the resources we're using */ 374 a_pNode->pParent = NULL; 375 376 RTMemFree(a_pNode->paChildren); 377 a_pNode->paChildren = NULL; 378 379 a_pNode->cChildren = 0; 380 a_pNode->iSelf = UINT32_MAX; 381 a_pNode->enmUnit = STAMUNIT_INVALID; 382 a_pNode->enmType = STAMTYPE_INVALID; 383 384 if (a_pNode->pDescStr) 385 { 386 delete a_pNode->pDescStr; 387 a_pNode->pDescStr = NULL; 388 } 389 } 390 391 392 /*static*/ PDBGGUISTATSNODE 393 VBoxDbgStatsModel::createNewTree(PVM a_pVM) 394 { 395 /** @todo */ 396 return NULL; 397 } 398 399 400 #if 0 401 /*static*/ PDBGGUISTATSNODE 402 VBoxDbgStatsModel::createNewTree(IMachineDebugger *a_pIMachineDebugger) 403 { 404 /** @todo */ 405 return NULL; 406 } 407 #endif 408 409 410 #if 0 411 /*static*/ PDBGGUISTATSNODE 412 VBoxDbgStatsModel::createNewTree(const char *pszFilename) 413 { 414 /** @todo */ 415 return NULL; 416 } 417 #endif 418 419 420 #if 0 421 /*static*/ PDBGGUISTATSNODE 422 VBoxDbgStatsModel::createDiffTree(PDBGGUISTATSNODE pTree1, PDBGGUISTATSNODE pTree2) 423 { 424 /** @todo */ 425 return NULL; 426 } 427 #endif 428 429 430 int 431 VBoxDbgStatsModel::columnCount(const QModelIndex &parent) const 432 { 433 return 9; /* fixed */ 434 } 435 436 437 int 438 VBoxDbgStatsModel::rowCount(const QModelIndex &a_rParent) const 439 { 440 PDBGGUISTATSNODE pParent = nodeFromIndex(a_rParent); 441 return pParent ? pParent->cChildren : 0; 442 } 443 444 445 bool 446 VBoxDbgStatsModel::hasChildren(const QModelIndex &a_rParent) const 447 { 448 PDBGGUISTATSNODE pParent = nodeFromIndex(a_rParent); 449 return pParent 450 && pParent->cChildren > 0; 451 } 452 453 454 QModelIndex 455 VBoxDbgStatsModel::index(int iRow, int iColumn, const QModelIndex &r_pParent) const 456 { 457 PDBGGUISTATSNODE pParent = nodeFromIndex(r_pParent); 458 if (!pParent) 459 return QModelIndex(); /* bug? */ 460 if ((unsigned)iRow >= pParent->cChildren) 461 return QModelIndex(); /* bug? */ 462 if ((unsigned)iColumn >= 9) 463 return QModelIndex(); /* bug? */ 464 465 return createIndex(iRow, iColumn, &pParent->paChildren[iRow]); 466 } 467 468 469 QModelIndex 470 VBoxDbgStatsModel::parent(const QModelIndex &a_rChild) const 471 { 472 PDBGGUISTATSNODE pChild = nodeFromIndex(a_rChild); 473 if (!pChild) 474 return QModelIndex(); /* bug */ 475 PDBGGUISTATSNODE pParent = pChild->pParent; 476 if (!pParent) 477 return QModelIndex(); /* root child */ 478 479 return createIndex(pParent->iSelf, a_rChild.column(), pParent); 480 } 481 482 483 QVariant 484 VBoxDbgStatsModel::headerData(int a_iSection, Qt::Orientation a_eOrientation, int a_eRole) const 485 { 486 if ( a_eOrientation != Qt::Horizontal 487 || a_eRole != Qt::DisplayRole) 488 return QVariant(); 489 switch (a_iSection) 490 { 491 case 0: return tr("Name"); 492 case 1: return tr("Unit"); 493 case 2: return tr("Value/Times"); 494 case 3: return tr("Min"); 495 case 4: return tr("Average"); 496 case 5: return tr("Max"); 497 case 6: return tr("Total"); 498 case 7: return tr("dInt"); 499 case 8: return tr("Description"); 500 default: 501 return QVariant(); /* bug */ 502 } 503 } 504 505 506 QVariant 507 VBoxDbgStatsModel::data(const QModelIndex &a_rIndex, int role) const 508 { 509 /** @todo data formatting... */ 510 return QVariant(); 511 } 59 512 60 513 … … 171 624 172 625 173 /**174 * Formats a number into a 64-byte buffer.175 */176 static char *formatNumber(char *psz, uint64_t u64)177 {178 static const char s_szDigits[] = "0123456789";179 psz += 63;180 *psz-- = '\0';181 unsigned cDigits = 0;182 for (;;)183 {184 const unsigned iDigit = u64 % 10;185 u64 /= 10;186 *psz = s_szDigits[iDigit];187 if (!u64)188 break;189 psz--;190 if (!(++cDigits % 3))191 *psz-- = ',';192 }193 return psz;194 }195 196 197 /**198 * Formats a number into a 64-byte buffer.199 * (18.446.744.073.709.551.615)200 */201 static char *formatNumberSigned(char *psz, int64_t i64)202 {203 static const char s_szDigits[] = "0123456789";204 psz += 63;205 *psz-- = '\0';206 const bool fNegative = i64 < 0;207 uint64_t u64 = fNegative ? -i64 : i64;208 unsigned cDigits = 0;209 for (;;)210 {211 const unsigned iDigit = u64 % 10;212 u64 /= 10;213 *psz = s_szDigits[iDigit];214 if (!u64)215 break;216 psz--;217 if (!(++cDigits % 3))218 *psz-- = ',';219 }220 if (fNegative)221 *--psz = '-';222 return psz;223 }224 225 226 /**227 * Formats a unsigned hexadecimal number into a into a 64-byte buffer.228 */229 static char *formatHexNumber(char *psz, uint64_t u64, unsigned cZeros)230 {231 static const char s_szDigits[] = "0123456789abcdef";232 psz += 63;233 *psz-- = '\0';234 unsigned cDigits = 0;235 for (;;)236 {237 const unsigned iDigit = u64 % 16;238 u64 /= 16;239 *psz = s_szDigits[iDigit];240 ++cDigits;241 if (!u64 && cDigits >= cZeros)242 break;243 psz--;244 if (!(cDigits % 8))245 *psz-- = '\'';246 }247 return psz;248 }249 250 251 /**252 * Formats a sort key number.253 */254 static void formatSortKey(char *psz, uint64_t u64)255 {256 static const char s_szDigits[] = "0123456789abcdef";257 /* signed */258 *psz++ = '+';259 260 /* 16 hex digits */261 psz[16] = '\0';262 unsigned i = 16;263 while (i-- > 0)264 {265 if (u64)266 {267 const unsigned iDigit = u64 % 16;268 u64 /= 16;269 psz[i] = s_szDigits[iDigit];270 }271 else272 psz[i] = '0';273 }274 }275 276 277 #if 0/* unused */278 /**279 * Formats a sort key number.280 */281 static void formatSortKeySigned(char *psz, int64_t i64)282 {283 static const char s_szDigits[] = "0123456789abcdef";284 285 /* signed */286 uint64_t u64;287 if (i64 >= 0)288 {289 *psz++ = '+';290 u64 = i64;291 }292 else293 {294 *psz++ = '-';295 u64 = -i64;296 }297 298 /* 16 hex digits */299 psz[16] = '\0';300 unsigned i = 16;301 while (i-- > 0)302 {303 if (u64)304 {305 const unsigned iDigit = u64 % 16;306 u64 /= 16;307 psz[i] = s_szDigits[iDigit];308 }309 else310 psz[i] = '0';311 }312 }313 #endif314 626 315 627
Note:
See TracChangeset
for help on using the changeset viewer.