1#include <cgv/base/register.h>
5#include <cgv/utils/dir.h>
6#include <cgv/utils/file.h>
7#include <cgv/utils/tokenizer.h>
16using namespace cgv::utils::file;
21std::string find_data_file_rec(
const std::string& path,
const std::string& file_name)
23 if (cgv::utils::file::exists(path+
'/'+file_name))
24 return path+
'/'+file_name;
25 void* h = find_first(path+
"*");
27 if (find_directory(h) && find_name(h) !=
"." && find_name(h) !=
"..") {
28 std::string fn = path+find_name(h)+
'/';
29 if (exists(fn+file_name))
31 fn = find_data_file_rec(fn, file_name);
40std::string find_data_file_1(
const std::string& base_path,
const std::string& sub_path,
const std::string& file_name,
bool recurse)
42 std::string base_path_prefix = base_path;
43 if (!base_path_prefix.empty() && base_path_prefix.back() !=
'/')
44 base_path_prefix +=
"/";
45 std::string dir_name = base_path_prefix+sub_path;
46 if (!dir_name.empty()) {
47 if (!dir::exists(dir_name))
49 if (dir_name.back() !=
'/')
52 if (exists(dir_name+file_name))
53 return dir_name+file_name;
56 return find_data_file_rec(dir_name, file_name);
61 for (
unsigned i=0;
i<strategy.size(); ++
i) {
62 switch (strategy[
i]) {
68 return std::string(
"res://")+file_name;
74 std::string
fn = find_data_file_1(
"",
sub_directory, file_name, strategy[
i] ==
'C');
123 return std::string();
128 std::cout << text << std::endl;
133 std::cerr << text << std::endl;
141 std::vector<cgv::utils::token> tokens;
143 std::cout << text <<
"\n select answer from {" <<
answers <<
"} with 0..." << tokens.size() - 1 <<
":>";
150std::string
std_ask_dir(
const std::string& text,
const std::string& path)
152 std::cout << text <<
"\n:>";
175 case 'M':
if (cgv::utils::dir::exists(
master_path))
213 if (
uf.query(
producer +
" wants to download <" + file_name +
"> but has no path to store it. Do you want to specify a path to store the download?",
227 if (!cgv::utils::dir::exists(
file_path)) {
230 if (
uf.query(
producer +
" wants to create directory <" +
file_path +
"> to store downloads. Do you allow this?",
233 if (!cgv::utils::dir::mkdir(
file_path)) {
235 uf.message(std::string(
"could not create subdirectory <") +
sub_directory +
"> in cache path");
245 std::string cmd =
"curl --output \"";
250 int result =
system(cmd.c_str());
251 if (result == -1 || !cgv::utils::file::exists(
file_path)) {
254 if (
uf.query(std::string(
"download of <") + file_name +
"> failed. Please check internet connectivity! Try again?",
263std::string clean_data_path(
const std::string& data_path)
265 if (data_path.size() == 0)
267 unsigned int p = (
unsigned int) data_path.size()-1;
268 if (data_path[p] ==
'/' || data_path[p] ==
'\\')
269 return clean_data_path(data_path.substr(0,p));
327bool find_and_extend_system_path(std::string& file_name)
329 std::string system_paths(std::getenv(
"PATH"));
330 std::vector<cgv::utils::token> path_tokens;
339 for (
unsigned int i = 0; i<path_tokens.size(); ++i) {
340 std::string system_path =
to_string(path_tokens[i]);
341 if (cgv::utils::file::exists(system_path +
"/" + file_name)) {
342 file_name = system_path +
"/" + file_name;
352 if (file_name.substr(0,6) !=
"res://")
353 return fopen(file_name.c_str(), mode);
354 std::map<std::string, resource_file_info>::const_iterator
i =
ref_resource_file_map().find(file_name.substr(6));
357 std::string source_file =
i->second.source_file;
358 if (source_file.empty())
364 if (!find_and_extend_system_path(source_file)) {
365 std::cerr <<
"ERROR: could not find " << source_file <<
" to import " <<
i->second.file_data << std::endl;
370 unsigned int off =
i->second.file_offset;
371 if (
off == (
unsigned int)-1) {
373 if (
off == (
unsigned int)-1) {
374 std::cerr <<
"ERROR: could not find offset of " <<
i->second.file_data <<
" to import from " << source_file << std::endl;
378 FILE* fp =
fopen(source_file.c_str(), mode);
380 std::cerr <<
"ERROR: could not open " << source_file <<
" to import " <<
i->second.file_data << std::endl;
390 if (file_name.substr(0, 6) ==
"str://") {
391 std::map<std::string, resource_file_info>::const_iterator
it =
ref_resource_file_map().find(file_name.substr(6));
394 content =
it->second.file_data;
397 if (file_name.substr(0, 6) !=
"res://")
398 return file::read(file_name, content,
ascii);
404 if (!
fread(&content[0], 1, n, fp)) {
415 if (file_name.substr(0,6) !=
"res://")
416 return (
unsigned int) file::size(file_name.c_str());
424 char* file_data = read(file_name,
false, &
file_size);
428 char*
fdata = file_data;
complete implementation of method actions that only call one method when entering a node
the tokenizer allows to split text into tokens in a convenient way.
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
std::string std_ask_dir(const std::string &text, const std::string &path)
std::cout and std::cin based implementation of the ask_dir function for third argument to the user_fe...
std::string & ref_prog_path_prefix()
return a refence to the path prefix of the started executable, this can be prepended for example to d...
std::string find_or_download_data_file(const std::string &file_name, const std::string &find_strategy, const std::string &url, const std::string &cache_strategy, const std::string &producer, const std::string &sub_directory, const std::string &master_path, user_feedback uf)
same as find_data_file() but in case file is not found, it is downloaded from the provided url and st...
void stderr_message(const std::string &text)
std::cerr based implementation of the message function for first argument to the user_feedback constr...
int std_query(const std::string &text, const std::string &answers, int default_answer)
std::cout and std::cin based implementation of the query function for second argument to the user_fee...
unsigned int find_file_offset(const std::string &file_name, const char *data, unsigned int data_size)
find the offset of the given data block in the given file
void pop_file_parent()
pop the latestly pushed parent path from the parent path stack.
void push_file_parent(const std::string &path_or_file_name)
extract a valid path from the given argument and push it onto the stack of parent paths....
std::vector< std::string > & ref_parent_file_stack()
return a reference to the data path list, which is constructed from the environment variable CGV_DATA
bool read_data_file(const std::string &file_name, std::string &content, bool ascii)
read ascii file into a string
std::vector< std::string > & ref_data_path_list()
return a reference to the data path list, which is constructed from the environment variable CGV_DATA
FILE * open_data_file(const std::string &file_name, const char *mode)
open a file with fopen supporting resource files, that have the prefix "res://"
std::map< std::string, resource_file_info > & ref_resource_file_map()
return a reference to a mapping of resource file names to resource file infos
std::string find_data_file(const std::string &file_name, const std::string &strategy, const std::string &sub_directory, const std::string &master_path)
Find a file with the given strategy and return the file name extended by the necessary path.
std::string & ref_prog_name()
return a refence to the name of the started executable
unsigned int data_file_size(const std::string &file_name)
return the file size of a given file with support for resource files, that have the prefix "res://"
void stdout_message(const std::string &text)
std::cout based implementation of the message function for first argument to the user_feedback constr...
namespace that holds tools that dont fit any other namespace
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
void bite_all(tokenizer &t, std::vector< token > &result)
bite all tokens into a token vector
function pointers implementing user feedback functionality of find_or_download_data_file() function