From 01aa2b6c6db5e3f8670adc3e236244836a858ce3 Mon Sep 17 00:00:00 2001
From: "SND\\ussrhero_cp"
 <SND\ussrhero_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Sun, 9 Apr 2017 08:34:35 +0000
Subject: [PATCH] [0.3.x] added : typedVar.rawBytes method ( return list of
 bytes )

git-svn-id: https://pykd.svn.codeplex.com/svn@91208 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/pykdver.h           |  2 +-
 pykd/pymod.cpp           | 15 ++++++++++
 pykd/pytypedvar.cpp      | 63 ++++++++++++++++++++++++++++++++++++++++
 pykd/pytypedvar.h        | 16 ++++------
 test/scripts/typedvar.py |  8 ++++-
 5 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/pykd/pykdver.h b/pykd/pykdver.h
index 1e29be6..4c9caf4 100644
--- a/pykd/pykdver.h
+++ b/pykd/pykdver.h
@@ -2,7 +2,7 @@
 #define PYKD_VERSION_MAJOR      0
 #define PYKD_VERSION_MINOR      3
 #define PYKD_VERSION_SUBVERSION 2
-#define PYKD_VERSION_BUILDNO    2
+#define PYKD_VERSION_BUILDNO    3
 
 #define __VER_STR2__(x) #x
 #define __VER_STR1__(x) __VER_STR2__(x)
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 86c4659..55fd67a 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -21,6 +21,7 @@
 #include "pytypeinfo.h"
 #include "pycpucontext.h"
 #include "pyprocess.h"
+#include "pydataaccess.h"
 
 using namespace pykd;
 
@@ -920,6 +921,7 @@ BOOST_PYTHON_MODULE( pykd )
 #endif
         ;
 
+
     python::class_<kdlib::TypedVar, kdlib::TypedVarPtr, python::bases<kdlib::NumBehavior>, boost::noncopyable >("typedVar", 
         "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", python::no_init  )
         .def("__init__", python::make_constructor(pykd::getTypedVarByName) )
@@ -952,6 +954,8 @@ BOOST_PYTHON_MODULE( pykd )
             "Return method of class as an object attribute" )
          .def("deref",TypedVarAdapter::deref,
             "Return value by pointer" )
+        .def("rawBytes", TypedVarAdapter::getRawBytes,
+            "Return list of bytes" )
         .def("type", TypedVarAdapter::getType,
             "Return typeInfo instance" )
         .def("castTo", TypedVarAdapter::castByName,
@@ -1311,6 +1315,17 @@ BOOST_PYTHON_MODULE( pykd )
         .def("__str__", pykd::printSyntheticSymbol,
             "Return object as a string");
 
+    //python::class_<pykd::DataAccessor, boost::noncopyable>("dataAccessor",
+    //   "class for abstract representation of data storage",python::no_init)
+    //    .def("readByte", &pykd::DataAccessor::readByte)
+    //    ;
+
+    //python::class_<pykd::ListDataAccessor, kdlib::DataAccessorPtr>("objectAccessor",
+    //    "class for data access to python objects", python::no_init)
+    //    .def( python::init<python::object&>() )
+    //    //.def("readByte", &pykd::ListDataAccessor::readByte, "")
+    //    ;
+
     // C++ exception translation to python
     pykd::registerExceptions();
 }
diff --git a/pykd/pytypedvar.cpp b/pykd/pytypedvar.cpp
index 9ff63fe..6b2f67e 100644
--- a/pykd/pytypedvar.cpp
+++ b/pykd/pytypedvar.cpp
@@ -7,6 +7,52 @@ namespace pykd {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+kdlib::TypedVarPtr getTypedVarByTypeName(const std::wstring &name, python::object& dataStorage)
+{
+    python::extract<kdlib::MEMOFFSET_64>  get_addr(dataStorage);
+    if ( get_addr.check() )
+    {
+        kdlib::MEMOFFSET_64   offset = get_addr();
+        AutoRestorePyState  pystate;
+        return kdlib::loadTypedVar( name, offset );
+    }
+
+    std::vector<char>   byteArray;
+
+    for (int i = 0; i < python::len(dataStorage); ++i)
+    {
+        byteArray.push_back( python::extract<unsigned char>(dataStorage[i]) );
+    }
+    
+    AutoRestorePyState  pystate;
+    return kdlib::loadTypedVar( name, kdlib::getCacheAccessor(byteArray) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+kdlib::TypedVarPtr getTypedVarByTypeInfo( const kdlib::TypeInfoPtr &typeInfo, python::object& dataStorage)
+{
+    python::extract<kdlib::MEMOFFSET_64>  get_addr(dataStorage);
+    if ( get_addr.check() )
+    {
+        kdlib::MEMOFFSET_64   offset = get_addr();
+        AutoRestorePyState  pystate;
+        return kdlib::loadTypedVar(typeInfo, offset );
+    }
+
+    std::vector<char>   byteArray;
+
+    for (int i = 0; i < python::len(dataStorage); ++i)
+    {
+        byteArray.push_back( python::extract<unsigned char>(dataStorage[i]) );
+    }
+    
+    AutoRestorePyState  pystate;
+    return kdlib::loadTypedVar(typeInfo, kdlib::getCacheAccessor(byteArray) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 python::list getTypedVarListByTypeName( kdlib::MEMOFFSET_64 offset, const std::wstring &typeName, const std::wstring &fieldName )
 {
     kdlib::TypedVarList  lst;
@@ -154,6 +200,23 @@ kdlib::TypedVarPtr TypedVarAdapter::getFieldAttr(kdlib::TypedVar& typedVar, cons
 
 ///////////////////////////////////////////////////////////////////////////////
 
+python::list TypedVarAdapter::getRawBytes(kdlib::TypedVar& typedVar)
+{
+
+   std::vector<unsigned char>   rawBytes;
+
+   {
+        AutoRestorePyState  pystate;
+        kdlib::DataAccessorPtr   dataStream = kdlib::getCacheAccessor(typedVar.getSize());
+        typedVar.writeBytes(dataStream);
+        dataStream->readBytes(rawBytes, typedVar.getSize());
+
+   }
+
+   return vectorToList( rawBytes );
+ }
+
+///////////////////////////////////////////////////////////////////////////////
 
 } // namesapce pykd
 
diff --git a/pykd/pytypedvar.h b/pykd/pytypedvar.h
index 301e3f9..ad02661 100644
--- a/pykd/pytypedvar.h
+++ b/pykd/pytypedvar.h
@@ -14,11 +14,7 @@ namespace python = boost::python;
 
 namespace pykd {
 
-inline kdlib::TypedVarPtr getTypedVarByTypeName( const std::wstring &name, kdlib::MEMOFFSET_64 addr ) 
-{
-    AutoRestorePyState  pystate;
-    return kdlib::loadTypedVar( name, addr );
-}
+kdlib::TypedVarPtr getTypedVarByTypeName(const std::wstring &name, python::object& dataStorage);
 
 inline kdlib::TypedVarPtr getTypedVarByName( const std::wstring &name ) 
 {
@@ -26,11 +22,7 @@ inline kdlib::TypedVarPtr getTypedVarByName( const std::wstring &name )
     return kdlib::loadTypedVar( name );
 }
 
-inline  kdlib::TypedVarPtr getTypedVarByTypeInfo( const kdlib::TypeInfoPtr &typeInfo, kdlib::MEMOFFSET_64 addr )
-{
-    AutoRestorePyState  pystate;
-    return kdlib::loadTypedVar( typeInfo, addr );
-}
+kdlib::TypedVarPtr getTypedVarByTypeInfo( const kdlib::TypeInfoPtr &typeInfo, python::object& dataStorage);
 
 inline kdlib::TypedVarPtr getTypedVarWithPrototype( const std::wstring &name, const std::wstring &prototype)
 {
@@ -38,6 +30,8 @@ inline kdlib::TypedVarPtr getTypedVarWithPrototype( const std::wstring &name, co
     return kdlib::loadTypedVar(name, prototype);
 }
 
+kdlib::TypedVarPtr getTypedVarByTypeNameWithBuffer(const std::wstring& name, python::object &bytes);
+
 python::list getTypedVarListByTypeName( kdlib::MEMOFFSET_64 offset, const std::wstring &typeName, const std::wstring &fieldName );
 python::list getTypedVarListByType( kdlib::MEMOFFSET_64 offset, kdlib::TypeInfoPtr &typeInfo, const std::wstring &fieldName );
 python::list getTypedVarArrayByTypeName( kdlib::MEMOFFSET_64 offset, const std::wstring &typeName, size_t number );
@@ -185,6 +179,8 @@ struct TypedVarAdapter {
         AutoRestorePyState  pystate;
         return typedVar.castTo(typeInfo);
     }
+
+    static python::list  getRawBytes(kdlib::TypedVar& typedVar);
 };
 
 } // end namespace pykd
diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py
index 3373295..9b6d146 100644
--- a/test/scripts/typedvar.py
+++ b/test/scripts/typedvar.py
@@ -419,4 +419,10 @@ class TypedVarTest( unittest.TestCase ):
         addr = pykd.getOffset("g_structTest")
         self.assertTrue( None != target.module.type( "structTest" ).getTypedVar(addr) )
 
-       
\ No newline at end of file
+    def testByteSequence(self):
+        self.assertEqual( 0x44332211, pykd.typedVar("UInt4B", [0x11, 0x22, 0x33, 0x44]) )
+        self.assertEqual( -1, pykd.typedVar( pykd.baseTypes.Int4B, [0xFF, 0xFF, 0xFF, 0xFF] ) )
+       
+    def testRawBytes(self):
+        self.assertEqual( [ 0x55, 0x55, 0, 0], target.module.typedVar( "ulongConst" ).rawBytes() )
+ 
\ No newline at end of file