diff --git a/include/blt/std/assert.h b/include/blt/std/assert.h index ad7028c..b29db63 100644 --- a/include/blt/std/assert.h +++ b/include/blt/std/assert.h @@ -20,7 +20,7 @@ namespace blt #define blt_assert(expr) do {static_cast(expr) ? void(0) : blt::b_assert_failed(#expr, __FILE__, __LINE__) } while (0) // prints error with stack trace then exits with failure. #define BLT_ASSERT(expr) do { \ - if (!static_cast(expr)) { \ + if (!static_cast(expr)) { \ blt::b_assert_failed(#expr, __FILE__, __LINE__); \ std::exit(EXIT_FAILURE); \ } \ diff --git a/include/blt/std/loader.h b/include/blt/std/loader.h index 037c34b..fb84bad 100755 --- a/include/blt/std/loader.h +++ b/include/blt/std/loader.h @@ -14,18 +14,45 @@ #include #include #include +#include -namespace blt::fs { +namespace blt::fs +{ + struct include_guard + { + char open = '<'; + char close = '>'; + }; + std::vector getLinesFromFile(const std::string& path); - std::vector recursiveShaderInclude(const std::string& path, const std::string& include_header = "#include"); + /** + * Recursively include files + * @param path initial file to load + * @param include_header the beginning of the line that should be used to recognize when a line is to be treated as an include + * @param guards characters used to identify the parts that specify the file path. if empty it will assume everything after the include header + * @return a list of lines in all files. added together in order. + */ + std::vector recursiveInclude(const std::string& path, const std::string& include_header = "#include", + const std::vector& guards = {{'<', '>'}, {'"', '"'}}); - static inline std::string loadShaderFile(const std::string& path) { + static inline std::string loadBrainFuckFile(const std::string& path) + { + std::string buffer; + + auto lines = recursiveInclude(path, "~"); + + return buffer; + } + + static inline std::string loadShaderFile(const std::string& path) + { std::stringstream stringStream; - auto lines = recursiveShaderInclude(path); + auto lines = recursiveInclude(path); - for (const auto& line : lines) { + for (const auto& line : lines) + { // now process the defines, if they exist // if (line.starts_with("#define")) { // auto defineParts = String::split(line, " "); diff --git a/src/blt/std/loader.cpp b/src/blt/std/loader.cpp index 322a209..183678e 100755 --- a/src/blt/std/loader.cpp +++ b/src/blt/std/loader.cpp @@ -4,15 +4,18 @@ * See LICENSE file for license detail */ #include +#include -std::vector blt::fs::getLinesFromFile(const std::string& path) { +std::vector blt::fs::getLinesFromFile(const std::string& path) +{ std::string shaderSource; std::ifstream shaderFile; if (!shaderFile.good()) BLT_ERROR("Input stream not good!\n"); // ensure ifstream objects can throw exceptions: shaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); - try { + try + { // open file shaderFile.open(path); std::stringstream shaderStream; @@ -22,7 +25,8 @@ std::vector blt::fs::getLinesFromFile(const std::string& path) { shaderFile.close(); // convert stream into std::string shaderSource = shaderStream.str(); - } catch (std::ifstream::failure& e) { + } catch (std::ifstream::failure& e) + { BLT_WARN("Unable to read file '%s'!\n", path.c_str()); BLT_WARN("Exception: %s", e.what()); throw std::runtime_error("Failed to read file!\n"); @@ -32,55 +36,74 @@ std::vector blt::fs::getLinesFromFile(const std::string& path) { return string::split(shaderSource, "\n"); } -std::vector blt::fs::recursiveShaderInclude(const std::string& path, const std::string& include_header) { +std::vector blt::fs::recursiveInclude(const std::string& path, const std::string& include_header, + const std::vector& guards) +{ std::string pathOnly = path.substr(0, path.find_last_of('/')); auto mainLines = getLinesFromFile(path); - std::unordered_map> includes; + std::vector return_lines; - for (unsigned int i = 0; i < mainLines.size(); i++) { - auto& line = mainLines[i]; + for (auto& line : mainLines) + { // if the line is an include statement then we want to add lines recursively. - if (string::starts_with(line, include_header)) { - std::vector include_statement = string::split(line, "<"); + auto include_pos = line.find(include_header); + if (include_pos != std::string::npos) + { + auto past_include = include_pos + include_header.size(); + BLT_TRACE(past_include); + BLT_TRACE("%c", (char)line[past_include]); + std::string file_to_include; - if (include_statement.size() <= 1) - include_statement = string::split(line, "\""); - - string::trim(line); - if (!(string::ends_with(line, ">") || string::ends_with(line, "\""))) { - BLT_FATAL("Shader file contains an invalid #include statement. (Missing terminator)\n"); - std::abort(); - } - try { - // filter out the > or " at the end of the include statement. - std::string file; - file = include_statement[1]; - if (string::ends_with(include_statement[1], ">")) - file = file.substr(0, file.size() - 1); + if (guards.empty()) + { + file_to_include = line.substr(line.find(include_header)); + } else + { + size_t index = past_include; + while (std::find_if(guards.begin(), guards.end(), [&](const include_guard& item) { + return line[index] == item.open; + }) == guards.end()) + index++; + index++; + BLT_ASSERT(index < line.size() && "Include found but no file was provided!"); - BLT_TRACE("Recusing into %s/%s\n", pathOnly.c_str(), file.c_str()); - - includes.insert({i, recursiveShaderInclude(pathOnly + "/" + file, include_header)}); - } catch (std::exception& e) { - BLT_FATAL("Shader file contains an invalid #include statement. (Missing < or \")\n"); - BLT_FATAL("Exception: %s", e.what()); - std::abort(); + std::cout << line.substr(index) << std::endl; } - } - } - - std::vector returnLines; - - // now combine all the loaded files while respecting the include's position in the file. - for (unsigned int i = 0; i < mainLines.size(); i++) { - if (!includes[i].empty()) { - auto includedFileLines = includes[i]; - - for (const auto& line : includedFileLines) - returnLines.push_back(line); + +// size_t index = 0; +// +// std::vector include_statement = string::split(line, "<"); +// +// if (include_statement.size() <= 1) +// include_statement = string::split(line, "\""); +// +// string::trim(line); +// if (!(string::ends_with(line, ">") || string::ends_with(line, "\""))) +// { +// BLT_FATAL("Shader file contains an invalid #include statement. (Missing terminator)\n"); +// std::abort(); +// } +// try +// { +// // filter out the > or " at the end of the include statement. +// std::string file; +// file = include_statement[1]; +// if (string::ends_with(include_statement[1], ">")) +// file = file.substr(0, file.size() - 1); +// +// BLT_TRACE("Recusing into %s/%s\n", pathOnly.c_str(), file.c_str()); +// +// includes.insert({i, recursiveInclude(pathOnly + "/" + file, include_header, guards)}); +// } catch (std::exception& e) +// { +// BLT_FATAL("Shader file contains an invalid #include statement. (Missing < or \")\n"); +// BLT_FATAL("Exception: %s", e.what()); +// std::abort(); +// } } else - returnLines.push_back(mainLines[i]); + return_lines.push_back(line); } - return returnLines; + + return return_lines; }