hrev45645 adds 1 changeset to branch 'master' old head: 879020baf11d142a48ba1714fcca1c419b93a4c3 new head: a69facf0517bfcea02258dcc0e17a037158938a1 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=a69facf+%5E879020b ---------------------------------------------------------------------------- a69facf: Implement #9756. ImageFunctionsView now builds... ...a source path-based tree of all the image's functions, and consequently organizes them into a nested hierarchy similar to the on-disk directory structure in which they were originally found (or at least, as close as we can get from the DWARF info). [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev45645 Commit: a69facf0517bfcea02258dcc0e17a037158938a1 URL: http://cgit.haiku-os.org/haiku/commit/?id=a69facf Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu May 9 03:24:12 2013 UTC Ticket: https://dev.haiku-os.org/ticket/9756 ---------------------------------------------------------------------------- 2 files changed, 300 insertions(+), 113 deletions(-) .../gui/team_window/ImageFunctionsView.cpp | 411 ++++++++++++++----- .../gui/team_window/ImageFunctionsView.h | 2 + ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.cpp b/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.cpp index 3a096fa..06eb89d 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -23,6 +23,135 @@ #include "Tracing.h" +// #pragma mark - SourcePathComponentNode + + +class ImageFunctionsView::SourcePathComponentNode : public BReferenceable { +public: + SourcePathComponentNode(SourcePathComponentNode* parent, + const BString& componentName, LocatableFile* sourceFile, + FunctionInstance* function) + : + fParent(parent), + fComponentName(componentName), + fSourceFile(sourceFile), + fFunction(function) + { + if (fParent != NULL) + fParent->AcquireReference(); + if (fSourceFile != NULL) + fSourceFile->AcquireReference(); + if (fFunction != NULL) + fFunction->AcquireReference(); + } + + virtual ~SourcePathComponentNode() + { + for (int32 i = 0; i < fChildPathComponents.CountItems(); i++) + fChildPathComponents.ItemAt(i)->ReleaseReference(); + + if (fParent != NULL) + fParent->ReleaseReference(); + + if (fSourceFile != NULL) + fSourceFile->ReleaseReference(); + + if (fFunction != NULL) + fFunction->AcquireReference(); + } + + const BString& ComponentName() const + { + return fComponentName; + } + + LocatableFile* SourceFile() const + { + return fSourceFile; + } + + FunctionInstance* Function() const + { + return fFunction; + } + + int32 CountChildren() const + { + return fChildPathComponents.CountItems(); + } + + SourcePathComponentNode* ChildAt(int32 index) + { + return fChildPathComponents.ItemAt(index); + } + + SourcePathComponentNode* FindChildByName(const BString& name) const + { + return fChildPathComponents.BinarySearchByKey(name, + &CompareByComponentName); + } + + int32 FindChildIndexByName(const BString& name) const + { + return fChildPathComponents.BinarySearchIndexByKey(name, + &CompareByComponentName); + } + + bool AddChild(SourcePathComponentNode* child) + { + if (!fChildPathComponents.BinaryInsert(child, + &CompareComponents)) { + return false; + } + + child->AcquireReference(); + + return true; + } + + bool RemoveChild(SourcePathComponentNode* child) + { + if (!fChildPathComponents.RemoveItem(child)) + return false; + + child->ReleaseReference(); + + return true; + } + + bool RemoveAllChildren() + { + for (int32 i = 0; i < fChildPathComponents.CountItems(); i++) + RemoveChild(fChildPathComponents.ItemAt(i)); + + return true; + } + +private: + static int CompareByComponentName(const BString* name, const + SourcePathComponentNode* node) + { + return name->Compare(node->ComponentName()); + } + + static int CompareComponents(const SourcePathComponentNode* a, + const SourcePathComponentNode* b) + { + return a->ComponentName().Compare(b->ComponentName()); + } + +private: + typedef BObjectList<SourcePathComponentNode> ChildPathComponentList; + +private: + SourcePathComponentNode* fParent; + BString fComponentName; + LocatableFile* fSourceFile; + FunctionInstance* fFunction; + ChildPathComponentList fChildPathComponents; +}; + + // #pragma mark - FunctionsTableModel @@ -31,10 +160,7 @@ public: FunctionsTableModel() : fImageDebugInfo(NULL), - fFunctions(NULL), - fFunctionCount(0), - fSourceFileIndices(NULL), - fSourceFileCount(0) + fSourcelessNode(NULL) { } @@ -46,16 +172,14 @@ public: void SetImageDebugInfo(ImageDebugInfo* imageDebugInfo) { // unset old functions - if (fSourceFileIndices != NULL) { - NotifyNodesRemoved(TreeTablePath(), 0, fSourceFileCount); - - delete[] fFunctions; - fFunctions = NULL; - fFunctionCount = 0; - - delete[] fSourceFileIndices; - fSourceFileIndices = NULL; - fSourceFileCount = 0; + if (fImageDebugInfo != NULL) { + NotifyNodesRemoved(TreeTablePath(), 0, + fChildPathComponents.CountItems()); + for (int32 i = 0; i < fChildPathComponents.CountItems(); i++) + fChildPathComponents.ItemAt(i)->ReleaseReference(); + + fChildPathComponents.MakeEmpty(); + fSourcelessNode = NULL; } fImageDebugInfo = imageDebugInfo; @@ -95,35 +219,27 @@ public: // The array might now be too large, but we can live with that. } - // count the different source files - int32 sourceFileCount = 1; - for (int32 i = 1; i < functionCount; i++) { - if (_CompareSourceFileNames(functions[i - 1]->SourceFile(), - functions[i]->SourceFile()) != 0) { - sourceFileCount++; - } - } + SourcePathComponentNode* sourcelessNode = new(std::nothrow) + SourcePathComponentNode(NULL, "<no source file>", NULL, NULL); + ObjectDeleter<SourcePathComponentNode> sourceNodeDeleter( + sourcelessNode); - // allocate and init the indices for the source files - fSourceFileIndices = new(std::nothrow) int32[sourceFileCount]; - if (fSourceFileIndices == NULL) - return; - fSourceFileCount = sourceFileCount; - fSourceFileIndices[0] = 0; + for (int32 i = 0; i < functionCount; i++) { + if (!_BuildFunctionSourcePath(functions[i], sourcelessNode)) + return; + } - int32 sourceFileIndex = 1; - for (int32 i = 1; i < functionCount; i++) { - if (_CompareSourceFileNames(functions[i - 1]->SourceFile(), - functions[i]->SourceFile()) != 0) { - fSourceFileIndices[sourceFileIndex++] = i; + if (sourcelessNode->CountChildren() != 0) { + if (fChildPathComponents.BinaryInsert(sourcelessNode, + &SourcePathComponentNode::CompareComponents)) { + fSourcelessNode = sourcelessNode; + sourceNodeDeleter.Detach(); } } - fFunctions = functionsDeleter.Detach(); - fFunctionCount = functionCount; - - NotifyNodesAdded(TreeTablePath(), 0, fSourceFileCount); + NotifyNodesAdded(TreeTablePath(), 0, + fChildPathComponents.CountItems()); } virtual int32 CountColumns() const @@ -139,34 +255,17 @@ public: virtual int32 CountChildren(void* parent) const { if (parent == this) - return fSourceFileCount; - - if (parent >= fSourceFileIndices - && parent < fSourceFileIndices + fSourceFileCount) { - int32 sourceIndex = (int32*)parent - fSourceFileIndices; - return _CountSourceFileFunctions(sourceIndex); - } + return fChildPathComponents.CountItems(); - return 0; + return ((SourcePathComponentNode*)parent)->CountChildren(); } virtual void* ChildAt(void* parent, int32 index) const { - if (parent == this) { - return index >= 0 && index < fSourceFileCount - ? fSourceFileIndices + index : NULL; - } - - if (parent >= fSourceFileIndices - && parent < fSourceFileIndices + fSourceFileCount) { - int32 sourceIndex = (int32*)parent - fSourceFileIndices; - int32 count = _CountSourceFileFunctions(sourceIndex); - int32 firstFunctionIndex = fSourceFileIndices[sourceIndex]; - return index >= 0 && index < count - ? fFunctions[firstFunctionIndex + index] : NULL; - } + if (parent == this) + return fChildPathComponents.ItemAt(index); - return NULL; + return ((SourcePathComponentNode*)parent)->ChildAt(index); } virtual bool GetValueAt(void* object, int32 columnIndex, BVariant& value) @@ -177,84 +276,168 @@ public: if (object == this) return false; - if (object >= fSourceFileIndices - && object < fSourceFileIndices + fSourceFileCount) { - int32 index = *(int32*)object; - if (LocatableFile* file = fFunctions[index]->SourceFile()) { - BString path; - file->GetPath(path); - value.SetTo(path); - } else - value.SetTo("<no source file>", B_VARIANT_DONT_COPY_DATA); + SourcePathComponentNode* node = (SourcePathComponentNode*)object; - return true; - } + value.SetTo(node->ComponentName(), B_VARIANT_DONT_COPY_DATA); - FunctionInstance* function = (FunctionInstance*)object; - value.SetTo(function->PrettyName(), B_VARIANT_DONT_COPY_DATA); return true; } bool GetFunctionPath(FunctionInstance* function, TreeTablePath& _path) { - int32 index = -1; - for (int32 i = 0; i < fFunctionCount; i++) { - if (fFunctions[i] == function) { - index = i; - break; + if (function == NULL) + return false; + + LocatableFile* sourceFile = function->SourceFile(); + SourcePathComponentNode* node = NULL; + int32 childIndex = -1; + if (sourceFile == NULL) { + node = fSourcelessNode; + _path.AddComponent(fChildPathComponents.IndexOf(node)); + } else { + BString sourcePath; + sourceFile->GetPath(sourcePath); + + if (sourcePath.IsEmpty()) + return false; + + BString searchPath; + while (!sourcePath.IsEmpty()) { + if (sourcePath[0] == '/') + sourcePath.Remove(0, 1); + int32 separatorIndex = sourcePath.FindFirst('/'); + if (separatorIndex == -1) { + searchPath = sourcePath; + sourcePath.Truncate(0); + } else + sourcePath.MoveInto(searchPath, 0, separatorIndex); + + if (node == NULL) { + childIndex = fChildPathComponents.BinarySearchIndexByKey( + searchPath, + &SourcePathComponentNode::CompareByComponentName); + node = fChildPathComponents.ItemAt(childIndex); + } else { + childIndex = node->FindChildIndexByName(searchPath); + node = node->ChildAt(childIndex); + } + + if (childIndex < 0) + return false; + + _path.AddComponent(childIndex); } } - if (index < 0) + if (node == NULL) return false; - int32 sourceIndex = fSourceFileCount - 1; - while (fSourceFileIndices[sourceIndex] > index) - sourceIndex--; + childIndex = node->FindChildIndexByName(function->PrettyName()); + if (childIndex < 0) + return false; - _path.Clear(); - return _path.AddComponent(sourceIndex) - && _path.AddComponent(index - fSourceFileIndices[sourceIndex]); + _path.AddComponent(childIndex); + return true; } bool GetObjectForPath(const TreeTablePath& path, LocatableFile*& _sourceFile, FunctionInstance*& _function) { - int32 componentCount = path.CountComponents(); - if (componentCount == 0 || componentCount > 2) - return false; + SourcePathComponentNode* node = fChildPathComponents.ItemAt( + path.ComponentAt(0)); - int32 sourceIndex = path.ComponentAt(0); - if (sourceIndex < 0 || sourceIndex >= fSourceFileCount) + if (node == NULL) return false; - _sourceFile = fFunctions[fSourceFileIndices[sourceIndex]]->SourceFile(); + for (int32 i = 1; i < path.CountComponents(); i++) + node = node->ChildAt(path.ComponentAt(i)); - _function = NULL; - - if (componentCount == 2) { - int32 index = path.ComponentAt(1); - if (index >= 0 && index < _CountSourceFileFunctions(sourceIndex)) - _function = fFunctions[fSourceFileIndices[sourceIndex] + index]; + if (node != NULL) { + _sourceFile = node->SourceFile(); + _function = node->Function(); + return true; } - return true; + return false; } - int32 CountSourceFiles() const +private: + bool _BuildFunctionSourcePath(FunctionInstance* function, + SourcePathComponentNode* sourcelessNode) { - return fSourceFileCount; + LocatableFile* sourceFile = function->SourceFile(); + if (sourceFile == NULL) + return _AddFunctionNode(sourcelessNode, function, NULL); + + BString sourcePath; + sourceFile->GetPath(sourcePath); + if (sourcePath.IsEmpty()) + return false; + + return _AddNextPathComponent(NULL, sourcePath, function, sourceFile); } -private: - int32 _CountSourceFileFunctions(int32 sourceIndex) const + bool _AddNextPathComponent(SourcePathComponentNode* parent, + BString& childPath, FunctionInstance* function, LocatableFile* file) { - if (sourceIndex < 0 || sourceIndex >= fSourceFileCount) - return 0; + if (childPath[0] == '/') + childPath.Remove(0, 1); + + BString pathComponent; + int32 pathSeparatorIndex = childPath.FindFirst('/'); + if (pathSeparatorIndex == -1) + pathComponent = childPath; + else + childPath.MoveInto(pathComponent, 0, pathSeparatorIndex); + + SourcePathComponentNode* currentNode = NULL; + if (parent == NULL) { + currentNode = fChildPathComponents.BinarySearchByKey(pathComponent, + SourcePathComponentNode::CompareByComponentName); + } else + currentNode = parent->FindChildByName(pathComponent); + + if (currentNode == NULL) { + currentNode = new(std::nothrow) SourcePathComponentNode(parent, + pathComponent, NULL, NULL); + if (currentNode == NULL) + return false; + ObjectDeleter<SourcePathComponentNode> nodeDeleter(currentNode); + if (parent != NULL) { + if (!parent->AddChild(currentNode)) + return false; + } else { + if (!fChildPathComponents.BinaryInsert(currentNode, + &SourcePathComponentNode::CompareComponents)) { + return false; + } + } + nodeDeleter.Detach(); + } + + if (pathSeparatorIndex == -1) + return _AddFunctionNode(currentNode, function, file); + + return _AddNextPathComponent(currentNode, childPath, function, file); + } + + bool _AddFunctionNode(SourcePathComponentNode* parent, + FunctionInstance* function, LocatableFile* file) + { + SourcePathComponentNode* functionNode = new(std::nothrow) + SourcePathComponentNode(parent, function->PrettyName(), file, + function); + + if (functionNode == NULL) + return B_NO_MEMORY; - int32 nextFunctionIndex = sourceIndex + 1 < fSourceFileCount - ? fSourceFileIndices[sourceIndex + 1] : fFunctionCount; - return nextFunctionIndex - fSourceFileIndices[sourceIndex]; + ObjectDeleter<SourcePathComponentNode> nodeDeleter(functionNode); + + if (!parent->AddChild(functionNode)) + return false; + + nodeDeleter.Detach(); + return true; } static int _CompareSourceFileNames(LocatableFile* a, LocatableFile* b) @@ -290,11 +473,12 @@ private: } private: - ImageDebugInfo* fImageDebugInfo; - FunctionInstance** fFunctions; - int32 fFunctionCount; - int32* fSourceFileIndices; - int32 fSourceFileCount; + typedef BObjectList<SourcePathComponentNode> ChildPathComponentList; + +private: + ImageDebugInfo* fImageDebugInfo; + ChildPathComponentList fChildPathComponents; + SourcePathComponentNode* fSourcelessNode; }; @@ -364,7 +548,7 @@ ImageFunctionsView::SetImageDebugInfo(ImageDebugInfo* imageDebugInfo) // If there's only one source file (i.e. "no source file"), expand the item. if (fImageDebugInfo != NULL - && fFunctionsTableModel->CountSourceFiles() == 1) { + && fFunctionsTableModel->CountChildren(fFunctionsTableModel) == 1) { TreeTablePath path; path.AddComponent(0); fFunctionsTable->SetNodeExpanded(path, true, false); @@ -388,6 +572,7 @@ ImageFunctionsView::SetFunction(FunctionInstance* function) fFunctionsTable->SetNodeExpanded(path, true, true); fFunctionsTable->SelectNode(path, false); fFunctionsTable->ScrollToNode(path); + fFunctionsTable->ResizeAllColumnsToPreferred(); } else fFunctionsTable->DeselectAllNodes(); } diff --git a/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.h b/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.h index eb4ed26..55fb959 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.h +++ b/src/apps/debugger/user_interface/gui/team_window/ImageFunctionsView.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef IMAGE_FUNCTIONS_VIEW_H @@ -36,6 +37,7 @@ public: private: class FunctionsTableModel; + class SourcePathComponentNode; private: // TreeTableListener