8 #include <OpenImageIO/filesystem.h>
9 #include <OpenImageIO/strutil.h>
10 #include <OpenImageIO/sysutil.h>
20 # define DIR_SEP_ALT '/'
26 # include <sys/types.h>
40 # if defined(_MSC_VER) || defined(__MINGW64__)
42 # elif defined(__MINGW32__)
48 # define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
61 class directory_iterator {
65 path_info(
const string &path,
const WIN32_FIND_DATAW &find_data)
66 : path_(path), find_data_(find_data)
72 return path_join(path_, string_from_wstring(find_data_.cFileName));
77 const WIN32_FIND_DATAW &find_data_;
80 directory_iterator() : path_info_(
"", find_data_), h_find_(INVALID_HANDLE_VALUE)
84 explicit directory_iterator(
const string &path) : path_(path), path_info_(path, find_data_)
86 string wildcard = path;
87 if (wildcard[wildcard.size() - 1] !=
DIR_SEP) {
91 h_find_ = FindFirstFileW(string_to_wstring(wildcard).c_str(), &find_data_);
92 if (h_find_ != INVALID_HANDLE_VALUE) {
99 if (h_find_ != INVALID_HANDLE_VALUE) {
110 path_info *operator->()
115 bool operator!=(
const directory_iterator &other)
117 return h_find_ != other.h_find_;
131 if (h_find_ != INVALID_HANDLE_VALUE) {
132 bool result = FindNextFileW(h_find_, &find_data_) == TRUE;
135 h_find_ = INVALID_HANDLE_VALUE;
144 while (wcscmp(find_data_.cFileName,
L".") == 0 || wcscmp(find_data_.cFileName,
L"..") == 0) {
153 path_info path_info_;
154 WIN32_FIND_DATAW find_data_;
159 class directory_iterator {
163 explicit path_info(
const string &path) : path_(path), entry_(
NULL)
172 void current_entry_set(
const struct dirent *entry)
179 const struct dirent *entry_;
182 directory_iterator() : path_info_(
""), name_list_(
NULL), num_entries_(-1), cur_entry_(-1)
186 explicit directory_iterator(
const string &path) : path_(path), path_info_(path_), cur_entry_(0)
188 num_entries_ = scandir(path.c_str(), &name_list_,
NULL, alphasort);
189 if (num_entries_ < 0) {
197 ~directory_iterator()
208 path_info *operator->()
210 path_info_.current_entry_set(name_list_[cur_entry_]);
214 bool operator!=(
const directory_iterator &other)
216 return name_list_ != other.name_list_;
231 if (cur_entry_ >= num_entries_) {
241 while (strcmp(name_list_[cur_entry_]->
d_name,
".") == 0 ||
242 strcmp(name_list_[cur_entry_]->
d_name,
"..") == 0) {
250 void destroy_name_list()
252 if (name_list_ ==
NULL) {
255 for (
int i = 0; i < num_entries_; ++i) {
263 path_info path_info_;
264 struct dirent **name_list_;
265 int num_entries_, cur_entry_;
270 size_t find_last_slash(
const string &path)
272 for (
size_t i = 0; i < path.size(); ++i) {
273 size_t index = path.size() - 1 - i;
275 if (path[index] ==
DIR_SEP || path[index] == DIR_SEP_ALT)
290 static bool env_init =
false;
291 static char *env_shader_path;
292 static char *env_source_path;
294 env_shader_path = getenv(
"CYCLES_SHADER_PATH");
296 env_source_path = getenv(
"CYCLES_KERNEL_PATH");
299 if (env_shader_path !=
NULL && sub ==
"shader") {
300 return env_shader_path;
302 else if (env_source_path !=
NULL && sub ==
"source") {
303 return env_source_path;
308 #if defined(__linux__) || defined(__APPLE__)
309 static string path_xdg_cache_get()
311 const char *home = getenv(
"XDG_CACHE_HOME");
316 home = getenv(
"HOME");
318 home = getpwuid(getuid())->pw_dir;
320 return path_join(
string(home),
".cache");
325 void path_init(
const string &path,
const string &user_path)
334 OIIO::Filesystem::exists(path);
360 #if defined(__linux__) || defined(__APPLE__)
372 #if defined(__linux__) || defined(__APPLE__)
373 string path_xdg_home_get(
const string &sub =
"");
378 size_t index = find_last_slash(path);
379 if (index != string::npos) {
382 if (index == 0 && path.size() == 1) {
386 if (index == path.size() - 1) {
394 return path.substr(index + 1, path.size() - index - 1);
401 size_t index = find_last_slash(path);
402 if (index != string::npos) {
404 if (index == 0 && path.size() > 1) {
408 return path.substr(0, index);
415 if (dir.size() == 0) {
418 if (
file.size() == 0) {
445 # ifdef HAVE_SHLWAPI_H
446 return PathIsRelative(path.c_str());
448 if (path.size() >= 3) {
449 return !(((path[0] >=
'a' && path[0] <=
'z') || (path[0] >=
'A' && path[0] <=
'Z')) &&
450 path[1] ==
':' && path[2] ==
DIR_SEP);
455 if (path.size() == 0) {
464 static string path_unc_add_slash_to_share(
const string &path)
466 size_t slash_after_server = path.find(
DIR_SEP, 2);
467 if (slash_after_server != string::npos) {
468 size_t slash_after_share = path.find(
DIR_SEP, slash_after_server + 1);
469 if (slash_after_share == string::npos) {
480 static string path_unc_to_short(
const string &path)
482 size_t len = path.size();
483 if ((
len > 3) && (path[0] ==
DIR_SEP) && (path[1] ==
DIR_SEP) && (path[2] ==
'?') &&
484 ((path[3] ==
DIR_SEP) || (path[3] == DIR_SEP_ALT))) {
485 if ((
len > 5) && (path[5] ==
':')) {
486 return path.substr(4,
len - 4);
488 else if ((
len > 7) && (path.substr(4, 3) ==
"UNC") &&
489 ((path[7] ==
DIR_SEP) || (path[7] == DIR_SEP_ALT))) {
490 return "\\\\" + path.substr(8,
len - 8);
496 static string path_cleanup_unc(
const string &path)
498 string result = path_unc_to_short(path);
499 if (path.size() > 2) {
502 return path_unc_add_slash_to_share(
result);
509 static string path_make_compatible(
const string &path)
517 if ((path.size() >= 3) && (path[0] ==
DIR_SEP) && (path[1] ==
DIR_SEP)) {
527 static int path_wstat(
const wstring &path_wc,
path_stat_t *
st)
529 # if defined(_MSC_VER) || defined(__MINGW64__)
530 return _wstat64(path_wc.c_str(),
st);
531 # elif defined(__MINGW32__)
532 return _wstati64(path_wc.c_str(),
st);
534 return _wstat(path_wc.c_str(),
st);
540 wstring path_wc = string_to_wstring(path);
541 return path_wstat(path_wc,
st);
546 return stat(path.c_str(),
st);
562 string fixed_path = path_make_compatible(path);
563 wstring path_wc = string_to_wstring(fixed_path);
565 if (path_wstat(path_wc, &
st) != 0) {
568 return st.st_mode != 0;
571 if (stat(path.c_str(), &
st) != 0) {
574 return st.st_mode != 0;
590 directory_iterator it(dir), it_end;
592 for (; it != it_end; ++it) {
597 string filepath = it->path();
599 hash.append((
const uint8_t *)filepath.c_str(), filepath.size());
600 hash.append_file(filepath);
613 return hash.get_hex();
628 if (parent.size() > 0 && parent != path) {
635 wstring path_wc = string_to_wstring(path);
636 return _wmkdir(path_wc.c_str()) == 0;
638 return mkdir(path.c_str(), 0777) == 0;
658 if (binary.size() > 0)
659 fwrite(&binary[0],
sizeof(
uint8_t), binary.size(), f);
669 std::copy(text.begin(), text.end(), binary.begin());
686 if (binary.size() == 0) {
691 if (fread(&binary[0],
sizeof(
uint8_t), binary.size(), f) != binary.size()) {
708 const char *
str = (
const char *)&binary[0];
709 size_t size = binary.size();
726 return remove(path.c_str()) == 0;
740 const string &source_filepath,
744 const string &source_filepath,
747 string result = preprocessor_line;
749 string rest_of_line =
string_strip(preprocessor_line.substr(1));
751 if (0 == strncmp(rest_of_line.c_str(),
"include", 7)) {
753 if (rest_of_line[0] ==
'"') {
754 const size_t n_start = 1;
755 const size_t n_end = rest_of_line.find(
"\"", n_start);
756 const string filename = rest_of_line.substr(n_start, n_end - n_start);
766 return "\n" + text +
"\n";
779 const string &source_filepath,
782 const string *psource = &_source;
785 auto pragma_once = _source.find(
"#pragma once");
786 if (pragma_once != string::npos) {
787 if (
state->pragma_onced.find(source_filepath) !=
state->pragma_onced.end()) {
790 state->pragma_onced.insert(source_filepath);
794 source_new = _source;
795 memcpy(source_new.data() + pragma_once,
"//pr", 4);
796 psource = &source_new;
802 SourceReplaceState::ProcessedMapping::iterator replaced_file =
state->processed_files.find(
804 if (replaced_file !=
state->processed_files.end()) {
805 return replaced_file->second;
808 const string &source = *psource;
812 const size_t source_length = source.length();
815 size_t line_number = 0, column_number = 1;
820 size_t token_start = 0, token_length = 0;
827 bool inside_preprocessor =
false;
828 string preprocessor_line =
"";
830 while (index < source_length) {
831 char ch = source[index];
834 if (inside_preprocessor) {
837 if (!block.empty()) {
844 inside_preprocessor =
false;
845 preprocessor_line =
"";
850 else if (ch ==
'#' && column_number == 1 && !inside_preprocessor) {
852 if (token_length != 0) {
853 result.append(source, token_start, token_length);
857 inside_preprocessor =
true;
860 if (inside_preprocessor) {
861 preprocessor_line += ch;
872 if (token_length != 0) {
873 result.append(source, token_start, token_length);
875 if (inside_preprocessor) {
893 wstring path_wc = string_to_wstring(path);
894 wstring mode_wc = string_to_wstring(mode);
895 return _wfopen(path_wc.c_str(), mode_wc.c_str());
897 return fopen(path.c_str(), mode.c_str());
906 directory_iterator it(dir), it_end;
908 for (; it != it_end; ++it) {
912 if (except.find(filename) == except.end())
void BLI_kdtree_nd_() free(KDTree *tree)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
#define CCL_NAMESPACE_END
GPUAttachmentType & operator++(GPUAttachmentType &a)
bool remove(void *owner, const AttributeIDRef &attribute_id)
constexpr bool operator!=(StringRef a, StringRef b)
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
size_t path_file_size(const string &path)
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)
string path_source_replace_includes(const string &source, const string &path)
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_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)
static string path_source_handle_preprocessor(const string &preprocessor_line, const string &source_filepath, SourceReplaceState *state)
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)
unsigned __int64 uint64_t
string string_strip(const string &s)
bool string_startswith(const string_view s, const string_view start)
void string_replace(string &haystack, const string &needle, const string &other)
ProcessedMapping processed_files
set< string > pragma_onced
map< string, string > ProcessedMapping