From bc6c66cc13c7e348c3568b389e4e179a1dd3bbe3 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Tue, 22 May 2012 11:46:58 +0000
Subject: [PATCH] [0.1.x] added : "subscription" for UDT typeInfo

git-svn-id: https://pykd.svn.codeplex.com/svn@76521 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/pymod.cpp           |  4 +++-
 pykd/typedvar.cpp        | 14 +++++++++-----
 pykd/typedvar.h          |  8 ++++----
 pykd/typeinfo.h          | 16 ++++++++++++++++
 test/scripts/typedvar.py |  4 +++-
 test/scripts/typeinfo.py |  6 ++++++
 6 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 853932e..c92e40a 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -532,7 +532,9 @@ BOOST_PYTHON_MODULE( pykd )
         .def( "asMap", &TypeInfo::asMap )
         .def( "deref", &TypeInfo::deref )
         .def( "__str__", &TypeInfo::print )
-        .def( "__getattr__", &TypeInfo::getField );
+        .def( "__getattr__", &TypeInfo::getField )
+        .def("__len__", &TypeInfo::getElementCount )
+        .def("__getitem__", &TypeInfo::getElementByIndex );
         
     python::class_<TypedVar, TypedVarPtr, python::bases<intBase>, boost::noncopyable >("typedVar", 
         "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", python::no_init  )
diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp
index 890e9a3..1faef89 100644
--- a/pykd/typedvar.cpp
+++ b/pykd/typedvar.cpp
@@ -213,14 +213,14 @@ std::string  ArrayTypedVar::printValue()
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-TypedVarPtr ArrayTypedVar::getElementByIndex( ULONG  index ) 
+python::object ArrayTypedVar::getElementByIndex( ULONG  index ) 
 {
     if ( index >= m_typeInfo->getCount() )
         throw PyException( PyExc_IndexError, "Index out of range" );
 
     TypeInfoPtr     elementType = m_typeInfo->getElementType();
 
-    return TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) );
+    return python::object( TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) ) );
 }
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -252,7 +252,7 @@ UdtTypedVar::getField( const std::string &fieldName )
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-TypedVarPtr 
+python::object
 UdtTypedVar::getElementByIndex( ULONG  index )
 {
     TypeInfoPtr     fieldType = m_typeInfo->getFieldByIndex(index);
@@ -262,7 +262,9 @@ UdtTypedVar::getElementByIndex( ULONG  index )
         if ( fieldType->getStaticOffset() == 0 )
             throw ImplementException( __FILE__, __LINE__, "Fix ME");
 
-        return  TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) );
+        return python::make_tuple(
+            m_typeInfo->getFieldNameByIndex(index), 
+            TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) );
     }
 
     ULONG   fieldOffset = fieldType->getOffset();
@@ -272,7 +274,9 @@ UdtTypedVar::getElementByIndex( ULONG  index )
         fieldOffset += getVirtualBaseDisplacement( fieldType );
     }
 
-    return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) );
+    return python::make_tuple( 
+            m_typeInfo->getFieldNameByIndex(index), 
+            TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ) );
 }
 
 ///////////////////////////////////////////////////////////////////////////////////
diff --git a/pykd/typedvar.h b/pykd/typedvar.h
index 8c2ddc0..11211bb 100644
--- a/pykd/typedvar.h
+++ b/pykd/typedvar.h
@@ -64,11 +64,11 @@ public:
         throw PyException( PyExc_TypeError, "object has no len()" );
     }
 
-    virtual TypedVarPtr getElementByIndex( ULONG  index ) {
+    virtual python::object getElementByIndex( ULONG  index ) {
         throw PyException( PyExc_TypeError, "object is unsubscriptable");  
     }
 
-    TypedVarPtr getElementByIndexPtr( const TypedVarPtr& tv ) {
+    python::object getElementByIndexPtr( const TypedVarPtr& tv ) {
         return getElementByIndex( boost::apply_visitor( VariantToULong(), tv->getValue() ) );
     }
 
@@ -158,7 +158,7 @@ public:
 
     virtual std::string  printValue();
 
-    virtual TypedVarPtr getElementByIndex( ULONG  index );
+    virtual python::object getElementByIndex( ULONG  index );
 };
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -184,7 +184,7 @@ protected:
         return m_typeInfo->getFieldCount();                
     }
 
-    virtual TypedVarPtr getElementByIndex( ULONG  index );
+    virtual python::object getElementByIndex( ULONG  index );
 
     LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo );
 };
diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h
index 320b545..ecc8b7a 100644
--- a/pykd/typeinfo.h
+++ b/pykd/typeinfo.h
@@ -128,6 +128,14 @@ public:
         throw TypeException( getName(), "type is not a pointer" );
     }
 
+    virtual ULONG getElementCount() {
+        throw PyException( PyExc_TypeError, "object has no len()" );
+    }
+
+    virtual python::tuple getElementByIndex( ULONG index ) {
+        throw PyException( PyExc_TypeError, "object is unsubscriptable");  
+    }
+
     void setOffset( ULONG offset ) {
         m_offset = offset;
     }
@@ -309,6 +317,14 @@ protected:
         return true;
     }
 
+    virtual ULONG getElementCount() {
+        return getFieldCount();
+    }
+
+    virtual python::tuple getElementByIndex( ULONG index ) {
+        return python::make_tuple( getFieldNameByIndex(index), getFieldByIndex(index) );
+    }
+
     virtual std::string print();
 
     pyDia::SymbolPtr    m_dia;
diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py
index b8a382b..e290126 100644
--- a/test/scripts/typedvar.py
+++ b/test/scripts/typedvar.py
@@ -258,6 +258,8 @@ class TypedVarTest( unittest.TestCase ):
     def testUdtSubscribe(self):
         tv = pykd.typedVar( "g_virtChild" )
         self.assertEqual( 5, len(tv) )
-        self.assertEqual( tv[4], tv.m_baseField )
+        fieldName, fieldVal = tv[4]
+        self.assertEqual( fieldName, "m_baseField" )
+        self.assertEqual( fieldVal, tv.m_baseField )
         for field in tv:
              str( field )
diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py
index 149cfe6..82f1be7 100644
--- a/test/scripts/typeinfo.py
+++ b/test/scripts/typeinfo.py
@@ -185,3 +185,9 @@ class TypeInfoTest( unittest.TestCase ):
         self.assertNotEqual( 0, ti.m_staticConst.offset() )
         self.assertNotEqual( 0, ti.m_stdstr.offset() )
         
+    def testUdtSubscribe(self):
+        tv = pykd.typeInfo( "g_virtChild" )
+        self.assertEqual( 5, len(tv) )
+        for field in tv:
+             str( field )
+