diff --git a/pykd/customtypes.cpp b/pykd/customtypes.cpp index cf0af7f..0b1020a 100644 --- a/pykd/customtypes.cpp +++ b/pykd/customtypes.cpp @@ -8,25 +8,7 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr CustomStruct::create(const std::string &name, ULONG alignReq /*= 0*/) -{ - return TypeInfoPtr( new CustomStruct(name, alignReq) ); -} - -//////////////////////////////////////////////////////////////////////////////// - -ULONG CustomStruct::getSize() -{ - if (UdtFieldColl::empty()) - return 0; - - UdtUtils::Field &field = UdtFieldColl::last(); - return field.m_offset + field.m_type->getSize(); -} - -//////////////////////////////////////////////////////////////////////////////// - -void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType) +void CustomTypeBase::throwIfFiledExist(const std::string &fieldName) { bool fieldExist = false; try @@ -40,10 +22,71 @@ void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldTy } if (fieldExist) throw TypeException(getName(), "duplicate field name: " + fieldName); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CustomTypeBase::throwIfTypeRecursive(TypeInfoPtr type) +{ + if (type->is(this)) + throw TypeException(getName(), "wrong type of field"); + + return throwIfTypeRecursiveImpl(type); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) +{ + if (type->isEnum()) + return; + + try + { + const ULONG fields = type->getFieldCount(); + for (ULONG i = 0; i < fields; ++i) + { + TypeInfoPtr fileldType = type->getFieldByIndex(i); + if (fileldType->is(this)) + throw TypeException(getName(), "wrong type of field"); + + throwIfTypeRecursiveImpl(fileldType); + } + } + catch (const TypeException &except) + { + DBG_UNREFERENCED_PARAMETER(except); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +TypeInfoPtr CustomStruct::create(const std::string &name, ULONG alignReq /*= 0*/) +{ + return TypeInfoPtr( new CustomStruct(name, alignReq) ); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG CustomStruct::getSize() +{ + if (Base::empty()) + return 0; + + UdtUtils::Field &field = Base::last(); + return field.m_offset + field.m_type->getSize(); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType) +{ + Base::throwIfFiledExist(fieldName); + Base::throwIfTypeRecursive(fieldType); ULONG offset = getSize(); offset += offset % (m_align ? m_align : fieldType->getAlignReq()); - UdtFieldColl::push_back( + Base::push_back( UdtUtils::Field(offset, fieldName, fieldType) ); } @@ -73,20 +116,10 @@ ULONG CustomUnion::getSize() void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr fieldType) { - bool fieldExist = false; - try - { - lookupField(fieldName); - fieldExist = true; - } - catch (const TypeException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - } - if (fieldExist) - throw TypeException(getName(), "duplicate field name: " + fieldName); + Base::throwIfFiledExist(fieldName); + Base::throwIfTypeRecursive(fieldType); - UdtFieldColl::push_back( + Base::push_back( UdtUtils::Field(0, fieldName, fieldType) ); } diff --git a/pykd/customtypes.h b/pykd/customtypes.h index ddfd44e..32c0747 100644 --- a/pykd/customtypes.h +++ b/pykd/customtypes.h @@ -12,14 +12,30 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -class CustomStruct : public UdtFieldColl +class CustomTypeBase : public UdtFieldColl { + typedef UdtFieldColl Base; +protected: + CustomTypeBase(const std::string &name) : UdtFieldColl(name) {} + + void throwIfFiledExist(const std::string &fieldName); + void throwIfTypeRecursive(TypeInfoPtr type); + +private: + void throwIfTypeRecursiveImpl(TypeInfoPtr type); +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CustomStruct : public CustomTypeBase +{ + typedef CustomTypeBase Base; public: static TypeInfoPtr create(const std::string &name, ULONG align = 0); protected: CustomStruct(const std::string &name, ULONG align) - : UdtFieldColl(name), m_name(name), m_align(align) + : Base(name), m_name(name), m_align(align) { } @@ -42,13 +58,14 @@ private: //////////////////////////////////////////////////////////////////////////////// -class CustomUnion : public UdtFieldColl +class CustomUnion : public CustomTypeBase { + typedef CustomTypeBase Base; public: static TypeInfoPtr create(const std::string &name); protected: - CustomUnion(const std::string &name) : UdtFieldColl(name) {} + CustomUnion(const std::string &name) : Base(name) {} virtual ULONG getSize() override; diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 046fcff..fe033ef 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -211,6 +211,10 @@ public: return m_virtualBaseType; } + bool is(TypeInfo *rhs) const { + return this == rhs; + } + protected: std::string getComplexName();