static void _environment_set_executable_paths( const char* executable_path )
{
	unsigned int last_path = string_rfind( executable_path, '/', STRING_NPOS );
	if( last_path != STRING_NPOS )
	{
		if( !string_length( _environment_executable_dir ) )
			string_copy( _environment_executable_dir, executable_path, last_path + 1 );
		if( !string_length( _environment_executable_name ) )
		{
			string_copy( _environment_executable_name, executable_path + last_path + 1, FOUNDATION_MAX_PATHLEN );
		}
	}
	else
	{
		if( !string_length( _environment_executable_dir ) )
			_environment_executable_dir[0] = 0;
		if( !string_length( _environment_executable_name ) )
			string_copy( _environment_executable_name, executable_path, FOUNDATION_MAX_PATHLEN );
	}
#if FOUNDATION_PLATFORM_WINDOWS
	last_path = string_length( _environment_executable_name );
	if( ( last_path > 4 ) && ( string_equal( _environment_executable_name + ( last_path - 4 ), ".exe" ) || string_equal( _environment_executable_name + ( last_path - 4 ), ".EXE" ) ) )
		_environment_executable_name[ last_path - 4 ] = 0;
#endif
	string_copy( _environment_executable_path, executable_path, FOUNDATION_MAX_PATHLEN );
}
Beispiel #2
0
int String::rfind(char ch, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  if (empty()) return -1;
  // Ignore taint in comparison functions.
  return string_rfind(m_px->dataIgnoreTaint(), m_px->size(), ch,
                      pos, caseSensitive);
}
Beispiel #3
0
char* path_file_extension( const char* path )
{
	unsigned int start = string_find_last_of( path, "/\\", STRING_NPOS );
	unsigned int end = string_rfind( path, '.', STRING_NPOS );
	if( ( end != STRING_NPOS ) && ( ( start == STRING_NPOS ) || ( end > start ) ) )
		return string_substr( path, end + 1, STRING_NPOS );
	return string_clone( "" );
}
Beispiel #4
0
int String::rfind(CStrRef s, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  if (empty()) return -1;
  if (s.size() == 1) {
    return rfind(*s.data(), pos, caseSensitive);
  }
  return string_rfind(m_px->data(), m_px->size(),
                      s.data(), s.size(), pos, caseSensitive);
}
Beispiel #5
0
int String::rfind(const char *s, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  assert(s);
  if (empty()) return -1;
  if (*s && *(s+1) == 0) {
    return rfind(*s, pos, caseSensitive);
  }
  return string_rfind(m_px->data(), m_px->size(), s, strlen(s),
                      pos, caseSensitive);
}
Beispiel #6
0
int String::rfind(CStrRef s, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  if (empty()) return -1;
  if (s.size() == 1) {
    return rfind(*s.dataIgnoreTaint(), pos, caseSensitive);
  }
  // Ignore taint in comparison functions.
  return string_rfind(m_px->dataIgnoreTaint(), m_px->size(),
                      s.dataIgnoreTaint(), s.size(), pos, caseSensitive);
}
Beispiel #7
0
int String::rfind(const char *s, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  ASSERT(s);
  if (empty()) return -1;
  if (*s && *(s+1) == 0) {
    return rfind(*s, pos, caseSensitive);
  }
  // Ignore taint in comparison functions.
  return string_rfind(m_px->dataIgnoreTaint(), m_px->size(), s, strlen(s),
                      pos, caseSensitive);
}
Beispiel #8
0
char* path_base_file_name_with_path( const char* path )
{
	unsigned int start, end;
	char* base;
	if( !path )
		return string_allocate( 0 );
	start = string_find_last_of( path, "/\\", STRING_NPOS );
	end = string_rfind( path, '.', STRING_NPOS );
	//For "dot" files, i.e files with names like "/path/to/.file", return the dot name ".file"
	if( !end || ( end == ( start + 1 ) ) || ( ( start != STRING_NPOS ) && ( end < start ) ) )
		end = STRING_NPOS;
	base = string_substr( path, 0, ( end != STRING_NPOS ) ? end : STRING_NPOS );
	base = path_clean( base, path_is_absolute( base ) );
	return base;
}
Beispiel #9
0
int String::rfind(char ch, int pos /* = 0 */,
                  bool caseSensitive /* = true */) const {
  if (empty()) return -1;
  return string_rfind(m_px->data(), m_px->size(), ch,
                      pos, caseSensitive);
}
Beispiel #10
0
DECLARE_TEST( string, queries )
{
	{
		char teststr[]  = "";
		char teststr2[] = "test";
		char teststr3[] = "testing long string with more than 16 characters";
		char teststr4[] = "01234567890123456789012345678901234567890123456789012345678901234567890123456789";

		char* str1 = string_substr( teststr, 0, 0 );
		char* str2 = string_substr( teststr2, 0, 4 );
		char* str3 = string_substr( teststr2, 0, 20 );
		char* str4 = string_substr( teststr3, 0, 0 );
		char* str5 = string_substr( teststr3, 0, 10 );
		char* str6 = string_substr( teststr3, 0, STRING_NPOS );
		char* str7 = string_substr( teststr4, 0, 0 );
		char* str8 = string_substr( teststr4, 0, 20 );
		char* str9 = string_substr( teststr4, 0, STRING_NPOS );

		EXPECT_EQ( 0, str1[0] );
		EXPECT_EQ( 0, str2[ string_length( str2 ) ] );
		EXPECT_EQ( 0, str3[ string_length( str3 ) ] );
		EXPECT_EQ( 0, str4[ string_length( str4 ) ] );
		EXPECT_EQ( 0, str5[ string_length( str5 ) ] );
		EXPECT_EQ( 0, str6[ string_length( str6 ) ] );
		EXPECT_EQ( 0, str7[ string_length( str7 ) ] );
		EXPECT_EQ( 0, str8[ string_length( str8 ) ] );
		EXPECT_EQ( 0, str9[ string_length( str9 ) ] );

		EXPECT_EQ( strlen( teststr ), string_length( str1 ) );
		EXPECT_EQ( strlen( teststr2 ), string_length( str2 ) );
		EXPECT_EQ( strlen( teststr2 ), string_length( str3 ) );
		EXPECT_EQ( 0U, string_length( str4 ) );
		EXPECT_EQ( 10U, string_length( str5 ) );
		EXPECT_EQ( strlen( teststr3 ), string_length( str6 ) );
		EXPECT_EQ( 0U, string_length( str7 ) );
		EXPECT_EQ( 20U, string_length( str8 ) );
		EXPECT_EQ( strlen( teststr4 ), string_length( str9 ) );

		string_deallocate( str1 );
		string_deallocate( str2 );
		string_deallocate( str3 );
		string_deallocate( str4 );
		string_deallocate( str5 );
		string_deallocate( str6 );
		string_deallocate( str7 );
		string_deallocate( str8 );
		string_deallocate( str9 );
	}
	{
		//Only ASCII characters, so wstring->string conversion should not introduce any extra UTF-8 sequences
		wchar_t teststr[]  = L"";
		wchar_t teststr2[] = L"test";
		wchar_t teststr3[] = L"testing long string with more than 16 characters";
		wchar_t teststr4[] = L"01234567890123456789012345678901234567890123456789012345678901234567890123456789";

		char* str1 = string_allocate_from_wstring( teststr, 0 );
		char* str2 = string_allocate_from_wstring( teststr2, 0 );
		char* str3 = string_allocate_from_wstring( teststr2, 20 );
		char* str4 = string_allocate_from_wstring( teststr3, 0 );
		char* str5 = string_allocate_from_wstring( teststr3, 10 );
		char* str6 = string_allocate_from_wstring( teststr3, STRING_NPOS );
		char* str7 = string_allocate_from_wstring( teststr4, 0 );
		char* str8 = string_allocate_from_wstring( teststr4, 20 );
		char* str9 = string_allocate_from_wstring( teststr4, STRING_NPOS );

		EXPECT_EQ( 0, str1[0] );
		EXPECT_EQ( 0, str2[ string_length( str2 ) ] );
		EXPECT_EQ( 0, str3[ string_length( str3 ) ] );
		EXPECT_EQ( 0, str4[ string_length( str4 ) ] );
		EXPECT_EQ( 0, str5[ string_length( str5 ) ] );
		EXPECT_EQ( 0, str6[ string_length( str6 ) ] );
		EXPECT_EQ( 0, str7[ string_length( str7 ) ] );
		EXPECT_EQ( 0, str8[ string_length( str8 ) ] );
		EXPECT_EQ( 0, str9[ string_length( str9 ) ] );

		EXPECT_EQ( wcslen( teststr ), string_length( str1 ) );
		EXPECT_EQ( wcslen( teststr2 ), string_length( str2 ) );
		EXPECT_EQ( wcslen( teststr2 ), string_length( str3 ) );
		EXPECT_EQ( wcslen( teststr3 ), string_length( str4 ) );
		EXPECT_EQ( 10U, string_length( str5 ) );
		EXPECT_EQ( wcslen( teststr3 ), string_length( str6 ) );
		EXPECT_EQ( wcslen( teststr4 ), string_length( str7 ) );
		EXPECT_EQ( 20U, string_length( str8 ) );
		EXPECT_EQ( wcslen( teststr4 ), string_length( str9 ) );

		string_deallocate( str1 );
		string_deallocate( str2 );
		string_deallocate( str3 );
		string_deallocate( str4 );
		string_deallocate( str5 );
		string_deallocate( str6 );
		string_deallocate( str7 );
		string_deallocate( str8 );
		string_deallocate( str9 );
	}
	{
		char* emptystr = string_allocate( 0 );
		char* shortstr = string_clone( "short string" );
		char* longstr  = string_clone( "testing utility string methods like finds, split, merge, explode and similar." );
		{
			unsigned int find     = string_find( longstr, ' ', 0 );
			unsigned int find2    = string_find( longstr, 12, 0 );
			unsigned int find3    = string_find( emptystr, ' ', 0 );
			unsigned int find4    = string_find( shortstr, ' ', 0 );
			unsigned int find5    = string_find( shortstr, 'z', 0 );
			unsigned int findofs  = string_find( longstr, ' ', find );
			unsigned int findofs2 = string_find( longstr, ' ', find + 1 );
			unsigned int findofs3 = string_find( longstr, 'z', 10 );
			unsigned int findofs4 = string_find( emptystr, 'z', STRING_NPOS );
			unsigned int findofs5 = string_find( shortstr, 's', 10 );
			unsigned int findofs6 = string_find( shortstr, 's', findofs5 );
			unsigned int findofs7 = string_find( shortstr, 't', 0 );
			unsigned int findofs8 = string_find( shortstr, ' ', 5 );
			unsigned int findofs9 = string_find( longstr, ' ', STRING_NPOS );

			EXPECT_EQ( find, 7U );
			EXPECT_EQ( find2, STRING_NPOS );
			EXPECT_EQ( find3, STRING_NPOS );
			EXPECT_EQ( find4, 5U );
			EXPECT_EQ( find5, STRING_NPOS );
			EXPECT_EQ( findofs, find );
			EXPECT_EQ( findofs2, 15U );
			EXPECT_EQ( findofs3, STRING_NPOS );
			EXPECT_EQ( findofs4, STRING_NPOS );
			EXPECT_EQ( findofs5, STRING_NPOS );
			EXPECT_EQ( findofs6, STRING_NPOS );
			EXPECT_EQ( findofs7, 4U );
			EXPECT_EQ( findofs8, 5U );
			EXPECT_EQ( findofs9, STRING_NPOS );
		}
		{
			unsigned int rfind     = string_rfind( longstr, ' ', STRING_NPOS );
			unsigned int rfind2    = string_rfind( longstr, ';', STRING_NPOS );
			unsigned int rfind3    = string_rfind( emptystr, ';', STRING_NPOS );
			unsigned int rfind4    = string_rfind( shortstr, 's', STRING_NPOS );
			unsigned int rfind5    = string_rfind( shortstr, 'z', STRING_NPOS );
			unsigned int rfindofs  = string_rfind( longstr, ' ', rfind );
			unsigned int rfindofs2 = string_rfind( longstr, ' ', rfind - 1 );
			unsigned int rfindofs3 = string_rfind( longstr, ' ', string_length( longstr ) - 1 );
			unsigned int rfindofs4 = string_rfind( emptystr, ' ', 0 );
			unsigned int rfindofs5 = string_rfind( longstr, ' ', 0 );
			unsigned int rfindofs6 = string_rfind( shortstr, 's', 5 );
			unsigned int rfindofs7 = string_rfind( shortstr, 's', 0 );
		
			EXPECT_EQ( rfind, 68U );
			EXPECT_EQ( rfind2, STRING_NPOS );
			EXPECT_EQ( rfind3, STRING_NPOS );
			EXPECT_EQ( rfind4, 6U );
			EXPECT_EQ( rfind5, STRING_NPOS );
			EXPECT_EQ( rfindofs, rfind );
			EXPECT_EQ( rfindofs2, 64U );
			EXPECT_EQ( rfindofs3, rfind );
			EXPECT_EQ( rfindofs4, STRING_NPOS );
			EXPECT_EQ( rfindofs5, STRING_NPOS );
			EXPECT_EQ( rfindofs6, 0U );
			EXPECT_EQ( rfindofs7, 0U );
		}
		{
			unsigned int findstr     = string_find_string( longstr, "st", 0 );
			unsigned int findstr2    = string_find_string( longstr, "xwqz", 0 );
			unsigned int findstr3    = string_find_string( emptystr, "xwqz", 0 );
			unsigned int findstr4    = string_find_string( longstr, "", 0 );
			unsigned int findstr5    = string_find_string( longstr, "dslike", 0 );
			unsigned int findstr6    = string_find_string( shortstr, "rt", 0 );
			unsigned int findstr7    = string_find_string( shortstr, "long key that does not exist", 0 );
			unsigned int findstr8    = string_find_string( shortstr, "so", 0 );
			unsigned int findstrofs   = string_find_string( longstr, "st", findstr );
			unsigned int findstrofs2  = string_find_string( longstr, "st", findstr + 1 );
			unsigned int findstrofs3  = string_find_string( longstr, "xwqz", string_length( longstr ) );
			unsigned int findstrofs4  = string_find_string( emptystr, "xwqz", string_length( emptystr ) );
			unsigned int findstrofs5  = string_find_string( shortstr, "", 5 );
			unsigned int findstrofs6  = string_find_string( shortstr, "string", 0 );
			unsigned int findstrofs7  = string_find_string( shortstr, "string", 7 );
			unsigned int findstrofs8  = string_find_string( longstr, "utility", 14 );
			unsigned int findstrofs9  = string_find_string( longstr, "", string_length( longstr ) );
			unsigned int findstrofs10 = string_find_string( longstr, "", STRING_NPOS );
			unsigned int findstrofs11 = string_find_string( longstr, "string", STRING_NPOS );
		
			EXPECT_EQ( findstr, 2U );
			EXPECT_EQ( findstr2, STRING_NPOS );
			EXPECT_EQ( findstr3, STRING_NPOS );
			EXPECT_EQ( findstr4, 0U );
			EXPECT_EQ( findstr5, STRING_NPOS );
			EXPECT_EQ( findstr6, 3U );
			EXPECT_EQ( findstr7, STRING_NPOS );
			EXPECT_EQ( findstr8, STRING_NPOS );
			EXPECT_EQ( findstrofs, findstr );
			EXPECT_EQ( findstrofs2, 16U );
			EXPECT_EQ( findstrofs3, STRING_NPOS );
			EXPECT_EQ( findstrofs4, STRING_NPOS );
			EXPECT_EQ( findstrofs5, 5U );
			EXPECT_EQ( findstrofs6, 6U );
			EXPECT_EQ( findstrofs7, STRING_NPOS );
			EXPECT_EQ( findstrofs8, STRING_NPOS );
			EXPECT_EQ( findstrofs9, strlen( longstr ) );
			EXPECT_EQ( findstrofs10, STRING_NPOS );
			EXPECT_EQ( findstrofs11, STRING_NPOS );
		}
		{
			unsigned int rfindstr     = string_rfind_string( longstr, ", ", STRING_NPOS );
			unsigned int rfindstr2    = string_rfind_string( longstr, ":;", STRING_NPOS );
			unsigned int rfindstr3    = string_rfind_string( emptystr, ":;", STRING_NPOS );
			unsigned int rfindstr4    = string_rfind_string( longstr, "", STRING_NPOS );
			unsigned int rfindstr5    = string_rfind_string( shortstr, "string", STRING_NPOS );
			unsigned int rfindstr6    = string_rfind_string( shortstr, " tring", STRING_NPOS );
			unsigned int rfindstrofs  = string_rfind_string( longstr, ", ", rfindstr );
			unsigned int rfindstrofs2 = string_rfind_string( longstr, ", ", rfindstr - 1 );
			unsigned int rfindstrofs3 = string_rfind_string( longstr, ":;", 0 );
			unsigned int rfindstrofs4 = string_rfind_string( emptystr, ":;", 0 );
			unsigned int rfindstrofs5 = string_rfind_string( longstr, "", 5 );
			unsigned int rfindstrofs6 = string_rfind_string( shortstr, "ort str", 6 );
			unsigned int rfindstrofs7 = string_rfind_string( shortstr, "ort str", 1 );

			EXPECT_EQ( rfindstr, 55U );
			EXPECT_EQ( rfindstr2, STRING_NPOS );
			EXPECT_EQ( rfindstr3, STRING_NPOS );
			EXPECT_EQ( rfindstr4, strlen( longstr ) );
			EXPECT_EQ( rfindstr5, 6U );
			EXPECT_EQ( rfindstr6, STRING_NPOS );
			EXPECT_EQ( rfindstrofs, rfindstr );
			EXPECT_EQ( rfindstrofs2, 48U );
			EXPECT_EQ( rfindstrofs3, STRING_NPOS );
			EXPECT_EQ( rfindstrofs4, STRING_NPOS );
			EXPECT_EQ( rfindstrofs5, 5U );
			EXPECT_EQ( rfindstrofs6, 2U );
			EXPECT_EQ( rfindstrofs7, STRING_NPOS );
		}
		{
			unsigned int findof        = string_find_first_of( longstr, "ui", 0 );
			unsigned int findof2       = string_find_first_of( longstr, ";:", 0 );
			unsigned int findof3       = string_find_first_of( emptystr, "", 0 );
			unsigned int findof4       = string_find_first_of( emptystr, " ", 0 );
			unsigned int findof5       = string_find_first_of( shortstr, "", 0 );
			unsigned int findofofs     = string_find_first_of( longstr, "ui", findof );
			unsigned int findofofs2    = string_find_first_of( longstr, "ui", findof - 1 );
			unsigned int findofofs3    = string_find_first_of( longstr, "ui", findof + 1 );
			unsigned int findofofs4    = string_find_first_of( longstr, "ui", string_length( longstr ) );
			unsigned int findofofs5    = string_find_first_of( emptystr, "", string_length( emptystr ) );
			unsigned int findofofs6    = string_find_first_of( shortstr, "string", 6 );
			unsigned int findofofs7    = string_find_first_of( shortstr, "", 6 );
			unsigned int findofofs8    = string_find_first_of( longstr, "", 10 );
			unsigned int findofofs9    = string_find_first_of( longstr, "", string_length( longstr ) );

			EXPECT_EQ( findof, 4U );
			EXPECT_EQ( findof2, STRING_NPOS );
			EXPECT_EQ( findof3, STRING_NPOS );
			EXPECT_EQ( findof4, STRING_NPOS );
			EXPECT_EQ( findof5, STRING_NPOS );
			EXPECT_EQ( findofofs, 4U );
			EXPECT_EQ( findofofs2, 4U );
			EXPECT_EQ( findofofs3, 8U );
			EXPECT_EQ( findofofs4, STRING_NPOS );
			EXPECT_EQ( findofofs5, STRING_NPOS );
			EXPECT_EQ( findofofs6, 6U );
			EXPECT_EQ( findofofs7, STRING_NPOS );
			EXPECT_EQ( findofofs8, STRING_NPOS );
			EXPECT_EQ( findofofs9, STRING_NPOS );
		}
		{
			unsigned int findnotof     = string_find_first_not_of( longstr, "testing ", 0 );
			unsigned int findnotof2    = string_find_first_not_of( longstr, longstr, 0 );
			unsigned int findnotof3    = string_find_first_not_of( shortstr, "", 0 );
			unsigned int findnotofofs  = string_find_first_not_of( longstr, "testing ", findnotof );
			unsigned int findnotofofs2 = string_find_first_not_of( longstr, "testing ", findnotof + 1 );
			unsigned int findnotofofs3 = string_find_first_not_of( longstr, "testing ", string_length( longstr ) );
			unsigned int findnotofofs4 = string_find_first_not_of( shortstr, "", string_length( shortstr ) );

			EXPECT_EQ( findnotof, 8U );
			EXPECT_EQ( findnotof2, STRING_NPOS );
			EXPECT_EQ( findnotof3, 0U );
			EXPECT_EQ( findnotofofs, 8U );
			EXPECT_EQ( findnotofofs2, 11U );
			EXPECT_EQ( findnotofofs3, STRING_NPOS );
			EXPECT_EQ( findnotofofs4, STRING_NPOS );
		}
		{
			unsigned int findlastof        = string_find_last_of( longstr, "xp", STRING_NPOS );
			unsigned int findlastof2       = string_find_last_of( longstr, ";:", STRING_NPOS );
			unsigned int findlastof3       = string_find_last_of( emptystr, "", STRING_NPOS );
			unsigned int findlastof4       = string_find_last_of( shortstr, "", STRING_NPOS );
			unsigned int findlastofofs     = string_find_last_of( longstr, "xp", findlastof );
			unsigned int findlastofofs2    = string_find_last_of( longstr, "xp", findlastof - 2 );
			unsigned int findlastofofs3    = string_find_last_of( longstr, "xp", 0 );
			unsigned int findlastofofs4    = string_find_last_of( emptystr, "", 0 );
			unsigned int findlastofofs5    = string_find_last_of( shortstr, "", 5 );
			unsigned int findlastofofs6    = string_find_last_of( shortstr, "", string_length( shortstr ) );
			unsigned int findlastofofs7    = string_find_last_of( shortstr, "short", 5 );

			EXPECT_EQ( findlastof, 59U );
			EXPECT_EQ( findlastof2, STRING_NPOS );
			EXPECT_EQ( findlastof3, STRING_NPOS );
			EXPECT_EQ( findlastof4, STRING_NPOS );
			EXPECT_EQ( findlastofofs, 59U );
			EXPECT_EQ( findlastofofs2, 44U );
			EXPECT_EQ( findlastofofs3, STRING_NPOS );
			EXPECT_EQ( findlastofofs4, STRING_NPOS );
			EXPECT_EQ( findlastofofs5, STRING_NPOS );
			EXPECT_EQ( findlastofofs6, STRING_NPOS );
			EXPECT_EQ( findlastofofs7, 4U );
		}
		{
			unsigned int findlastnotof     = string_find_last_not_of( longstr, " similar.", STRING_NPOS );
			unsigned int findlastnotof2    = string_find_last_not_of( longstr, longstr, STRING_NPOS );
			unsigned int findlastnotof3    = string_find_last_not_of( emptystr, "", STRING_NPOS );
			unsigned int findlastnotof4    = string_find_last_not_of( shortstr, "", STRING_NPOS );
			unsigned int findlastnotof5    = string_find_last_not_of( longstr, " similar", STRING_NPOS );
			unsigned int findlastnotofofs  = string_find_last_not_of( longstr, " similar.", findlastnotof );
			unsigned int findlastnotofofs2 = string_find_last_not_of( longstr, " and similar.", findlastnotof - 1 );
			unsigned int findlastnotofofs3 = string_find_last_not_of( longstr, longstr, 0 );
			unsigned int findlastnotofofs4 = string_find_last_not_of( emptystr, "", 0 );
			unsigned int findlastnotofofs5 = string_find_last_not_of( shortstr, "string", 5 );
			unsigned int findlastnotofofs6 = string_find_last_not_of( shortstr, "string ", 5 );
			unsigned int findlastnotofofs7 = string_find_last_not_of( shortstr, "", 5 );
			unsigned int findlastnotofofs8 = string_find_last_not_of( longstr, "", string_length( longstr ) );

			EXPECT_EQ( findlastnotof, 67U );
			EXPECT_EQ( findlastnotof2, STRING_NPOS );
			EXPECT_EQ( findlastnotof3, STRING_NPOS );
			EXPECT_EQ( findlastnotof4, 11U );
			EXPECT_EQ( findlastnotof5, 76U );
			EXPECT_EQ( findlastnotofofs, 67U );
			EXPECT_EQ( findlastnotofofs2, 63U );
			EXPECT_EQ( findlastnotofofs3, STRING_NPOS );
			EXPECT_EQ( findlastnotofofs4, STRING_NPOS );
			EXPECT_EQ( findlastnotofofs5, 5U );
			EXPECT_EQ( findlastnotofofs6, 2U );
			EXPECT_EQ( findlastnotofofs7, 5U );
			EXPECT_EQ( findlastnotofofs8, strlen( longstr ) - 1 );
		}
		string_deallocate( emptystr );
		string_deallocate( shortstr );
		string_deallocate( longstr );
	}
	return 0;
}
Beispiel #11
0
void config_parse( stream_t* stream, hash_t filter_section, bool overwrite )
{
	char* buffer;
	hash_t section = 0;
	hash_t key = 0;
	unsigned int line = 0;

#if BUILD_ENABLE_DEBUG_CONFIG
	log_debugf( HASH_CONFIG, "Parsing config stream: %s", stream_path( stream ) );
#endif
	buffer = memory_allocate_zero( 1024ULL, 0, MEMORY_TEMPORARY );
	while( !stream_eos( stream ) )
	{
		++line;
		stream_read_line_buffer( stream, buffer, 1024, '\n' );
		string_strip( buffer, " \t\n\r" );
		if( !string_length( buffer ) || ( buffer[0] == ';' ) || ( buffer[0] == '#' ) )
			continue;
		if( buffer[0] == '[' )
		{
			//Section declaration
			unsigned int endpos = string_rfind( buffer, ']', string_length( buffer ) - 1 );
			if( ( endpos == STRING_NPOS ) || ( endpos < 1 ) )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid section declaration on line %d in config stream '%s'", line, stream_path( stream ) );
				continue;
			}
			buffer[endpos] = 0;
			section = hash( buffer + 1, endpos - 1 );
#if BUILD_ENABLE_DEBUG_CONFIG
			log_debugf( HASH_CONFIG, "  config: section set to '%s' (0x%llx)", buffer + 1, section );
#endif
		}
		else if( !filter_section || ( filter_section == section ) )
		{
			//name=value declaration
			char* name;
			char* value;
			unsigned int separator = string_find( buffer, '=', 0 );
			if( separator == STRING_NPOS )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', missing assignment operator '=': %s", line, stream_path( stream ), buffer );
				continue;
			}
			
			name = string_strip_substr( buffer, " \t", separator );
			value = string_strip( buffer + separator + 1, " \t" );
			if( !string_length( name ) )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', empty name string", line, stream_path( stream ) );
				continue;
			}

			key = hash( name, string_length( name ) );

			if( overwrite || !config_key( section, key, false ) )
			{
#if BUILD_ENABLE_DEBUG_CONFIG
				log_debugf( HASH_CONFIG, "  config: %s (0x%llx) = %s", name, key, value );
#endif

				if( !string_length( value ) )
					config_set_string( section, key, "" );
				else if( string_equal( value, "false" ) )
					config_set_bool( section, key, false );
				else if( string_equal( value, "true" ) )
					config_set_bool( section, key, true );
				else if( ( string_find( value, '.', 0 ) != STRING_NPOS ) && ( string_find_first_not_of( value, "0123456789.", 0 ) == STRING_NPOS ) && ( string_find( value, '.', string_find( value, '.', 0 ) + 1 ) == STRING_NPOS ) ) //Exactly one "."
					config_set_real( section, key, string_to_real( value ) );
				else if( string_find_first_not_of( value, "0123456789", 0 ) == STRING_NPOS )
					config_set_int( section, key, string_to_int64( value ) );
				else
					config_set_string( section, key, value );
			}
		}
	}
	memory_deallocate( buffer );
}
Beispiel #12
0
char* path_make_absolute( const char* path )
{
	unsigned int up, last, length, protocollen;
	char* abspath = string_clone( path );
	if( !path_is_absolute( abspath ) )
	{
		abspath = string_prepend( abspath, "/" );
		abspath = string_prepend( abspath, environment_current_working_directory() );
		abspath = path_clean( abspath, true );
	}
	else
	{
		abspath = path_clean( abspath, true );
	}

	protocollen = string_find_string( abspath, "://", 0 );
	if( protocollen != STRING_NPOS )
		protocollen += 3; //Also skip the "://" separator
	else
		protocollen = 0;

	//Deal with .. references
	while( ( up = string_find_string( abspath, "/../", 0 ) ) != STRING_NPOS )
	{
		char* subpath;
		if( ( protocollen && ( up == ( protocollen - 1 ) ) ) || ( !protocollen && ( up == 0 ) ) )
		{
			//This moves mem so "prot://../path" ends up as "prot://path"
			memmove( abspath + protocollen, abspath + 3 + protocollen, string_length( abspath ) + 1 - ( 3 + protocollen ) );
			continue;
		}
		last = string_rfind( abspath, '/', up - 1 );
		if( last == STRING_NPOS )
		{
			//Must be a path like C:/../something since other absolute paths
			last = up;
		}
		subpath = string_substr( abspath, 0, last );
		subpath = string_append( subpath, abspath + up + 3 ); // +3 will include the / of the later part of the path
		string_deallocate( abspath );
		abspath = subpath;
	}

	length = string_length( abspath );
	if( length >= 3 )
	{
		while( ( length >= 3 ) && ( abspath[length-3] == '/' ) && ( abspath[length-2] == '.' ) && ( abspath[length-1] == L'.' ) )
		{
			//Step up
			if( length == 3 )
			{
				abspath[1] = 0;
				length = 1;
			}
			else
			{
				length = string_rfind( abspath, '/', length - 4 );
				abspath[length] = 0;
			}
		}
	}

	return abspath;
}
Beispiel #13
0
char* path_clean( char* path, bool absolute )
{
	//Since this function is used a lot we want to perform as much operations
	//in place instead of splicing up into a string array and remerge
	char* replace;
	char* inpath;
	char* next;
	unsigned int inlength, length, remain, protocollen, up, last_up, prev_up, driveofs;

	if( !path )
		return string_allocate( 0 );

	inpath = path;
	inlength = string_length( path );
	protocollen = string_find_string( path, "://", 0 );
	if( ( protocollen != STRING_NPOS ) && ( protocollen > 1 ) )
	{
		absolute = true;
		protocollen += 3; //Also skip the "://" separator
		inlength -= protocollen;
		path += protocollen;
	}
	else
	{
		protocollen = 0;
	}
	length = inlength;
	driveofs = 0;

	replace = path;
	while( ( replace = strchr( replace, '\\' ) ) != 0 )
		*replace++ = '/';

	remain = length;
	replace = path;
	while( ( next = strstr( replace, "/./" ) ) != 0 )
	{
		remain -= (unsigned int)( next - replace ) + 2;
		length -= 2;
		memmove( next + 1, next + 3, remain ); //Include terminating zero to avoid looping when string ends in "/./"
		replace = next;
	}

	remain = length;
	replace = path;
	while( ( next = strstr( replace, "//" ) ) != 0 )
	{
		remain -= (unsigned int)( next - replace ) + 1;
		--length;
		memmove( next + 1, next + 2, remain ); //Include terminating zero to avoid looping when string ends in "//"
		replace = next;
	}

	path[length] = 0;

	if( string_equal( path, "." ) )
	{
		length = 0;
		path[0] = 0;
	}
	else if( length > 1 )
	{
		if( ( path[ length - 2 ] == '/' ) && ( path[ length - 1 ] == '.' ) )
		{
			path[ length - 2 ] = 0;
			length -= 2;
		}
		if( string_equal( path, "." ) )
		{
			length = 0;
			path[0] = 0;
		}
		else if( string_equal( path, "./" ) )
		{
			length = 1;
			path[0] = '/';
			path[1] = 0;
		}
		else if( ( length > 1 ) && ( path[0] == '.' ) && ( path[1] == '/' ) )
		{
			--length;
			memmove( path, path + 1, length );
			path[length] = 0;
		}
	}

	if( absolute )
	{
		if( !length )
		{
			if( !inlength )
			{
				inlength = 2;
				inpath = memory_reallocate( inpath, inlength + protocollen + 1, 0, protocollen + 1 );
				path = inpath + protocollen;
			}
			path[0] = '/';
			path[1] = 0;
			++length;
		}
		else if( ( length >= 2 ) && ( path[1] == ':' ) )
		{
			driveofs = 2;

			//Make sure first character is upper case
			if( ( path[0] >= 'a' ) && ( path[0] <= 'z' ) )
				path[0] = ( path[0] - (char)( (int)'a' - (int)'A' ) );

			if( length == 2 )
			{
				if( inlength <= 2 )
				{
					inpath = memory_reallocate( inpath, inlength + 2 + protocollen + 1, 0, inlength + protocollen + 1 );
					inlength += 2;
					path = inpath + protocollen;
				}
				path[2] = '/';
				++length;
			}
			else if( path[2] != '/' )
			{
				//splice in slash in weird-format paths (C:foo/bar/...)
				if( inlength < ( length + 1 ) )
				{
					//Need more space
					inpath = memory_reallocate( inpath, length + protocollen + 2, 0, inlength + protocollen + 1 );
					inlength = length + 1;
					path = inpath + protocollen;
				}

				memmove( path + 3, path + 2, length + 1 - 2 );
				path[2] = '/';
				++length;
			}
		}
		else if( !protocollen && ( path[0] != '/' ) )
		{
			//make sure capacity is enough to hold additional character
			if( inlength < ( length + 1 ) )
			{
				//Need more space
				inpath = memory_reallocate( inpath, length + protocollen + 2, 0, inlength + protocollen + 1 );
				inlength = length + 1;
				path = inpath + protocollen;
			}

			memmove( path + 1, path, length + 1 );
			path[0] = '/';
			++length;
		}
	}
	else //relative
	{
		if( length && ( path[0] == '/' ) )
		{
			memmove( path, path + 1, length - 1 );
			--length;
		}
	}

	//Deal with .. references
	last_up = driveofs;
	while( ( up = string_find_string( path, "/../", last_up ) ) != STRING_NPOS )
	{
		if( up >= length )
			break;
		if( up == driveofs )
		{
			if( absolute )
			{
				memmove( path + driveofs + 1, path + driveofs + 4, length - ( driveofs + 3 ) );
				length -= 3;
			}
			else
			{
				last_up = driveofs + 3;
			}
			continue;
		}
		prev_up = string_rfind( path, '/', up - 1 );
		if( prev_up == STRING_NPOS )
		{
			if( absolute )
			{
				memmove( path, path + up + 3, length - up - 2 );
				length -= ( up + 3 );
			}
			else
			{
				memmove( path, path + up + 4, length - up - 3 );
				length -= ( up + 4 );
			}
		}
		else if( prev_up >= last_up )
		{
			memmove( path + prev_up, path + up + 3, length - up - 2 );
			length -= ( up - prev_up + 3 );
		}
		else
		{
			last_up = up + 1;
		}
	}

	if( length > 1 )
	{
		if( path[ length - 1 ] == '/' )
		{
			path[ length - 1 ] = 0;
			--length;
		}
	}

	if( protocollen )
	{
		if( path[0] == '/' )
		{
			if( length == 1 )
				length = 0;
			else
			{
				memmove( path, path + 1, length );
				--length;
			}
		}
		length += protocollen;
		path = inpath;
	}

	path[length] = 0;

	return path;
}
unsigned int stacktrace_capture( void** trace, unsigned int max_depth, unsigned int skip_frames )
{
	unsigned int num_frames = 0;
	
	if( !trace )
		return 0;

	if( !max_depth )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;
		
	if( max_depth > BUILD_SIZE_STACKTRACE_DEPTH )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;

	if( !_stackwalk_initialized )
	{
		if( !_initialize_stackwalker() )
		{
			memset( trace, 0, sizeof( void* ) * max_depth );
			return num_frames;
		}
	}
		
#if FOUNDATION_PLATFORM_WINDOWS && ( FOUNDATION_COMPILER_MSVC || FOUNDATION_COMPILER_INTEL )
	// Add 1 skip frame for this function call
	++skip_frames;
#  if USE_CAPTURESTACKBACKTRACE
	if( CallRtlCaptureStackBackTrace )
	{
		void* local_trace[BUILD_SIZE_STACKTRACE_DEPTH];
		if( max_depth + skip_frames > BUILD_SIZE_STACKTRACE_DEPTH )
			max_depth = BUILD_SIZE_STACKTRACE_DEPTH - skip_frames;
		num_frames = (unsigned int)CallRtlCaptureStackBackTrace( skip_frames, max_depth, local_trace, 0 );
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, local_trace, sizeof( void* ) * num_frames );
		memset( trace + num_frames, 0, sizeof( void* ) * ( max_depth - num_frames ) );
	}
	else
	{
#  else
	{
#  endif
#  if FOUNDATION_PLATFORM_ARCH_X86_64
	// Raise an exception so helper has access to context record.
	__try
	{
		RaiseException(	0,			// Application-defined exception code.
						0,			// Zero indicates continuable exception.
						0,			// Number of arguments in args array (ignored if args is null)
						0 );		// Array of arguments
	}
	__except( _capture_stack_trace_helper( trace, max_depth, skip_frames, (GetExceptionInformation())->ContextRecord ) )
	{
	}
#  else
	// Use a bit of inline assembly to capture the information relevant to stack walking which is
	// basically EIP and EBP.
	CONTEXT context;
	memset( &context, 0, sizeof( CONTEXT ) );
	context.ContextFlags = CONTEXT_FULL;

	log_warnf( WARNING_DEPRECATED, "********** REIMPLEMENT FALLBACK STACKTRACE **********" );
	/* Use a fake function call to pop the return address and retrieve EIP.*/
	__asm
	{
		call FakeStackTraceCall
		FakeStackTraceCall: 
		pop eax
		mov context.Eip, eax
		mov context.Ebp, ebp
		mov context.Esp, esp
	}

	// Capture the back trace.
	_capture_stack_trace_helper( trace, max_depth, skip_frames, &context );
#  endif
	}
#elif FOUNDATION_PLATFORM_APPLE
	//TODO: Implement
#elif FOUNDATION_PLATFORM_POSIX
	// Add 1 skip frames for this function call
	skip_frames += 1;

	void* localframes[BUILD_SIZE_STACKTRACE_DEPTH];
	num_frames = (unsigned int)backtrace( localframes, BUILD_SIZE_STACKTRACE_DEPTH );

	if( num_frames > skip_frames )
	{
		num_frames -= skip_frames;
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, localframes + skip_frames, sizeof( void* ) * num_frames );
	}
	else
		trace[0] = 0;
#endif

	return num_frames;
}


static bool _symbol_resolve_initialized = false;

static bool _initialize_symbol_resolve()
{
	if( _symbol_resolve_initialized )
		return true;

#if FOUNDATION_PLATFORM_WINDOWS
	{
		unsigned int options;
		void* dll = LoadLibraryA( "PSAPI.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallEnumProcesses = (EnumProcessesFn)GetProcAddress( dll, "EnumProcesses" );
		CallEnumProcessModules = (EnumProcessModulesFn)GetProcAddress(  dll, "EnumProcessModules" );
		CallGetModuleFileNameEx = (GetModuleFileNameExFn)GetProcAddress(  dll, "GetModuleFileNameExA" );
		CallGetModuleBaseName = (GetModuleBaseNameFn)GetProcAddress(  dll, "GetModuleBaseNameA" );
		CallGetModuleInformation = (GetModuleInformationFn)GetProcAddress( dll, "GetModuleInformation" );

		if( !CallEnumProcesses || !CallEnumProcessModules || !CallGetModuleFileNameEx || !CallGetModuleBaseName || !CallGetModuleInformation )
			return _symbol_resolve_initialized;

		dll = LoadLibraryA( "DBGHELP.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallSymInitialize = (SymInitializeFn)GetProcAddress( dll, "SymInitialize" );
		CallSymSetOptions = (SymSetOptionsFn)GetProcAddress( dll, "SymSetOptions" );
		CallSymGetOptions = (SymGetOptionsFn)GetProcAddress( dll, "SymGetOptions" );
		CallSymLoadModule64 = (SymLoadModule64Fn)GetProcAddress( dll, "SymLoadModule64" );
		CallSymSetSearchPath = (SymSetSearchPathFn)GetProcAddress( dll, "SymSetSearchPath" );
		CallSymGetModuleInfo64 = (SymGetModuleInfo64Fn)GetProcAddress( dll, "SymGetModuleInfo64" );
		CallSymGetLineFromAddr64 = (SymGetLineFromAddr64Fn)GetProcAddress( dll, "SymGetLineFromAddr64" );
		CallSymGetSymFromAddr64 = (SymGetSymFromAddr64Fn)GetProcAddress( dll, "SymGetSymFromAddr64" );
		CallSymGetModuleBase64 = (SymGetModuleBase64Fn)GetProcAddress( dll, "SymGetModuleBase64" );
		CallSymFunctionTableAccess64 = (SymFunctionTableAccess64Fn)GetProcAddress( dll, "SymFunctionTableAccess64" );

		if( !CallSymInitialize || !CallSymSetOptions || !CallSymGetOptions || !CallSymLoadModule64 || !CallSymSetSearchPath || !CallSymGetModuleInfo64 || !CallSymGetLineFromAddr64 || !CallSymGetSymFromAddr64  || !CallSymGetModuleBase64 || !CallSymFunctionTableAccess64 )
			return _symbol_resolve_initialized;

		options = CallSymGetOptions();
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_DEBUG;
		options |= SYMOPT_UNDNAME;
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_FAIL_CRITICAL_ERRORS;
		options |= SYMOPT_DEFERRED_LOADS;
		options |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS;
		options |= SYMOPT_EXACT_SYMBOLS;
		options |= SYMOPT_CASE_INSENSITIVE;
		CallSymSetOptions( options );

		CallSymInitialize( GetCurrentProcess(), 0, TRUE );
	}
	
	_load_process_modules();

	_symbol_resolve_initialized = true;

#else
	
	_symbol_resolve_initialized = true;
	
#endif

	return _symbol_resolve_initialized;
}


static NOINLINE char** _resolve_stack_frames( void** frames, unsigned int max_frames )
{
#if FOUNDATION_PLATFORM_WINDOWS
	char**              lines = 0;
	char                symbol_buffer[ sizeof( IMAGEHLP_SYMBOL64 ) + 512 ];
	PIMAGEHLP_SYMBOL64  symbol;
	DWORD               displacement = 0;
	uint64_t            displacement64 = 0;
	unsigned int        iaddr = 0;
	unsigned int        last_error;
	bool                found = false;
	HANDLE              process_handle = GetCurrentProcess();
	int                 buffer_offset = 0;
	bool                last_was_main = false;
	IMAGEHLP_LINE64     line64;
	IMAGEHLP_MODULE64   module64;

	for( iaddr = 0; ( iaddr < max_frames ) && !last_was_main; ++iaddr )
	{
		char* resolved = 0;
		const char* function_name = "??";
		const char* file_name = "??";
		const char* module_name = "??";
		unsigned int line_number = 0;

		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;

		// Initialize symbol.
		symbol = (PIMAGEHLP_SYMBOL64)symbol_buffer;
		memset( symbol, 0, sizeof( symbol_buffer ) );
		symbol->SizeOfStruct = sizeof( symbol_buffer );
		symbol->MaxNameLength = 512;

		// Get symbol from address.
		if( CallSymGetSymFromAddr64 && CallSymGetSymFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement64, symbol ) )
		{
			int offset = 0;
			while( symbol->Name[offset] < 32 )
				++offset;
			function_name = symbol->Name + offset;
		}
		else
		{
			// No symbol found for this address.
			last_error = GetLastError();
		}

		memset( &line64, 0, sizeof( line64 ) );
		line64.SizeOfStruct = sizeof( line64 );
		if( CallSymGetLineFromAddr64 && CallSymGetLineFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement, &line64 ) )
		{
			file_name = line64.FileName;
			line_number = line64.LineNumber;
		}

		memset( &module64, 0, sizeof( module64 ) );
		module64.SizeOfStruct = sizeof( module64 );
		if( CallSymGetModuleInfo64 && CallSymGetModuleInfo64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &module64 ) )
		{
			int last_slash = STRING_NPOS;
			module_name = module64.ImageName;
			last_slash = string_rfind( module_name, '\\', STRING_NPOS );
			if( last_slash != STRING_NPOS )
				module_name += last_slash + 1;
		}

		resolved = string_format( "[" STRING_FORMAT_POINTER "] %s (%s:%d +%d bytes) [in %s]", frames[iaddr], function_name, file_name, line_number, displacement, module_name );
		array_push( lines, resolved );
	
		if( string_equal( function_name, "main" ) )
			last_was_main = true;
	}

	return lines;

#elif FOUNDATION_PLATFORM_LINUX

	char** addrs = 0;
	char** lines = 0;
	const char** args = 0;
	process_t* proc = process_allocate();
	unsigned int num_frames = 0;
	unsigned int requested_frames = 0;
	bool last_was_main = false;

	if( !string_length( environment_executable_path() ) )
	{
		for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
		{
			//Allow first frame to be null in case of a function call to a null pointer
			if( iaddr && !frames[iaddr] )
				break;
		
			array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]", frames[iaddr] ) );
		}
		return lines;
	}
	
	array_push( args, "-e" );
	array_push( args, environment_executable_path() );
	array_push( args, "-f" );

	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		char* addr = string_format( STRING_FORMAT_POINTER, frames[iaddr] );
		array_push( addrs, addr );
		array_push( args, addr );

		++requested_frames;
	}
	
	process_set_working_directory( proc, environment_initial_working_directory() );
	process_set_executable_path( proc, "/usr/bin/addr2line" );
	process_set_arguments( proc, args, array_size( args ) );
	process_set_flags( proc, PROCESS_ATTACHED | PROCESS_STDSTREAMS );

	process_spawn( proc );

	stream_t* procout = process_stdout( proc );
	while( !stream_eos( procout ) && ( num_frames < requested_frames ) && !last_was_main )
	{
		char* function = stream_read_line( procout, '\n' );
		char* filename = stream_read_line( procout, '\n' );

		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "] %s (%s)",
			frames[num_frames],
			function && string_length( function ) ? function : "??",
			filename && string_length( filename ) ? filename : "??"
		) );
	
		if( string_equal( function, "main" ) )
			last_was_main = true;

		string_deallocate( function );
		string_deallocate( filename );

		++num_frames;
	}
	
	process_wait( proc );
	process_deallocate( proc );
	
	string_array_deallocate( addrs );
	array_deallocate( args );	
	
	return lines;
	
#else

	char** lines = 0;
	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]\n", frames[iaddr] ) );
	}
		
	return lines;

#endif
}