From 78bfb316aae08bbcd2fa8b6bd1187d4fe4d9cd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20S=C3=BC=C3=9Fenbach?= Date: Fri, 2 Feb 2024 12:53:29 +0100 Subject: [PATCH] Add support of attribute "len" for array-sized structure members. (#1779) --- VulkanHppGenerator.cpp | 250 ++++++++++++++++++++++++++++++++--------- XMLHelper.hpp | 9 +- 2 files changed, 203 insertions(+), 56 deletions(-) diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index b67e9e1..1a58021 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -7969,8 +7969,9 @@ std::string VulkanHppGenerator::generateLenInitializer( assert( ( arrayIt->lenExpressions.front() == litit->first->name ) || ( ( arrayIt->lenExpressions.front() == "codeSize / 4" ) && ( litit->first->name == "codeSize" ) ) ); - assert( arrayIt->name.starts_with( "p" ) ); - std::string argumentName = startLowerCase( stripPrefix( arrayIt->name, "p" ) ) + "_"; + assert( arrayIt->type.isPointer() || !arrayIt->arraySizes.empty() ); + assert( !arrayIt->type.isPointer() || arrayIt->name.starts_with( "p" ) ); + std::string argumentName = ( arrayIt->type.isPointer() ? startLowerCase( stripPrefix( arrayIt->name, "p" ) ) : arrayIt->name ) + "_"; assert( mit->type.prefix.empty() && mit->type.postfix.empty() ); initializer = argumentName + ".size()"; @@ -7988,6 +7989,11 @@ std::string VulkanHppGenerator::generateLenInitializer( { initializer = "static_cast<" + mit->type.type + ">( " + initializer + " )"; } + if ( !litit->second.front()->arraySizes.empty() ) + { + assert( litit->second.front()->arraySizes.size() == 1 ); + initializer = "std::min( " + initializer + ", " + litit->second.front()->arraySizes[0] + " )"; + } return initializer; } @@ -10390,14 +10396,28 @@ std::string VulkanHppGenerator::generateStructCompareOperators( std::pair rhs.${name}[i]; cmp != 0 ) return cmp; + } +)"; + spaceshipMembers += replaceWithMap( spaceshipMemberTemplate, { { "count", member.lenExpressions[0] }, { "name", member.name } } ); + } else { // for all others, we use the operator== of that type @@ -10565,7 +10606,7 @@ std::string VulkanHppGenerator::generateStructConstructorsEnhanced( std::pairname + "( " + generateLenInitializer( mit, litit, structData.second.mutualExclusiveLens ) + " )"; sizeChecks += generateSizeCheck( litit->second, stripPrefix( structData.first, "Vk" ), structData.second.mutualExclusiveLens ); } else if ( hasLen( *mit ) ) { - assert( mit->name.starts_with( "p" ) ); - std::string argumentName = startLowerCase( stripPrefix( mit->name, "p" ) ) + "_"; + assert( mit->type.isPointer() || !mit->arraySizes.empty() ); + std::string argumentName = ( mit->type.isPointer() ? startLowerCase( stripPrefix( mit->name, "p" ) ) : mit->name ) + "_"; - assert( mit->type.postfix.ends_with( "*" ) ); - std::string argumentType = trimEnd( stripPostfix( mit->type.compose( "VULKAN_HPP_NAMESPACE" ), "*" ) ); + std::string argumentType = mit->type.compose( "VULKAN_HPP_NAMESPACE" ); + if ( mit->type.isPointer() ) + { + argumentType = trimEnd( stripPostfix( argumentType, "*" ) ); + } if ( ( mit->type.type == "void" ) && ( argumentType.find( '*' ) == std::string::npos ) ) { // the argument after stripping one pointer is just void @@ -10603,7 +10647,20 @@ std::string VulkanHppGenerator::generateStructConstructorsEnhanced( std::pair const & " + argumentName; + if ( mit->lenExpressions[0] == "null-terminated" ) + { + assert( ( mit->type.type == "char" ) && ( mit->arraySizes.size() == 1 ) ); + arguments += "std::string const & " + argumentName; + } + else if ( mit->arraySizes.empty() ) + { + arguments += "VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<" + argumentType + "> const & " + argumentName; + } + else + { + assert( mit->arraySizes.size() == 1 ); + arguments += "VULKAN_HPP_NAMESPACE::ArrayProxy<" + argumentType + "> const & " + argumentName; + } if ( arrayListed ) { arguments += " = {}"; @@ -10611,7 +10668,26 @@ std::string VulkanHppGenerator::generateStructConstructorsEnhanced( std::pairname + "( " + argumentName + ".data() )"; + if ( mit->type.isPointer() ) + { + initializers += ( firstArgument ? ": " : ", " ) + mit->name + "( " + argumentName + ".data() )"; + } + else + { + assert( mit->arraySizes.size() == 1 ); + static const std::string copyOpsTemplate = R"( + VULKAN_HPP_ASSERT( ${memberName}_.size() < ${arraySize} ); + ${copyOp}( ${memberName}, ${memberName}_.data(), ${arraySizeExpression} );)"; + + std::string arraySizeExpression = ( mit->lenExpressions[0] == "null-terminated" ) + ? ( "std::min( " + mit->name + "_.size(), " + mit->arraySizes[0] + " )" ) + : ( mit->lenExpressions[0] + " * sizeof( " + argumentType + " )" ); + copyOps += replaceWithMap( copyOpsTemplate, + { { "arraySize", mit->arraySizes[0] }, + { "arraySizeExpression", arraySizeExpression }, + { "copyOp", mit->lenExpressions[0] == "null-terminated" ? "strncpy" : "memcpy" }, + { "memberName", mit->name } } ); + } } else { @@ -10639,12 +10715,13 @@ std::string VulkanHppGenerator::generateStructConstructorsEnhanced( std::pairtype.prefix.empty() && lenMember->type.postfix.empty() ); - if ( lenMember->type.type != "size_t" ) - { - lenValue = "static_cast<" + lenMember->type.type + ">( " + lenValue + " )"; - } + auto lenMember = findStructMemberIt( lenName, memberData ); + assert( lenMember != memberData.end() && lenMember->type.prefix.empty() && lenMember->type.postfix.empty() ); + if ( lenMember->type.type != "size_t" ) + { + lenValue = "static_cast<" + lenMember->type.type + ">( " + lenValue + " )"; + } - static const std::string setArrayTemplate = R"( + if ( !member.arraySizes.empty() ) + { + assert( member.arraySizes.size() == 1 ); + lenValue = "std::min( " + lenValue + ", " + member.arraySizes[0] + " )"; + } + + if ( member.type.isPointer() ) + { + static const std::string setArrayTemplate = R"( #if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) ${templateHeader}${structureName} & set${ArrayName}( VULKAN_HPP_NAMESPACE::ArrayProxyNoTemporaries<${memberType}> const & ${arrayName}_ ) VULKAN_HPP_NOEXCEPT { @@ -11277,15 +11390,43 @@ std::string VulkanHppGenerator::generateStructSetter( std::string const & struct #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ )"; - str += replaceWithMap( setArrayTemplate, - { { "arrayName", arrayName }, - { "ArrayName", startUpperCase( arrayName ) }, - { "lenName", lenName }, - { "lenValue", lenValue }, - { "memberName", member.name }, - { "memberType", memberType }, - { "structureName", structureName }, - { "templateHeader", templateHeader } } ); + str += replaceWithMap( setArrayTemplate, + { { "arrayName", arrayName }, + { "ArrayName", startUpperCase( arrayName ) }, + { "lenName", lenName }, + { "lenValue", lenValue }, + { "memberName", member.name }, + { "memberType", memberType }, + { "structureName", structureName }, + { "templateHeader", templateHeader } } ); + } + else + { + assert( member.arraySizes.size() == 1 ); + + static const std::string setArrayTemplate = R"( +#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) + ${templateHeader}${structureName} & set${ArrayName}( VULKAN_HPP_NAMESPACE::ArrayProxy<${memberType}> const & ${arrayName}_ ) VULKAN_HPP_NOEXCEPT + { + VULKAN_HPP_ASSERT( ${arrayName}_.size() <= ${arraySize} ); + ${lenName} = ${lenValue}; + memcpy( ${arrayName}, ${arrayName}_.data(), ${lenName} ); + return *this; + } +#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ +)"; + + str += replaceWithMap( setArrayTemplate, + { { "arrayName", arrayName }, + { "ArrayName", startUpperCase( arrayName ) }, + { "arraySize", member.arraySizes[0] }, + { "lenName", lenName }, + { "lenValue", lenValue }, + { "memberType", member.type.compose( "VULKAN_HPP_NAMESPACE" ) }, + { "structureName", structureName }, + { "templateHeader", templateHeader } } ); + } + } } } return str; @@ -12249,8 +12390,9 @@ bool VulkanHppGenerator::handleRemovalType( std::string const & type, std::vecto bool VulkanHppGenerator::hasLen( MemberData const & memberData ) const { assert( memberData.lenMembers.size() <= memberData.lenExpressions.size() ); - return !memberData.lenMembers.empty() && ( ( memberData.lenExpressions[0] == memberData.lenMembers[0].first ) || - ( memberData.lenExpressions[0] == ( memberData.lenMembers[0].first + " / 4" ) ) ); + return ( !memberData.lenMembers.empty() && ( ( memberData.lenExpressions[0] == memberData.lenMembers[0].first ) || + ( memberData.lenExpressions[0] == ( memberData.lenMembers[0].first + " / 4" ) ) ) ) || + ( !memberData.lenExpressions.empty() && ( memberData.lenExpressions[0] == "null-terminated" ) && !memberData.arraySizes.empty() ); } bool VulkanHppGenerator::hasParentHandle( std::string const & handle, std::string const & parent ) const diff --git a/XMLHelper.hpp b/XMLHelper.hpp index 1fc06ad..e7eda93 100644 --- a/XMLHelper.hpp +++ b/XMLHelper.hpp @@ -82,12 +82,17 @@ struct TypeInfo bool isConstPointer() const noexcept { - return ( prefix.find( "const" ) != std::string::npos ) && ( postfix.find( '*' ) != std::string::npos ); + return isPointer() && ( prefix.find( "const" ) != std::string::npos ); } bool isNonConstPointer() const noexcept { - return ( prefix.find( "const" ) == std::string::npos ) && ( postfix.find( '*' ) != std::string::npos ); + return isPointer() && ( prefix.find( "const" ) == std::string::npos ); + } + + bool isPointer() const noexcept + { + return postfix.find( '*' ) != std::string::npos; } bool isValue() const noexcept