Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions tinyxml2.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,22 +561,28 @@ class TINYXML2_LIB XMLUtil
static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {
return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
}
inline static bool IsSpace( unsigned char ch ) {
static constexpr uint64_t mask =
1ULL << 9
| 1ULL << 10
| 1ULL << 11
| 1ULL << 12
| 1ULL << 13
| 1ULL << 32;
if ( ch > 32 ) {
return false;
}
return mask >> ch & 1;
}

// Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
// correct, but simple, and usually works.
static bool IsWhiteSpace( char p ) {
return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
return IsSpace( static_cast<unsigned char>(p) );
}

// The method checks a char for matching ':', '_', alphabetic symbols or char >= 128 by bit mask
inline static bool IsNameStartChar( unsigned char ch ) {
if ( ch >= 128 ) {
// This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
return true;
}
if ( isalpha( ch ) ) {
return true;
}
return ch == ':' || ch == '_';
static constexpr uint64_t mask[4] = { 1ULL << 58 , 1ULL << 31 | 0x07FFFFFE07FFFFFE , ~0ULL, ~0ULL};
return ( mask[ch >> 6] >> ( ch & 63 ) ) & 1;
}

inline static bool IsNameChar( unsigned char ch ) {
Expand Down
20 changes: 20 additions & 0 deletions xmltest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2729,6 +2729,26 @@ int main( int argc, const char ** argv )
}
}
}

// ---------- Testing IsNameStartChar ----------
{
XMLUtil test;
// Tests validate key edge cases for IsNameStartChar without exhaustive coverage
XMLTest("IsNameStartChar(':')", true, test.IsNameStartChar(':'));
XMLTest("IsNameStartChar('_')", true, test.IsNameStartChar('_'));
XMLTest("IsNameStartChar('@')", false, test.IsNameStartChar('@'));
XMLTest("IsNameStartChar('A')", true, test.IsNameStartChar('A'));
XMLTest("IsNameStartChar('Z')", true, test.IsNameStartChar('Z'));
XMLTest("IsNameStartChar('[')", false, test.IsNameStartChar('['));
XMLTest("IsNameStartChar('`')", false, test.IsNameStartChar('`'));
XMLTest("IsNameStartChar('a')", true, test.IsNameStartChar('a'));
XMLTest("IsNameStartChar('z')", true, test.IsNameStartChar('z'));
XMLTest("IsNameStartChar('{')", false, test.IsNameStartChar('{'));
XMLTest("IsNameStartChar(127)", false, test.IsNameStartChar(static_cast<unsigned char>(127)));
XMLTest("IsNameStartChar(128)", true, test.IsNameStartChar(static_cast<unsigned char>(128)));
XMLTest("IsNameStartChar(255)", true, test.IsNameStartChar(static_cast<unsigned char>(255)));
}


// ----------- Performance tracking --------------
{
Expand Down