foobar2000 SDK  2015-01-14
create_directory_helper.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
4 {
5  static void create_path_internal(const char * p_path,t_size p_base,abort_callback & p_abort) {
7  for(t_size walk = p_base; p_path[walk]; walk++) {
8  if (p_path[walk] == '\\') {
9  temp.set_string(p_path,walk);
10  try {filesystem::g_create_directory(temp.get_ptr(),p_abort);} catch(exception_io_already_exists) {}
11  }
12  }
13  }
14 
15  static bool is_valid_netpath_char(char p_char) {
16  return pfc::char_is_ascii_alphanumeric(p_char) || p_char == '_' || p_char == '-' || p_char == '.';
17  }
18 
19  static bool test_localpath(const char * p_path) {
20  if (pfc::strcmp_partial(p_path,"file://") == 0) p_path += strlen("file://");
21  return pfc::char_is_ascii_alpha(p_path[0]) &&
22  p_path[1] == ':' &&
23  p_path[2] == '\\';
24  }
25  static bool test_netpath(const char * p_path) {
26  if (pfc::strcmp_partial(p_path,"file://") == 0) p_path += strlen("file://");
27  if (*p_path != '\\') return false;
28  p_path++;
29  if (*p_path != '\\') return false;
30  p_path++;
31  if (!is_valid_netpath_char(*p_path)) return false;
32  p_path++;
33  while(is_valid_netpath_char(*p_path)) p_path++;
34  if (*p_path != '\\') return false;
35  return true;
36  }
37 
38  void create_path(const char * p_path,abort_callback & p_abort) {
39  if (test_localpath(p_path)) {
40  t_size walk = 0;
41  if (pfc::strcmp_partial(p_path,"file://") == 0) walk += strlen("file://");
42  create_path_internal(p_path,walk + 3,p_abort);
43  } else if (test_netpath(p_path)) {
44  t_size walk = 0;
45  if (pfc::strcmp_partial(p_path,"file://") == 0) walk += strlen("file://");
46  while(p_path[walk] == '\\') walk++;
47  while(p_path[walk] != 0 && p_path[walk] != '\\') walk++;
48  while(p_path[walk] == '\\') walk++;
49  while(p_path[walk] != 0 && p_path[walk] != '\\') walk++;
50  while(p_path[walk] == '\\') walk++;
51  create_path_internal(p_path,walk,p_abort);
52  } else {
53  pfc::throw_exception_with_message< exception_io > ("Could not create directory structure; unknown path format");
54  }
55  }
56 
57 #ifdef _WIN32
58  static bool is_bad_dirchar(char c)
59  {
60  return c==' ' || c=='.';
61  }
62 #endif
63 
64  void make_path(const char * parent,const char * filename,const char * extension,bool allow_new_dirs,pfc::string8 & out,bool really_create_dirs,abort_callback & p_abort)
65  {
66  out.reset();
67  if (parent && *parent)
68  {
69  out = parent;
70  out.fix_dir_separator('\\');
71  }
72  bool last_char_is_dir_sep = true;
73  while(*filename)
74  {
75 #ifdef WIN32
76  if (allow_new_dirs && is_bad_dirchar(*filename))
77  {
78  const char * ptr = filename+1;
79  while(is_bad_dirchar(*ptr)) ptr++;
80  if (*ptr!='\\' && *ptr!='/') out.add_string(filename,ptr-filename);
81  filename = ptr;
82  if (*filename==0) break;
83  }
84 #endif
85  if (pfc::is_path_bad_char(*filename))
86  {
87  if (allow_new_dirs && (*filename=='\\' || *filename=='/'))
88  {
89  if (!last_char_is_dir_sep)
90  {
91  if (really_create_dirs) try{filesystem::g_create_directory(out,p_abort);}catch(exception_io_already_exists){}
92  out.add_char('\\');
93  last_char_is_dir_sep = true;
94  }
95  }
96  else
97  out.add_char('_');
98  }
99  else
100  {
101  out.add_byte(*filename);
102  last_char_is_dir_sep = false;
103  }
104  filename++;
105  }
106  if (out.length()>0 && out[out.length()-1]=='\\')
107  {
108  out.add_string("noname");
109  }
110  if (extension && *extension)
111  {
112  out.add_char('.');
113  out.add_string(extension);
114  }
115  }
116 }
117 
119  pfc::string out;
120  t_size curSegBase = 0;
121  for(t_size walk = 0; ; ++walk) {
122  const char c = formatted[walk];
123  if (c == 0 || pfc::io::path::isSeparator(c)) {
124  if (curSegBase < walk) {
125  pfc::string seg( formatted + curSegBase, walk - curSegBase );
127  }
128  if (c == 0) break;
129  curSegBase = walk + 1;
130  }
131  }
132  return out;
133 };
134 
135 void create_directory_helper::format_filename_ex(const metadb_handle_ptr & handle,titleformat_hook * p_hook,titleformat_object::ptr spec,const char * suffix, pfc::string_base & out) {
136  pfc::string_formatter formatted;
138  handle->format_title(p_hook,formatted,spec,&filter);
139  formatted << suffix;
140  out = sanitize_formatted_path(formatted).ptr();
141 }
142 void create_directory_helper::format_filename(const metadb_handle_ptr & handle,titleformat_hook * p_hook,titleformat_object::ptr spec,pfc::string_base & out) {
143  format_filename_ex(handle, p_hook, spec, "", out);
144 }
146 {
148  if (static_api_ptr_t<titleformat_compiler>()->compile(script,spec)) {
149  format_filename(handle, p_hook, script, out);
150  } else {
151  out.reset();
152  }
153 }
154 
155 void create_directory_helper::titleformat_text_filter_myimpl::write(const GUID & p_inputType,pfc::string_receiver & p_out,const char * p_data,t_size p_dataLength) {
156  if (p_inputType == titleformat_inputtypes::meta) {
158  for(t_size walk = 0; walk < p_dataLength; ++walk) {
159  char c = p_data[walk];
160  if (c == 0) break;
162  c = '-';
163  }
164  temp.add_byte(c);
165  }
166  p_out.add_string(temp);
167  } else p_out.add_string(p_data,p_dataLength);
168 }
void format_filename_ex(const metadb_handle_ptr &handle, titleformat_hook *p_hook, titleformat_object::ptr spec, const char *suffix, pfc::string_base &out)
Definition: pfc.h:53
void create_path(const char *p_path, abort_callback &p_abort)
static bool test_netpath(const char *p_path)
void fix_dir_separator(char c= '\\')
bool char_is_ascii_alpha(char p_char)
Definition: string_base.h:103
string combine(string basePath, string fileName)
Definition: pathUtils.cpp:41
static bool test_localpath(const char *p_path)
void make_path(const char *parent, const char *filename, const char *extension, bool allow_new_dirs, pfc::string8 &out, bool really_create_dirs, abort_callback &p_abort)
void write(const GUID &p_inputType, pfc::string_receiver &p_out, const char *p_data, t_size p_dataLength)
string validateFileName(string name, bool allowWC)
Definition: pathUtils.cpp:155
const char * ptr() const
Definition: stringNew.h:124
bool isSeparator(char c)
Definition: pathUtils.cpp:53
void format_filename(const metadb_handle_ptr &handle, titleformat_hook *p_hook, const char *spec, pfc::string_base &out)
"String parameter" helper class, to use in function parameters, allowing functions to take any type o...
Definition: stringNew.h:223
void add_string(const char *p_string, t_size p_length=~0)
Definition: string8_impl.h:4
virtual void add_string(const char *p_string, t_size p_string_size=~0)=0
static bool is_bad_dirchar(char c)
size_t t_size
Definition: int_types.h:48
string8_fastalloc string_formatter
Definition: string_base.h:614
pfc::string sanitize_formatted_path(pfc::stringp str, bool allowWC=false)
static void create_path_internal(const char *p_path, t_size p_base, abort_callback &p_abort)
void add_char(t_uint32 c)
Definition: string_base.cpp:5
int strcmp_partial(const char *str, const char *substr)
Definition: string_base.h:1088
Autopointer class to be used with all services. Manages reference counter calls behind-the-scenes.
Definition: service.h:55
void add_byte(char c)
Definition: string_base.h:42
New EXPERIMENTAL string class, allowing efficient copies and returning from functions. Does not implement the string_base interface so you still need string8 in many cases. Safe to pass between DLLs, but since a reference is used, objects possibly created by other DLLs must be released before owning DLLs are unloaded.
Definition: stringNew.h:19
static bool is_valid_netpath_char(char p_char)
bool is_path_bad_char(unsigned c)
Definition: string_base.cpp:64
Helper template used to easily access core services. Usage: static_api_ptr_t api; api->doso...
Definition: service.h:533
bool char_is_ascii_alphanumeric(char p_char)
Definition: string_base.h:104
string8_t< pfc::alloc_fast_aggressive > string8_fastalloc
Definition: string_base.h:435
t_size length() const
For compatibility with old conventions.
Definition: string_base.h:208