forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
@ -0,0 +1,116 @@
|
||||
# Project name.
|
||||
project(openvr_api)
|
||||
|
||||
set( LIBNAME "openvr_api" )
|
||||
set(OPENVR_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../headers)
|
||||
|
||||
# Set some properies for specific files.
|
||||
if(APPLE)
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set_source_files_properties(vrcommon/pathtools_public.cpp vrcommon/vrpathregistry_public.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
endif()
|
||||
if(BUILD_SHARED OR BUILD_FRAMEWORK)
|
||||
find_library(FOUNDATION_FRAMEWORK Foundation)
|
||||
mark_as_advanced(FOUNDATION_FRAMEWORK)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK})
|
||||
endif(BUILD_SHARED OR BUILD_FRAMEWORK)
|
||||
elseif(WIN32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions( -DWIN64 )
|
||||
set( LIBNAME "openvr_api64" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add include folders.
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../headers ${CMAKE_CURRENT_SOURCE_DIR}/vrcommon)
|
||||
|
||||
if(USE_CUSTOM_LIBCXX)
|
||||
link_directories(
|
||||
${LIBCXX_LIB_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set the source group and files.
|
||||
set(CORE_FILES
|
||||
openvr_api_public.cpp
|
||||
jsoncpp.cpp
|
||||
)
|
||||
set(VRCOMMON_FILES
|
||||
vrcommon/dirtools_public.cpp
|
||||
vrcommon/envvartools_public.cpp
|
||||
vrcommon/pathtools_public.cpp
|
||||
vrcommon/sharedlibtools_public.cpp
|
||||
vrcommon/hmderrors_public.cpp
|
||||
vrcommon/vrpathregistry_public.cpp
|
||||
vrcommon/strtools_public.cpp
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
${CORE_FILES}
|
||||
${VRCOMMON_FILES}
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADER_FILES
|
||||
${OPENVR_HEADER_DIR}/openvr_driver.h
|
||||
${OPENVR_HEADER_DIR}/openvr_capi.h
|
||||
${OPENVR_HEADER_DIR}/openvr.h
|
||||
)
|
||||
|
||||
source_group("Src" FILES
|
||||
${CORE_FILES}
|
||||
)
|
||||
|
||||
source_group("VRCommon" FILES
|
||||
${VRCOMMON_FILES}
|
||||
)
|
||||
|
||||
# Build the library.
|
||||
if(BUILD_SHARED)
|
||||
add_library(${LIBNAME} SHARED ${SOURCE_FILES})
|
||||
elseif(BUILD_FRAMEWORK)
|
||||
set( LIBNAME "OpenVR" )
|
||||
add_library( ${LIBNAME}
|
||||
SHARED ${SOURCE_FILES}
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr.h
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_api.cs
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_api.json
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_capi.h
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_driver.h
|
||||
)
|
||||
set_target_properties(OpenVR PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION A
|
||||
MACOSX_FRAMEWORK_IDENTIFIER com.valvesoftware.OpenVR.framework
|
||||
MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_SOURCE_DIR}/src/Info.plist
|
||||
# "current version" in semantic format in Mach-O binary file
|
||||
VERSION 1.0.6
|
||||
# "compatibility version" in semantic format in Mach-O binary file
|
||||
SOVERSION 1.0.0
|
||||
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/headers/openvr.h;${CMAKE_SOURCE_DIR}/headers/openvr_api.cs;${CMAKE_SOURCE_DIR}/headers/openvr_api.json;${CMAKE_SOURCE_DIR}/headers/openvr_capi.h;${CMAKE_SOURCE_DIR}/headers/openvr_driver.h"
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
else()
|
||||
add_library(${LIBNAME} STATIC ${SOURCE_FILES})
|
||||
endif()
|
||||
|
||||
if(USE_CUSTOM_LIBCXX)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} c++ c++abi)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${LIBNAME} ${EXTRA_LIBS} ${CMAKE_DL_LIBS})
|
||||
target_include_directories(${LIBNAME} PUBLIC ${OPENVR_HEADER_DIR})
|
||||
|
||||
install(TARGETS ${LIBNAME} DESTINATION lib)
|
||||
install(FILES ${PUBLIC_HEADER_FILES} DESTINATION include/openvr)
|
||||
|
||||
# Generate a .pc file for linux environments
|
||||
if(PLATFORM_NAME MATCHES "linux")
|
||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
CONFIGURE_FILE("openvr.pc.in" "openvr.pc" @ONLY)
|
||||
|
||||
set(OPENVR_PC ${CMAKE_CURRENT_BINARY_DIR}/openvr.pc)
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${OPENVR_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
||||
endif()
|
@ -0,0 +1,39 @@
|
||||
This is the source code for the OpenVR API client binding library which connects
|
||||
OpenVR applications to the SteamVR runtime, taking into account the version
|
||||
of the OpenVR interface they were compiled against.
|
||||
|
||||
The client binding library - openvr_api.dll on Windows, openvr_api.so on
|
||||
Linux, and openvr_api.dylib or OpenVR.framework on macOS - knows how to find
|
||||
and read the SteamVR runtime installation information which allows it to
|
||||
find and dynamically connect to the installed runtime. In combination with the
|
||||
interface version identifiers from /include/openvr.h which are baked
|
||||
into applications at the time they are built, the OpenVR API client
|
||||
binding library captures and conveys to the SteamVR runtime the version
|
||||
of the OpenVR API interface behavior that the application expects.
|
||||
|
||||
Applications carry with them a private/local copy of the client binding
|
||||
library when they ship, and they should install it locally to their
|
||||
application. Applications should not install the client binding library
|
||||
globally or attempt to link to a globally installed client binding library.
|
||||
Doing so negates at least part of the ability for the client binding library
|
||||
to accurately reflect the version of the OpenVR API that the application
|
||||
was built against, and so hinders compatibility support in the face of
|
||||
API changes.
|
||||
|
||||
Most applications should simply link to and redistribute with their application
|
||||
the pre-built client binding library found in the /bin directory of this
|
||||
repository. Some small number of applications which have specific requirements
|
||||
around redistributing only binaries they build themselves should build
|
||||
the client library from this source and either statically link it into
|
||||
their application or redistribute the binary they build.
|
||||
|
||||
This is a cmake project, to build it use the version of cmake appropriate
|
||||
for your platform. For example, to build on a POSIX system simply perform
|
||||
|
||||
cd src; mkdir _build; cd _build; cmake ..; make
|
||||
|
||||
and you will end up with the static library /src/bin/<arch>/libopenvr_api.a
|
||||
|
||||
To build a shared library, pass -DBUILD_SHARED=1 to cmake.
|
||||
To build as a framework on apple platforms, pass -DBUILD_FRAMEWORK=1 to cmake.
|
||||
To see a complete list of configurable build options, use `cmake -LAH`
|
@ -0,0 +1,35 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
namespace vr
|
||||
{
|
||||
|
||||
class IVRClientCore
|
||||
{
|
||||
public:
|
||||
/** Initializes the system */
|
||||
virtual EVRInitError Init(vr::EVRApplicationType eApplicationType, const char* pStartupInfo) = 0;
|
||||
|
||||
/** cleans up everything in vrclient.dll and prepares the DLL to be unloaded */
|
||||
virtual void Cleanup() = 0;
|
||||
|
||||
/** checks to see if the specified interface/version is supported in this vrclient.dll */
|
||||
virtual EVRInitError IsInterfaceVersionValid(const char* pchInterfaceVersion) = 0;
|
||||
|
||||
/** Retrieves any interface from vrclient.dll */
|
||||
virtual void* GetGenericInterface(const char* pchNameAndVersion, EVRInitError* peError) = 0;
|
||||
|
||||
/** Returns true if any driver has an HMD attached. Can be called outside of Init/Cleanup */
|
||||
virtual bool BIsHmdPresent() = 0;
|
||||
|
||||
/** Returns an English error string from inside vrclient.dll which might be newer than the API DLL */
|
||||
virtual const char* GetEnglishStringForHmdError(vr::EVRInitError eError) = 0;
|
||||
|
||||
/** Returns an error symbol from inside vrclient.dll which might be newer than the API DLL */
|
||||
virtual const char* GetIDForVRInitError(vr::EVRInitError eError) = 0;
|
||||
};
|
||||
|
||||
static const char* const IVRClientCore_Version = "IVRClientCore_003";
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
|
||||
/// It is intended to be used with #include "json/json-forwards.h"
|
||||
/// This header provides forward declaration for all JsonCpp types.
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
|
||||
released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
Copyright (c) 2007-2010 Baptiste Lepilleur
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
========================================================================
|
||||
(END LICENSE TEXT)
|
||||
|
||||
The MIT license is compatible with both the GPL and commercial
|
||||
software, affording one all of the rights of Public Domain with the
|
||||
minor nuisance of being required to keep the above copyright notice
|
||||
and license text in the source code. Note also that by accepting the
|
||||
Public Domain "license" you can re-license your copy using whatever
|
||||
license you like.
|
||||
|
||||
*/
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
# define JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
#define JSON_IS_AMALGAMATION
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
#define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of
|
||||
/// std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
|
||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||
// assertion macros. The default is to use exceptions.
|
||||
#ifndef JSON_USE_EXCEPTION
|
||||
#define JSON_USE_EXCEPTION 1
|
||||
#endif
|
||||
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
/// Remarks: it is automatically defined in the generated amalgated header.
|
||||
// #define JSON_IS_AMALGAMATION
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#include <cpptl/config.h>
|
||||
#ifndef JSON_USE_CPPTL
|
||||
#define JSON_USE_CPPTL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#define JSON_API CPPTL_API
|
||||
#elif defined(JSON_DLL_BUILD)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllexport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#elif defined(JSON_DLL)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllimport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#endif // ifdef JSON_IN_CPPTL
|
||||
#if !defined(JSON_API)
|
||||
#define JSON_API
|
||||
#endif
|
||||
|
||||
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||
// integer
|
||||
// Storages, and 64 bits integer support is disabled.
|
||||
// #define JSON_NO_INT64 1
|
||||
|
||||
#if defined(_MSC_VER) // MSVC
|
||||
# if _MSC_VER <= 1200 // MSVC 6
|
||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||
// (no conversion from unsigned __int64).
|
||||
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||
// characters in the debug information)
|
||||
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||
// with pragma push/pop).
|
||||
# pragma warning(disable : 4786)
|
||||
# endif // MSVC 6
|
||||
|
||||
# if _MSC_VER >= 1500 // MSVC 2008
|
||||
/// Indicates that the following function is deprecated.
|
||||
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# endif
|
||||
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
|
||||
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // MSVC >= 2010
|
||||
|
||||
#ifdef __clang__
|
||||
#if __has_feature(cxx_rvalue_references)
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // has_feature
|
||||
|
||||
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // GXX_EXPERIMENTAL
|
||||
|
||||
#endif // __clang__ || __GNUC__
|
||||
|
||||
#endif // not defined JSON_HAS_RVALUE_REFERENCES
|
||||
|
||||
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||
#define JSON_HAS_RVALUE_REFERENCES 0
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||
# endif // GNUC version
|
||||
#endif // __clang__ || __GNUC__
|
||||
|
||||
#if !defined(JSONCPP_DEPRECATED)
|
||||
#define JSONCPP_DEPRECATED(message)
|
||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||
|
||||
namespace Json {
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
#if defined(JSON_NO_INT64)
|
||||
typedef int LargestInt;
|
||||
typedef unsigned int LargestUInt;
|
||||
#undef JSON_HAS_INT64
|
||||
#else // if defined(JSON_NO_INT64)
|
||||
// For Microsoft Visual use specific types as long long is not supported
|
||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#endif // if defined(_MSC_VER)
|
||||
typedef Int64 LargestInt;
|
||||
typedef UInt64 LargestUInt;
|
||||
#define JSON_HAS_INT64
|
||||
#endif // if defined(JSON_NO_INT64)
|
||||
} // end namespace Json
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
#define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "config.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef unsigned int ArrayIndex;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
2077
Kha/Kinc/Backends/System/Windows/Libraries/SteamVR/src/json/json.h
Normal file
2077
Kha/Kinc/Backends/System/Windows/Libraries/SteamVR/src/json/json.h
Normal file
File diff suppressed because it is too large
Load Diff
5313
Kha/Kinc/Backends/System/Windows/Libraries/SteamVR/src/jsoncpp.cpp
Normal file
5313
Kha/Kinc/Backends/System/Windows/Libraries/SteamVR/src/jsoncpp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,298 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#define VR_API_EXPORT 1
|
||||
#include "openvr.h"
|
||||
#include "ivrclientcore.h"
|
||||
#include "pathtools_public.h"
|
||||
#include "sharedlibtools_public.h"
|
||||
#include "envvartools_public.h"
|
||||
#include "hmderrors_public.h"
|
||||
#include "vrpathregistry_public.h"
|
||||
#include <mutex>
|
||||
|
||||
using vr::EVRInitError;
|
||||
using vr::IVRSystem;
|
||||
using vr::IVRClientCore;
|
||||
using vr::VRInitError_None;
|
||||
|
||||
namespace vr
|
||||
{
|
||||
|
||||
static void* g_pVRModule = NULL;
|
||||
static IVRClientCore* g_pHmdSystem = NULL;
|
||||
static std::recursive_mutex g_mutexSystem;
|
||||
|
||||
|
||||
typedef void* (*VRClientCoreFactoryFn)(const char* pInterfaceName, int* pReturnCode);
|
||||
|
||||
static uint32_t g_nVRToken = 0;
|
||||
|
||||
uint32_t VR_GetInitToken()
|
||||
{
|
||||
return g_nVRToken;
|
||||
}
|
||||
|
||||
EVRInitError VR_LoadHmdSystemInternal();
|
||||
void CleanupInternalInterfaces();
|
||||
|
||||
|
||||
uint32_t VR_InitInternal2(EVRInitError* peError, vr::EVRApplicationType eApplicationType, const char* pStartupInfo)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
EVRInitError err = VR_LoadHmdSystemInternal();
|
||||
if (err == vr::VRInitError_None)
|
||||
{
|
||||
err = g_pHmdSystem->Init(eApplicationType, pStartupInfo);
|
||||
}
|
||||
|
||||
if (peError)
|
||||
* peError = err;
|
||||
|
||||
if (err != VRInitError_None)
|
||||
{
|
||||
SharedLib_Unload(g_pVRModule);
|
||||
g_pHmdSystem = NULL;
|
||||
g_pVRModule = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ++g_nVRToken;
|
||||
}
|
||||
|
||||
VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal(EVRInitError* peError, EVRApplicationType eApplicationType);
|
||||
|
||||
uint32_t VR_InitInternal(EVRInitError* peError, vr::EVRApplicationType eApplicationType)
|
||||
{
|
||||
return VR_InitInternal2(peError, eApplicationType, nullptr);
|
||||
}
|
||||
|
||||
void VR_ShutdownInternal()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (g_pHmdSystem)
|
||||
{
|
||||
g_pHmdSystem->Cleanup();
|
||||
g_pHmdSystem = NULL;
|
||||
}
|
||||
if (g_pVRModule)
|
||||
{
|
||||
SharedLib_Unload(g_pVRModule);
|
||||
g_pVRModule = NULL;
|
||||
}
|
||||
|
||||
#if !defined( VR_API_PUBLIC )
|
||||
CleanupInternalInterfaces();
|
||||
#endif
|
||||
|
||||
++g_nVRToken;
|
||||
}
|
||||
|
||||
EVRInitError VR_LoadHmdSystemInternal()
|
||||
{
|
||||
std::string sRuntimePath, sConfigPath, sLogPath;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths(&sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL);
|
||||
if (!bReadPathRegistry)
|
||||
{
|
||||
return vr::VRInitError_Init_PathRegistryNotFound;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if (!Path_IsDirectory(sRuntimePath))
|
||||
{
|
||||
return vr::VRInitError_Init_InstallationNotFound;
|
||||
}
|
||||
|
||||
// Because we don't have a way to select debug vs. release yet we'll just
|
||||
// use debug if it's there
|
||||
#if defined( LINUX64 )
|
||||
std::string sTestPath = Path_Join(sRuntimePath, "bin", PLATSUBDIR);
|
||||
#else
|
||||
std::string sTestPath = Path_Join(sRuntimePath, "bin");
|
||||
#endif
|
||||
if (!Path_IsDirectory(sTestPath))
|
||||
{
|
||||
return vr::VRInitError_Init_InstallationCorrupt;
|
||||
}
|
||||
|
||||
#if defined( WIN64 )
|
||||
std::string sDLLPath = Path_Join(sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT);
|
||||
#else
|
||||
std::string sDLLPath = Path_Join(sTestPath, "vrclient" DYNAMIC_LIB_EXT);
|
||||
#endif
|
||||
|
||||
// only look in the override
|
||||
void* pMod = SharedLib_Load(sDLLPath.c_str());
|
||||
// nothing more to do if we can't load the DLL
|
||||
if (!pMod)
|
||||
{
|
||||
return vr::VRInitError_Init_VRClientDLLNotFound;
|
||||
}
|
||||
|
||||
VRClientCoreFactoryFn fnFactory = (VRClientCoreFactoryFn)(SharedLib_GetFunction(pMod, "VRClientCoreFactory"));
|
||||
if (!fnFactory)
|
||||
{
|
||||
SharedLib_Unload(pMod);
|
||||
return vr::VRInitError_Init_FactoryNotFound;
|
||||
}
|
||||
|
||||
int nReturnCode = 0;
|
||||
g_pHmdSystem = static_cast<IVRClientCore*> (fnFactory(vr::IVRClientCore_Version, &nReturnCode));
|
||||
if (!g_pHmdSystem)
|
||||
{
|
||||
SharedLib_Unload(pMod);
|
||||
return vr::VRInitError_Init_InterfaceNotFound;
|
||||
}
|
||||
|
||||
g_pVRModule = pMod;
|
||||
return VRInitError_None;
|
||||
}
|
||||
|
||||
|
||||
void* VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (!g_pHmdSystem)
|
||||
{
|
||||
if (peError)
|
||||
* peError = vr::VRInitError_Init_NotInitialized;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError);
|
||||
}
|
||||
|
||||
bool VR_IsInterfaceVersionValid(const char* pchInterfaceVersion)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (!g_pHmdSystem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None;
|
||||
}
|
||||
|
||||
bool VR_IsHmdPresent()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (g_pHmdSystem)
|
||||
{
|
||||
// if we're already initialized, just call through
|
||||
return g_pHmdSystem->BIsHmdPresent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
EVRInitError err = VR_LoadHmdSystemInternal();
|
||||
if (err != VRInitError_None)
|
||||
return false;
|
||||
|
||||
bool bHasHmd = g_pHmdSystem->BIsHmdPresent();
|
||||
|
||||
g_pHmdSystem = NULL;
|
||||
SharedLib_Unload(g_pVRModule);
|
||||
g_pVRModule = NULL;
|
||||
|
||||
return bHasHmd;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the OpenVR runtime is installed. */
|
||||
bool VR_IsRuntimeInstalled()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (g_pHmdSystem)
|
||||
{
|
||||
// if we're already initialized, OpenVR is obviously installed
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
std::string sRuntimePath, sConfigPath, sLogPath;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths(&sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL);
|
||||
if (!bReadPathRegistry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if (!Path_IsDirectory(sRuntimePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// the installation may be corrupt in some way, but it certainly looks installed
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns where OpenVR runtime is installed. */
|
||||
const char* VR_RuntimePath()
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
static std::string sRuntimePath;
|
||||
std::string sConfigPath, sLogPath;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths(&sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL);
|
||||
if (!bReadPathRegistry)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if (!Path_IsDirectory(sRuntimePath))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sRuntimePath.c_str();
|
||||
}
|
||||
|
||||
|
||||
/** Returns the symbol version of an HMD error. */
|
||||
const char* VR_GetVRInitErrorAsSymbol(EVRInitError error)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (g_pHmdSystem)
|
||||
return g_pHmdSystem->GetIDForVRInitError(error);
|
||||
else
|
||||
return GetIDForVRInitError(error);
|
||||
}
|
||||
|
||||
|
||||
/** Returns the english string version of an HMD error. */
|
||||
const char* VR_GetVRInitErrorAsEnglishDescription(EVRInitError error)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(g_mutexSystem);
|
||||
|
||||
if (g_pHmdSystem)
|
||||
return g_pHmdSystem->GetEnglishStringForHmdError(error);
|
||||
else
|
||||
return GetEnglishStringForHmdError(error);
|
||||
}
|
||||
|
||||
|
||||
VR_INTERFACE const char* VR_CALLTYPE VR_GetStringForHmdError(vr::EVRInitError error);
|
||||
|
||||
/** Returns the english string version of an HMD error. */
|
||||
const char* VR_GetStringForHmdError(EVRInitError error)
|
||||
{
|
||||
return VR_GetVRInitErrorAsEnglishDescription(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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);
|
@ -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
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
const char* GetEnglishStringForHmdError(vr::EVRInitError eError);
|
||||
const char* GetIDForVRInitError(vr::EVRInitError eError);
|
@ -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
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
Reference in New Issue
Block a user