From c0cfd5f666e50db17a800161f54731871572c89e Mon Sep 17 00:00:00 2001
From: "SND\\ussrhero_cp"
 <SND\ussrhero_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Sat, 3 Dec 2016 18:34:58 +0000
Subject: [PATCH] [0.3.x] added : method typeInfo.baseClass ( return a base
 class's type by name or by index )

git-svn-id: https://pykd.svn.codeplex.com/svn@91074 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/pymod.cpp           |  6 ++++++
 pykd/pytypeinfo.cpp      | 26 +++++++++++++++++++++++++-
 pykd/pytypeinfo.h        | 33 +++++++++++++++++++--------------
 test/scripts/typeinfo.py |  6 ++++++
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 9196ded..7bb78b5 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -852,6 +852,12 @@ BOOST_PYTHON_MODULE( pykd )
             "Return method's type by name")
         .def( "method", TypeInfoAdapter::getMethodByIndex,
             "Return method's by index")
+        .def( "getNumberBaseClasses", TypeInfoAdapter::getBaseClassesCount,
+            "Return number of base classes" )
+        .def( "baseClass", TypeInfoAdapter::getBaseClassByName,
+            "Return a base class's type by name" )
+        .def( "baseClass", TypeInfoAdapter::getBaseClassByIndex,
+            "Return a base class's type by index" )
         .def( "deref", TypeInfoAdapter::deref,
             "Return type of pointer" )
         .def( "append", TypeInfoAdapter::appendField,
diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp
index 8ea60c9..44a9b8c 100644
--- a/pykd/pytypeinfo.cpp
+++ b/pykd/pytypeinfo.cpp
@@ -105,6 +105,31 @@ python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo )
 
 ///////////////////////////////////////////////////////////////////////////////
 
+kdlib::TypeInfoPtr TypeInfoAdapter::getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name)
+{
+    {
+        AutoRestorePyState  pystate;
+
+        try {
+            return typeInfo.getElement(name);
+        }
+        catch (kdlib::TypeException&)
+        {}
+
+        try {
+            return typeInfo.getMethod(name);
+        }
+        catch (kdlib::TypeException&)
+        {}
+    }
+
+    std::wstringstream sstr;
+    sstr << L'\'' << typeInfo.getName() << L'\'' << L" type has no field " << L'\'' << name << L'\'';
+    throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo)
 {
     std::list<std::wstring>  lst;
@@ -132,7 +157,6 @@ python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo)
     return pylst;
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 
 python::object  callTypedVar(kdlib::TypedVarPtr& funcobj, python::tuple& args)
diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h
index 8c7276b..55234e1 100644
--- a/pykd/pytypeinfo.h
+++ b/pykd/pytypeinfo.h
@@ -124,20 +124,7 @@ struct TypeInfoAdapter : public kdlib::TypeInfo {
         return typeInfo.getElement(name);
     }
 
-    static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name)
-    {
-        try
-        {
-            return getElementByName(typeInfo, name);
-        }
-        catch (kdlib::DbgException&)
-        {
-            std::wstringstream sstr;
-            sstr << L'\'' << typeInfo.getName() << L'\'' << L" type has no field " << L'\'' << name << L'\'';
-            throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
-        }
-    }
-
+    static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name);
 
     static kdlib::TypeInfoPtr getElementByIndex( kdlib::TypeInfo &typeInfo, size_t index )
     {
@@ -163,6 +150,24 @@ struct TypeInfoAdapter : public kdlib::TypeInfo {
         return typeInfo.getMethod(index);
     }
 
+    static size_t getBaseClassesCount(kdlib::TypeInfo &typeInfo )
+    {
+        AutoRestorePyState  pystate;
+        return typeInfo.getBaseClassesCount();
+    }
+
+    static kdlib::TypeInfoPtr getBaseClassByName(kdlib::TypeInfo &typeInfo, const std::wstring&  className)
+    {
+        AutoRestorePyState  pystate;
+        return typeInfo.getBaseClass(className);
+    }
+       
+    static kdlib::TypeInfoPtr getBaseClassByIndex(kdlib::TypeInfo &typeInfo, size_t index)
+    {
+        AutoRestorePyState  pystate;
+        return typeInfo.getBaseClass(index);
+    }
+
     static kdlib::TypeInfoPtr ptrTo( kdlib::TypeInfo &typeInfo, size_t ptrSize = 0 ) 
     {
         AutoRestorePyState  pystate;
diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py
index 83c7836..7dbfcb3 100644
--- a/test/scripts/typeinfo.py
+++ b/test/scripts/typeinfo.py
@@ -333,4 +333,10 @@ class TypeInfoTest( unittest.TestCase ):
 
     def testGetMethod(self):
         self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").method("childMethod").name() )
+        self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").childMethod.name() )
         self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").method(1).name() )
+
+    def testGteBaseClass(self):
+        classChild = target.module.type("classChild")
+        self.assertEqual( ["classBase1", "classBase2"], [ classChild.baseClass(i).name() for i in xrange(classChild.getNumberBaseClasses()) ] )
+