1919#include < vector>
2020
2121void checkNoList ( std::string const & item, int line );
22+ bool containsByNameAndExport ( std::vector<Command> const & commands, std::string const & name, std::vector<std::string> const & exports );
2223bool isLenByStructMember ( std::string const & name, std::vector<Param> const & params, std::map<std::string, Struct> const & structs );
2324std::pair<std::string, BaseType>
2425 parseBaseType ( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes, std::string const & api );
2526std::pair<std::vector<std::string>, std::pair<std::string, Bitmask>> parseBitmask ( tinyxml2::XMLElement const * element,
2627 std::map<std::string, std::string> const & attributes );
27- void parseCommand ( tinyxml2::XMLElement const * element,
28- std::string const & api,
29- std::map<std::string, Command> & commands,
30- std::vector<std::pair<std::string, Command>> & skippedCommands );
31- std::pair<std::map<std::string, Command>, std::vector<std::pair<std::string, Command>>> parseCommands ( tinyxml2::XMLElement const * element,
32- std::string const & api );
33- std::pair<std::string, Constant> parseConstant ( tinyxml2::XMLElement const * element );
28+ void parseCommand ( tinyxml2::XMLElement const * element, std::vector<Command> & commands );
29+ std::vector<Command> parseCommands ( tinyxml2::XMLElement const * element );
30+ std::pair<std::string, Constant> parseConstant ( tinyxml2::XMLElement const * element );
3431CategoryAlias parseCategoryAlias ( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes, std::string const & category );
3532std::pair<std::vector<std::string>, std::pair<std::string, Define>> parseDefine ( tinyxml2::XMLElement const * element,
3633 std::map<std::string, std::string> const & attributes );
@@ -68,6 +65,21 @@ void checkNoList( std::string const & item, int line )
6865 checkForError ( " vk.xml" , item.find ( ' ,' ) == std::string::npos, line, " item <" + item + " > contains unexpected coma, looks like list" );
6966}
7067
68+ bool containsByNameAndExport ( std::vector<Command> const & commands, std::string const & name, std::vector<std::string> const & exports )
69+ {
70+ // check if there is a command with the specified name and at least one export in the specified exports list
71+ return std::ranges::any_of (
72+ commands,
73+ [&name, &exports]( Command const & command )
74+ {
75+ return ( command.name == name ) &&
76+ std::ranges::any_of (
77+ command.exports ,
78+ [&exports]( std::string const & commandExport )
79+ { return std::ranges::any_of ( exports, [&commandExport]( std::string const & exportItem ) { return exportItem == commandExport; } ); } );
80+ } );
81+ }
82+
7183bool isLenByStructMember ( std::string const & name, std::vector<Param> const & params, std::map<std::string, Struct> const & structs )
7284{
7385 // check if name specifies a member of a struct
@@ -167,10 +179,7 @@ std::pair<std::vector<std::string>, std::pair<std::string, Bitmask>> parseBitmas
167179 return { api, { name, { .require = require, .type = type, .xmlLine = line } } };
168180}
169181
170- void parseCommand ( tinyxml2::XMLElement const * element,
171- std::string const & api,
172- std::map<std::string, Command> & commands,
173- std::vector<std::pair<std::string, Command>> & skippedCommands )
182+ void parseCommand ( tinyxml2::XMLElement const * element, std::vector<Command> & commands )
174183{
175184 int const line = element->GetLineNum ();
176185 std::map<std::string, std::string> attributes = getAttributes ( element );
@@ -195,12 +204,14 @@ void parseCommand( tinyxml2::XMLElement const * element,
195204 }
196205 }
197206
198- auto commandIt = commands. find ( alias );
207+ auto commandIt = findByName ( commands, alias );
199208 checkForError ( " vk.xml" , commandIt != commands.end (), line, " command <" + name + " > is aliased to unknown command <" + alias + " >" );
200209 checkForError ( " vk.xml" ,
201- commandIt-> second . aliases . insert ( { name, line } ). second ,
210+ std::find_if ( std::next ( commandIt ), commands. end (), [&alias]( Command const & c ) { return c. name == alias; } ) == commands. end () ,
202211 line,
203- " command <" + name + " > is already listed as alias for command <" + alias + " >" );
212+ " command <" + name + " > is aliased to multiply specfied command <" + alias + " >" );
213+ checkForError (
214+ " vk.xml" , commandIt->aliases .insert ( { name, line } ).second , line, " command <" + name + " > is already listed as alias for command <" + alias + " >" );
204215 }
205216 else
206217 {
@@ -255,7 +266,7 @@ void parseCommand( tinyxml2::XMLElement const * element,
255266 }
256267 else if ( attribute.first == " export" )
257268 {
258- command.export_ = tokenize ( attribute.second , " ," );
269+ command.exports = tokenize ( attribute.second , " ," );
259270 }
260271 else if ( attribute.first == " queues" )
261272 {
@@ -281,7 +292,6 @@ void parseCommand( tinyxml2::XMLElement const * element,
281292 }
282293 }
283294
284- std::string name;
285295 for ( auto child : children )
286296 {
287297 std::string value = child->Value ();
@@ -291,15 +301,29 @@ void parseCommand( tinyxml2::XMLElement const * element,
291301 }
292302 else if ( value == " param" )
293303 {
294- Param param = parseParam ( child );
295- if ( param.api .empty () || ( std::ranges::find ( param.api , api ) != param.api .end () ) )
304+ Param param = parseParam ( child );
305+ auto paramIt = findByName ( command.params , param.name );
306+ if ( paramIt == command.params .end () )
296307 {
297308 command.params .push_back ( std::move ( param ) );
298309 }
310+ else
311+ {
312+ checkForError ( " vk.xml" ,
313+ param.api != paramIt->api ,
314+ param.xmlLine ,
315+ " command <" + command.name + " > has the parameter <" + param.name + " > multiply defined for the same set of apis" );
316+ std::vector<std::string> api = param.api ;
317+ param.api = paramIt->api ;
318+ checkForError ( " vk.xml" ,
319+ param == *paramIt,
320+ param.xmlLine ,
321+ " command <" + command.name + " > has the parameter <" + param.name + " > multiply defined with different attributes" );
322+ }
299323 }
300324 else if ( value == " proto" )
301325 {
302- std::tie ( name, command.returnType ) = parseProto ( child );
326+ std::tie ( command. name , command.returnType ) = parseProto ( child );
303327 }
304328 }
305329
@@ -330,46 +354,38 @@ void parseCommand( tinyxml2::XMLElement const * element,
330354 checkForError ( " vk.xml" ,
331355 ( command.returnType .name == " VkResult" ) || command.errorCodes .empty (),
332356 line,
333- " command <" + name + " > does not return a VkResult but specifies errorcodes" );
357+ " command <" + command. name + " > does not return a VkResult but specifies errorcodes" );
334358 checkForError ( " vk.xml" ,
335359 ( command.returnType .name == " VkResult" ) || command.successCodes .empty (),
336360 line,
337- " command <" + name + " > does not return a VkResult but specifies successcodes" );
361+ " command <" + command. name + " > does not return a VkResult but specifies successcodes" );
338362 checkForError (
339363 " vk.xml" ,
340- command.api .empty () || command.export_ .empty () ||
341- ( ( command.export_ .size () == 1 ) && std::ranges::any_of ( command.api , [&command]( auto const & a ) { return a == command.export_ .front (); } ) ),
364+ command.api .empty () || command.exports .empty () ||
365+ ( ( command.exports .size () == 1 ) && std::ranges::any_of ( command.api , [&command]( auto const & a ) { return a == command.exports .front (); } ) ),
342366 line,
343- " command <" + name + " > has disjunct attributes <api> and <export>" );
367+ " command <" + command. name + " > has disjunct attributes <api> and <export>" );
344368
345- if ( command.api .empty () || ( std::ranges::find ( command.api , api ) != command.api .end () ) )
346- {
347- checkForError ( " vk.xml" , commands.insert ( { name, command } ).second , line, " command <" + name + " > already specified for api <" + api + " >" );
348- }
349- else
350- {
351- skippedCommands.push_back ( { name, command } );
352- }
369+ checkForError ( " vk.xml" , !containsByNameAndExport ( commands, command.name , command.exports ), line, " command <" + command.name + " > already specified" );
370+ commands.push_back ( std::move ( command ) );
353371 }
354372}
355373
356- std::pair<std::map<std::string, Command>, std::vector<std::pair<std::string, Command>>> parseCommands ( tinyxml2::XMLElement const * element,
357- std::string const & api )
374+ std::vector<Command> parseCommands ( tinyxml2::XMLElement const * element )
358375{
359376 int const line = element->GetLineNum ();
360377 checkAttributes ( " vk.xml" , line, getAttributes ( element ), {}, { { " comment" , {} } } );
361378
362379 std::vector<tinyxml2::XMLElement const *> children = getChildElements ( element );
363380 checkElements ( " vk.xml" , line, children, { { " command" , MultipleAllowed::Yes } } );
364381
365- std::map<std::string, Command> commands;
366- std::vector<std::pair<std::string, Command>> skippedCommands;
382+ std::vector<Command> commands;
367383 for ( auto child : children )
368384 {
369- parseCommand ( child, api, commands, skippedCommands );
385+ parseCommand ( child, commands );
370386 }
371387
372- return { commands, skippedCommands } ;
388+ return commands;
373389}
374390
375391std::pair<std::string, Constant> parseConstant ( tinyxml2::XMLElement const * element )
@@ -1020,12 +1036,11 @@ Vkxml parseRegistry( tinyxml2::XMLElement const * element, std::string const & a
10201036 std::string const value = child->Value ();
10211037 if ( value == " commands" )
10221038 {
1023- std::vector<std::pair<std::string, Command>> skippedCommands;
1024- std::tie ( vkxml.commands , skippedCommands ) = parseCommands ( child, api );
1039+ vkxml.commands = parseCommands ( child );
10251040
10261041 for ( auto const & command : vkxml.commands )
10271042 {
1028- for ( auto const & param : command.second . params )
1043+ for ( auto const & param : command.params )
10291044 {
10301045 if ( param.externSync .starts_with ( " maybe:" ) )
10311046 {
@@ -1034,36 +1049,36 @@ Vkxml parseRegistry( tinyxml2::XMLElement const * element, std::string const & a
10341049 pos != std::string::npos,
10351050 param.xmlLine ,
10361051 " unexpected value <" + param.externSync + " > for attribute externsync of parameter <" + param.name + " > of command <" +
1037- command.first + " >, expected format is \" maybe:<paramname>[].<membername>\" " );
1052+ command.name + " >, expected format is \" maybe:<paramname>[].<membername>\" " );
10381053 std::string memberName = param.externSync .substr ( pos + 1 );
10391054 auto structIt = vkxml.structs .find ( param.type .name );
10401055 checkForError ( " vk.xml" ,
10411056 structIt != vkxml.structs .end (),
10421057 param.xmlLine ,
1043- " type <" + param.type .name + " > of parameter <" + param.name + " > of command <" + command.first +
1058+ " type <" + param.type .name + " > of parameter <" + param.name + " > of command <" + command.name +
10441059 " > with externsync attribute is not a struct" );
10451060 checkForError ( " vk.xml" ,
10461061 containsByName ( structIt->second .members , memberName ),
10471062 param.xmlLine ,
1048- " struct <" + param.type .name + " > used in externsync attribute of parameter <" + param.name + " > of command <" + command.first +
1063+ " struct <" + param.type .name + " > used in externsync attribute of parameter <" + param.name + " > of command <" + command.name +
10491064 " > does not have member <" + memberName + " >" );
10501065 }
10511066 checkForError ( " vk.xml" ,
10521067 param.len .empty () || ( param.len == " null-terminated" ) || ( param.len == " 1" ) || param.len .starts_with ( " latexmath:" ) ||
1053- containsByName ( command.second . params , param.len ) || isLenByStructMember ( param.len , command. second .params , vkxml.structs ),
1068+ containsByName ( command.params , param.len ) || isLenByStructMember ( param.len , command.params , vkxml.structs ),
10541069 param.xmlLine ,
1055- " unknown len <" + param.len + " > specified for parameter <" + param.name + " > of command <" + command.first + " >" );
1070+ " unknown len <" + param.len + " > specified for parameter <" + param.name + " > of command <" + command.name + " >" );
10561071 checkForError ( " vk.xml" ,
10571072 vkxml.baseTypes .contains ( param.type .name ) || vkxml.bitmasks .contains ( param.type .name ) ||
10581073 containsByNameOrAlias ( vkxml.enums , param.type .name ) || vkxml.externalTypes .contains ( param.type .name ) ||
10591074 vkxml.handles .contains ( param.type .name ) || containsByNameOrAlias ( vkxml.structs , param.type .name ) ||
10601075 vkxml.unions .contains ( param.type .name ),
10611076 param.xmlLine ,
1062- " unknown type <" + param.type .name + " > of parameter <" + param.name + " > of command <" + command.first + " >" );
1077+ " unknown type <" + param.type .name + " > of parameter <" + param.name + " > of command <" + command.name + " >" );
10631078 checkForError ( " vk.xml" ,
10641079 param.validStructs .empty () || vkxml.structs .contains ( param.validStructs ),
10651080 param.xmlLine ,
1066- " unknown validstructs <" + param.validStructs + " > specified for parameter <" + param.name + " > of command <" + command.first + " >" );
1081+ " unknown validstructs <" + param.validStructs + " > specified for parameter <" + param.name + " > of command <" + command.name + " >" );
10671082 }
10681083 }
10691084 }
0 commit comments