/* Copyright (c) 2022, NVIDIA 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: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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. */ // These are helper functions for the SDK samples (string parsing, timers, etc) #ifndef COMMON_HELPER_STRING_H_ #define COMMON_HELPER_STRING_H_ #include #include #include #include #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE #endif #ifndef STRCASECMP #define STRCASECMP _stricmp #endif #ifndef STRNCASECMP #define STRNCASECMP _strnicmp #endif #ifndef STRCPY #define STRCPY(sFilePath, nLength, sPath) strcpy_s(sFilePath, nLength, sPath) #endif #ifndef FOPEN #define FOPEN(fHandle, filename, mode) fopen_s(&fHandle, filename, mode) #endif #ifndef FOPEN_FAIL #define FOPEN_FAIL(result) (result != 0) #endif #ifndef SSCANF #define SSCANF sscanf_s #endif #ifndef SPRINTF #define SPRINTF sprintf_s #endif #else // Linux Includes #include #include #ifndef STRCASECMP #define STRCASECMP strcasecmp #endif #ifndef STRNCASECMP #define STRNCASECMP strncasecmp #endif #ifndef STRCPY #define STRCPY(sFilePath, nLength, sPath) strcpy(sFilePath, sPath) #endif #ifndef FOPEN #define FOPEN(fHandle, filename, mode) (fHandle = fopen(filename, mode)) #endif #ifndef FOPEN_FAIL #define FOPEN_FAIL(result) (result == NULL) #endif #ifndef SSCANF #define SSCANF sscanf #endif #ifndef SPRINTF #define SPRINTF sprintf #endif #endif #ifndef EXIT_WAIVED #define EXIT_WAIVED 2 #endif // CUDA Utility Helper Functions inline int stringRemoveDelimiter(char delimiter, const char *string) { int string_start = 0; while (string[string_start] == delimiter) { string_start++; } if (string_start >= static_cast(strlen(string) - 1)) { return 0; } return string_start; } inline int getFileExtension(char *filename, char **extension) { int string_length = static_cast(strlen(filename)); while (filename[string_length--] != '.') { if (string_length == 0) break; } if (string_length > 0) string_length += 2; if (string_length == 0) *extension = NULL; else *extension = &filename[string_length]; return string_length; } inline bool checkCmdLineFlag(const int argc, const char **argv, const char *string_ref) { bool bFound = false; if (argc >= 1) { for (int i = 1; i < argc; i++) { int string_start = stringRemoveDelimiter('-', argv[i]); const char *string_argv = &argv[i][string_start]; const char *equal_pos = strchr(string_argv, '='); int argv_length = static_cast( equal_pos == 0 ? strlen(string_argv) : equal_pos - string_argv); int length = static_cast(strlen(string_ref)); if (length == argv_length && !STRNCASECMP(string_argv, string_ref, length)) { bFound = true; continue; } } } return bFound; } // This function wraps the CUDA Driver API into a template function template inline bool getCmdLineArgumentValue(const int argc, const char **argv, const char *string_ref, T *value) { bool bFound = false; if (argc >= 1) { for (int i = 1; i < argc; i++) { int string_start = stringRemoveDelimiter('-', argv[i]); const char *string_argv = &argv[i][string_start]; int length = static_cast(strlen(string_ref)); if (!STRNCASECMP(string_argv, string_ref, length)) { if (length + 1 <= static_cast(strlen(string_argv))) { int auto_inc = (string_argv[length] == '=') ? 1 : 0; *value = (T)atoi(&string_argv[length + auto_inc]); } bFound = true; i = argc; } } } return bFound; } inline int getCmdLineArgumentInt(const int argc, const char **argv, const char *string_ref) { bool bFound = false; int value = -1; if (argc >= 1) { for (int i = 1; i < argc; i++) { int string_start = stringRemoveDelimiter('-', argv[i]); const char *string_argv = &argv[i][string_start]; int length = static_cast(strlen(string_ref)); if (!STRNCASECMP(string_argv, string_ref, length)) { if (length + 1 <= static_cast(strlen(string_argv))) { int auto_inc = (string_argv[length] == '=') ? 1 : 0; value = atoi(&string_argv[length + auto_inc]); } else { value = 0; } bFound = true; continue; } } } if (bFound) { return value; } else { return 0; } } inline float getCmdLineArgumentFloat(const int argc, const char **argv, const char *string_ref) { bool bFound = false; float value = -1; if (argc >= 1) { for (int i = 1; i < argc; i++) { int string_start = stringRemoveDelimiter('-', argv[i]); const char *string_argv = &argv[i][string_start]; int length = static_cast(strlen(string_ref)); if (!STRNCASECMP(string_argv, string_ref, length)) { if (length + 1 <= static_cast(strlen(string_argv))) { int auto_inc = (string_argv[length] == '=') ? 1 : 0; value = static_cast(atof(&string_argv[length + auto_inc])); } else { value = 0.f; } bFound = true; continue; } } } if (bFound) { return value; } else { return 0; } } inline bool getCmdLineArgumentString(const int argc, const char **argv, const char *string_ref, char **string_retval) { bool bFound = false; if (argc >= 1) { for (int i = 1; i < argc; i++) { int string_start = stringRemoveDelimiter('-', argv[i]); char *string_argv = const_cast(&argv[i][string_start]); int length = static_cast(strlen(string_ref)); if (!STRNCASECMP(string_argv, string_ref, length)) { *string_retval = &string_argv[length + 1]; bFound = true; continue; } } } if (!bFound) { *string_retval = NULL; } return bFound; } ////////////////////////////////////////////////////////////////////////////// //! Find the path for a file assuming that //! files are found in the searchPath. //! //! @return the path if succeeded, otherwise 0 //! @param filename name of the file //! @param executable_path optional absolute path of the executable ////////////////////////////////////////////////////////////////////////////// inline char *sdkFindFilePath(const char *filename, const char *executable_path) { // defines a variable that is replaced with the name of the // executable // Typical relative search paths to locate needed companion files (e.g. sample // input data, or JIT source files) The origin for the relative search may be // the .exe file, a .bat file launching an .exe, a browser .exe launching the // .exe or .bat, etc const char *searchPath[] = { "./", // same dir "./data/", // same dir "../../../../Samples//", // up 4 in tree "../../../Samples//", // up 3 in tree "../../Samples//", // up 2 in tree "../../../../Samples//data/", // up 4 in tree "../../../Samples//data/", // up 3 in tree "../../Samples//data/", // up 2 in tree "../../../../Samples/0_Introduction//", // up 4 in tree "../../../Samples/0_Introduction//", // up 3 in tree "../../Samples/0_Introduction//", // up 2 in tree "../../../../Samples/1_Utilities//", // up 4 in tree "../../../Samples/1_Utilities//", // up 3 in tree "../../Samples/1_Utilities//", // up 2 in tree "../../../../Samples/2_Concepts_and_Techniques//", // up 4 in tree "../../../Samples/2_Concepts_and_Techniques//", // up 3 in tree "../../Samples/2_Concepts_and_Techniques//", // up 2 in tree "../../../../Samples/3_CUDA_Features//", // up 4 in tree "../../../Samples/3_CUDA_Features//", // up 3 in tree "../../Samples/3_CUDA_Features//", // up 2 in tree "../../../../Samples/4_CUDA_Libraries//", // up 4 in tree "../../../Samples/4_CUDA_Libraries//", // up 3 in tree "../../Samples/4_CUDA_Libraries//", // up 2 in tree "../../../../Samples/5_Domain_Specific//", // up 4 in tree "../../../Samples/5_Domain_Specific//", // up 3 in tree "../../Samples/5_Domain_Specific//", // up 2 in tree "../../../../Samples/6_Performance//", // up 4 in tree "../../../Samples/6_Performance//", // up 3 in tree "../../Samples/6_Performance//", // up 2 in tree "../../../../Samples/0_Introduction//data/", // up 4 in tree "../../../Samples/0_Introduction//data/", // up 3 in tree "../../Samples/0_Introduction//data/", // up 2 in tree "../../../../Samples/1_Utilities//data/", // up 4 in tree "../../../Samples/1_Utilities//data/", // up 3 in tree "../../Samples/1_Utilities//data/", // up 2 in tree "../../../../Samples/2_Concepts_and_Techniques//data/", // up 4 in tree "../../../Samples/2_Concepts_and_Techniques//data/", // up 3 in tree "../../Samples/2_Concepts_and_Techniques//data/", // up 2 in tree "../../../../Samples/3_CUDA_Features//data/", // up 4 in tree "../../../Samples/3_CUDA_Features//data/", // up 3 in tree "../../Samples/3_CUDA_Features//data/", // up 2 in tree "../../../../Samples/4_CUDA_Libraries//data/", // up 4 in tree "../../../Samples/4_CUDA_Libraries//data/", // up 3 in tree "../../Samples/4_CUDA_Libraries//data/", // up 2 in tree "../../../../Samples/5_Domain_Specific//data/", // up 4 in tree "../../../Samples/5_Domain_Specific//data/", // up 3 in tree "../../Samples/5_Domain_Specific//data/", // up 2 in tree "../../../../Samples/6_Performance//data/", // up 4 in tree "../../../Samples/6_Performance//data/", // up 3 in tree "../../Samples/6_Performance//data/", // up 2 in tree "../../../../Common/data/", // up 4 in tree "../../../Common/data/", // up 3 in tree "../../Common/data/" // up 2 in tree }; // Extract the executable name std::string executable_name; if (executable_path != 0) { executable_name = std::string(executable_path); #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) // Windows path delimiter size_t delimiter_pos = executable_name.find_last_of('\\'); executable_name.erase(0, delimiter_pos + 1); if (executable_name.rfind(".exe") != std::string::npos) { // we strip .exe, only if the .exe is found executable_name.resize(executable_name.size() - 4); } #else // Linux & OSX path delimiter size_t delimiter_pos = executable_name.find_last_of('/'); executable_name.erase(0, delimiter_pos + 1); #endif } // Loop over all search paths and return the first hit for (unsigned int i = 0; i < sizeof(searchPath) / sizeof(char *); ++i) { std::string path(searchPath[i]); size_t executable_name_pos = path.find(""); // If there is executable_name variable in the searchPath // replace it with the value if (executable_name_pos != std::string::npos) { if (executable_path != 0) { path.replace(executable_name_pos, strlen(""), executable_name); } else { // Skip this path entry if no executable argument is given continue; } } #ifdef _DEBUG printf("sdkFindFilePath <%s> in %s\n", filename, path.c_str()); #endif // Test if the file exists path.append(filename); FILE *fp; FOPEN(fp, path.c_str(), "rb"); if (fp != NULL) { fclose(fp); // File found // returning an allocated array here for backwards compatibility reasons char *file_path = reinterpret_cast(malloc(path.length() + 1)); STRCPY(file_path, path.length() + 1, path.c_str()); return file_path; } if (fp) { fclose(fp); } } // File not found printf("\nerror: sdkFindFilePath: file <%s> not found!\n", filename); return 0; } #endif // COMMON_HELPER_STRING_H_