Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,100 @@
//========= Copyright Valve Corporation ============//
#include "dirtools_public.h"
#include "strtools_public.h"
#include "pathtools_public.h"
#include <errno.h>
#include <string.h>
#ifdef _WIN32
#include "windows.h"
#else
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#if defined( OSX )
#include <sys/syslimits.h>
#endif
//-----------------------------------------------------------------------------
// Purpose: utility function to create dirs & subdirs
//-----------------------------------------------------------------------------
bool BCreateDirectoryRecursive(const char* pchPath)
{
// Does it already exist?
if (Path_IsDirectory(pchPath))
return true;
// copy the path into something we can munge
int len = (int)strlen(pchPath);
char* path = (char*)malloc(len + 1);
strcpy(path, pchPath);
// Walk backwards to first non-existing dir that we find
char* s = path + len - 1;
const char slash = Path_GetSlash();
while (s > path)
{
if (*s == slash)
{
*s = '\0';
bool bExists = Path_IsDirectory(path);
*s = slash;
if (bExists)
{
++s;
break;
}
}
--s;
}
// and then move forwards from there
while (*s)
{
if (*s == slash)
{
*s = '\0';
BCreateDirectory(path);
*s = slash;
}
s++;
}
bool bRetVal = BCreateDirectory(path);
free(path);
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose: Creates the directory, returning true if it is created, or if it already existed
//-----------------------------------------------------------------------------
bool BCreateDirectory(const char* pchPath)
{
#ifdef WIN32
std::wstring wPath = UTF8to16(pchPath);
if (::CreateDirectoryW(wPath.c_str(), NULL))
return true;
if (::GetLastError() == ERROR_ALREADY_EXISTS)
return true;
return false;
#else
int i = mkdir(pchPath, S_IRWXU | S_IRWXG | S_IRWXO);
if (i == 0)
return true;
if (errno == EEXIST)
return true;
return false;
#endif
}

View File

@ -0,0 +1,15 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <stdint.h>
#include <string>
#if !defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
#endif
extern bool BCreateDirectoryRecursive(const char* pchPath);
extern bool BCreateDirectory(const char* pchPath);

View File

@ -0,0 +1,46 @@
//========= Copyright Valve Corporation ============//
#include "envvartools_public.h"
#include <stdlib.h>
#if defined(_WIN32)
#include <windows.h>
#undef GetEnvironmentVariable
#undef SetEnvironmentVariable
#endif
std::string GetEnvironmentVariable(const char* pchVarName)
{
#if defined(_WIN32)
char rchValue[32767]; // max size for an env var on Windows
DWORD cChars = GetEnvironmentVariableA(pchVarName, rchValue, sizeof(rchValue));
if (cChars == 0)
return "";
else
return rchValue;
#elif defined(POSIX)
char* pchValue = getenv(pchVarName);
if (pchValue)
return pchValue;
else
return "";
#else
#error "Unsupported Platform"
#endif
}
bool SetEnvironmentVariable(const char* pchVarName, const char* pchVarValue)
{
#if defined(_WIN32)
return 0 != SetEnvironmentVariableA(pchVarName, pchVarValue);
#elif defined(POSIX)
if (pchVarValue == NULL)
return 0 == unsetenv(pchVarName);
else
return 0 == setenv(pchVarName, pchVarValue, 1);
#else
#error "Unsupported Platform"
#endif
}

View File

@ -0,0 +1,7 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
std::string GetEnvironmentVariable(const char* pchVarName);
bool SetEnvironmentVariable(const char* pchVarName, const char* pchVarValue);

View File

@ -0,0 +1,309 @@
//========= Copyright Valve Corporation ============//
#include "openvr.h"
#include "hmderrors_public.h"
#include <stdio.h>
#include <algorithm>
using namespace vr;
#define RETURN_ENUM_AS_STRING(enumValue) case enumValue: return #enumValue;
const char* GetEnglishStringForHmdError(vr::EVRInitError eError)
{
switch (eError)
{
case VRInitError_None: return "No Error (0)";
case VRInitError_Init_InstallationNotFound: return "Installation Not Found (100)";
case VRInitError_Init_InstallationCorrupt: return "Installation Corrupt (101)";
case VRInitError_Init_VRClientDLLNotFound: return "vrclient Shared Lib Not Found (102)";
case VRInitError_Init_FileNotFound: return "File Not Found (103)";
case VRInitError_Init_FactoryNotFound: return "Factory Function Not Found (104)";
case VRInitError_Init_InterfaceNotFound: return "Interface Not Found (105)";
case VRInitError_Init_InvalidInterface: return "Invalid Interface (106)";
case VRInitError_Init_UserConfigDirectoryInvalid: return "User Config Directory Invalid (107)";
case VRInitError_Init_HmdNotFound: return "Hmd Not Found (108)";
case VRInitError_Init_NotInitialized: return "Not Initialized (109)";
case VRInitError_Init_PathRegistryNotFound: return "Installation path could not be located (110)";
case VRInitError_Init_NoConfigPath: return "Config path could not be located (111)";
case VRInitError_Init_NoLogPath: return "Log path could not be located (112)";
case VRInitError_Init_PathRegistryNotWritable: return "Unable to write path registry (113)";
case VRInitError_Init_AppInfoInitFailed: return "App info manager init failed (114)";
case VRInitError_Init_Retry: return "Internal Retry (115)";
case VRInitError_Init_InitCanceledByUser: return "User Canceled Init (116)";
case VRInitError_Init_AnotherAppLaunching: return "Another app was already launching (117)";
case VRInitError_Init_SettingsInitFailed: return "Settings manager init failed (118)";
case VRInitError_Init_ShuttingDown: return "VR system shutting down (119)";
case VRInitError_Init_TooManyObjects: return "Too many tracked objects (120)";
case VRInitError_Init_NoServerForBackgroundApp: return "Not starting vrserver for background app (121)";
case VRInitError_Init_NotSupportedWithCompositor: return "The requested interface is incompatible with the compositor and the compositor is running (122)";
case VRInitError_Init_NotAvailableToUtilityApps: return "This interface is not available to utility applications (123)";
case VRInitError_Init_Internal: return "vrserver internal error (124)";
case VRInitError_Init_HmdDriverIdIsNone: return "Hmd DriverId is invalid (125)";
case VRInitError_Init_HmdNotFoundPresenceFailed: return "Hmd Not Found Presence Failed (126)";
case VRInitError_Init_VRMonitorNotFound: return "VR Monitor Not Found (127)";
case VRInitError_Init_VRMonitorStartupFailed: return "VR Monitor startup failed (128)";
case VRInitError_Init_LowPowerWatchdogNotSupported: return "Low Power Watchdog Not Supported (129)";
case VRInitError_Init_InvalidApplicationType: return "Invalid Application Type (130)";
case VRInitError_Init_NotAvailableToWatchdogApps: return "Not available to watchdog apps (131)";
case VRInitError_Init_WatchdogDisabledInSettings: return "Watchdog disabled in settings (132)";
case VRInitError_Init_VRDashboardNotFound: return "VR Dashboard Not Found (133)";
case VRInitError_Init_VRDashboardStartupFailed: return "VR Dashboard startup failed (134)";
case VRInitError_Init_VRHomeNotFound: return "VR Home Not Found (135)";
case VRInitError_Init_VRHomeStartupFailed: return "VR home startup failed (136)";
case VRInitError_Init_RebootingBusy: return "Rebooting In Progress (137)";
case VRInitError_Init_FirmwareUpdateBusy: return "Firmware Update In Progress (138)";
case VRInitError_Init_FirmwareRecoveryBusy: return "Firmware Recovery In Progress (139)";
case VRInitError_Init_USBServiceBusy: return "USB Service Busy (140)";
case VRInitError_Driver_Failed: return "Driver Failed (200)";
case VRInitError_Driver_Unknown: return "Driver Not Known (201)";
case VRInitError_Driver_HmdUnknown: return "HMD Not Known (202)";
case VRInitError_Driver_NotLoaded: return "Driver Not Loaded (203)";
case VRInitError_Driver_RuntimeOutOfDate: return "Driver runtime is out of date (204)";
case VRInitError_Driver_HmdInUse: return "HMD already in use by another application (205)";
case VRInitError_Driver_NotCalibrated: return "Device is not calibrated (206)";
case VRInitError_Driver_CalibrationInvalid: return "Device Calibration is invalid (207)";
case VRInitError_Driver_HmdDisplayNotFound: return "HMD detected over USB, but Monitor not found (208)";
case VRInitError_Driver_TrackedDeviceInterfaceUnknown: return "Driver Tracked Device Interface unknown (209)";
// case VRInitError_Driver_HmdDisplayNotFoundAfterFix: return "HMD detected over USB, but Monitor not found after attempt to fix (210)"; // taken out upon Ben's request: He thinks that there is no need to separate that error from 208
case VRInitError_Driver_HmdDriverIdOutOfBounds: return "Hmd DriverId is our of bounds (211)";
case VRInitError_Driver_HmdDisplayMirrored: return "HMD detected over USB, but Monitor may be mirrored instead of extended (212)";
case VRInitError_IPC_ServerInitFailed: return "VR Server Init Failed (300)";
case VRInitError_IPC_ConnectFailed: return "Connect to VR Server Failed (301)";
case VRInitError_IPC_SharedStateInitFailed: return "Shared IPC State Init Failed (302)";
case VRInitError_IPC_CompositorInitFailed: return "Shared IPC Compositor Init Failed (303)";
case VRInitError_IPC_MutexInitFailed: return "Shared IPC Mutex Init Failed (304)";
case VRInitError_IPC_Failed: return "Shared IPC Failed (305)";
case VRInitError_IPC_CompositorConnectFailed: return "Shared IPC Compositor Connect Failed (306)";
case VRInitError_IPC_CompositorInvalidConnectResponse: return "Shared IPC Compositor Invalid Connect Response (307)";
case VRInitError_IPC_ConnectFailedAfterMultipleAttempts: return "Shared IPC Connect Failed After Multiple Attempts (308)";
case VRInitError_Compositor_Failed: return "Compositor failed to initialize (400)";
case VRInitError_Compositor_D3D11HardwareRequired: return "Compositor failed to find DX11 hardware (401)";
case VRInitError_Compositor_FirmwareRequiresUpdate: return "Compositor requires mandatory firmware update (402)";
case VRInitError_Compositor_OverlayInitFailed: return "Compositor initialization succeeded, but overlay init failed (403)";
case VRInitError_Compositor_ScreenshotsInitFailed: return "Compositor initialization succeeded, but screenshot init failed (404)";
case VRInitError_Compositor_UnableToCreateDevice: return "Compositor unable to create graphics device (405)";
// Oculus
case VRInitError_VendorSpecific_UnableToConnectToOculusRuntime: return "Unable to connect to Oculus Runtime (1000)";
// Lighthouse
case VRInitError_VendorSpecific_HmdFound_CantOpenDevice: return "HMD found, but can not open device (1101)";
case VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart: return "HMD found, but unable to request config (1102)";
case VRInitError_VendorSpecific_HmdFound_NoStoredConfig: return "HMD found, but no stored config (1103)";
case VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck: return "HMD found, but failed configuration check (1113)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooBig: return "HMD found, but config too big (1104)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooSmall: return "HMD found, but config too small (1105)";
case VRInitError_VendorSpecific_HmdFound_UnableToInitZLib: return "HMD found, but unable to init ZLib (1106)";
case VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion: return "HMD found, but problems with the data (1107)";
case VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart: return "HMD found, but problems with the data (1108)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart: return "HMD found, but problems with the data (1109)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext: return "HMD found, but problems with the data (1110)";
case VRInitError_VendorSpecific_HmdFound_UserDataAddressRange: return "HMD found, but problems with the data (1111)";
case VRInitError_VendorSpecific_HmdFound_UserDataError: return "HMD found, but problems with the data (1112)";
case VRInitError_Steam_SteamInstallationNotFound: return "Unable to find Steam installation (2000)";
default:
return GetIDForVRInitError(eError);
}
}
const char* GetIDForVRInitError(vr::EVRInitError eError)
{
switch (eError)
{
RETURN_ENUM_AS_STRING(VRInitError_None);
RETURN_ENUM_AS_STRING(VRInitError_Unknown);
RETURN_ENUM_AS_STRING(VRInitError_Init_InstallationNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_InstallationCorrupt);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRClientDLLNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_FileNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_FactoryNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_InterfaceNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_InvalidInterface);
RETURN_ENUM_AS_STRING(VRInitError_Init_UserConfigDirectoryInvalid);
RETURN_ENUM_AS_STRING(VRInitError_Init_HmdNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_NotInitialized);
RETURN_ENUM_AS_STRING(VRInitError_Init_PathRegistryNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_NoConfigPath);
RETURN_ENUM_AS_STRING(VRInitError_Init_NoLogPath);
RETURN_ENUM_AS_STRING(VRInitError_Init_PathRegistryNotWritable);
RETURN_ENUM_AS_STRING(VRInitError_Init_AppInfoInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_Retry);
RETURN_ENUM_AS_STRING(VRInitError_Init_InitCanceledByUser);
RETURN_ENUM_AS_STRING(VRInitError_Init_AnotherAppLaunching);
RETURN_ENUM_AS_STRING(VRInitError_Init_SettingsInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_ShuttingDown);
RETURN_ENUM_AS_STRING(VRInitError_Init_TooManyObjects);
RETURN_ENUM_AS_STRING(VRInitError_Init_NoServerForBackgroundApp);
RETURN_ENUM_AS_STRING(VRInitError_Init_NotSupportedWithCompositor);
RETURN_ENUM_AS_STRING(VRInitError_Init_NotAvailableToUtilityApps);
RETURN_ENUM_AS_STRING(VRInitError_Init_Internal);
RETURN_ENUM_AS_STRING(VRInitError_Init_HmdDriverIdIsNone);
RETURN_ENUM_AS_STRING(VRInitError_Init_HmdNotFoundPresenceFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRMonitorNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRMonitorStartupFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_LowPowerWatchdogNotSupported);
RETURN_ENUM_AS_STRING(VRInitError_Init_InvalidApplicationType);
RETURN_ENUM_AS_STRING(VRInitError_Init_NotAvailableToWatchdogApps);
RETURN_ENUM_AS_STRING(VRInitError_Init_WatchdogDisabledInSettings);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRDashboardNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRDashboardStartupFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRHomeNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRHomeStartupFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_RebootingBusy);
RETURN_ENUM_AS_STRING(VRInitError_Init_FirmwareUpdateBusy);
RETURN_ENUM_AS_STRING(VRInitError_Init_FirmwareRecoveryBusy);
RETURN_ENUM_AS_STRING(VRInitError_Init_USBServiceBusy);
RETURN_ENUM_AS_STRING(VRInitError_Init_VRWebHelperStartupFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_TrackerManagerInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_Init_AlreadyRunning);
RETURN_ENUM_AS_STRING(VRInitError_Driver_Failed);
RETURN_ENUM_AS_STRING(VRInitError_Driver_Unknown);
RETURN_ENUM_AS_STRING(VRInitError_Driver_HmdUnknown);
RETURN_ENUM_AS_STRING(VRInitError_Driver_NotLoaded);
RETURN_ENUM_AS_STRING(VRInitError_Driver_RuntimeOutOfDate);
RETURN_ENUM_AS_STRING(VRInitError_Driver_HmdInUse);
RETURN_ENUM_AS_STRING(VRInitError_Driver_NotCalibrated);
RETURN_ENUM_AS_STRING(VRInitError_Driver_CalibrationInvalid);
RETURN_ENUM_AS_STRING(VRInitError_Driver_HmdDisplayNotFound);
RETURN_ENUM_AS_STRING(VRInitError_Driver_TrackedDeviceInterfaceUnknown);
// RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundAfterFix );
RETURN_ENUM_AS_STRING(VRInitError_Driver_HmdDriverIdOutOfBounds);
RETURN_ENUM_AS_STRING(VRInitError_Driver_HmdDisplayMirrored);
RETURN_ENUM_AS_STRING(VRInitError_IPC_ServerInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_ConnectFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_SharedStateInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_CompositorInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_MutexInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_Failed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_CompositorConnectFailed);
RETURN_ENUM_AS_STRING(VRInitError_IPC_CompositorInvalidConnectResponse);
RETURN_ENUM_AS_STRING(VRInitError_IPC_ConnectFailedAfterMultipleAttempts);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_Failed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_D3D11HardwareRequired);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FirmwareRequiresUpdate);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_OverlayInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_ScreenshotsInitFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_UnableToCreateDevice);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_SharedStateIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_NotificationManagerIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_ResourceManagerClientIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_MessageOverlaySharedStateInitFailure);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_PropertiesInterfaceIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateFullscreenWindowFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_SettingsInterfaceIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToShowWindow);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_DistortInterfaceIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_DisplayFrequencyFailure);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_RendererInitializationFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_DXGIFactoryInterfaceIsNull);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_DXGIFactoryCreateFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_DXGIFactoryQueryFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_InvalidAdapterDesktop);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_InvalidHmdAttachment);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_InvalidOutputDesktop);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_InvalidDeviceProvided);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_D3D11RendererInitializationFailed);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToFindDisplayMode);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateSwapChain);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToGetBackBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateRenderTarget);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateDXGI2SwapChain);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedtoGetDXGI2BackBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateDXGI2RenderTarget);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToGetDXGIDeviceInterface);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_SelectDisplayMode);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateNvAPIRenderTargets);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_NvAPISetDisplayMode);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_FailedToCreateDirectModeDisplay);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_InvalidHmdPropertyContainer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_UpdateDisplayFrequency);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateRasterizerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateWireframeRasterizerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateSamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateClampToBorderSamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateAnisoSamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateOverlaySamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreatePanoramaSamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateFontSamplerState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateNoBlendState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateBlendState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateAlphaBlendState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateBlendStateMaskR);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateBlendStateMaskG);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateBlendStateMaskB);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateDepthStencilState);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateDepthStencilStateNoWrite);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateDepthStencilStateNoDepth);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateFlushTexture);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateDistortionSurfaces);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateHmdPoseConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateHmdPoseStagingConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateSharedFrameInfoConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateOverlayConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateSceneTextureIndexConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateReadableSceneTextureIndexConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateLayerGraphicsTextureIndexConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateLayerComputeTextureIndexConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateLayerComputeSceneTextureIndexConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateComputeHmdPoseConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateGeomConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreatePanelMaskConstantBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreatePixelSimUBO);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateMSAARenderTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateResolveRenderTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateComputeResolveRenderTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateDriverDirectModeResolveTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_OpenDriverDirectModeResolveTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateFallbackSyncTexture);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_ShareFallbackSyncTexture);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateOverlayIndexBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateOverlayVertextBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateTextVertexBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateTextIndexBuffer);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateMirrorTextures);
RETURN_ENUM_AS_STRING(VRInitError_Compositor_CreateLastFrameRenderTexture);
// Vendor-specific errors
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_UnableToConnectToOculusRuntime);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_WindowsNotInDevMode);
// Lighthouse
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_CantOpenDevice);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_NoStoredConfig);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_ConfigTooBig);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_ConfigTooSmall);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UnableToInitZLib);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UserDataAddressRange);
RETURN_ENUM_AS_STRING(VRInitError_VendorSpecific_HmdFound_UserDataError);
RETURN_ENUM_AS_STRING(VRInitError_Steam_SteamInstallationNotFound);
default:
{
static char buf[128];
sprintf(buf, "Unknown error (%d)", eError);
return buf;
}
}
}

View File

@ -0,0 +1,5 @@
//========= Copyright Valve Corporation ============//
#pragma once
const char* GetEnglishStringForHmdError(vr::EVRInitError eError);
const char* GetIDForVRInitError(vr::EVRInitError eError);

View File

@ -0,0 +1,875 @@
//========= Copyright Valve Corporation ============//
#include "strtools_public.h"
#include "pathtools_public.h"
#if defined( _WIN32)
#include <windows.h>
#include <direct.h>
#include <shobjidl.h>
#include <knownfolders.h>
#include <shlobj.h>
#include <share.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>
#include <algorithm>
/** Returns the path (including filename) to the current executable */
std::string Path_GetExecutablePath()
{
#if defined( _WIN32 )
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;
#if defined( _WIN32 )
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;
}
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory(const std::string& sPath)
{
bool bSuccess;
#if defined( _WIN32 )
std::wstring wsPath = UTF8to16(sPath.c_str());
bSuccess = 0 == _wchdir(wsPath.c_str());
#else
bSuccess = 0 == chdir(sPath.c_str());
#endif
return bSuccess;
}
/** Gets the path to a temporary directory. */
std::string Path_GetTemporaryDirectory()
{
#if defined( _WIN32 )
wchar_t buf[MAX_UNICODE_PATH];
if (GetTempPathW(MAX_UNICODE_PATH, buf) == 0)
return Path_GetWorkingDirectory();
return UTF16to8(buf);
#else
const char* pchTmpDir = getenv("TMPDIR");
if (pchTmpDir == NULL)
{
return "";
}
return pchTmpDir;
#endif
}
/** Returns the specified path without its filename */
std::string Path_StripFilename(const std::string& sPath, char slash)
{
if (slash == 0)
slash = Path_GetSlash();
std::string::size_type n = sPath.find_last_of(slash);
if (n == std::string::npos)
return sPath;
else
return std::string(sPath.begin(), sPath.begin() + n);
}
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory(const std::string & sPath, char slash)
{
if (slash == 0)
slash = Path_GetSlash();
std::string::size_type n = sPath.find_last_of(slash);
if (n == std::string::npos)
return sPath;
else
return std::string(sPath.begin() + n + 1, sPath.end());
}
/** returns just the filename with no extension of the provided filename.
* If there is a path the path is left intact. */
std::string Path_StripExtension(const std::string & sPath)
{
for (std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++)
{
if (*i == '.')
{
return std::string(sPath.begin(), i.base() - 1);
}
// if we find a slash there is no extension
if (*i == '\\' || *i == '/')
break;
}
// we didn't find an extension
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 defined( WIN32 )
if (sPath.size() < 3) // must be c:\x or \\x at least
return false;
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;
}
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute(const std::string & sRelativePath, const std::string & sBasePath)
{
if (Path_IsAbsolute(sRelativePath))
return Path_Compact(sRelativePath);
else
{
if (!Path_IsAbsolute(sBasePath))
return "";
std::string sCompacted = Path_Compact(Path_Join(sBasePath, sRelativePath));
if (Path_IsAbsolute(sCompacted))
return sCompacted;
else
return "";
}
}
/** Fixes the directory separators for the current platform */
std::string Path_FixSlashes(const std::string & sPath, char slash)
{
if (slash == 0)
slash = Path_GetSlash();
std::string sFixed = sPath;
for (std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++)
{
if (*i == '/' || *i == '\\')
* i = slash;
}
return sFixed;
}
char Path_GetSlash()
{
#if defined(_WIN32)
return '\\';
#else
return '/';
#endif
}
/** Jams two paths together with the right kind of slash */
std::string Path_Join(const std::string & first, const std::string & second, char slash)
{
if (slash == 0)
slash = Path_GetSlash();
// 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--;
#else
char last_char = first[first.length() - 1];
if (last_char == '\\' || last_char == '/')
nLen--;
#endif
return first.substr(0, nLen) + std::string(1, slash) + second;
}
std::string Path_Join(const std::string & first, const std::string & second, const std::string & third, char slash)
{
return Path_Join(Path_Join(first, second, slash), third, slash);
}
std::string Path_Join(const std::string & first, const std::string & second, const std::string & third, const std::string & fourth, char slash)
{
return Path_Join(Path_Join(Path_Join(first, second, slash), third, slash), fourth, slash);
}
std::string Path_Join(
const std::string & first,
const std::string & second,
const std::string & third,
const std::string & fourth,
const std::string & fifth,
char slash)
{
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)
{
if (slash == 0)
slash = Path_GetSlash();
std::string sPath = Path_FixSlashes(sRawPath, slash);
std::string sSlashString(1, slash);
// strip out all /./
for (std::string::size_type i = 0; (i + 3) < sPath.length(); )
{
if (sPath[i] == slash && sPath[i + 1] == '.' && sPath[i + 2] == slash)
{
sPath.replace(i, 3, sSlashString);
}
else
{
++i;
}
}
// get rid of trailing /. but leave the path separator
if (sPath.length() > 2)
{
std::string::size_type len = sPath.length();
if (sPath[len - 1] == '.' && sPath[len - 2] == slash)
{
// sPath.pop_back();
sPath[len - 1] = 0; // for now, at least
}
}
// get rid of leading ./
if (sPath.length() > 2)
{
if (sPath[0] == '.' && sPath[1] == slash)
{
sPath.replace(0, 2, "");
}
}
// each time we encounter .. back up until we've found the previous directory name
// then get rid of both
std::string::size_type i = 0;
while (i < sPath.length())
{
if (i > 0 && sPath.length() - i >= 2
&& sPath[i] == '.'
&& sPath[i + 1] == '.'
&& (i + 2 == sPath.length() || sPath[i + 2] == slash)
&& sPath[i - 1] == slash)
{
// check if we've hit the start of the string and have a bogus path
if (i == 1)
return "";
// find the separator before i-1
std::string::size_type iDirStart = i - 2;
while (iDirStart > 0 && sPath[iDirStart - 1] != slash)
--iDirStart;
// remove everything from iDirStart to i+2
sPath.replace(iDirStart, (i - iDirStart) + 3, "");
// start over
i = 0;
}
else
{
++i;
}
}
return sPath;
}
/** Returns the path to the current DLL or exe */
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>(Path_GetThisModulePath), &hmodule);
wchar_t* pwchPath = new wchar_t[MAX_UNICODE_PATH];
char* pchPath = new char[MAX_UNICODE_PATH_IN_UTF8];
::GetModuleFileNameW(hmodule, 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 ) || defined( LINUX )
// get the addr of a function in vrclient.so and then ask the dlopen system about it
Dl_info info;
dladdr((void*)Path_GetThisModulePath, &info);
return info.dli_fname;
#endif
}
/** returns true if the specified path exists and is a directory */
bool Path_IsDirectory(const std::string & sPath)
{
std::string sFixedPath = Path_FixSlashes(sPath);
if (sFixedPath.empty())
return false;
char cLast = sFixedPath[sFixedPath.length() - 1];
if (cLast == '/' || cLast == '\\')
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)
{
return false;
}
#if defined( LINUX ) || defined( OSX )
return S_ISDIR(buf.st_mode);
#else
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)
@autoreleasepool {
NSBundle* bundle = [NSBundle bundleWithPath : [NSString stringWithUTF8String : sPath.c_str()] ];
bool bisAppBundle = (nullptr != bundle);
return bisAppBundle;
}
#else
return false;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the the path exists
//-----------------------------------------------------------------------------
bool Path_Exists(const std::string & sPath)
{
std::string sFixedPath = Path_FixSlashes(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;
}
//-----------------------------------------------------------------------------
// Purpose: helper to find a directory upstream from a given path
//-----------------------------------------------------------------------------
std::string Path_FindParentDirectoryRecursively(const std::string & strStartDirectory, const std::string & strDirectoryName)
{
std::string strFoundPath = "";
std::string strCurrentPath = Path_FixSlashes(strStartDirectory);
if (strCurrentPath.length() == 0)
return "";
bool bExists = Path_Exists(strCurrentPath);
std::string strCurrentDirectoryName = Path_StripDirectory(strCurrentPath);
if (bExists && stricmp(strCurrentDirectoryName.c_str(), strDirectoryName.c_str()) == 0)
return strCurrentPath;
while (bExists && strCurrentPath.length() != 0)
{
strCurrentPath = Path_StripFilename(strCurrentPath);
strCurrentDirectoryName = Path_StripDirectory(strCurrentPath);
bExists = Path_Exists(strCurrentPath);
if (bExists && stricmp(strCurrentDirectoryName.c_str(), strDirectoryName.c_str()) == 0)
return strCurrentPath;
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose: helper to find a subdirectory upstream from a given path
//-----------------------------------------------------------------------------
std::string Path_FindParentSubDirectoryRecursively(const std::string & strStartDirectory, const std::string & strDirectoryName)
{
std::string strFoundPath = "";
std::string strCurrentPath = Path_FixSlashes(strStartDirectory);
if (strCurrentPath.length() == 0)
return "";
bool bExists = Path_Exists(strCurrentPath);
while (bExists && strCurrentPath.length() != 0)
{
strCurrentPath = Path_StripFilename(strCurrentPath);
bExists = Path_Exists(strCurrentPath);
if (Path_Exists(Path_Join(strCurrentPath, strDirectoryName)))
{
strFoundPath = Path_Join(strCurrentPath, strDirectoryName);
break;
}
}
return strFoundPath;
}
//-----------------------------------------------------------------------------
// Purpose: reading and writing files in the vortex directory
//-----------------------------------------------------------------------------
unsigned char* Path_ReadBinaryFile(const std::string & strFilename, int* pSize)
{
FILE* f;
#if defined( POSIX )
f = fopen(strFilename.c_str(), "rb");
#else
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;
if (f != NULL)
{
fseek(f, 0, SEEK_END);
int size = ftell(f);
fseek(f, 0, SEEK_SET);
buf = new unsigned char[size];
if (buf && fread(buf, size, 1, f) == 1)
{
if (pSize)
* pSize = size;
}
else
{
delete[] buf;
buf = 0;
}
fclose(f);
}
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)
{
// doing it this way seems backwards, but I don't
// see an easy way to do this with C/C++ style IO
// that isn't worse...
int size;
unsigned char* buf = Path_ReadBinaryFile(strFilename, &size);
if (!buf)
return "";
// convert CRLF -> LF
size_t outsize = 1;
for (int i = 1; i < size; i++)
{
if (buf[i] == '\n' && buf[i - 1] == '\r') // CRLF
buf[outsize - 1] = '\n'; // ->LF
else
buf[outsize++] = buf[i]; // just copy
}
std::string ret((char*)buf, outsize);
delete[] buf;
return ret;
}
bool Path_MakeWritable(const std::string & strFilename)
{
#if defined ( _WIN32 )
std::wstring wstrFilename = UTF8to16(strFilename.c_str());
DWORD dwAttrs = GetFileAttributesW(wstrFilename.c_str());
if (dwAttrs != INVALID_FILE_ATTRIBUTES && (dwAttrs & FILE_ATTRIBUTE_READONLY))
{
return SetFileAttributesW(wstrFilename.c_str(), dwAttrs & ~FILE_ATTRIBUTE_READONLY);
}
#else
struct stat sb;
if (stat(strFilename.c_str(), &sb) == 0 && !(sb.st_mode & S_IWUSR))
{
return (chmod(strFilename.c_str(), sb.st_mode | S_IWUSR) == 0);
}
#endif
return true;
}
bool Path_WriteStringToTextFile(const std::string & strFilename, const char* pchData)
{
FILE* f;
#if defined( POSIX )
f = fopen(strFilename.c_str(), "w");
#else
std::wstring wstrFilename = UTF8to16(strFilename.c_str());
errno_t err = _wfopen_s(&f, wstrFilename.c_str(), L"w");
if (err != 0)
{
f = NULL;
}
#endif
bool ok = false;
if (f != NULL)
{
ok = fputs(pchData, f) >= 0;
fclose(f);
}
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 (StringHasPrefix(sRelativePath, "http://")
|| StringHasPrefix(sRelativePath, "https://")
|| StringHasPrefix(sRelativePath, "vr-input-workshop://")
|| StringHasPrefix(sRelativePath, "file://")
)
{
return sRelativePath;
}
else
{
std::string sAbsolute = Path_MakeAbsolute(sRelativePath, sBasePath);
if (sAbsolute.empty())
return sAbsolute;
sAbsolute = Path_FixSlashes(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)))
{
std::string sRet = sFileUrl.c_str() + strlen(FILE_URL_PREFIX);
sRet = Path_FixSlashes(sRet);
return sRet;
}
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
}
// -----------------------------------------------------------------------------------------------------
// Purpose: deletes / unlinks a single file
// -----------------------------------------------------------------------------------------------------
bool Path_UnlinkFile(const std::string & strFilename)
{
#if defined( WIN32 )
std::wstring wsFilename = UTF8to16(strFilename.c_str());
return (0 != DeleteFileW(wsFilename.c_str()));
#else
return (0 == unlink(strFilename.c_str()));
#endif
}

View File

@ -0,0 +1,141 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
/** Returns the path (including filename) to the current executable */
std::string Path_GetExecutablePath();
/** Returns the path of the current working directory */
std::string Path_GetWorkingDirectory();
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory(const std::string& sPath);
/** Gets the path to a temporary directory. */
std::string Path_GetTemporaryDirectory();
/** returns the path (including filename) of the current shared lib or DLL */
std::string Path_GetThisModulePath();
/** Returns the specified path without its filename.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_StripFilename(const std::string& sPath, char slash = 0);
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory(const std::string& sPath, char slash = 0);
/** returns just the filename with no extension of the provided filename.
* 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);
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute(const std::string& sRelativePath, const std::string& sBasePath);
/** Fixes the directory separators for the current platform.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_FixSlashes(const std::string& sPath, char slash = 0);
/** Returns the path separator for the current platform */
char Path_GetSlash();
/** Jams two paths together with the right kind of slash */
std::string Path_Join(const std::string& first, const std::string& second, char slash = 0);
std::string Path_Join(const std::string& first, const std::string& second, const std::string& third, char slash = 0);
std::string Path_Join(const std::string& first, const std::string& second, const std::string& third, const std::string& fourth, char slash = 0);
std::string Path_Join(
const std::string& first,
const std::string& second,
const std::string& third,
const std::string& fourth,
const std::string& fifth,
char slash = 0);
/** 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.
* If slash is unspecified the native path separator of the current platform
* 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 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);
/** Helper functions to find parent directories or subdirectories of parent directories */
std::string Path_FindParentDirectoryRecursively(const std::string& strStartDirectory, const std::string& strDirectoryName);
std::string Path_FindParentSubDirectoryRecursively(const std::string& strStartDirectory, const std::string& strDirectoryName);
/** Make a text file writable. */
bool Path_MakeWritable(const std::string& strFilename);
/** 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();
/** deletes / unlinks a single file */
bool Path_UnlinkFile(const std::string& strFilename);
#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)
#define DYNAMIC_LIB_EXT ".dll"
#define PROGRAM_EXT ".exe"
#ifdef _WIN64
#define PLATSUBDIR "win64"
#else
#define PLATSUBDIR "win32"
#endif
#elif defined(OSX)
#define DYNAMIC_LIB_EXT ".dylib"
#define PLATSUBDIR "osx32"
#define PROGRAM_EXT ""
#elif defined(LINUX)
#define DYNAMIC_LIB_EXT ".so"
#define PROGRAM_EXT ""
#if defined( LINUX32 )
#define PLATSUBDIR "linux32"
#else
#define PLATSUBDIR "linux64"
#endif
#else
#warning "Unknown platform for PLATSUBDIR"
#define PLATSUBDIR "unknown_platform"
#endif

View File

@ -0,0 +1,43 @@
//========= Copyright Valve Corporation ============//
#include "sharedlibtools_public.h"
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#if defined(POSIX)
#include <dlfcn.h>
#endif
SharedLibHandle SharedLib_Load(const char* pchPath)
{
#if defined( _WIN32)
return (SharedLibHandle)LoadLibraryExA(pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#elif defined(POSIX)
return (SharedLibHandle)dlopen(pchPath, RTLD_LOCAL | RTLD_NOW);
#endif
}
void* SharedLib_GetFunction(SharedLibHandle lib, const char* pchFunctionName)
{
#if defined( _WIN32)
return (void*)GetProcAddress((HMODULE)lib, pchFunctionName);
#elif defined(POSIX)
return dlsym(lib, pchFunctionName);
#endif
}
void SharedLib_Unload(SharedLibHandle lib)
{
if (!lib)
return;
#if defined( _WIN32)
FreeLibrary((HMODULE)lib);
#elif defined(POSIX)
dlclose(lib);
#endif
}

View File

@ -0,0 +1,9 @@
//========= Copyright Valve Corporation ============//
#pragma once
typedef void* SharedLibHandle;
SharedLibHandle SharedLib_Load(const char* pchPath);
void* SharedLib_GetFunction(SharedLibHandle lib, const char* pchFunctionName);
void SharedLib_Unload(SharedLibHandle lib);

View File

@ -0,0 +1,449 @@
//========= Copyright Valve Corporation ============//
#include "strtools_public.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <iostream>
//-----------------------------------------------------------------------------
// 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)
{
strncpy(pchBuffer, pchSource, unBufferSizeBytes - 1);
pchBuffer[unBufferSizeBytes - 1] = '\0';
}
// --------------------------------------------------------------------
// 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;
}
/** 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);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Tokenizes a string into a vector of strings
//-----------------------------------------------------------------------------
std::vector<std::string> TokenizeString(const std::string & sString, char cToken)
{
std::vector<std::string> vecStrings;
std::istringstream stream(sString);
std::string s;
while (std::getline(stream, s, cToken))
{
vecStrings.push_back(s);
}
return vecStrings;
}

View File

@ -0,0 +1,132 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
#include <sys/types.h>
#include <vector>
/** 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); }
#ifndef _strnicmp
#define _strnicmp strnicmp
#endif
#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);
/** 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);
/** Tokenizes a string into a vector of strings */
std::vector<std::string> TokenizeString(const std::string& sString, char cToken);

View File

@ -0,0 +1,411 @@
//========= Copyright Valve Corporation ============//
#include "vrpathregistry_public.h"
#include "json/json.h"
#include "pathtools_public.h"
#include "envvartools_public.h"
#include "strtools_public.h"
#include "dirtools_public.h"
#if defined( WIN32 )
#include <windows.h>
#include <shlobj.h>
#undef GetEnvironmentVariable
#elif defined OSX
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#elif defined(LINUX)
#include <dlfcn.h>
#include <stdio.h>
#endif
#include <algorithm>
#ifndef VRLog
#if defined( __MINGW32__ )
#define VRLog(args...) fprintf(stderr, args)
#elif defined( WIN32 )
#define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define VRLog(args...) fprintf(stderr, args)
#endif
#endif
/** Returns the root of the directory the system wants us to store user config data in */
static std::string GetAppSettingsPath()
{
#if defined( WIN32 )
WCHAR rwchPath[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA | 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 )
std::string sSettingsDir;
@autoreleasepool {
// Search for the path
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
if ([paths count] == 0)
{
return "";
}
NSString* resolvedPath = [paths objectAtIndex : 0];
resolvedPath = [resolvedPath stringByAppendingPathComponent : @"OpenVR"];
if (![[NSFileManager defaultManager]createDirectoryAtPath:resolvedPath withIntermediateDirectories : YES attributes : nil error : nil] )
{
return "";
}
sSettingsDir.assign([resolvedPath UTF8String]);
}
return sSettingsDir;
#elif defined( LINUX )
// As defined by XDG Base Directory Specification
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
const char* pchHome = getenv("XDG_CONFIG_HOME");
if ((pchHome != NULL) && (pchHome[0] != '\0'))
{
return pchHome;
}
//
// XDG_CONFIG_HOME is not defined, use ~/.config instead
//
pchHome = getenv("HOME");
if (pchHome == NULL)
{
return "";
}
std::string sUserPath(pchHome);
sUserPath = Path_Join(sUserPath, ".config");
return sUserPath;
#else
#warning "Unsupported platform"
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Constructor
// ---------------------------------------------------------------------------
CVRPathRegistry_Public::CVRPathRegistry_Public()
{
}
// ---------------------------------------------------------------------------
// Purpose: Computes the registry filename
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetOpenVRConfigPath()
{
std::string sConfigPath = GetAppSettingsPath();
if (sConfigPath.empty())
return "";
#if defined( _WIN32 ) || defined( LINUX )
sConfigPath = Path_Join(sConfigPath, "openvr");
#elif defined ( OSX )
sConfigPath = Path_Join(sConfigPath, ".openvr");
#else
#warning "Unsupported platform"
#endif
sConfigPath = Path_FixSlashes(sConfigPath);
return sConfigPath;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetVRPathRegistryFilename()
{
std::string sPath = GetOpenVRConfigPath();
if (sPath.empty())
return "";
#if defined( _WIN32 )
sPath = Path_Join(sPath, "openvrpaths.vrpath");
#elif defined ( POSIX )
sPath = Path_Join(sPath, "openvrpaths.vrpath");
#else
#error "Unsupported platform"
#endif
sPath = Path_FixSlashes(sPath);
return sPath;
}
// ---------------------------------------------------------------------------
// Purpose: Converts JSON to a history array
// ---------------------------------------------------------------------------
static void ParseStringListFromJson(std::vector< std::string >* pvecHistory, const Json::Value& root, const char* pchArrayName)
{
if (!root.isMember(pchArrayName))
return;
const Json::Value& arrayNode = root[pchArrayName];
if (!arrayNode)
{
VRLog("VR Path Registry node %s is not an array\n", pchArrayName);
return;
}
pvecHistory->clear();
pvecHistory->reserve(arrayNode.size());
for (uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++)
{
std::string sPath(arrayNode[unIndex].asString());
pvecHistory->push_back(sPath);
}
}
// ---------------------------------------------------------------------------
// Purpose: Converts a history array to JSON
// ---------------------------------------------------------------------------
static void StringListToJson(const std::vector< std::string >& vecHistory, Json::Value& root, const char* pchArrayName)
{
Json::Value& arrayNode = root[pchArrayName];
for (auto i = vecHistory.begin(); i != vecHistory.end(); i++)
{
arrayNode.append(*i);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CVRPathRegistry_Public::ToJsonString(std::string& sJsonString)
{
std::string sRegPath = GetVRPathRegistryFilename();
if (sRegPath.empty())
return false;
std::string sRegistryContents = Path_ReadTextFile(sRegPath);
if (sRegistryContents.empty())
return false;
sJsonString = sRegistryContents;
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Loads the config file from its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BLoadFromFile()
{
std::string sRegPath = GetVRPathRegistryFilename();
if (sRegPath.empty())
{
VRLog("Unable to determine VR Path Registry filename\n");
return false;
}
std::string sRegistryContents = Path_ReadTextFile(sRegPath);
if (sRegistryContents.empty())
{
VRLog("Unable to read VR Path Registry from %s\n", sRegPath.c_str());
return false;
}
Json::Value root;
Json::Reader reader;
if (!reader.parse(sRegistryContents, root))
{
VRLog("Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str());
return false;
}
ParseStringListFromJson(&m_vecRuntimePath, root, "runtime");
ParseStringListFromJson(&m_vecConfigPath, root, "config");
ParseStringListFromJson(&m_vecLogPath, root, "log");
if (root.isMember("external_drivers") && root["external_drivers"].isArray())
{
ParseStringListFromJson(&m_vecExternalDrivers, root, "external_drivers");
}
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Saves the config file to its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BSaveToFile() const
{
#if defined( DASHBOARD_BUILD_MODE )
return false;
#else
std::string sRegPath = GetVRPathRegistryFilename();
if (sRegPath.empty())
return false;
Json::Value root;
root["version"] = 1;
root["jsonid"] = "vrpathreg";
StringListToJson(m_vecRuntimePath, root, "runtime");
StringListToJson(m_vecConfigPath, root, "config");
StringListToJson(m_vecLogPath, root, "log");
StringListToJson(m_vecExternalDrivers, root, "external_drivers");
Json::StyledWriter writer;
std::string sRegistryContents = writer.write(root);
// make sure the directory we're writing into actually exists
std::string sRegDirectory = Path_StripFilename(sRegPath);
if (!BCreateDirectoryRecursive(sRegDirectory.c_str()))
{
VRLog("Unable to create path registry directory %s\n", sRegDirectory.c_str());
return false;
}
if (!Path_WriteStringToTextFile(sRegPath, sRegistryContents.c_str()))
{
VRLog("Unable to write VR path registry to %s\n", sRegPath.c_str());
return false;
}
return true;
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current runtime path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetRuntimePath() const
{
if (m_vecRuntimePath.empty())
return "";
else
return m_vecRuntimePath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current config path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetConfigPath() const
{
if (m_vecConfigPath.empty())
return "";
else
return m_vecConfigPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current log path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetLogPath() const
{
if (m_vecLogPath.empty())
return "";
else
return m_vecLogPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns paths using the path registry and the provided override
// values. Pass NULL for any paths you don't care about.
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::GetPaths(std::string* psRuntimePath, std::string* psConfigPath, std::string* psLogPath, const char* pchConfigPathOverride, const char* pchLogPathOverride, std::vector<std::string>* pvecExternalDrivers)
{
CVRPathRegistry_Public pathReg;
bool bLoadedRegistry = pathReg.BLoadFromFile();
int nCountEnvironmentVariables = 0;
if (psRuntimePath)
{
if (GetEnvironmentVariable(k_pchRuntimeOverrideVar).length() != 0)
{
*psRuntimePath = GetEnvironmentVariable(k_pchRuntimeOverrideVar);
nCountEnvironmentVariables++;
}
else if (!pathReg.GetRuntimePath().empty())
{
*psRuntimePath = pathReg.GetRuntimePath();
}
else
{
*psRuntimePath = "";
}
}
if (psConfigPath)
{
if (GetEnvironmentVariable(k_pchConfigOverrideVar).length() != 0)
{
*psConfigPath = GetEnvironmentVariable(k_pchConfigOverrideVar);
nCountEnvironmentVariables++;
}
else if (pchConfigPathOverride)
{
*psConfigPath = pchConfigPathOverride;
}
else if (!pathReg.GetConfigPath().empty())
{
*psConfigPath = pathReg.GetConfigPath();
}
else
{
*psConfigPath = "";
}
}
if (psLogPath)
{
if (GetEnvironmentVariable(k_pchLogOverrideVar).length() != 0)
{
*psLogPath = GetEnvironmentVariable(k_pchLogOverrideVar);
nCountEnvironmentVariables++;
}
else if (pchLogPathOverride)
{
*psLogPath = pchLogPathOverride;
}
else if (!pathReg.GetLogPath().empty())
{
*psLogPath = pathReg.GetLogPath();
}
else
{
*psLogPath = "";
}
}
if (pvecExternalDrivers)
{
*pvecExternalDrivers = pathReg.m_vecExternalDrivers;
}
if (nCountEnvironmentVariables == 3)
{
// all three environment variables were set, so we don't need the physical file
return true;
}
return bLoadedRegistry;
}

View File

@ -0,0 +1,45 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <vector>
#include <stdint.h>
static const char* k_pchRuntimeOverrideVar = "VR_OVERRIDE";
static const char* k_pchConfigOverrideVar = "VR_CONFIG_PATH";
static const char* k_pchLogOverrideVar = "VR_LOG_PATH";
class CVRPathRegistry_Public
{
public:
static std::string GetVRPathRegistryFilename();
static std::string GetOpenVRConfigPath();
public:
CVRPathRegistry_Public();
/** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about.
* Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */
static bool GetPaths(std::string* psRuntimePath, std::string* psConfigPath, std::string* psLogPath, const char* pchConfigPathOverride, const char* pchLogPathOverride, std::vector<std::string>* pvecExternalDrivers = NULL);
bool BLoadFromFile();
bool BSaveToFile() const;
bool ToJsonString(std::string& sJsonString);
// methods to get the current values
std::string GetRuntimePath() const;
std::string GetConfigPath() const;
std::string GetLogPath() const;
protected:
typedef std::vector< std::string > StringVector_t;
// index 0 is the current setting
StringVector_t m_vecRuntimePath;
StringVector_t m_vecLogPath;
StringVector_t m_vecConfigPath;
// full list of external drivers
StringVector_t m_vecExternalDrivers;
};