update to OpenVR 1.07 from https://github.com/ValveSoftware/openvr
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#define vsprintf_s sprintf
|
||||
#define _stricmp strcmp
|
||||
#define stricmp strcmp
|
||||
#define strnicmp strncasecmp
|
||||
#define strcpy_s(dst, n, src) int(strncpy(dst, src, n) != nullptr)
|
||||
#define fopen_s(fd, path, mode) int((*fd = fopen(path, mode)) != nullptr)
|
||||
#define _vsnprintf_s(buffer, size, fmt, ap) vsnprintf(buffer, size, fmt, ap)
|
||||
@@ -24,4 +25,4 @@ typedef int errno_t;
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_
|
||||
#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#include "compat.h"
|
||||
#include "strtools.h"
|
||||
#include "pathtools.h"
|
||||
//#include "hmdplatform_private.h"
|
||||
//#include "vrcommon/strtools.h"
|
||||
|
||||
#if defined( _WIN32)
|
||||
#include <Windows.h>
|
||||
#include <direct.h>
|
||||
#include <Shobjidl.h>
|
||||
#include <KnownFolders.h>
|
||||
#elif defined OSX
|
||||
#include <mach-o/dyld.h>
|
||||
#include <dlfcn.h>
|
||||
#include "osxfilebridge.h"
|
||||
#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet
|
||||
#define _MAX_PATH MAX_PATH // yet another form of _PATH define we use
|
||||
#elif defined(LINUX)
|
||||
#include <Shlobj.h>
|
||||
|
||||
#undef GetEnvironmentVariable
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if defined OSX
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
@@ -26,44 +31,54 @@
|
||||
/** Returns the path (including filename) to the current executable */
|
||||
std::string Path_GetExecutablePath()
|
||||
{
|
||||
bool bSuccess = false;
|
||||
char rchPath[ 1024 ];
|
||||
size_t nBuff = sizeof(rchPath);
|
||||
#if defined( _WIN32 )
|
||||
bSuccess = ::GetModuleFileNameA(NULL, rchPath, (DWORD)nBuff) > 0;
|
||||
#elif defined OSX
|
||||
uint32_t _nBuff = nBuff;
|
||||
bSuccess = _NSGetExecutablePath(rchPath, &_nBuff) == 0;
|
||||
rchPath[nBuff-1] = '\0';
|
||||
#elif defined LINUX
|
||||
ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 );
|
||||
if ( nRead != -1 )
|
||||
{
|
||||
rchPath[ nRead ] = 0;
|
||||
bSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rchPath[ 0 ] = '\0';
|
||||
}
|
||||
#else
|
||||
AssertMsg( false, "Implement Plat_GetExecutablePath" );
|
||||
#endif
|
||||
wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
|
||||
char *pchPath = new char[MAX_UNICODE_PATH_IN_UTF8];
|
||||
::GetModuleFileNameW( NULL, pwchPath, MAX_UNICODE_PATH );
|
||||
WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
|
||||
delete[] pwchPath;
|
||||
|
||||
std::string sPath = pchPath;
|
||||
delete[] pchPath;
|
||||
return sPath;
|
||||
#elif defined( OSX )
|
||||
char rchPath[1024];
|
||||
uint32_t nBuff = sizeof( rchPath );
|
||||
bool bSuccess = _NSGetExecutablePath(rchPath, &nBuff) == 0;
|
||||
rchPath[nBuff-1] = '\0';
|
||||
if( bSuccess )
|
||||
return rchPath;
|
||||
else
|
||||
return "";
|
||||
#elif defined LINUX
|
||||
char rchPath[1024];
|
||||
size_t nBuff = sizeof( rchPath );
|
||||
ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 );
|
||||
if ( nRead != -1 )
|
||||
{
|
||||
rchPath[ nRead ] = 0;
|
||||
return rchPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
AssertMsg( false, "Implement Plat_GetExecutablePath" );
|
||||
return "";
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/** Returns the path of the current working directory */
|
||||
std::string Path_GetWorkingDirectory()
|
||||
{
|
||||
std::string sPath;
|
||||
char buf[ 1024 ];
|
||||
#if defined( _WIN32 )
|
||||
sPath = _getcwd( buf, sizeof( buf ) );
|
||||
wchar_t buf[MAX_UNICODE_PATH];
|
||||
sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) );
|
||||
#else
|
||||
char buf[ 1024 ];
|
||||
sPath = getcwd( buf, sizeof( buf ) );
|
||||
#endif
|
||||
return sPath;
|
||||
@@ -74,37 +89,14 @@ bool Path_SetWorkingDirectory( const std::string & sPath )
|
||||
{
|
||||
bool bSuccess;
|
||||
#if defined( _WIN32 )
|
||||
bSuccess = 0 == _chdir( sPath.c_str() );
|
||||
std::wstring wsPath = UTF8to16( sPath.c_str() );
|
||||
bSuccess = 0 == _wchdir( wsPath.c_str() );
|
||||
#else
|
||||
bSuccess = 0 == chdir( sPath.c_str() );
|
||||
#endif
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
std::string Path_GetModulePath()
|
||||
{
|
||||
#if defined( _WIN32 )
|
||||
char path[32768];
|
||||
HMODULE hm = NULL;
|
||||
|
||||
if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(LPCSTR) &Path_GetModulePath,
|
||||
&hm))
|
||||
{
|
||||
int ret = GetLastError();
|
||||
fprintf(stderr, "GetModuleHandle returned %d\n", ret);
|
||||
return "";
|
||||
}
|
||||
GetModuleFileNameA(hm, path, sizeof(path));
|
||||
FreeLibrary( hm );
|
||||
return path;
|
||||
#else
|
||||
Dl_info dl_info;
|
||||
dladdr((void *)Path_GetModulePath, &dl_info);
|
||||
return dl_info.dli_fname;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Returns the specified path without its filename */
|
||||
std::string Path_StripFilename( const std::string & sPath, char slash )
|
||||
{
|
||||
@@ -151,17 +143,45 @@ std::string Path_StripExtension( const std::string & sPath )
|
||||
return sPath;
|
||||
}
|
||||
|
||||
/** returns just extension of the provided filename (if any). */
|
||||
std::string Path_GetExtension( const std::string & sPath )
|
||||
{
|
||||
for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
|
||||
{
|
||||
if ( *i == '.' )
|
||||
{
|
||||
return std::string( i.base(), sPath.end() );
|
||||
}
|
||||
|
||||
// if we find a slash there is no extension
|
||||
if ( *i == '\\' || *i == '/' )
|
||||
break;
|
||||
}
|
||||
|
||||
// we didn't find an extension
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Path_IsAbsolute( const std::string & sPath )
|
||||
{
|
||||
if( sPath.empty() )
|
||||
return false;
|
||||
|
||||
if( sPath.find( ':' ) != std::string::npos )
|
||||
return true;
|
||||
#if defined( WIN32 )
|
||||
if ( sPath.size() < 3 ) // must be c:\x or \\x at least
|
||||
return false;
|
||||
|
||||
if( sPath[0] == '\\' || sPath[0] == '/' )
|
||||
if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases
|
||||
{
|
||||
if ( sPath[2] == '\\' || sPath[2] == '/' )
|
||||
return true;
|
||||
}
|
||||
else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path
|
||||
return true;
|
||||
#else
|
||||
if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -223,6 +243,8 @@ std::string Path_Join( const std::string & first, const std::string & second, ch
|
||||
|
||||
// only insert a slash if we don't already have one
|
||||
std::string::size_type nLen = first.length();
|
||||
if( !nLen )
|
||||
return second;
|
||||
#if defined(_WIN32)
|
||||
if( first.back() == '\\' || first.back() == '/' )
|
||||
nLen--;
|
||||
@@ -257,6 +279,41 @@ std::string Path_Join(
|
||||
return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash );
|
||||
}
|
||||
|
||||
|
||||
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash )
|
||||
{
|
||||
if ( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string sPath = sRawPath;
|
||||
std::string::size_type nCurrent = sRawPath.length();
|
||||
if ( nCurrent == 0 )
|
||||
return sPath;
|
||||
|
||||
int nLastFound = -1;
|
||||
nCurrent--;
|
||||
while( nCurrent != 0 )
|
||||
{
|
||||
if ( sRawPath[ nCurrent ] == slash )
|
||||
{
|
||||
nLastFound = (int)nCurrent;
|
||||
nCurrent--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( nLastFound >= 0 )
|
||||
{
|
||||
sPath.erase( nLastFound, std::string::npos );
|
||||
}
|
||||
|
||||
return sPath;
|
||||
}
|
||||
|
||||
|
||||
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
|
||||
* specified path has a broken number of directories for its number of ..s */
|
||||
std::string Path_Compact( const std::string & sRawPath, char slash )
|
||||
@@ -336,17 +393,15 @@ std::string Path_Compact( const std::string & sRawPath, char slash )
|
||||
return sPath;
|
||||
}
|
||||
|
||||
#define MAX_UNICODE_PATH 32768
|
||||
#define MAX_UNICODE_PATH_IN_UTF8 ( MAX_UNICODE_PATH * 4 )
|
||||
|
||||
/** Returns the path to the current DLL or exe */
|
||||
std::string GetThisModulePath()
|
||||
std::string Path_GetThisModulePath()
|
||||
{
|
||||
// gets the path of vrclient.dll itself
|
||||
#ifdef WIN32
|
||||
HMODULE hmodule = NULL;
|
||||
|
||||
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(GetThisModulePath), &hmodule);
|
||||
::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(Path_GetThisModulePath), &hmodule );
|
||||
|
||||
wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
|
||||
char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
|
||||
@@ -361,7 +416,7 @@ std::string GetThisModulePath()
|
||||
#elif defined( OSX ) || defined( LINUX )
|
||||
// get the addr of a function in vrclient.so and then ask the dlopen system about it
|
||||
Dl_info info;
|
||||
dladdr( (void *)GetThisModulePath, &info );
|
||||
dladdr( (void *)Path_GetThisModulePath, &info );
|
||||
return info.dli_fname;
|
||||
#endif
|
||||
|
||||
@@ -379,19 +434,44 @@ bool Path_IsDirectory( const std::string & sPath )
|
||||
sFixedPath.erase( sFixedPath.end() - 1, sFixedPath.end() );
|
||||
|
||||
// see if the specified path actually exists.
|
||||
|
||||
#if defined(POSIX)
|
||||
struct stat buf;
|
||||
if ( stat ( sFixedPath.c_str(), &buf ) == -1)
|
||||
if ( stat( sFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(LINUX)
|
||||
#if defined( LINUX ) || defined( OSX )
|
||||
return S_ISDIR( buf.st_mode );
|
||||
#else
|
||||
return ( buf.st_mode & _S_IFDIR ) != 0;
|
||||
return (buf.st_mode & _S_IFDIR) != 0;
|
||||
#endif
|
||||
|
||||
#else
|
||||
struct _stat buf;
|
||||
std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
|
||||
if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (buf.st_mode & _S_IFDIR) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** returns true if the specified path represents an app bundle */
|
||||
bool Path_IsAppBundle( const std::string & sPath )
|
||||
{
|
||||
#if defined(OSX)
|
||||
NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ];
|
||||
bool bisAppBundle = ( nullptr != bundle );
|
||||
[ bundle release ];
|
||||
return bisAppBundle;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns true if the the path exists
|
||||
@@ -402,11 +482,20 @@ bool Path_Exists( const std::string & sPath )
|
||||
if( sFixedPath.empty() )
|
||||
return false;
|
||||
|
||||
#if defined( WIN32 )
|
||||
struct _stat buf;
|
||||
std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
|
||||
if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
struct stat buf;
|
||||
if ( stat ( sFixedPath.c_str(), &buf ) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -475,11 +564,9 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "rb" );
|
||||
#else
|
||||
errno_t err = fopen_s(&f, strFilename.c_str(), "rb");
|
||||
if ( err != 0 )
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
// the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s
|
||||
f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO );
|
||||
#endif
|
||||
|
||||
unsigned char* buf = NULL;
|
||||
@@ -508,6 +595,68 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize )
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "rb" );
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"rb" );
|
||||
if ( err != 0 )
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t unSizeToReturn = 0;
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
fseek( f, 0, SEEK_END );
|
||||
uint32_t size = (uint32_t)ftell( f );
|
||||
fseek( f, 0, SEEK_SET );
|
||||
|
||||
if ( size > unSize || !pBuffer )
|
||||
{
|
||||
unSizeToReturn = (uint32_t)size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( fread( pBuffer, size, 1, f ) == 1 )
|
||||
{
|
||||
unSizeToReturn = (uint32_t)size;
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
return unSizeToReturn;
|
||||
}
|
||||
|
||||
bool Path_WriteBinaryFile(const std::string &strFilename, unsigned char *pData, unsigned nSize)
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen(strFilename.c_str(), "wb");
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"wb" );
|
||||
if (err != 0)
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t written = 0;
|
||||
if (f != NULL) {
|
||||
written = fwrite(pData, sizeof(unsigned char), nSize, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return written = nSize ? true : false;
|
||||
}
|
||||
|
||||
std::string Path_ReadTextFile( const std::string &strFilename )
|
||||
{
|
||||
@@ -520,7 +669,7 @@ std::string Path_ReadTextFile( const std::string &strFilename )
|
||||
return "";
|
||||
|
||||
// convert CRLF -> LF
|
||||
int outsize = 1;
|
||||
size_t outsize = 1;
|
||||
for (int i=1; i < size; i++)
|
||||
{
|
||||
if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF
|
||||
@@ -529,7 +678,7 @@ std::string Path_ReadTextFile( const std::string &strFilename )
|
||||
buf[outsize++] = buf[i]; // just copy
|
||||
}
|
||||
|
||||
std::string ret((char *)buf, (char *)(buf + outsize));
|
||||
std::string ret((char *)buf, outsize);
|
||||
delete[] buf;
|
||||
return ret;
|
||||
}
|
||||
@@ -541,7 +690,8 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "w" );
|
||||
#else
|
||||
errno_t err = fopen_s(&f, strFilename.c_str(), "w");
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"w" );
|
||||
if ( err != 0 )
|
||||
{
|
||||
f = NULL;
|
||||
@@ -557,4 +707,113 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData )
|
||||
{
|
||||
std::string strTmpFilename = strFilename + ".tmp";
|
||||
|
||||
if ( !Path_WriteStringToTextFile( strTmpFilename, pchData ) )
|
||||
return false;
|
||||
|
||||
// Platform specific atomic file replacement
|
||||
#if defined( _WIN32 )
|
||||
std::wstring wsFilename = UTF8to16( strFilename.c_str() );
|
||||
std::wstring wsTmpFilename = UTF8to16( strTmpFilename.c_str() );
|
||||
if ( !::ReplaceFileW( wsFilename.c_str(), wsTmpFilename.c_str(), nullptr, 0, 0, 0 ) )
|
||||
{
|
||||
// if we couldn't ReplaceFile, try a non-atomic write as a fallback
|
||||
if ( !Path_WriteStringToTextFile( strFilename, pchData ) )
|
||||
return false;
|
||||
}
|
||||
#elif defined( POSIX )
|
||||
if ( rename( strTmpFilename.c_str(), strFilename.c_str() ) == -1 )
|
||||
return false;
|
||||
#else
|
||||
#error Do not know how to write atomic file
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
#define FILE_URL_PREFIX "file:///"
|
||||
#else
|
||||
#define FILE_URL_PREFIX "file://"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL)
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath )
|
||||
{
|
||||
if ( !strnicmp( sRelativePath.c_str(), "http://", 7 )
|
||||
|| !strnicmp( sRelativePath.c_str(), "https://", 8 )
|
||||
|| !strnicmp( sRelativePath.c_str(), "file://", 7 ) )
|
||||
{
|
||||
return sRelativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath );
|
||||
if ( sAbsolute.empty() )
|
||||
return sAbsolute;
|
||||
return std::string( FILE_URL_PREFIX ) + sAbsolute;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
std::string Path_UrlToFilePath( const std::string & sFileUrl )
|
||||
{
|
||||
if ( !strnicmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) )
|
||||
{
|
||||
return sFileUrl.c_str() + strlen( FILE_URL_PREFIX );
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Purpose: Returns the root of the directory the system wants us to store user documents in
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
std::string GetUserDocumentsPath()
|
||||
{
|
||||
#if defined( WIN32 )
|
||||
WCHAR rwchPath[MAX_PATH];
|
||||
|
||||
if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Convert the path to UTF-8 and store in the output
|
||||
std::string sUserPath = UTF16to8( rwchPath );
|
||||
|
||||
return sUserPath;
|
||||
#elif defined( OSX )
|
||||
@autoreleasepool {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
|
||||
if ( [paths count] == 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return [[paths objectAtIndex:0] UTF8String];
|
||||
}
|
||||
#elif defined( LINUX )
|
||||
// @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste
|
||||
const char *pchHome = getenv( "HOME" );
|
||||
if ( pchHome == NULL )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return pchHome;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Returns the path (including filename) to the current executable */
|
||||
std::string Path_GetExecutablePath();
|
||||
@@ -13,7 +14,7 @@ std::string Path_GetWorkingDirectory();
|
||||
bool Path_SetWorkingDirectory( const std::string & sPath );
|
||||
|
||||
/** returns the path (including filename) of the current shared lib or DLL */
|
||||
std::string Path_GetModulePath();
|
||||
std::string Path_GetThisModulePath();
|
||||
|
||||
/** Returns the specified path without its filename.
|
||||
* If slash is unspecified the native path separator of the current platform
|
||||
@@ -27,6 +28,9 @@ std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
|
||||
* If there is a path the path is left intact. */
|
||||
std::string Path_StripExtension( const std::string & sPath );
|
||||
|
||||
/** returns just extension of the provided filename (if any). */
|
||||
std::string Path_GetExtension( const std::string & sPath );
|
||||
|
||||
/** Returns true if the path is absolute */
|
||||
bool Path_IsAbsolute( const std::string & sPath );
|
||||
|
||||
@@ -60,11 +64,14 @@ std::string Path_Join(
|
||||
* will be used. */
|
||||
std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
|
||||
|
||||
//** Removed trailing slashes */
|
||||
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
|
||||
|
||||
/** returns true if the specified path exists and is a directory */
|
||||
bool Path_IsDirectory( const std::string & sPath );
|
||||
|
||||
/** Returns the path to the current DLL or exe */
|
||||
std::string GetThisModulePath();
|
||||
/** returns true if the specified path represents an app bundle */
|
||||
bool Path_IsAppBundle( const std::string & sPath );
|
||||
|
||||
/** returns true if the the path exists */
|
||||
bool Path_Exists( const std::string & sPath );
|
||||
@@ -75,11 +82,31 @@ std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartD
|
||||
|
||||
/** Path operations to read or write text/binary files */
|
||||
unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize );
|
||||
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize );
|
||||
bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize );
|
||||
std::string Path_ReadTextFile( const std::string &strFilename );
|
||||
bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData );
|
||||
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData );
|
||||
|
||||
/** Returns a file:// url for paths, or an http or https url if that's what was provided */
|
||||
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
|
||||
|
||||
/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
|
||||
std::string Path_UrlToFilePath( const std::string & sFileUrl );
|
||||
|
||||
/** Returns the root of the directory the system wants us to store user documents in */
|
||||
std::string GetUserDocumentsPath();
|
||||
|
||||
#ifndef MAX_UNICODE_PATH
|
||||
#define MAX_UNICODE_PATH 32767
|
||||
#endif
|
||||
|
||||
#ifndef MAX_UNICODE_PATH_IN_UTF8
|
||||
#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined(_WIN32)
|
||||
#if defined(WIN32)
|
||||
#define DYNAMIC_LIB_EXT ".dll"
|
||||
#ifdef _WIN64
|
||||
#define PLATSUBDIR "win64"
|
||||
@@ -91,8 +118,12 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch
|
||||
#define PLATSUBDIR "osx32"
|
||||
#elif defined(LINUX)
|
||||
#define DYNAMIC_LIB_EXT ".so"
|
||||
#if defined( LINUX32 )
|
||||
#define PLATSUBDIR "linux32"
|
||||
#else
|
||||
#define PLATSUBDIR "linux64"
|
||||
#endif
|
||||
#else
|
||||
#warning "Unknown platform for PLATSUBDIR"
|
||||
#define PLATSUBDIR "unknown_platform"
|
||||
#endif
|
||||
|
||||
437
examples/ThirdPartyLibs/openvr/samples/shared/strtools.cpp
Normal file
437
examples/ThirdPartyLibs/openvr/samples/shared/strtools.cpp
Normal file
@@ -0,0 +1,437 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#include "strtools.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
|
||||
{
|
||||
return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
|
||||
}
|
||||
|
||||
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
|
||||
{
|
||||
return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
|
||||
}
|
||||
|
||||
|
||||
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
|
||||
{
|
||||
size_t cStrLen = sString.length();
|
||||
size_t cSuffixLen = sSuffix.length();
|
||||
|
||||
if ( cSuffixLen > cStrLen )
|
||||
return false;
|
||||
|
||||
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
|
||||
|
||||
return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
|
||||
}
|
||||
|
||||
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
|
||||
{
|
||||
size_t cStrLen = sString.length();
|
||||
size_t cSuffixLen = sSuffix.length();
|
||||
|
||||
if ( cSuffixLen > cStrLen )
|
||||
return false;
|
||||
|
||||
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
|
||||
|
||||
return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string UTF16to8(const wchar_t * in)
|
||||
{
|
||||
std::string out;
|
||||
unsigned int codepoint = 0;
|
||||
for ( ; in && *in != 0; ++in )
|
||||
{
|
||||
if (*in >= 0xd800 && *in <= 0xdbff)
|
||||
codepoint = ((*in - 0xd800) << 10) + 0x10000;
|
||||
else
|
||||
{
|
||||
if (*in >= 0xdc00 && *in <= 0xdfff)
|
||||
codepoint |= *in - 0xdc00;
|
||||
else
|
||||
codepoint = *in;
|
||||
|
||||
if (codepoint <= 0x7f)
|
||||
out.append(1, static_cast<char>(codepoint));
|
||||
else if (codepoint <= 0x7ff)
|
||||
{
|
||||
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
|
||||
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
|
||||
}
|
||||
else if (codepoint <= 0xffff)
|
||||
{
|
||||
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
|
||||
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
|
||||
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
|
||||
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
|
||||
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
|
||||
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
|
||||
}
|
||||
codepoint = 0;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::wstring UTF8to16(const char * in)
|
||||
{
|
||||
std::wstring out;
|
||||
unsigned int codepoint = 0;
|
||||
int following = 0;
|
||||
for ( ; in && *in != 0; ++in )
|
||||
{
|
||||
unsigned char ch = *in;
|
||||
if (ch <= 0x7f)
|
||||
{
|
||||
codepoint = ch;
|
||||
following = 0;
|
||||
}
|
||||
else if (ch <= 0xbf)
|
||||
{
|
||||
if (following > 0)
|
||||
{
|
||||
codepoint = (codepoint << 6) | (ch & 0x3f);
|
||||
--following;
|
||||
}
|
||||
}
|
||||
else if (ch <= 0xdf)
|
||||
{
|
||||
codepoint = ch & 0x1f;
|
||||
following = 1;
|
||||
}
|
||||
else if (ch <= 0xef)
|
||||
{
|
||||
codepoint = ch & 0x0f;
|
||||
following = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoint = ch & 0x07;
|
||||
following = 3;
|
||||
}
|
||||
if (following == 0)
|
||||
{
|
||||
if (codepoint > 0xffff)
|
||||
{
|
||||
out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
|
||||
out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
|
||||
}
|
||||
else
|
||||
out.append(1, static_cast<wchar_t>(codepoint));
|
||||
codepoint = 0;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
|
||||
{
|
||||
pchBuffer[ unBufferSizeBytes - 1 ] = '\0';
|
||||
strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Purpose: converts a string to upper case
|
||||
// --------------------------------------------------------------------
|
||||
std::string StringToUpper( const std::string & sString )
|
||||
{
|
||||
std::string sOut;
|
||||
sOut.reserve( sString.size() + 1 );
|
||||
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
|
||||
{
|
||||
sOut.push_back( (char)toupper( *i ) );
|
||||
}
|
||||
|
||||
return sOut;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Purpose: converts a string to lower case
|
||||
// --------------------------------------------------------------------
|
||||
std::string StringToLower( const std::string & sString )
|
||||
{
|
||||
std::string sOut;
|
||||
sOut.reserve( sString.size() + 1 );
|
||||
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
|
||||
{
|
||||
sOut.push_back( (char)tolower( *i ) );
|
||||
}
|
||||
|
||||
return sOut;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
|
||||
{
|
||||
uint32_t unLen = (uint32_t)sValue.length() + 1;
|
||||
if( !pchBuffer || !unBufferLen )
|
||||
return unLen;
|
||||
|
||||
if( unBufferLen < unLen )
|
||||
{
|
||||
pchBuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( pchBuffer, sValue.c_str(), unLen );
|
||||
}
|
||||
|
||||
return unLen;
|
||||
}
|
||||
|
||||
void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen )
|
||||
{
|
||||
sDest.resize( unBufferLen + 1 );
|
||||
memcpy( const_cast< char* >( sDest.c_str() ), pchBuffer, unBufferLen );
|
||||
const_cast< char* >( sDest.c_str() )[ unBufferLen ] = '\0';
|
||||
}
|
||||
|
||||
/** Returns a std::string from a uint64_t */
|
||||
std::string Uint64ToString( uint64_t ulValue )
|
||||
{
|
||||
char buf[ 22 ];
|
||||
#if defined( _WIN32 )
|
||||
sprintf_s( buf, "%llu", ulValue );
|
||||
#else
|
||||
snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/** returns a uint64_t from a string */
|
||||
uint64_t StringToUint64( const std::string & sValue )
|
||||
{
|
||||
return strtoull( sValue.c_str(), NULL, 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
|
||||
//-----------------------------------------------------------------------------
|
||||
char cIntToHexDigit( int nValue )
|
||||
{
|
||||
//Assert( nValue >= 0 && nValue <= 15 );
|
||||
return "0123456789ABCDEF"[ nValue & 15 ];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
|
||||
// is not a valid hex digit.
|
||||
//-----------------------------------------------------------------------------
|
||||
int iHexCharToInt( char cValue )
|
||||
{
|
||||
int32_t iValue = cValue;
|
||||
if ( (uint32_t)( iValue - '0' ) < 10 )
|
||||
return iValue - '0';
|
||||
|
||||
iValue |= 0x20;
|
||||
if ( (uint32_t)( iValue - 'a' ) < 6 )
|
||||
return iValue - 'a' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
|
||||
// with spaces turned to + like HTML form encoding.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
|
||||
{
|
||||
//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
|
||||
|
||||
int iDestPos = 0;
|
||||
for ( int i=0; i < nSourceLen; ++i )
|
||||
{
|
||||
// worst case we need 3 additional chars
|
||||
if( (iDestPos+3) > nDestLen )
|
||||
{
|
||||
pchDest[0] = '\0';
|
||||
// AssertMsg( false, "Target buffer too short\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
|
||||
// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
|
||||
// Current specs also allow '~', but that is forbidden under original RFC 1738.
|
||||
if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
|
||||
&& pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'
|
||||
)
|
||||
{
|
||||
if ( bUsePlusForSpace && pchSource[i] == ' ' )
|
||||
{
|
||||
pchDest[iDestPos++] = '+';
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDest[iDestPos++] = '%';
|
||||
uint8_t iValue = pchSource[i];
|
||||
if ( iValue == 0 )
|
||||
{
|
||||
pchDest[iDestPos++] = '0';
|
||||
pchDest[iDestPos++] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
char cHexDigit1 = cIntToHexDigit( iValue % 16 );
|
||||
iValue /= 16;
|
||||
char cHexDigit2 = cIntToHexDigit( iValue );
|
||||
pchDest[iDestPos++] = cHexDigit2;
|
||||
pchDest[iDestPos++] = cHexDigit1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDest[iDestPos++] = pchSource[i];
|
||||
}
|
||||
}
|
||||
|
||||
if( (iDestPos+1) > nDestLen )
|
||||
{
|
||||
pchDest[0] = '\0';
|
||||
//AssertMsg( false, "Target buffer too short to terminate\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Null terminate
|
||||
pchDest[iDestPos++] = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
|
||||
// with spaces turned to + like HTML form encoding.
|
||||
//
|
||||
// Returns the amount of space used in the output buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
|
||||
{
|
||||
if ( nDecodeDestLen < nEncodedSourceLen )
|
||||
{
|
||||
//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iDestPos = 0;
|
||||
for( int i=0; i < nEncodedSourceLen; ++i )
|
||||
{
|
||||
if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = ' ';
|
||||
}
|
||||
else if ( pchEncodedSource[i] == '%' )
|
||||
{
|
||||
// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
|
||||
|
||||
// First make sure we have 2 more chars
|
||||
if ( i < nEncodedSourceLen - 2 )
|
||||
{
|
||||
char cHexDigit1 = pchEncodedSource[i+1];
|
||||
char cHexDigit2 = pchEncodedSource[i+2];
|
||||
|
||||
// Turn the chars into a hex value, if they are not valid, then we'll
|
||||
// just place the % and the following two chars direct into the string,
|
||||
// even though this really shouldn't happen, who knows what bad clients
|
||||
// may do with encoding.
|
||||
bool bValid = false;
|
||||
int iValue = iHexCharToInt( cHexDigit1 );
|
||||
if ( iValue != -1 )
|
||||
{
|
||||
iValue *= 16;
|
||||
int iValue2 = iHexCharToInt( cHexDigit2 );
|
||||
if ( iValue2 != -1 )
|
||||
{
|
||||
iValue += iValue2;
|
||||
pchDecodeDest[ iDestPos++ ] = (char)iValue;
|
||||
bValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bValid )
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = '%';
|
||||
pchDecodeDest[ iDestPos++ ] = cHexDigit1;
|
||||
pchDecodeDest[ iDestPos++ ] = cHexDigit2;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip ahead
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
|
||||
}
|
||||
}
|
||||
|
||||
// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
|
||||
// go ahead and do it as this can avoid bugs.
|
||||
if ( iDestPos < nDecodeDestLen )
|
||||
{
|
||||
pchDecodeDest[iDestPos] = 0;
|
||||
}
|
||||
|
||||
return (size_t)iDestPos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
|
||||
{
|
||||
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
|
||||
{
|
||||
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_StripExtension( std::string &in )
|
||||
{
|
||||
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
|
||||
// directory specifier like ../../somedir/./blah.
|
||||
std::string::size_type test = in.rfind( '.' );
|
||||
if ( test != std::string::npos )
|
||||
{
|
||||
// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
|
||||
// Which would otherwise wind up with "" and "c:\my@email", respectively.
|
||||
if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
|
||||
{
|
||||
in.resize( test );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
130
examples/ThirdPartyLibs/openvr/samples/shared/strtools.h
Normal file
130
examples/ThirdPartyLibs/openvr/samples/shared/strtools.h
Normal file
@@ -0,0 +1,130 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/** returns true if the string has the prefix */
|
||||
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
|
||||
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
|
||||
|
||||
/** returns if the string has the suffix */
|
||||
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
|
||||
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
|
||||
|
||||
/** converts a UTF-16 string to a UTF-8 string */
|
||||
std::string UTF16to8(const wchar_t * in);
|
||||
|
||||
/** converts a UTF-8 string to a UTF-16 string */
|
||||
std::wstring UTF8to16(const char * in);
|
||||
#define Utf16FromUtf8 UTF8to16
|
||||
|
||||
/** safely copy a string into a buffer */
|
||||
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
|
||||
template< size_t bufferSize >
|
||||
void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource )
|
||||
{
|
||||
strcpy_safe( buffer, bufferSize, pchSource );
|
||||
}
|
||||
|
||||
|
||||
/** converts a string to upper case */
|
||||
std::string StringToUpper( const std::string & sString );
|
||||
|
||||
/** converts a string to lower case */
|
||||
std::string StringToLower( const std::string & sString );
|
||||
|
||||
// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
|
||||
#if defined( OSX ) || defined( LINUX )
|
||||
#include <strings.h>
|
||||
inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); }
|
||||
#ifndef _stricmp
|
||||
#define _stricmp stricmp
|
||||
#endif
|
||||
inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); }
|
||||
#define _strnicmp strnicmp
|
||||
|
||||
#ifndef _vsnprintf_s
|
||||
#define _vsnprintf_s vsnprintf
|
||||
#endif
|
||||
|
||||
#define _TRUNCATE ((size_t)-1)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( OSX )
|
||||
// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
|
||||
// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
|
||||
inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
|
||||
{
|
||||
return wcslcpy(strDest, strSource, numberOfElements);
|
||||
}
|
||||
|
||||
inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
|
||||
{
|
||||
return strlcpy(strDest, strSource, numberOfElements);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( LINUX )
|
||||
// this implementation does not return whether or not the destination was
|
||||
// truncated, but that is straightforward to fix if anybody actually needs the
|
||||
// return code.
|
||||
#include "string.h"
|
||||
inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
|
||||
{
|
||||
wcsncpy(strDest, strSource, numberOfElements);
|
||||
strDest[numberOfElements-1] = '\0';
|
||||
}
|
||||
|
||||
inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
|
||||
{
|
||||
strncpy(strDest, strSource, numberOfElements);
|
||||
strDest[numberOfElements-1] = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 ) && _MSC_VER < 1800
|
||||
inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
|
||||
#endif
|
||||
|
||||
/* Handles copying a std::string into a buffer as would be provided in an API */
|
||||
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
|
||||
|
||||
/* Handles copying a buffer into an std::string and auto adds null terminator */
|
||||
void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen );
|
||||
|
||||
/** Returns a std::string from a uint64_t */
|
||||
std::string Uint64ToString( uint64_t ulValue );
|
||||
|
||||
/** returns a uint64_t from a string */
|
||||
uint64_t StringToUint64( const std::string & sValue );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: strip extension from a path
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_StripExtension( std::string &in );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user