Add GotoNextGame() function to skip an entire game

This commit is contained in:
Loic Guegan 2023-01-05 17:15:19 +01:00
parent bebbc79824
commit ef75681956
4 changed files with 78 additions and 2 deletions

View file

@ -45,6 +45,46 @@ void PGN::FromString(std::string pgn_content) {
this->pgn_content.FromString(pgn_content);
}
void PGN::GotoNextGame(){
// Search for new game
if (IS_EOF) {
throw NoGameFound();
}
loctype loc = GotoNextToken(LastGameEndLoc);
if (IS_EOF) {
throw NoGameFound();
}
// First skip current game tags
while (!IS_EOF) {
char c = pgn_content[loc];
if (!IS_BLANK(c)) {
if (c == '[') {
loc = ParseNextTag(loc); // Here we are at ']' after the call to ParseNextTag
} else
break;
}
loc++;
}
// Goto next game '[' by skipping the entire game
while (!IS_EOF) {
char c = pgn_content[loc];
if (!IS_BLANK(c)) {
if (c == '[') {
LastGameEndLoc=loc;
return;
} else if(c== '{'){
// We skip the comments as they can contains '['
while(!IS_EOF && c != '}'){
loc++;
c = pgn_content[loc];
}
}
}
loc++;
}
throw NoGameFound();
}
void PGN::ParseNextGame() {
// Clean previous parse
if (moves != NULL) {

View file

@ -37,6 +37,8 @@ public:
* last parsed game data. Be careful.
*/
void ParseNextGame();
/// @brief Goto the next game while avoiding to parse entire game moves
void GotoNextGame();
/// @brief Check if PGN contains a specific tag
bool HasTag(std::string);
/// @brief Perform a Seven Tag Roster compliance check

View file

@ -89,4 +89,32 @@ TEST_CASE("Kramnik PGN", "[combined/kramnik]") {
pgn.GetMoves(m);
CHECK(m->comment == "E32: Nimzo-Indian: Classical (4 Qc2): 4...0-0");
}
}
}
TEST_CASE("Goto Next Game Tests", "[combined/hartwig/GotoNextGame]") {
// PGN source: https://www.angelfire.com/games3/smartbridge/
pgnp::PGN pgn;
pgn.FromFile("pgn_files/combined/hartwig.pgn");
// First goto game 3
pgn.GotoNextGame();
pgn.GotoNextGame();
// Parse game 3
pgn.ParseNextGame();
CHECK(pgn.GetTagValue("Event") == "Clichy");
// Goto game 5
pgn.GotoNextGame();
// Parse game 5
pgn.ParseNextGame();
CHECK(pgn.GetTagValue("Event") == "World Open U2200");
CHECK(pgn.GetTagValue("Site") == "Philadelphia");
CHECK(pgn.GetTagValue("Black") == "Thomas, Rodney");
// Goto game 8
pgn.GotoNextGame(); // Goto game 7
pgn.GotoNextGame(); // Goto game 8
// Parse game 8
pgn.ParseNextGame();
CHECK(pgn.GetTagValue("Event") == "Hastings");
CHECK(pgn.GetTagValue("White") == "Plaskett, James");
CHECK(pgn.GetTagValue("Black") == "Shipov, Sergei");
}

View file

@ -7,7 +7,7 @@ TEST_CASE("Valid PGN", "[valid/pgn1]") {
PGN pgn;
REQUIRE_NOTHROW(pgn.FromFile("pgn_files/valid/pgn1.pgn"));
REQUIRE_NOTHROW(pgn.ParseNextGame());
REQUIRE_THROWS(pgn.STRCheck());
REQUIRE_THROWS_AS(pgn.STRCheck(),pgnp::STRCheckFailed);
HalfMove *m = new HalfMove();
pgn.GetMoves(m);
@ -178,3 +178,9 @@ TEST_CASE("Valid PGN", "[valid/pgn3]") {
REQUIRE(m->GetHalfMoveAt(52)->variations[0]->MainLine->variations[0]->MainLine->NAG == "$18");
}
}
TEST_CASE("Goto Next Game Tests", "[valid/pgn3/GotoNextGame]") {
PGN pgn;
REQUIRE_NOTHROW(pgn.FromFile("pgn_files/valid/pgn3.pgn"));
REQUIRE_THROWS_AS(pgn.GotoNextGame(),pgnp::NoGameFound);
}