2022-06-15 00:09:51 +00:00
|
|
|
#include "slang_helpers.hpp"
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <filesystem>
|
|
|
|
#include <cmath>
|
2023-01-30 23:54:23 +00:00
|
|
|
#include <cctype>
|
2022-06-15 00:09:51 +00:00
|
|
|
|
|
|
|
using std::string;
|
|
|
|
using std::string_view;
|
|
|
|
using std::vector;
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
|
|
|
|
int mipmap_levels_for_size(int width, int height)
|
|
|
|
{
|
|
|
|
return (int)log2(width > height ? width : height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void trim(string_view &view)
|
|
|
|
{
|
2023-02-01 20:47:42 +00:00
|
|
|
while (view.length() > 0 && isspace((unsigned char)view.at(0)))
|
2022-06-15 00:09:51 +00:00
|
|
|
view.remove_prefix(1);
|
2023-01-23 21:02:56 +00:00
|
|
|
|
2023-02-01 20:47:42 +00:00
|
|
|
while (view.length() > 0 && isspace((unsigned char)view.at(view.length() - 1)))
|
2022-06-15 00:09:51 +00:00
|
|
|
view.remove_suffix(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
string trim(const string& str)
|
|
|
|
{
|
|
|
|
string_view sv(str);
|
|
|
|
trim(sv);
|
|
|
|
return string(sv);
|
|
|
|
}
|
|
|
|
|
2023-01-23 21:02:56 +00:00
|
|
|
int get_significant_digits(const string_view &view)
|
2022-06-15 00:09:51 +00:00
|
|
|
{
|
|
|
|
auto pos = view.rfind('.');
|
|
|
|
if (pos == string_view::npos)
|
|
|
|
return 0;
|
|
|
|
return view.size() - pos - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<string> split_string_quotes(const string_view &view)
|
|
|
|
{
|
|
|
|
vector<string> tokens;
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
|
|
while (pos < view.length())
|
|
|
|
{
|
|
|
|
size_t indexa = view.find_first_not_of("\t\r\n ", pos);
|
|
|
|
size_t indexb = 0;
|
|
|
|
if (indexa == string::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (view.at(indexa) == '\"')
|
|
|
|
{
|
|
|
|
indexa++;
|
|
|
|
indexb = view.find_first_of('\"', indexa);
|
|
|
|
if (indexb == string::npos)
|
|
|
|
break;
|
|
|
|
}
|
2023-01-23 21:02:56 +00:00
|
|
|
else
|
2022-06-15 00:09:51 +00:00
|
|
|
{
|
|
|
|
indexb = view.find_first_of("\t\r\n ", indexa);
|
|
|
|
if (indexb == string::npos)
|
|
|
|
indexb = view.size();
|
|
|
|
}
|
2023-01-23 21:02:56 +00:00
|
|
|
|
2022-06-15 00:09:51 +00:00
|
|
|
if (indexb > indexa)
|
|
|
|
tokens.push_back(string{view.substr(indexa, indexb - indexa)});
|
|
|
|
pos = indexb + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tokens;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<string> split_string(const string_view &str, unsigned char delim)
|
|
|
|
{
|
|
|
|
vector<string> tokens;
|
|
|
|
size_t pos = 0;
|
|
|
|
size_t index;
|
2023-01-23 21:02:56 +00:00
|
|
|
|
2022-06-15 00:09:51 +00:00
|
|
|
while (pos < str.length())
|
|
|
|
{
|
|
|
|
index = str.find(delim, pos);
|
|
|
|
if (index == string::npos)
|
|
|
|
{
|
|
|
|
if (pos < str.length())
|
|
|
|
{
|
2023-01-23 21:02:56 +00:00
|
|
|
tokens.push_back(string{str.substr(pos)});
|
2022-06-15 00:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (index > pos)
|
|
|
|
{
|
|
|
|
tokens.push_back(string{str.substr(pos, index - pos)});
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = index + 1;
|
2023-01-23 21:02:56 +00:00
|
|
|
}
|
2022-06-15 00:09:51 +00:00
|
|
|
|
|
|
|
return tokens;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ends_with(const string &str, const string &ext)
|
|
|
|
{
|
|
|
|
if (ext.size() > str.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto icmp = [](const unsigned char a, const unsigned char b) -> bool {
|
|
|
|
return std::tolower(a) == std::tolower(b);
|
|
|
|
};
|
2023-01-23 21:02:56 +00:00
|
|
|
|
2022-06-15 00:09:51 +00:00
|
|
|
return std::equal(ext.crbegin(), ext.crend(), str.crbegin(), icmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void canonicalize(string &filename, const string &base)
|
|
|
|
{
|
|
|
|
fs::path path(filename);
|
|
|
|
|
|
|
|
if (path.is_relative())
|
|
|
|
{
|
|
|
|
fs::path base_path(base);
|
|
|
|
base_path.remove_filename();
|
|
|
|
path = fs::weakly_canonical(base_path / path);
|
|
|
|
filename = path.string();
|
|
|
|
}
|
|
|
|
}
|