Skip to content

Commit

Permalink
Parsing tools: added GetArrayIndex function
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Jan 22, 2024
1 parent 32feb3a commit c4708d5
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
70 changes: 70 additions & 0 deletions Common/interface/ParsingTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <cstring>
#include <sstream>
#include <limits>

#include "../../Primitives/interface/BasicTypes.h"
#include "../../Primitives/interface/FlagEnum.h"
Expand Down Expand Up @@ -1155,6 +1156,75 @@ inline std::string RefinePreprocessorDirective(const char* Str, size_t Len = 0)
return RefinePreprocessorDirective(Str, Str + Len);
}

static constexpr int InvalidArrayIndex = std::numeric_limits<int>::min();

/// Returns the array index if the given variable name is an indexed array element.
///
/// \param [in] Start - starting position.
/// \param [in] End - end of the input string.
/// \param [out] NameEnd - ending position of the variable name.
///
/// \return - Array index if the given variable name is an array element.
/// - -1 if the given variable name is a valid identifier and is not an array element.
/// - INT_MIN if the array index is invalid.
template <typename InteratorType>
inline int GetArrayIndex(const InteratorType& Start, const InteratorType& End, InteratorType& NameEnd)
{
NameEnd = SkipIdentifier(Start, End);
// Empty name is not a valid identifier
if (NameEnd == Start)
{
//
// ^
return InvalidArrayIndex;
}

if (NameEnd == End)
{
// MyArray
// ^
return -1;
}
// MyArray [ 16 ]
// ^

auto Pos = SkipDelimiters(NameEnd, End, " \t");
// MyArray [ 16 ]
// ^
if (Pos == End || *Pos != '[')
return InvalidArrayIndex;

Pos = SkipDelimiters(Pos + 1, End, " \t");
// MyArray [ 16 ]
// ^
if (Pos == End)
return InvalidArrayIndex;

int Index = InvalidArrayIndex;
Pos = ParseInteger(Pos, End, Index);
// MyArray [ 16 ]
// ^

Pos = SkipDelimiters(Pos, End, " \t");
// MyArray [ 16 ]
// ^
return (Pos != End && *Pos == ']') ? Index : InvalidArrayIndex;
}

template <typename InteratorType>
inline int GetArrayIndex(const InteratorType& Start, const InteratorType& End, std::string& NameWithoutBrackets)
{
std::string::const_iterator NameEnd = End;
const auto Index = GetArrayIndex(Start, End, NameEnd);
NameWithoutBrackets.assign(Start, NameEnd);
return Index;
}

inline int GetArrayIndex(const std::string& Var, std::string& NameWithoutBrackets)
{
return GetArrayIndex(Var.begin(), Var.end(), NameWithoutBrackets);
}

} // namespace Parsing

} // namespace Diligent
37 changes: 37 additions & 0 deletions Tests/DiligentCoreTest/src/Common/ParsingToolsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1405,4 +1405,41 @@ TEST(Common_ParsingTools, ParseInteger)
}
};


TEST(Common_ParsingTools, GetArrayIndex)
{
auto Test = [](const std::string Var, size_t RefNameEndPos, int RefIndex) {
std::string NameWOBrackets;
int Index = GetArrayIndex(Var, NameWOBrackets);

EXPECT_EQ(NameWOBrackets, Var.substr(0, RefNameEndPos));
EXPECT_EQ(Index, RefIndex);
};

Test("", 0, InvalidArrayIndex);
Test(" ", 0, InvalidArrayIndex);
Test("1", 0, InvalidArrayIndex);
Test("?", 0, InvalidArrayIndex);
Test("x", 1, -1);
Test("abc", 3, -1);
Test("xy1 ", 3, InvalidArrayIndex);
Test("xy2[", 3, InvalidArrayIndex);
Test("xy3 [", 3, InvalidArrayIndex);
Test("xy4[ ", 3, InvalidArrayIndex);
Test("xy5 [ ", 3, InvalidArrayIndex);
Test("xy6[10]", 3, 10);
Test("xy7[11 ]", 3, 11);
Test("xy8[ 12]", 3, 12);
Test("xy9[ 13 ]", 3, 13);
Test("xy0 [14]", 3, 14);
Test("xy1 [ 15]", 3, 15);
Test("xy2 [16 ]", 3, 16);
Test("xy3 [ 18 ]", 3, 18);
Test("xy4[x]", 3, INT_MIN);
Test("xy5 [ x ] ", 3, INT_MIN);
Test("xy6[12x]", 3, INT_MIN);
Test("xy7[12", 3, INT_MIN);
Test("xy7[12 ", 3, INT_MIN);
}

} // namespace

0 comments on commit c4708d5

Please sign in to comment.