mirror of
				https://git.wownero.com/dsc/openvr.git
				synced 2024-08-15 01:03:30 +00:00 
			
		
		
		
	Initial commit
This commit is contained in:
		
						commit
						7e1249a813
					
				
					 33 changed files with 38389 additions and 0 deletions
				
			
		
							
								
								
									
										42
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | # Set the default behavior, in case people don't have core.autocrlf set. | ||||||
|  | * text=auto | ||||||
|  | 
 | ||||||
|  | # Explicitly declare text files you want to always be normalized and converted | ||||||
|  | # to native line endings on checkout. | ||||||
|  | *.bat text | ||||||
|  | *.txt text | ||||||
|  | *.c text | ||||||
|  | *.h text | ||||||
|  | *.H text | ||||||
|  | *.cc text | ||||||
|  | *.cpp text | ||||||
|  | *.awk text | ||||||
|  | *.pl text | ||||||
|  | *.py text | ||||||
|  | *.xcconfig text | ||||||
|  | *.vcd text | ||||||
|  | *.vbsp text | ||||||
|  | *.proto text | ||||||
|  | *.inc text | ||||||
|  | *.fxc text | ||||||
|  | *.vsh text | ||||||
|  | *.lst text | ||||||
|  | *.mm text | ||||||
|  | *.cfg text | ||||||
|  | *.res text | ||||||
|  | *.rc text | ||||||
|  | *.def text | ||||||
|  | *.vmt text | ||||||
|  | *.inl text | ||||||
|  | *.asm text | ||||||
|  | 
 | ||||||
|  | .gitignore text | ||||||
|  | README text | ||||||
|  | CONTRIBUTING text | ||||||
|  | LICENSE text | ||||||
|  | 
 | ||||||
|  | # Declare files that will always have LF line endings on checkout. | ||||||
|  | *.sh eol=lf | ||||||
|  | 
 | ||||||
|  | # Denote all files that are truly binary and should not be modified. | ||||||
|  | *.exe binary | ||||||
							
								
								
									
										96
									
								
								CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | ||||||
|  | # Set the minimum required version of CMake for this project. | ||||||
|  | cmake_minimum_required(VERSION 2.8) | ||||||
|  | 
 | ||||||
|  | # Set project name. | ||||||
|  | project(OpenVRSDK) | ||||||
|  | 
 | ||||||
|  | # Fetch the version from the headers | ||||||
|  | set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/headers/openvr.h") | ||||||
|  | 
 | ||||||
|  | set(VERSION_MAJOR_REGEX "\tstatic const uint32_t k_nSteamVRVersionMajor = (.+);") | ||||||
|  | set(VERSION_MINOR_REGEX "\tstatic const uint32_t k_nSteamVRVersionMinor = (.+);") | ||||||
|  | set(VERSION_BUILD_REGEX "\tstatic const uint32_t k_nSteamVRVersionBuild = (.+);") | ||||||
|  | 
 | ||||||
|  | file(STRINGS "${VERSION_FILE}" VERSION_MAJOR_STRING REGEX "${VERSION_MAJOR_REGEX}") | ||||||
|  | file(STRINGS "${VERSION_FILE}" VERSION_MINOR_STRING REGEX "${VERSION_MINOR_REGEX}") | ||||||
|  | file(STRINGS "${VERSION_FILE}" VERSION_BUILD_STRING REGEX "${VERSION_BUILD_REGEX}") | ||||||
|  | 
 | ||||||
|  | string(REGEX REPLACE "${VERSION_MAJOR_REGEX}" "\\1" VERSION_MAJOR ${VERSION_MAJOR_STRING}) | ||||||
|  | string(REGEX REPLACE "${VERSION_MINOR_REGEX}" "\\1" VERSION_MINOR ${VERSION_MINOR_STRING}) | ||||||
|  | string(REGEX REPLACE "${VERSION_BUILD_REGEX}" "\\1" VERSION_BUILD ${VERSION_BUILD_STRING}) | ||||||
|  | 
 | ||||||
|  | set(OPENVR_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}") | ||||||
|  | 
 | ||||||
|  | # Setup some options. | ||||||
|  | option(BUILD_SHARED "Builds the library as shared library" OFF) | ||||||
|  | option(BUILD_FRAMEWORK "Builds the library as an apple Framework" OFF) | ||||||
|  | option(BUILD_UNIVERSAL "Builds the shared or framework as a universal (fat, 32- & 64-bit) binary" ON) | ||||||
|  | option(BUILD_OSX_I386 "Builds the shared or framework as a 32-bit binary, even on a 64-bit platform" OFF) | ||||||
|  | option(USE_LIBCXX "Uses libc++ instead of libstdc++" ON) | ||||||
|  | option(USE_CUSTOM_LIBCXX "Uses a custom libc++" OFF) | ||||||
|  | 
 | ||||||
|  | add_definitions( -DVR_API_PUBLIC ) | ||||||
|  | 
 | ||||||
|  | # Check if 32 or 64 bit system. | ||||||
|  | set(SIZEOF_VOIDP ${CMAKE_SIZEOF_VOID_P}) | ||||||
|  | if(CMAKE_SIZEOF_VOID_P EQUAL 8) | ||||||
|  |   set(PROCESSOR_ARCH "64") | ||||||
|  | else() | ||||||
|  |   set(PROCESSOR_ARCH "32") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | # Get platform. | ||||||
|  | if(WIN32) | ||||||
|  |   set(PLATFORM_NAME "win") | ||||||
|  |   if(NOT BUILD_SHARED) | ||||||
|  |     add_definitions(-DOPENVR_BUILD_STATIC) | ||||||
|  |   endif() | ||||||
|  | elseif(UNIX AND NOT APPLE) | ||||||
|  |   if(CMAKE_SYSTEM_NAME MATCHES ".*Linux") | ||||||
|  |     set(PLATFORM_NAME "linux") | ||||||
|  |     add_definitions(-DLINUX -DPOSIX) | ||||||
|  |     if(PROCESSOR_ARCH MATCHES "64") | ||||||
|  |         add_definitions(-DLINUX64) | ||||||
|  |     endif() | ||||||
|  |   endif() | ||||||
|  | elseif(APPLE) | ||||||
|  |   if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*" OR CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*") | ||||||
|  |     set(PLATFORM_NAME "osx") | ||||||
|  |     add_definitions(-DOSX -DPOSIX) | ||||||
|  |     if(BUILD_UNIVERSAL) | ||||||
|  |       set(CMAKE_OSX_ARCHITECTURES "i386;x86_64") | ||||||
|  |     endif() | ||||||
|  |     if(BUILD_OSX_I386) | ||||||
|  |       set(PROCESSOR_ARCH "32") | ||||||
|  |       set(CMAKE_OSX_ARCHITECTURES "i386") | ||||||
|  |     endif() | ||||||
|  |   endif() | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | # Set output folder for static and shared libraries | ||||||
|  | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) | ||||||
|  | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) | ||||||
|  | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) | ||||||
|  | 
 | ||||||
|  | # Enable some properties. | ||||||
|  | if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") | ||||||
|  | 	# Enable c++11 and hide symbols which shouldn't be visible | ||||||
|  | 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -fvisibility=hidden") | ||||||
|  | 
 | ||||||
|  | 	# Set custom libc++ usage here | ||||||
|  | 	if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND USE_LIBCXX) | ||||||
|  | 		if(USE_CUSTOM_LIBCXX) | ||||||
|  | 			if(BUILD_SHARED) | ||||||
|  | 				set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++") | ||||||
|  | 			endif() | ||||||
|  | 			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") | ||||||
|  | 			include_directories( ${LIBCXX_INCLUDE} ${LIBCXX_ABI_INCLUDE}) | ||||||
|  | 			message(STATUS "Using custom libc++") | ||||||
|  | 		else() | ||||||
|  | 			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") | ||||||
|  | 			message(STATUS "Using libc++") | ||||||
|  | 		endif() | ||||||
|  | 	endif() | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | add_subdirectory(src) | ||||||
							
								
								
									
										27
									
								
								LICENSE
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								LICENSE
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | Copyright (c) 2015, Valve Corporation | ||||||
|  | All rights reserved. | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without modification, | ||||||
|  | are permitted provided that the following conditions are met: | ||||||
|  | 
 | ||||||
|  | 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  | list of conditions and the following disclaimer. | ||||||
|  | 
 | ||||||
|  | 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  | this list of conditions and the following disclaimer in the documentation and/or | ||||||
|  | other materials provided with the distribution. | ||||||
|  | 
 | ||||||
|  | 3. Neither the name of the copyright holder nor the names of its contributors | ||||||
|  | may be used to endorse or promote products derived from this software without | ||||||
|  | specific prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||||
|  | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
|  | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
							
								
								
									
										13
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | OpenVR SDK | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | OpenVR is an API and runtime that allows access to VR hardware from multiple  | ||||||
|  | vendors without requiring that applications have specific knowledge of the  | ||||||
|  | hardware they are targeting. This repository is an SDK that contains the API  | ||||||
|  | and samples. The runtime is under SteamVR in Tools on Steam.  | ||||||
|  | 
 | ||||||
|  | ### Documentation | ||||||
|  | 
 | ||||||
|  | Documentation for the API is available on the [GitHub Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation) | ||||||
|  | 
 | ||||||
|  | More information on OpenVR and SteamVR can be found on http://steamvr.com | ||||||
							
								
								
									
										9
									
								
								Toolchain-clang.cmake
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Toolchain-clang.cmake
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | set(CMAKE_SYSTEM_NAME Linux) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_C_COMPILER clang) | ||||||
|  | set(CMAKE_CXX_COMPILER clang++) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||||||
|  | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||||||
|  | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||||||
|  | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | ||||||
							
								
								
									
										5624
									
								
								headers/openvr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5624
									
								
								headers/openvr.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										8220
									
								
								headers/openvr_api.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8220
									
								
								headers/openvr_api.cs
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										5761
									
								
								headers/openvr_api.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5761
									
								
								headers/openvr_api.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										3117
									
								
								headers/openvr_capi.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3117
									
								
								headers/openvr_capi.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										4212
									
								
								headers/openvr_driver.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4212
									
								
								headers/openvr_driver.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										116
									
								
								src/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -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() | ||||||
							
								
								
									
										18
									
								
								src/Info.plist
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Info.plist
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<key>CFBundleIdentifier</key> | ||||||
|  | 	<string>com.valvesoftware.OpenVR.framework</string> | ||||||
|  | 	<key>CFBundleInfoDictionaryVersion</key> | ||||||
|  | 	<string>6.0</string> | ||||||
|  | 	<key>CFBundleName</key> | ||||||
|  | 	<string>OpenVR</string> | ||||||
|  | 	<key>CFBundlePackageType</key> | ||||||
|  | 	<string>FMWK</string> | ||||||
|  | 	<key>CFBundleShortVersionString</key> | ||||||
|  | 	<string>1.0</string> | ||||||
|  | 	<key>CFBundleVersion</key> | ||||||
|  | 	<string>1.0</string> | ||||||
|  | </dict> | ||||||
|  | </plist> | ||||||
							
								
								
									
										39
									
								
								src/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -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` | ||||||
							
								
								
									
										35
									
								
								src/ivrclientcore.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/ivrclientcore.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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"; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										284
									
								
								src/json/json-forwards.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								src/json/json-forwards.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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
									
								
								src/json/json.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2077
									
								
								src/json/json.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										5266
									
								
								src/jsoncpp.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5266
									
								
								src/jsoncpp.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										11
									
								
								src/openvr.pc.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/openvr.pc.in
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | prefix=@CMAKE_INSTALL_PREFIX@ | ||||||
|  | exec_prefix=${prefix} | ||||||
|  | libdir=${prefix}/lib | ||||||
|  | includedir=${prefix}/include/openvr | ||||||
|  | 
 | ||||||
|  | Name: openvr | ||||||
|  | Description: OpenVR is an API and runtime that allos access to VR hardware. | ||||||
|  | Version: @OPENVR_VERSION@ | ||||||
|  | 
 | ||||||
|  | Libs: -L${libdir} -lopenvr_api -ldl | ||||||
|  | Cflags: -I${includedir} | ||||||
							
								
								
									
										353
									
								
								src/openvr_api_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								src/openvr_api_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,353 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #define VR_API_EXPORT 1 | ||||||
|  | #include "openvr.h" | ||||||
|  | #include "ivrclientcore.h" | ||||||
|  | #include <vrcore/pathtools_public.h> | ||||||
|  | #include <vrcore/sharedlibtools_public.h> | ||||||
|  | #include <vrcore/envvartools_public.h> | ||||||
|  | #include "hmderrors_public.h" | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <vrcore/vrpathregistry_public.h> | ||||||
|  | #include <mutex> | ||||||
|  | 
 | ||||||
|  | using vr::EVRInitError; | ||||||
|  | using vr::IVRSystem; | ||||||
|  | using vr::IVRClientCore; | ||||||
|  | using vr::VRInitError_None; | ||||||
|  | 
 | ||||||
|  | // figure out how to import from the VR API dll
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  | 
 | ||||||
|  | #if !defined(OPENVR_BUILD_STATIC) | ||||||
|  | #define VR_EXPORT_INTERFACE extern "C" __declspec( dllexport ) | ||||||
|  | #else | ||||||
|  | #define VR_EXPORT_INTERFACE extern "C" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__) | ||||||
|  | 
 | ||||||
|  | #define VR_EXPORT_INTERFACE extern "C" __attribute__((visibility("default"))) | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | #error "Unsupported Platform." | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 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 !defined( VR_API_PUBLIC ) | ||||||
|  | 	CleanupInternalInterfaces(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	if ( g_pHmdSystem ) | ||||||
|  | 	{ | ||||||
|  | 		g_pHmdSystem->Cleanup(); | ||||||
|  | 		g_pHmdSystem = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ( g_pVRModule ) | ||||||
|  | 	{ | ||||||
|  | 		SharedLib_Unload( g_pVRModule ); | ||||||
|  | 		g_pVRModule = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	++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 ) || defined( LINUXARM64 ) | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // -------------------------------------------------------------------------------
 | ||||||
|  | // Purpose: This is the old Runtime Path interface that is no longer exported in the
 | ||||||
|  | //			latest header. We still want to export it from the DLL, though, so updating
 | ||||||
|  | //			to a new DLL doesn't break old compiled code. This version was not thread 
 | ||||||
|  | //			safe and could change the buffer pointer to by a previous result on a 
 | ||||||
|  | //			subsequent call
 | ||||||
|  | // -------------------------------------------------------------------------------
 | ||||||
|  | VR_EXPORT_INTERFACE const char *VR_CALLTYPE VR_RuntimePath(); | ||||||
|  | 
 | ||||||
|  | /** Returns where OpenVR runtime is installed. */ | ||||||
|  | const char *VR_RuntimePath() | ||||||
|  | { | ||||||
|  | 	static char rchBuffer[1024]; | ||||||
|  | 	uint32_t unRequiredSize; | ||||||
|  | 	if ( VR_GetRuntimePath( rchBuffer, sizeof( rchBuffer ), &unRequiredSize ) && unRequiredSize < sizeof( rchBuffer ) ) | ||||||
|  | 	{ | ||||||
|  | 		return rchBuffer; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		return nullptr; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** Returns where OpenVR runtime is installed. */ | ||||||
|  | bool VR_GetRuntimePath( char *pchPathBuffer, uint32_t unBufferSize, uint32_t *punRequiredBufferSize ) | ||||||
|  | { | ||||||
|  | 	// otherwise we need to do a bit more work
 | ||||||
|  | 	std::string sRuntimePath; | ||||||
|  | 
 | ||||||
|  | 	*punRequiredBufferSize = 0; | ||||||
|  | 
 | ||||||
|  | 	bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, nullptr, nullptr, nullptr, nullptr ); | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*punRequiredBufferSize = (uint32_t)sRuntimePath.size() + 1; | ||||||
|  | 	if ( sRuntimePath.size() >= unBufferSize ) | ||||||
|  | 	{ | ||||||
|  | 		*pchPathBuffer = '\0'; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		strcpy_safe( pchPathBuffer, unBufferSize, sRuntimePath.c_str() ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** 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 ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										101
									
								
								src/vrcommon/dirtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/vrcommon/dirtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,101 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #include <vrcore/dirtools_public.h> | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <vrcore/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 | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										17
									
								
								src/vrcommon/dirtools_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/vrcommon/dirtools_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | //========= 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 ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										88
									
								
								src/vrcommon/envvartools_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/vrcommon/envvartools_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #include <vrcore/envvartools_public.h> | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string> | ||||||
|  | #include <cctype> | ||||||
|  | 
 | ||||||
|  | #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 GetEnvironmentVariableAsBool( const char *pchVarName, bool bDefault ) | ||||||
|  | { | ||||||
|  | 	std::string sValue = GetEnvironmentVariable( pchVarName ); | ||||||
|  | 
 | ||||||
|  | 	if ( sValue.empty() ) | ||||||
|  | 	{ | ||||||
|  | 		return bDefault; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sValue = StringToLower( sValue ); | ||||||
|  | 	std::string sYesValues[] = { "y", "yes", "true" }; | ||||||
|  | 	std::string sNoValues[] = { "n", "no", "false" }; | ||||||
|  | 
 | ||||||
|  | 	for ( std::string &sMatch : sYesValues ) | ||||||
|  | 	{ | ||||||
|  | 		if ( sMatch == sValue ) | ||||||
|  | 		{ | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for ( std::string &sMatch : sNoValues ) | ||||||
|  | 	{ | ||||||
|  | 		if ( sMatch == sValue ) | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ( std::isdigit( sValue.at(0) ) ) | ||||||
|  | 	{ | ||||||
|  | 		return atoi( sValue.c_str() ) != 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fprintf( stderr, | ||||||
|  | 			 "GetEnvironmentVariableAsBool(%s): Unable to parse value '%s', using default %d\n", | ||||||
|  | 			 pchVarName, sValue.c_str(), bDefault ); | ||||||
|  | 	return bDefault; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/vrcommon/envvartools_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/vrcommon/envvartools_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | std::string GetEnvironmentVariable( const char *pchVarName ); | ||||||
|  | bool GetEnvironmentVariableAsBool( const char *pchVarName, bool bDefault ); | ||||||
|  | bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue ); | ||||||
							
								
								
									
										338
									
								
								src/vrcommon/hmderrors_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								src/vrcommon/hmderrors_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,338 @@ | ||||||
|  | //========= 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_Driver_HmdDisplayNotFoundLaptop:		return "On laptop, HMD detected over USB, but Monitor not found (213)"; | ||||||
|  | 
 | ||||||
|  | 	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_IPC_ConnectFailedAfterTargetExited:		return "Shared IPC Connect Failed After Target Exited (309)"; | ||||||
|  | 	case VRInitError_IPC_NamespaceUnavailable:					return "Shared IPC Namespace Unavailable (310)"; | ||||||
|  | 
 | ||||||
|  | 	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)"; | ||||||
|  | 	case VRInitError_VendorSpecific_OculusRuntimeBadInstall:		return "Unable to connect to Oculus Runtime, possible bad install (1114)"; | ||||||
|  | 
 | ||||||
|  | 	// 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_Init_FailedForVrMonitor); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_PropertyManagerInitFailed ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_WebServerFailed ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_IllegalTypeTransition ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_MismatchedRuntimes ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidProcessId ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_VRServiceStartupFailed ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_PrismNeedsNewDrivers ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_PrismStartupTimedOut ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_CouldNotStartPrism ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_CreateDriverDirectDeviceFailed ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Init_PrismExitedUnexpectedly ); | ||||||
|  | 
 | ||||||
|  | 		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_Driver_HmdDisplayNotFoundLaptop ); | ||||||
|  | 
 | ||||||
|  | 		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_IPC_ConnectFailedAfterTargetExited ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_IPC_NamespaceUnavailable ); | ||||||
|  | 
 | ||||||
|  | 		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_CreateOverlayVertexBuffer ); | ||||||
|  | 		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 ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateMirrorOverlay ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateVirtualDisplayBackbuffer ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_DisplayModeNotSupported ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayInvalidCall ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayAlreadyInitialized ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateMailbox ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_WindowInterfaceIsNull ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_SystemLayerCreateInstance ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_Compositor_SystemLayerCreateSession ); | ||||||
|  | 
 | ||||||
|  | 		// Vendor-specific errors
 | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_UnableToConnectToOculusRuntime); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_WindowsNotInDevMode ); | ||||||
|  | 		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_OculusRuntimeBadInstall ); | ||||||
|  | 
 | ||||||
|  | 		// 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; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										6
									
								
								src/vrcommon/hmderrors_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/vrcommon/hmderrors_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | const char *GetEnglishStringForHmdError( vr::EVRInitError eError ); | ||||||
|  | const char *GetIDForVRInitError( vr::EVRInitError eError ); | ||||||
|  | 
 | ||||||
							
								
								
									
										988
									
								
								src/vrcommon/pathtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										988
									
								
								src/vrcommon/pathtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,988 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <vrcore/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> | ||||||
|  | #include <alloca.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(); | ||||||
|  | 			//Not sure why the following line of code was used for a while.  It causes problems with strlen.
 | ||||||
|  | 			//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 true if these two paths are the same without respect for internal . or ..
 | ||||||
|  | * sequences, slash type, or case (on case-insensitive platforms). */ | ||||||
|  | bool Path_IsSamePath( const std::string & sPath1, const std::string & sPath2 ) | ||||||
|  | { | ||||||
|  | 	std::string sCompact1 = Path_Compact( sPath1 ); | ||||||
|  | 	std::string sCompact2 = Path_Compact( sPath2 ); | ||||||
|  | #if defined(WIN32) | ||||||
|  | 	return !stricmp( sCompact1.c_str(), sCompact2.c_str() ); | ||||||
|  | #else | ||||||
|  | 	return !strcmp( sCompact1.c_str(), sCompact2.c_str() ); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** 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
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | std::vector<uint8_t> Path_ReadBinaryFile( const std::string & strFilename ) | ||||||
|  | { | ||||||
|  | 	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 | ||||||
|  | 
 | ||||||
|  | 	std::vector<uint8_t> vecFileContents; | ||||||
|  | 
 | ||||||
|  | 	if ( f != NULL ) | ||||||
|  | 	{ | ||||||
|  | 		fseek( f, 0, SEEK_END ); | ||||||
|  | 		int size = ftell( f ); | ||||||
|  | 		fseek( f, 0, SEEK_SET ); | ||||||
|  | 
 | ||||||
|  | 		vecFileContents.resize( size ); | ||||||
|  | 		if ( fread( &vecFileContents[ 0 ], size, 1, f ) == 1 ) | ||||||
|  | 		{ | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			vecFileContents.clear(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fclose( f ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return vecFileContents ; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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, '/' ); | ||||||
|  | 
 | ||||||
|  | 		size_t unBufferSize = sAbsolute.length() * 3; | ||||||
|  | 		char *pchBuffer = (char *)alloca( unBufferSize ); | ||||||
|  | 		V_URLEncodeFullPath( pchBuffer, (int)unBufferSize, sAbsolute.c_str(), (int)sAbsolute.length() ); | ||||||
|  | 
 | ||||||
|  | 		return std::string( FILE_URL_PREFIX ) + pchBuffer; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // -----------------------------------------------------------------------------------------------------
 | ||||||
|  | // 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 ) ) ) | ||||||
|  | 	{ | ||||||
|  | 		char *pchBuffer = (char *)alloca( sFileUrl.length() ); | ||||||
|  | 		V_URLDecodeNoPlusForSpace( pchBuffer, (int)sFileUrl.length(),  | ||||||
|  | 			sFileUrl.c_str() + strlen( FILE_URL_PREFIX ), (int)( sFileUrl.length() - strlen( FILE_URL_PREFIX ) ) ); | ||||||
|  | 
 | ||||||
|  | 		return Path_FixSlashes( pchBuffer ); | ||||||
|  | 	} | ||||||
|  | 	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 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // -----------------------------------------------------------------------------------------------------
 | ||||||
|  | // Limits the set of characters that are allowed in filenames
 | ||||||
|  | // -----------------------------------------------------------------------------------------------------
 | ||||||
|  | std::string Path_SanitizeFilename( const std::string& sFilename ) | ||||||
|  | { | ||||||
|  | 	std::string sFixed = sFilename; | ||||||
|  | 	std::string::iterator iLastDot = sFixed.end(); | ||||||
|  | 	for ( std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++ ) | ||||||
|  | 	{ | ||||||
|  | 		if ( *i == '.' ) | ||||||
|  | 		{ | ||||||
|  | 			iLastDot = i; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// path-related characters are forbidden (except the last period)
 | ||||||
|  | 		switch ( *i ) | ||||||
|  | 		{ | ||||||
|  | 			case '\0': | ||||||
|  | 			case '.': | ||||||
|  | 			case '\\': | ||||||
|  | 			case '/': | ||||||
|  | 			case ':': | ||||||
|  | 			case '|': | ||||||
|  | 			case '?': | ||||||
|  | 			case '>': | ||||||
|  | 			case '<': | ||||||
|  | 			case '&': | ||||||
|  | 			case '%': | ||||||
|  | 			case '@': | ||||||
|  | 			case '$': | ||||||
|  | 			case '*': | ||||||
|  | 			case '\"': | ||||||
|  | 				*i = '_'; | ||||||
|  | 				break; | ||||||
|  | 
 | ||||||
|  | 			default: | ||||||
|  | 				if ( *i < 32 ) | ||||||
|  | 				{ | ||||||
|  | 					*i = '_'; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ( iLastDot != sFixed.end() && iLastDot != sFixed.begin()  | ||||||
|  | 		&& iLastDot+1 != sFixed.end() ) | ||||||
|  | 	{ | ||||||
|  | 		*iLastDot = '.'; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sFixed; | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								src/vrcommon/pathtools_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/vrcommon/pathtools_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | #include <vector> | ||||||
|  | #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 ); | ||||||
|  | 
 | ||||||
|  | /** Returns true if these two paths are the same without respect for internal . or ..
 | ||||||
|  | * sequences, slash type, or case (on case-insensitive platforms). */ | ||||||
|  | bool Path_IsSamePath( const std::string & sPath1, const std::string & sPath2 ); | ||||||
|  | 
 | ||||||
|  | //** 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 ); | ||||||
|  | std::vector<uint8_t> Path_ReadBinaryFile( const std::string & strFilename ); | ||||||
|  | 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 ); | ||||||
|  | 
 | ||||||
|  | std::string Path_SanitizeFilename( const std::string& sFilename ); | ||||||
|  | 
 | ||||||
|  | #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" | ||||||
|  | #elif defined( ANDROIDARM64 ) | ||||||
|  | #define PLATSUBDIR	"androidarm64"  | ||||||
|  | #elif defined( LINUXARM64 ) | ||||||
|  | #define PLATSUBDIR	"linuxarm64"  | ||||||
|  | #else | ||||||
|  | #define PLATSUBDIR	"linux64" | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  | #warning "Unknown platform for PLATSUBDIR" | ||||||
|  | #define PLATSUBDIR	"unknown_platform" | ||||||
|  | #endif | ||||||
							
								
								
									
										63
									
								
								src/vrcommon/sharedlibtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/vrcommon/sharedlibtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #include <vrcore/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, uint32_t *pErrorCode ) | ||||||
|  | { | ||||||
|  | 	SharedLibHandle pHandle = nullptr; | ||||||
|  | #if defined( _WIN32) | ||||||
|  | 	pHandle = ( SharedLibHandle )LoadLibraryEx( pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); | ||||||
|  | #elif defined(POSIX) | ||||||
|  | 	pHandle = (SharedLibHandle) dlopen(pchPath, RTLD_LOCAL|RTLD_NOW); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	if ( pErrorCode ) | ||||||
|  | 	{ | ||||||
|  | 		if ( pHandle == nullptr ) | ||||||
|  | 		{ | ||||||
|  | #if defined( _WIN32) | ||||||
|  | 			*pErrorCode = ( uint32_t ) GetLastError(); | ||||||
|  | #elif defined(POSIX) | ||||||
|  | 			*pErrorCode = 1; | ||||||
|  | #endif | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			*pErrorCode = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return pHandle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										12
									
								
								src/vrcommon/sharedlibtools_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/vrcommon/sharedlibtools_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | typedef void *SharedLibHandle; | ||||||
|  | 
 | ||||||
|  | SharedLibHandle SharedLib_Load( const char *pchPath, uint32_t *pErrorCode = nullptr ); | ||||||
|  | void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName); | ||||||
|  | void SharedLib_Unload( SharedLibHandle lib ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										606
									
								
								src/vrcommon/strtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										606
									
								
								src/vrcommon/strtools_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,606 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <sstream> | ||||||
|  | #include <codecvt> | ||||||
|  | #include <iostream> | ||||||
|  | #include <functional> | ||||||
|  | #include <locale> | ||||||
|  | #include <codecvt> | ||||||
|  | #include <vrcore/assert.h> | ||||||
|  | 
 | ||||||
|  | #if defined( _WIN32 ) | ||||||
|  | #include <windows.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if defined( OSX ) || defined( LINUX ) | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose:  stricmp -> strcasecmp bridge
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | int stricmp( const char *pStr1, const char *pStr2 ) | ||||||
|  | { | ||||||
|  | 	return strcasecmp( pStr1, pStr2 ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose: strincmp -> strncasecmp bridge
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) | ||||||
|  | { | ||||||
|  | 	return strncasecmp( pStr1, pStr2, unBufferLen ); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // 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:
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | typedef std::codecvt_utf8< wchar_t > convert_type; | ||||||
|  | 
 | ||||||
|  | std::string UTF16to8(const wchar_t * in) | ||||||
|  | { | ||||||
|  | 	static std::wstring_convert< convert_type, wchar_t > s_converter;  // construction of this can be expensive (or even serialized) depending on locale
 | ||||||
|  | 
 | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		return s_converter.to_bytes( in ); | ||||||
|  | 	} | ||||||
|  | 	catch ( ... ) | ||||||
|  | 	{ | ||||||
|  | 		return std::string(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string UTF16to8( const std::wstring & in ) { return UTF16to8( in.c_str() ); } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | std::wstring UTF8to16(const char * in) | ||||||
|  | { | ||||||
|  | 	static std::wstring_convert< convert_type, wchar_t > s_converter;  // construction of this can be expensive (or even serialized) depending on locale
 | ||||||
|  | 
 | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		return s_converter.from_bytes( in ); | ||||||
|  | 	} | ||||||
|  | 	catch ( ... ) | ||||||
|  | 	{ | ||||||
|  | 		return std::wstring(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::wstring UTF8to16( const std::string & in ) { return UTF8to16( in.c_str() ); } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose: Format string to std::string converter
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | std::string Format( const char *pchFormat, ... ) | ||||||
|  | { | ||||||
|  | 	static constexpr size_t k_ulMaxStackString = 4096; | ||||||
|  | 
 | ||||||
|  | 	va_list args; | ||||||
|  | 	char pchBuffer[k_ulMaxStackString]; | ||||||
|  | 
 | ||||||
|  | 	va_start( args, pchFormat ); | ||||||
|  | 	int unSize = vsnprintf( pchBuffer, sizeof( pchBuffer ), pchFormat, args ); | ||||||
|  | 	va_end( args ); | ||||||
|  | 
 | ||||||
|  | 	// Something went fairly wrong
 | ||||||
|  | 	if ( unSize < 0 ) | ||||||
|  | 	{ | ||||||
|  | 		AssertMsg( false, "Format string parse failure" ); | ||||||
|  | 		return ""; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Processing on the stack worked, success
 | ||||||
|  | 	if ( unSize < k_ulMaxStackString ) | ||||||
|  | 	{ | ||||||
|  | 		return pchBuffer; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// If processing on the stack failed, fallback to a dynamic allocation
 | ||||||
|  | 	std::vector< char > vecChar{}; | ||||||
|  | 	vecChar.resize( unSize + 1 ); | ||||||
|  | 
 | ||||||
|  | 	va_start( args, pchFormat ); | ||||||
|  | 	unSize = vsnprintf( vecChar.data(), vecChar.size(), pchFormat, args ); | ||||||
|  | 	va_end( args ); | ||||||
|  | 
 | ||||||
|  | 	// Double check, just in case
 | ||||||
|  | 	if ( unSize < 0 ) | ||||||
|  | 	{ | ||||||
|  | 		AssertMsg( false, "Format string parse failure" ); | ||||||
|  | 		return ""; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return vecChar.data(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #if defined( _WIN32 ) | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose: Convert LPSTR in the default CodePage to UTF8
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | std::string DefaultACPtoUTF8( const char *pszStr ) | ||||||
|  | { | ||||||
|  | 	if ( GetACP() == CP_UTF8 ) | ||||||
|  | 	{ | ||||||
|  | 		return pszStr; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		std::vector<wchar_t> vecBuf( strlen( pszStr ) + 1 ); // should be guaranteed to be enough
 | ||||||
|  | 		MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszStr, -1, vecBuf.data(), (int) vecBuf.size() ); | ||||||
|  | 		return UTF16to8( vecBuf.data() ); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | // --------------------------------------------------------------------
 | ||||||
|  | // Purpose:
 | ||||||
|  | // --------------------------------------------------------------------
 | ||||||
|  | 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: These define the set of characters to filter for components (which
 | ||||||
|  | //			need all the escaping we can muster) vs. paths (which don't want
 | ||||||
|  | //			/ and : escaped so we don't break less compliant URL handling code.
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | static bool CharNeedsEscape_Component( const char c ) | ||||||
|  | { | ||||||
|  | 	return (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9') | ||||||
|  | 		&& c != '-' && c != '_' && c != '.'); | ||||||
|  | } | ||||||
|  | static bool CharNeedsEscape_FullPath( const char c ) | ||||||
|  | { | ||||||
|  | 	return (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9') | ||||||
|  | 		&& c != '-' && c != '_' && c != '.' && c != '/' && c != ':' ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // 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, std::function< bool(const char)> fnNeedsEscape ) | ||||||
|  | { | ||||||
|  | 	//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 ( fnNeedsEscape( 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, CharNeedsEscape_Component ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void V_URLEncodeNoPlusForSpace( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ) | ||||||
|  | { | ||||||
|  | 	return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, false, CharNeedsEscape_Component ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void V_URLEncodeFullPath( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ) | ||||||
|  | { | ||||||
|  | 	return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, false, CharNeedsEscape_FullPath ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // 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 ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t V_URLDecodeNoPlusForSpace( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen ) | ||||||
|  | { | ||||||
|  | 	return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, false ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | 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 ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ( !sString.empty() && sString.back() == cToken ) | ||||||
|  | 	{ | ||||||
|  | 		vecStrings.push_back( "" ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return vecStrings; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose: Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | bool RepairUTF8( const char *pbegin, const char *pend, std::string & sOutputUtf8 ) | ||||||
|  | { | ||||||
|  | 	typedef std::codecvt_utf8<char32_t> facet_type; | ||||||
|  | 	facet_type myfacet; | ||||||
|  | 
 | ||||||
|  | 	std::mbstate_t mystate = std::mbstate_t(); | ||||||
|  | 
 | ||||||
|  | 	sOutputUtf8.clear(); | ||||||
|  | 	sOutputUtf8.reserve( pend - pbegin ); | ||||||
|  | 	bool bSqueakyClean = true; | ||||||
|  | 
 | ||||||
|  | 	const char *pmid = pbegin; | ||||||
|  | 	while ( pmid != pend ) | ||||||
|  | 	{ | ||||||
|  | 		bool bHasError = false; | ||||||
|  | 		bool bHasValidData = false; | ||||||
|  | 
 | ||||||
|  | 		char32_t out = 0xdeadbeef, *pout; | ||||||
|  | 		pbegin = pmid; | ||||||
|  | 		switch ( myfacet.in( mystate, pbegin, pend, pmid, &out, &out + 1, pout ) ) | ||||||
|  | 		{ | ||||||
|  | 		case facet_type::ok: | ||||||
|  | 			bHasValidData = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case facet_type::noconv: | ||||||
|  | 			// unexpected! always converting type
 | ||||||
|  | 			bSqueakyClean = false; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case facet_type::partial: | ||||||
|  | 			bHasError = pbegin == pmid; | ||||||
|  | 			if ( bHasError ) | ||||||
|  | 			{ | ||||||
|  | 				bSqueakyClean = false; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				bHasValidData = true; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case facet_type::error: | ||||||
|  | 			bHasError = true; | ||||||
|  | 			bSqueakyClean = false; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ( bHasValidData ) | ||||||
|  | 		{ | ||||||
|  | 			// could convert back, but no need
 | ||||||
|  | 			for ( const char *p = pbegin; p != pmid; ++p ) | ||||||
|  | 			{ | ||||||
|  | 				sOutputUtf8 += *p; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ( bHasError ) | ||||||
|  | 		{ | ||||||
|  | 			sOutputUtf8 += '?'; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ( pmid == pbegin ) | ||||||
|  | 		{ | ||||||
|  | 			pmid++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return bSqueakyClean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // Purpose: Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | bool RepairUTF8( const std::string & sInputUtf8, std::string & sOutputUtf8 ) | ||||||
|  | { | ||||||
|  | 	return RepairUTF8( sInputUtf8.data(), sInputUtf8.data() + sInputUtf8.size(), sOutputUtf8 ); | ||||||
|  | } | ||||||
							
								
								
									
										154
									
								
								src/vrcommon/strtools_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/vrcommon/strtools_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | ||||||
|  | //========= 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 ); | ||||||
|  | std::string UTF16to8( const std::wstring & in ); | ||||||
|  | 
 | ||||||
|  | /** converts a UTF-8 string to a UTF-16 string */ | ||||||
|  | std::wstring UTF8to16(const char * in); | ||||||
|  | std::wstring UTF8to16( const std::string & in ); | ||||||
|  | #define Utf16FromUtf8 UTF8to16 | ||||||
|  | 
 | ||||||
|  | #if defined( _WIN32 ) | ||||||
|  | std::string DefaultACPtoUTF8( const char *pszStr ); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /** Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere */ | ||||||
|  | bool RepairUTF8( const char *begin, const char *end, std::string & sOutputUtf8 ); | ||||||
|  | bool RepairUTF8( const std::string & sInputUtf8, std::string & sOutputUtf8 ); | ||||||
|  | 
 | ||||||
|  | /** 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 ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Turns printf-style format args into a std::string */ | ||||||
|  | std::string Format( const char *pchFormat, ... ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** 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 ) | ||||||
|  | int stricmp(const char *pStr1, const char *pStr2); | ||||||
|  | #ifndef _stricmp | ||||||
|  | #define _stricmp stricmp | ||||||
|  | #endif | ||||||
|  | int strnicmp( const char *pStr1, const char *pStr2, size_t 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 ); | ||||||
|  | 
 | ||||||
|  | /** Same as V_URLEncode, but without plus for space. */ | ||||||
|  | void V_URLEncodeNoPlusForSpace( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ); | ||||||
|  | 
 | ||||||
|  | /** Same as V_URLEncodeNoPlusForSpace, but without escaping / and : */ | ||||||
|  | void V_URLEncodeFullPath( 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 ); | ||||||
|  | 
 | ||||||
|  | /** Same as V_URLDecode, but without plus for space. */ | ||||||
|  | size_t V_URLDecodeNoPlusForSpace( 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 ); | ||||||
							
								
								
									
										483
									
								
								src/vrcommon/vrpathregistry_public.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										483
									
								
								src/vrcommon/vrpathregistry_public.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,483 @@ | ||||||
|  | //========= Copyright Valve Corporation ============//
 | ||||||
|  | 
 | ||||||
|  | #include <vrcore/vrpathregistry_public.h> | ||||||
|  | #include <json/json.h> | ||||||
|  | #include <vrcore/pathtools_public.h> | ||||||
|  | #include <vrcore/envvartools_public.h> | ||||||
|  | #include <vrcore/strtools_public.h> | ||||||
|  | #include <vrcore/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> | ||||||
|  | #include <sstream> | ||||||
|  | 
 | ||||||
|  | #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 sOverridePath = GetEnvironmentVariable( "VR_PATHREG_OVERRIDE" ); | ||||||
|  | 	if ( !sOverridePath.empty() ) | ||||||
|  | 		return sOverridePath; | ||||||
|  | 
 | ||||||
|  | 	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 *psLoadError ) | ||||||
|  | { | ||||||
|  | 	std::string sRegPath = GetVRPathRegistryFilename(); | ||||||
|  | 	if( sRegPath.empty() ) | ||||||
|  | 	{ | ||||||
|  | 		if ( psLoadError ) | ||||||
|  | 		{ | ||||||
|  | 			*psLoadError = "Unable to determine VR Path Registry filename"; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	std::string sRegistryContents = Path_ReadTextFile( sRegPath ); | ||||||
|  | 	if( sRegistryContents.empty() ) | ||||||
|  | 	{ | ||||||
|  | 		if ( psLoadError ) | ||||||
|  | 		{ | ||||||
|  | 			*psLoadError = "Unable to read VR Path Registry from " + sRegPath; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Json::Value root; | ||||||
|  | 	Json::CharReaderBuilder builder; | ||||||
|  | 	std::istringstream istream( sRegistryContents ); | ||||||
|  | 	std::string sErrors; | ||||||
|  | 
 | ||||||
|  | 	try { | ||||||
|  | 		if ( !parseFromStream( builder, istream, &root, &sErrors ) ) | ||||||
|  | 		{ | ||||||
|  | 			if ( psLoadError ) | ||||||
|  | 			{ | ||||||
|  | 				*psLoadError = "Unable to parse " + sRegPath + ": " + sErrors; | ||||||
|  | 			} | ||||||
|  | 			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" ); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	catch ( ... ) | ||||||
|  | 	{ | ||||||
|  | 		if ( psLoadError ) | ||||||
|  | 		{ | ||||||
|  | 			*psLoadError = "Unable to parse " + sRegPath + ": exception thrown in JSON library"; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // ---------------------------------------------------------------------------
 | ||||||
|  | // Purpose: Saves the config file to its well known location
 | ||||||
|  | // ---------------------------------------------------------------------------
 | ||||||
|  | bool CVRPathRegistry_Public::BSaveToFile() const | ||||||
|  | { | ||||||
|  | 	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::StreamWriterBuilder builder; | ||||||
|  | 	std::string sRegistryContents = Json::writeString( builder, 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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // ---------------------------------------------------------------------------
 | ||||||
|  | // 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 ) | ||||||
|  | { | ||||||
|  | 	std::string sLoadError; | ||||||
|  | 	CVRPathRegistry_Public pathReg; | ||||||
|  | 	bool bLoadedRegistry = pathReg.BLoadFromFile( &sLoadError ); | ||||||
|  | 	int nCountEnvironmentVariables = 0; | ||||||
|  | 	int nRequestedPaths = 0; | ||||||
|  | 
 | ||||||
|  | 	if( psRuntimePath ) | ||||||
|  | 	{ | ||||||
|  | 		nRequestedPaths++; | ||||||
|  | 		if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 ) | ||||||
|  | 		{ | ||||||
|  | 			*psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar ); | ||||||
|  | 			nCountEnvironmentVariables++; | ||||||
|  | 		} | ||||||
|  | 		else if( !pathReg.GetRuntimePath().empty() ) | ||||||
|  | 		{ | ||||||
|  | 			*psRuntimePath = pathReg.GetRuntimePath(); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			*psRuntimePath = ""; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if( psConfigPath ) | ||||||
|  | 	{ | ||||||
|  | 		nRequestedPaths++; | ||||||
|  | 		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 ) | ||||||
|  | 	{ | ||||||
|  | 		nRequestedPaths++; | ||||||
|  | 		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 == nRequestedPaths ) | ||||||
|  | 	{ | ||||||
|  | 		// all three environment variables were set, so we don't need the physical file
 | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	else if( !bLoadedRegistry ) | ||||||
|  | 	{ | ||||||
|  | 		VRLog( "%s\n", sLoadError.c_str() ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return bLoadedRegistry; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | uint32_t CVRPathRegistry_Public::GetSteamAppId() | ||||||
|  | { | ||||||
|  | #if !defined( REL_BRANCH_ONLY ) | ||||||
|  | 	uint32_t nSteamAppId = k_unSteamVRMainAppId; | ||||||
|  | #else | ||||||
|  | 	uint32_t nSteamAppId = k_unSteamVRAppId; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	return nSteamAppId; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | bool CVRPathRegistry_Public::IsSteamVRMain() | ||||||
|  | { | ||||||
|  | #if defined( REL_BRANCH_ONLY ) | ||||||
|  | 	return false; | ||||||
|  | #else | ||||||
|  | 	return true; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | uint32_t CVRPathRegistry_Public::InitSteamAppId() | ||||||
|  | { | ||||||
|  | 	uint32_t nSteamAppId = CVRPathRegistry_Public::GetSteamAppId(); | ||||||
|  | 
 | ||||||
|  | 	// Forcefully setting to what it should be before SteamAPI_Init() since SteamVR is more often
 | ||||||
|  | 	// started as child processes of the game app and otherwise Steam then considers us as the
 | ||||||
|  | 	// wrong app id.
 | ||||||
|  | 	SetEnvironmentVariable( "SteamAppId", std::to_string( nSteamAppId ).c_str() ); | ||||||
|  | 	SetEnvironmentVariable( "SteamGameId", std::to_string( nSteamAppId ).c_str() ); | ||||||
|  | 
 | ||||||
|  | 	return nSteamAppId; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										52
									
								
								src/vrcommon/vrpathregistry_public.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/vrcommon/vrpathregistry_public.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | ||||||
|  | //========= 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"; | ||||||
|  | 
 | ||||||
|  | static const uint32_t k_unSteamVRAppId = 250820; | ||||||
|  | static const uint32_t k_unSteamVRMainAppId = 330050; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class CVRPathRegistry_Public | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	static std::string GetVRPathRegistryFilename(); | ||||||
|  | 	static std::string GetOpenVRConfigPath(); | ||||||
|  | 	static uint32_t GetSteamAppId(); | ||||||
|  | 	static bool IsSteamVRMain(); | ||||||
|  | 	static uint32_t InitSteamAppId(); | ||||||
|  | 
 | ||||||
|  | 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( std::string *psError = nullptr ); | ||||||
|  | 	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; | ||||||
|  | }; | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue