// AStringAssignment //------------------------------------------------------------------------------ void TestAString::AStringAssignment() const { AString str; str = "test"; TEST_ASSERT( str.GetLength() == 4 ); TEST_ASSERT( str.GetReserved() >= 4 ); TEST_ASSERT( str.IsEmpty() == false ); TEST_ASSERT( str.MemoryMustBeFreed() == true ); AString str2; str2 = str; TEST_ASSERT( str2.GetLength() == 4 ); TEST_ASSERT( str2.GetReserved() >= 4 ); TEST_ASSERT( str2.IsEmpty() == false ); TEST_ASSERT( str2.MemoryMustBeFreed() == true ); const char * testData = "hellozzzzzzzzz"; AString str3; str3.Assign( testData, testData + 5 ); TEST_ASSERT( str3.GetLength() == 5 ); TEST_ASSERT( str3.GetReserved() >= 5 ); TEST_ASSERT( str3.IsEmpty() == false ); TEST_ASSERT( str3.MemoryMustBeFreed() == true ); // assign empty { AString dst; dst.Assign( AString::GetEmpty() ); } { AString dst; dst.Assign( AString::GetEmpty().Get(), AString::GetEmpty().Get() ); } }
// GetFolderPath //------------------------------------------------------------------------------ void VSProjectGenerator::GetFolderPath( const AString & fileName, AString & folder ) const { const AString * const bEnd = m_BasePaths.End(); for ( const AString * bIt = m_BasePaths.Begin(); bIt != bEnd; ++bIt ) { const AString & basePath = *bIt; const char * begin = fileName.Get(); const char * end = fileName.GetEnd(); if ( fileName.BeginsWithI( basePath ) ) { begin = fileName.Get() + basePath.GetLength(); const char * lastSlash = fileName.FindLast( BACK_SLASH ); end = ( lastSlash ) ? lastSlash : end; if ( begin < end ) { folder.Assign( begin, end ); return; } } } // no matching base path (use root) folder.Clear(); }
// GetToken //------------------------------------------------------------------------------ bool TextReader::GetToken( AString & token ) { SkipWhitespace(); const char * tokenStart = m_Pos; loop: const char c = *m_Pos; if ( ( c != ' ' ) && ( c != '\t' ) && ( c != '\r' ) && ( c != '\n' ) && ( c != 0 ) ) { ++m_Pos; goto loop; } const char * tokenEnd = m_Pos; if ( tokenEnd == tokenStart ) { return false; } token.Assign( tokenStart, tokenEnd ); return true; }
// ParseNamedVariableName //------------------------------------------------------------------------------ /*static*/ bool BFFParser::ParseVariableName( BFFIterator & iter, AString & name, bool & parentScope ) { // skip over the declaration symbol ASSERT( *iter == BFF_DECLARE_VAR_INTERNAL || *iter == BFF_DECLARE_VAR_PARENT ); parentScope = ( *iter == BFF_DECLARE_VAR_PARENT ); const BFFIterator varNameStart = iter; // include type token in var name iter++; // make sure we haven't hit the end of the file if ( iter.IsAtEnd() ) { Error::Error_1012_UnexpectedEndOfFile( iter ); return false; } // make sure immediately after the symbol starts a variable name if ( iter.IsAtValidVariableNameCharacter() == false ) { Error::Error_1013_UnexpectedCharInVariableName( iter, nullptr ); return false; } // find the end of the variable name iter.SkipVariableName(); const BFFIterator varNameEnd = iter; // sanity check it is a sensible length size_t varNameLen = varNameStart.GetDistTo( varNameEnd ); if ( varNameLen > MAX_VARIABLE_NAME_LENGTH ) { Error::Error_1014_VariableNameIsTooLong( iter, (uint32_t)varNameLen, (uint32_t)MAX_VARIABLE_NAME_LENGTH ); return false; } // store variable name name.Assign( varNameStart.GetCurrent(), varNameEnd.GetCurrent() ); if ( parentScope ) { // exchange '^' with '.' ASSERT( BFF_DECLARE_VAR_PARENT == name[0] ); name[0] = BFF_DECLARE_VAR_INTERNAL; } return true; }
// Generate //------------------------------------------------------------------------------ /*static*/ void Args::StripQuotes( const char * start, const char * end, AString & out ) { ASSERT( start ); ASSERT( end ); // handle empty inputs if ( start == end ) { out.Clear(); return; } // strip first quote if there is one const char firstChar = *start; if ( ( firstChar == '"' ) || ( firstChar == '\'' ) ) { ++start; } // strip first quote if there is one const char lastChar = *( end - 1 ); if ( ( lastChar == '"' ) || ( lastChar == '\'' ) ) { --end; } // handle invalid strings (i.e. just one quote) if ( end < start ) { out.Clear(); return; } // assign unquoted string (could be empty, and that's ok) out.Assign( start, end ); }
// ParseNamedVariableName //------------------------------------------------------------------------------ /*static*/ bool BFFParser::ParseVariableName( BFFIterator & iter, AString & name, bool & parentScope ) { // skip over the declaration symbol ASSERT( *iter == BFF_DECLARE_VAR_INTERNAL || *iter == BFF_DECLARE_VAR_PARENT ); parentScope = ( *iter == BFF_DECLARE_VAR_PARENT ); const BFFIterator varNameStart = iter; // include type token in var name iter++; // make sure we haven't hit the end of the file if ( iter.IsAtEnd() ) { Error::Error_1012_UnexpectedEndOfFile( iter ); return false; } if ( *iter == '\'' || *iter == '"' ) { // parse the string const BFFIterator openToken = iter; iter.SkipString( *openToken ); if ( *iter != *openToken ) { Error::Error_1002_MatchingClosingTokenNotFound( openToken, nullptr, *openToken ); return false; } BFFIterator stringStart = openToken; stringStart++; // unescape and subsitute embedded variables AStackString< 256 > value; if ( PerformVariableSubstitutions( stringStart, iter, value ) == false ) { return false; } iter++; // skip close token BFFIterator varNameIter( value.Get(), value.GetLength(), iter.GetFileName().Get(), iter.GetFileTimeStamp() ); // sanity check it is a sensible length if ( value.GetLength() + 1/* '.' will be added */ > MAX_VARIABLE_NAME_LENGTH ) { Error::Error_1014_VariableNameIsTooLong( varNameIter, (uint32_t)value.GetLength(), (uint32_t)MAX_VARIABLE_NAME_LENGTH ); return false; } // sanity check it is a valid variable name while ( varNameIter.IsAtEnd() == false ) { if ( varNameIter.IsAtValidVariableNameCharacter() == false ) { Error::Error_1013_UnexpectedCharInVariableName( varNameIter, nullptr ); return false; } varNameIter++; } // append '.' to variable name name = "."; name.Append( value ); } else { // make sure immediately after the symbol starts a variable name if ( iter.IsAtValidVariableNameCharacter() == false ) { Error::Error_1013_UnexpectedCharInVariableName( iter, nullptr ); return false; } // find the end of the variable name iter.SkipVariableName(); const BFFIterator varNameEnd = iter; // sanity check it is a sensible length size_t varNameLen = varNameStart.GetDistTo( varNameEnd ); if ( varNameLen > MAX_VARIABLE_NAME_LENGTH ) { Error::Error_1014_VariableNameIsTooLong( iter, (uint32_t)varNameLen, (uint32_t)MAX_VARIABLE_NAME_LENGTH ); return false; } // store variable name name.Assign( varNameStart.GetCurrent(), varNameEnd.GetCurrent() ); } ASSERT( name.GetLength() > 0 ); if ( parentScope ) { // exchange '^' with '.' ASSERT( BFF_DECLARE_VAR_PARENT == name[0] ); name[0] = BFF_DECLARE_VAR_INTERNAL; } return true; }
// EmbeddedNuls //------------------------------------------------------------------------------ void TestAString::EmbeddedNuls() const { // Create a string with an embedded nul and check various behaviours AStackString<> string( "0123456789" ); const uint32_t originalStringLen = string.GetLength(); string[ 5 ] = 0; // insert null terminator // Copy construction { AString copy( string ); TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); } // Assignment (operator =) { AString copy; copy = string; TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); } // Assignment (Assign) { AString copy; copy.Assign( string ); TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); } // Assignment (Assign with iterators) { AString copy; copy.Assign( string.Get(), string.GetEnd() ); TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); } // Append (operator +=) { // Append to empty AString copy; copy += string; TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( AString::StrNCmp( string.Get(), copy.Get(), originalStringLen ) == 0 ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); // Append to existing AString copy2( string ); copy2 += string; TEST_ASSERT( copy2.GetLength() == ( originalStringLen * 2 ) ); TEST_ASSERT( memcmp( "01234" "\0" "678901234" "\0" "6789", copy2.Get(), ( originalStringLen * 2 ) ) == 0 ); } // Append (Append) { // Append to empty AString copy; copy.Append( string ); TEST_ASSERT( copy.GetLength() == originalStringLen ); TEST_ASSERT( memcmp( "01234" "\0" "6789", copy.Get(), originalStringLen ) == 0 ); // Append to existing AString copy2( string ); copy2.Append( string ); TEST_ASSERT( copy2.GetLength() == ( originalStringLen * 2 ) ); TEST_ASSERT( memcmp( "01234" "\0" "678901234" "\0" "6789", copy2.Get(), ( originalStringLen * 2 ) ) == 0 ); } }