21 #include <OpenImageIO/filesystem.h>
22 #include <OpenImageIO/strutil.h>
23 #include <OpenImageIO/sysutil.h>
33 # define DIR_SEP_ALT '/'
39 # include <sys/types.h>
53 # if defined(_MSC_VER) || defined(__MINGW64__)
55 # elif defined(__MINGW32__)
61 # define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
74 class directory_iterator {
78 path_info(
const string &path,
const WIN32_FIND_DATAW &find_data)
79 : path_(path), find_data_(find_data)
85 return path_join(path_, string_from_wstring(find_data_.cFileName));
90 const WIN32_FIND_DATAW &find_data_;
93 directory_iterator() : path_info_(
"", find_data_), h_find_(INVALID_HANDLE_VALUE)
97 explicit directory_iterator(
const string &path) : path_(path), path_info_(path, find_data_)
99 string wildcard = path;
100 if (wildcard[wildcard.size() - 1] !=
DIR_SEP) {
104 h_find_ = FindFirstFileW(string_to_wstring(wildcard).c_str(), &find_data_);
105 if (h_find_ != INVALID_HANDLE_VALUE) {
110 ~directory_iterator()
112 if (h_find_ != INVALID_HANDLE_VALUE) {
123 path_info *operator->()
128 bool operator!=(
const directory_iterator &other)
130 return h_find_ != other.h_find_;
144 if (h_find_ != INVALID_HANDLE_VALUE) {
145 bool result = FindNextFileW(h_find_, &find_data_) == TRUE;
148 h_find_ = INVALID_HANDLE_VALUE;
157 while (wcscmp(find_data_.cFileName,
L".") == 0 || wcscmp(find_data_.cFileName,
L"..") == 0) {
166 path_info path_info_;
167 WIN32_FIND_DATAW find_data_;
172 class directory_iterator {
176 explicit path_info(
const string &path) : path_(path), entry_(
NULL)
185 void current_entry_set(
const struct dirent *entry)
192 const struct dirent *entry_;
195 directory_iterator() : path_info_(
""), name_list_(
NULL), num_entries_(-1), cur_entry_(-1)
199 explicit directory_iterator(
const string &path) : path_(path), path_info_(path_), cur_entry_(0)
201 num_entries_ = scandir(path.c_str(), &name_list_,
NULL, alphasort);
202 if (num_entries_ < 0) {
210 ~directory_iterator()
221 path_info *operator->()
223 path_info_.current_entry_set(name_list_[cur_entry_]);
227 bool operator!=(
const directory_iterator &other)
229 return name_list_ != other.name_list_;
244 if (cur_entry_ >= num_entries_) {
254 while (strcmp(name_list_[cur_entry_]->
d_name,
".") == 0 ||
255 strcmp(name_list_[cur_entry_]->
d_name,
"..") == 0) {
263 void destroy_name_list()
265 if (name_list_ ==
NULL) {
268 for (
int i = 0; i < num_entries_; ++i) {
276 path_info path_info_;
277 struct dirent **name_list_;
278 int num_entries_, cur_entry_;
283 size_t find_last_slash(
const string &path)
285 for (
size_t i = 0; i < path.size(); ++i) {
286 size_t index = path.size() - 1 - i;
288 if (path[index] ==
DIR_SEP || path[index] == DIR_SEP_ALT)
303 static bool env_init =
false;
304 static char *env_shader_path;
305 static char *env_source_path;
307 env_shader_path = getenv(
"CYCLES_SHADER_PATH");
309 env_source_path = getenv(
"CYCLES_KERNEL_PATH");
312 if (env_shader_path !=
NULL && sub ==
"shader") {
313 return env_shader_path;
315 else if (env_shader_path !=
NULL && sub ==
"source") {
316 return env_source_path;
321 #if defined(__linux__) || defined(__APPLE__)
322 static string path_xdg_cache_get()
324 const char *home = getenv(
"XDG_CACHE_HOME");
329 home = getenv(
"HOME");
331 home = getpwuid(getuid())->pw_dir;
333 return path_join(
string(home),
".cache");
338 void path_init(
const string &path,
const string &user_path)
347 OIIO::Filesystem::exists(path);
373 #if defined(__linux__) || defined(__APPLE__)
385 #if defined(__linux__) || defined(__APPLE__)
386 string path_xdg_home_get(
const string &sub =
"");
391 size_t index = find_last_slash(path);
392 if (index != string::npos) {
395 if (index == 0 && path.size() == 1) {
399 if (index == path.size() - 1) {
407 return path.substr(index + 1, path.size() - index - 1);
414 size_t index = find_last_slash(path);
415 if (index != string::npos) {
417 if (index == 0 && path.size() > 1) {
421 return path.substr(0, index);
428 if (dir.size() == 0) {
431 if (
file.size() == 0) {
458 # ifdef HAVE_SHLWAPI_H
459 return PathIsRelative(path.c_str());
461 if (path.size() >= 3) {
462 return !(((path[0] >=
'a' && path[0] <=
'z') || (path[0] >=
'A' && path[0] <=
'Z')) &&
463 path[1] ==
':' && path[2] ==
DIR_SEP);
468 if (path.size() == 0) {
477 static string path_unc_add_slash_to_share(
const string &path)
479 size_t slash_after_server = path.find(
DIR_SEP, 2);
480 if (slash_after_server != string::npos) {
481 size_t slash_after_share = path.find(
DIR_SEP, slash_after_server + 1);
482 if (slash_after_share == string::npos) {
493 static string path_unc_to_short(
const string &path)
495 size_t len = path.size();
496 if ((
len > 3) && (path[0] ==
DIR_SEP) && (path[1] ==
DIR_SEP) && (path[2] ==
'?') &&
497 ((path[3] ==
DIR_SEP) || (path[3] == DIR_SEP_ALT))) {
498 if ((
len > 5) && (path[5] ==
':')) {
499 return path.substr(4,
len - 4);
501 else if ((
len > 7) && (path.substr(4, 3) ==
"UNC") &&
502 ((path[7] ==
DIR_SEP) || (path[7] == DIR_SEP_ALT))) {
503 return "\\\\" + path.substr(8,
len - 8);
509 static string path_cleanup_unc(
const string &path)
511 string result = path_unc_to_short(path);
512 if (path.size() > 2) {
515 return path_unc_add_slash_to_share(
result);
522 static string path_make_compatible(
const string &path)
530 if ((path.size() >= 3) && (path[0] ==
DIR_SEP) && (path[1] ==
DIR_SEP)) {
540 static int path_wstat(
const wstring &path_wc,
path_stat_t *st)
542 # if defined(_MSC_VER) || defined(__MINGW64__)
543 return _wstat64(path_wc.c_str(), st);
544 # elif defined(__MINGW32__)
545 return _wstati64(path_wc.c_str(), st);
547 return _wstat(path_wc.c_str(), st);
553 wstring path_wc = string_to_wstring(path);
554 return path_wstat(path_wc, st);
559 return stat(path.c_str(), st);
575 string fixed_path = path_make_compatible(path);
576 wstring path_wc = string_to_wstring(fixed_path);
578 if (path_wstat(path_wc, &st) != 0) {
581 return st.st_mode != 0;
584 if (stat(path.c_str(), &st) != 0) {
587 return st.st_mode != 0;
603 directory_iterator it(dir), it_end;
605 for (; it != it_end; ++it) {
610 string filepath = it->path();
612 hash.append((
const uint8_t *)filepath.c_str(), filepath.size());
613 hash.append_file(filepath);
626 return hash.get_hex();
641 if (parent.size() > 0 && parent != path) {
648 wstring path_wc = string_to_wstring(path);
649 return _wmkdir(path_wc.c_str()) == 0;
651 return mkdir(path.c_str(), 0777) == 0;
671 if (binary.size() > 0)
672 fwrite(&binary[0],
sizeof(
uint8_t), binary.size(), f);
682 std::copy(text.begin(), text.end(), binary.begin());
699 if (binary.size() == 0) {
704 if (fread(&binary[0],
sizeof(
uint8_t), binary.size(), f) != binary.size()) {
721 const char *
str = (
const char *)&binary[0];
722 size_t size = binary.size();
739 return remove(path.c_str()) == 0;
755 const string &source_filepath,
760 string unescaped_path = path;
764 const size_t base_len =
state.base.length();
765 unescaped_path = base_file +
766 unescaped_path.substr(base_len, unescaped_path.length() - base_len);
769 const size_t length = unescaped_path.length();
770 string escaped_path =
"";
771 for (
size_t i = 0; i <
length; ++i) {
772 const char ch = unescaped_path[i];
773 if (strchr(
"\"\'\?\\", ch) !=
NULL) {
774 escaped_path +=
"\\";
781 return string_printf(
"#line %d \"%s\"", line, escaped_path.c_str());
785 const string &source_filepath,
786 const size_t line_number,
789 string result = preprocessor_line;
790 string token =
string_strip(preprocessor_line.substr(1, preprocessor_line.size() - 1));
792 token =
string_strip(token.substr(7, token.size() - 7));
793 if (token[0] ==
'"') {
794 const size_t n_start = 1;
795 const size_t n_end = token.find(
"\"", n_start);
796 const string filename = token.substr(n_start, n_end - n_start);
802 if (is_precompiled) {
803 state->precompiled_headers.insert(filepath);
822 const string &source_filepath,
828 SourceReplaceState::ProcessedMapping::iterator replaced_file =
state->processed_files.find(
830 if (replaced_file !=
state->processed_files.end()) {
831 if (
state->precompiled_headers.find(source_filepath) !=
state->precompiled_headers.end()) {
834 return replaced_file->second;
838 const size_t source_length = source.length();
841 size_t line_number = 0, column_number = 1;
846 size_t token_start = 0, token_length = 0;
853 bool inside_preprocessor =
false;
854 string preprocessor_line =
"";
856 while (index < source_length) {
857 const char ch = source[index];
859 if (inside_preprocessor) {
861 preprocessor_line, source_filepath, line_number,
state);
866 inside_preprocessor =
false;
867 preprocessor_line =
"";
871 else if (ch ==
'#' && column_number == 1 && !inside_preprocessor) {
873 if (token_length != 0) {
874 result.append(source, token_start, token_length);
878 inside_preprocessor =
true;
880 if (inside_preprocessor) {
881 preprocessor_line += ch;
892 if (token_length != 0) {
893 result.append(source, token_start, token_length);
895 if (inside_preprocessor) {
897 preprocessor_line, source_filepath, line_number,
state);
906 const string &source_filename)
916 wstring path_wc = string_to_wstring(path);
917 wstring mode_wc = string_to_wstring(mode);
918 return _wfopen(path_wc.c_str(), mode_wc.c_str());
920 return fopen(path.c_str(), mode.c_str());
929 directory_iterator it(dir), it_end;
931 for (; it != it_end; ++it) {
935 if (except.find(filename) == except.end())
void BLI_kdtree_nd_() free(KDTree *tree)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
GPUAttachmentType & operator++(GPUAttachmentType &a)
#define CCL_NAMESPACE_END
constexpr bool operator!=(StringRef a, StringRef b)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
unsigned __int64 uint64_t
set< string > precompiled_headers
ProcessedMapping processed_files
map< string, string > ProcessedMapping
size_t path_file_size(const string &path)
static string line_directive(const SourceReplaceState &state, const string &path, const int line)
FILE * path_fopen(const string &path, const string &mode)
static string path_source_replace_includes_recursive(const string &source, const string &source_filepath, SourceReplaceState *state)
static string cached_user_path
void path_cache_clear_except(const string &name, const set< string > &except)
string path_user_get(const string &sub)
string path_cache_get(const string &sub)
bool path_is_directory(const string &path)
string path_dirname(const string &path)
static string path_source_handle_preprocessor(const string &preprocessor_line, const string &source_filepath, const size_t line_number, SourceReplaceState *state)
typedefCCL_NAMESPACE_BEGIN struct stat path_stat_t
static int path_stat(const string &path, path_stat_t *st)
string path_get(const string &sub)
string path_source_replace_includes(const string &source, const string &path, const string &source_filename)
string path_files_md5_hash(const string &dir)
bool path_is_relative(const string &path)
uint64_t path_modified_time(const string &path)
string path_join(const string &dir, const string &file)
bool path_exists(const string &path)
static bool create_directories_recursivey(const string &path)
string path_escape(const string &path)
bool path_write_binary(const string &path, const vector< uint8_t > &binary)
void path_create_directories(const string &filepath)
bool path_write_text(const string &path, string &text)
static void path_files_md5_hash_recursive(MD5Hash &hash, const string &dir)
bool path_read_text(const string &path, string &text)
static string cached_xdg_cache_path
string path_filename(const string &path)
static string cached_path
static char * path_specials(const string &sub)
bool path_remove(const string &path)
void path_init(const string &path, const string &user_path)
bool path_read_binary(const string &path, vector< uint8_t > &binary)
string string_strip(const string &s)
bool string_startswith(const string &s, const char *start)
bool string_endswith(const string &s, const string &end)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
void string_replace(string &haystack, const string &needle, const string &other)