foobar2000 SDK  2015-08-03
titleformat.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
3 
4 #define tf_profiler(x) // profiler(x)
5 
6 void titleformat_compiler::remove_color_marks(const char * src,pfc::string_base & out)//helper
7 {
8  out.reset();
9  while(*src)
10  {
11  if (*src==3)
12  {
13  src++;
14  while(*src && *src!=3) src++;
15  if (*src==3) src++;
16  }
17  else out.add_byte(*src++);
18  }
19 }
20 
21 static bool test_for_bad_char(const char * source,t_size source_char_len,const char * reserved)
22 {
23  return pfc::strstr_ex(reserved,(t_size)(-1),source,source_char_len) != (t_size)(-1);
24 }
25 
26 void titleformat_compiler::remove_forbidden_chars(titleformat_text_out * p_out,const GUID & p_inputtype,const char * p_source,t_size p_source_len,const char * p_reserved_chars)
27 {
28  if (p_reserved_chars == 0 || *p_reserved_chars == 0)
29  {
30  p_out->write(p_inputtype,p_source,p_source_len);
31  }
32  else
33  {
34  p_source_len = pfc::strlen_max(p_source,p_source_len);
35  t_size index = 0;
36  t_size good_byte_count = 0;
37  while(index < p_source_len)
38  {
39  t_size delta = pfc::utf8_char_len(p_source + index,p_source_len - index);
40  if (delta == 0) break;
41  if (test_for_bad_char(p_source+index,delta,p_reserved_chars))
42  {
43  if (good_byte_count > 0) {p_out->write(p_inputtype,p_source+index-good_byte_count,good_byte_count);good_byte_count=0;}
44  p_out->write(p_inputtype,"_",1);
45  }
46  else
47  {
48  good_byte_count += delta;
49  }
50  index += delta;
51  }
52  if (good_byte_count > 0) {p_out->write(p_inputtype,p_source+index-good_byte_count,good_byte_count);good_byte_count=0;}
53  }
54 }
55 
56 void titleformat_compiler::remove_forbidden_chars_string_append(pfc::string_receiver & p_out,const char * p_source,t_size p_source_len,const char * p_reserved_chars)
57 {
58  remove_forbidden_chars(&titleformat_text_out_impl_string(p_out),pfc::guid_null,p_source,p_source_len,p_reserved_chars);
59 }
60 
61 void titleformat_compiler::remove_forbidden_chars_string(pfc::string_base & p_out,const char * p_source,t_size p_source_len,const char * p_reserved_chars)
62 {
63  p_out.reset();
64  remove_forbidden_chars_string_append(p_out,p_source,p_source_len,p_reserved_chars);
65 }
66 
67 bool titleformat_hook_impl_file_info::process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) {
68  return m_api->process_field(*m_info,m_location,p_out,p_name,p_name_length,p_found_flag);
69 }
70 bool titleformat_hook_impl_file_info::process_function(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,titleformat_hook_function_params * p_params,bool & p_found_flag) {
71  return m_api->process_function(*m_info,m_location,p_out,p_name,p_name_length,p_params,p_found_flag);
72 }
73 
74 void titleformat_object::run_hook(const playable_location & p_location,const file_info * p_source,titleformat_hook * p_hook,pfc::string_base & p_out,titleformat_text_filter * p_filter)
75 {
76  if (p_hook)
77  {
78  run(
80  p_hook,
81  &titleformat_hook_impl_file_info(p_location,p_source)
82  ),
83  p_out,p_filter);
84  }
85  else
86  {
87  run(
88  &titleformat_hook_impl_file_info(p_location,p_source),
89  p_out,p_filter);
90  }
91 }
92 
93 void titleformat_object::run_simple(const playable_location & p_location,const file_info * p_source,pfc::string_base & p_out)
94 {
95  run(&titleformat_hook_impl_file_info(p_location,p_source),p_out,NULL);
96 }
97 
99 {
100  const char * str;
101  t_size str_len;
102  get_param(index,str,str_len);
103  return pfc::atoui_ex(str,str_len);
104 }
105 
106 
107 void titleformat_text_out_impl_filter_chars::write(const GUID & p_inputtype,const char * p_data,t_size p_data_length)
108 {
109  titleformat_compiler::remove_forbidden_chars(m_chain,p_inputtype,p_data,p_data_length,m_restricted_chars);
110 }
111 
112 bool titleformat_hook_impl_splitter::process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag)
113 {
114  p_found_flag = false;
115  if (m_hook1 && m_hook1->process_field(p_out,p_name,p_name_length,p_found_flag)) return true;
116  p_found_flag = false;
117  if (m_hook2 && m_hook2->process_field(p_out,p_name,p_name_length,p_found_flag)) return true;
118  p_found_flag = false;
119  return false;
120 }
121 
122 bool titleformat_hook_impl_splitter::process_function(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,titleformat_hook_function_params * p_params,bool & p_found_flag)
123 {
124  p_found_flag = false;
125  if (m_hook1 && m_hook1->process_function(p_out,p_name,p_name_length,p_params,p_found_flag)) return true;
126  p_found_flag = false;
127  if (m_hook2 && m_hook2->process_function(p_out,p_name,p_name_length,p_params,p_found_flag)) return true;
128  p_found_flag = false;
129  return false;
130 }
131 
132 void titleformat_text_out::write_int_padded(const GUID & p_inputtype,t_int64 val,t_int64 maxval)
133 {
134  unsigned width = 0;
135  while(maxval > 0) {maxval/=10;width++;}
136  write(p_inputtype,pfc::format_int(val,width));
137 }
138 
139 void titleformat_text_out::write_int(const GUID & p_inputtype,t_int64 val)
140 {
141  write(p_inputtype,pfc::format_int(val));
142 }
143 void titleformat_text_filter_impl_reserved_chars::write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length)
144 {
145  if (p_inputtype == titleformat_inputtypes::meta) titleformat_compiler::remove_forbidden_chars_string_append(p_out,p_data,p_data_length,m_reserved_chars);
146  else p_out.add_string(p_data,p_data_length);
147 }
148 
149 void titleformat_compiler::run(titleformat_hook * p_source,pfc::string_base & p_out,const char * p_spec)
150 {
152  if (!compile(ptr,p_spec)) p_out = "[COMPILATION ERROR]";
153  else ptr->run(p_source,p_out,NULL);
154 }
155 
157 {
158  if (!compile(p_out,p_spec)) {
159  compile_force(p_out,"%filename%");
160  }
161 }
162 
163 
165  const GUID meta = { 0xcd839c8e, 0x5c66, 0x4ae1, { 0x8d, 0xad, 0x71, 0x1f, 0x86, 0x0, 0xa, 0xe3 } };
166  const GUID unknown = { 0x673aa1cd, 0xa7a8, 0x40c8, { 0xbf, 0x9b, 0x34, 0x37, 0x99, 0x29, 0x16, 0x3b } };
167 };
168 
169 void titleformat_text_filter_impl_filename_chars::write(const GUID & p_inputType,pfc::string_receiver & p_out,const char * p_data,t_size p_dataLength) {
170  if (p_inputType == titleformat_inputtypes::meta) {
171  //slightly inefficient...
172  p_out.add_string( pfc::io::path::replaceIllegalNameChars(pfc::string(p_data,p_dataLength)).ptr());
173  } else p_out.add_string(p_data,p_dataLength);
174 }
175 
176 void titleformat_compiler::compile_safe_ex(titleformat_object::ptr & p_out,const char * p_spec,const char * p_fallback) {
177  if (!compile(p_out,p_spec)) compile_force(p_out,p_fallback);
178 }
179 
180 
181 void titleformat_text_filter_nontext_chars::write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length) {
182  for(t_size walk = 0;;) {
183  t_size base = walk;
184  while(walk < p_data_length && !isReserved(p_data[walk]) && p_data[walk] != 0) walk++;
185  p_out.add_string(p_data+base,walk-base);
186  if (walk >= p_data_length || p_data[walk] == 0) break;
187  p_out.add_byte('_'); walk++;
188  }
189 }
void write(const GUID &p_inputtype, const char *p_data, t_size p_data_length)
bool process_function(titleformat_text_out *p_out, const char *p_name, t_size p_name_length, titleformat_hook_function_params *p_params, bool &p_found_flag)
Definition: titleformat.cpp:70
t_size strstr_ex(const char *p_string, t_size p_string_len, const char *p_substring, t_size p_substring_len)
virtual void write(const GUID &p_inputtype, const char *p_data, t_size p_data_length=~0)=0
Definition: pfc.h:71
void compile_safe_ex(titleformat_object::ptr &p_out, const char *p_spec, const char *p_fallback="<ERROR>")
Falls back to p_fallback in case of failure.
void write_int_padded(const GUID &p_inputtype, t_int64 val, t_int64 maxval)
bool process_field(titleformat_text_out *p_out, const char *p_name, t_size p_name_length, bool &p_found_flag)
Definition: titleformat.cpp:67
void compile_safe(titleformat_object::ptr &p_out, const char *p_spec)
Should never fail, falls back to filename% in case of failure.
static void remove_forbidden_chars_string(pfc::string_base &p_out, const char *p_source, t_size p_source_len, const char *p_forbidden_chars)
Definition: titleformat.cpp:61
static void remove_forbidden_chars_string_append(pfc::string_receiver &p_out, const char *p_source, t_size p_source_len, const char *p_forbidden_chars)
Definition: titleformat.cpp:56
Main interface class for information about some playable object.
Definition: file_info.h:73
t_size get_param_uint(t_size index)
Definition: titleformat.cpp:98
t_size strlen_max(const char *ptr, t_size max)
Definition: string_base.h:91
virtual void add_string(const char *p_string, t_size p_string_size=~0)=0
size_t t_size
Definition: int_types.h:48
static void remove_color_marks(const char *src, pfc::string_base &out)
Definition: titleformat.cpp:6
void write(const service_ptr_t< file > &p_file, abort_callback &p_abort, const char *p_string, bool is_utf8)
unsigned atoui_ex(const char *p_string, t_size p_string_len)
string replaceIllegalNameChars(string fn, bool allowWC)
Definition: pathUtils.cpp:93
static bool test_for_bad_char(const char *source, t_size source_char_len, const char *reserved)
Definition: titleformat.cpp:21
void run_simple(const playable_location &p_location, const file_info *p_source, pfc::string_base &p_out)
Definition: titleformat.cpp:93
void write(const GUID &p_inputtype, pfc::string_receiver &p_out, const char *p_data, t_size p_data_length)
void write_int(const GUID &p_inputtype, t_int64 val)
void run_hook(const playable_location &p_location, const file_info *p_source, titleformat_hook *p_hook, pfc::string_base &p_out, titleformat_text_filter *p_filter)
Definition: titleformat.cpp:74
void add_byte(char c)
Definition: string_base.h:42
bool process_function(titleformat_text_out *p_out, const char *p_name, t_size p_name_length, titleformat_hook_function_params *p_params, bool &p_found_flag)
virtual bool compile(titleformat_object::ptr &p_out, const char *p_spec)=0
Returns false in case of a compilation error.
void compile_force(titleformat_object::ptr &p_out, const char *p_spec)
Throws a bug check exception when script can&#39;t be compiled. For use with hardcoded scripts only...
Definition: titleformat.h:68
virtual void write(const GUID &p_inputtype, pfc::string_receiver &p_out, const char *p_data, t_size p_data_length)
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
void run(titleformat_hook *p_source, pfc::string_base &p_out, const char *p_spec)
Helper;.
const GUID guid_null
Definition: guid.cpp:175
t_size utf8_char_len(const char *s, t_size max=~0)
Definition: utf8.cpp:246
static void remove_forbidden_chars(titleformat_text_out *p_out, const GUID &p_inputtype, const char *p_source, t_size p_source_len, const char *p_forbidden_chars)
Definition: titleformat.cpp:26
bool process_field(titleformat_text_out *p_out, const char *p_name, t_size p_name_length, bool &p_found_flag)
void write(const GUID &p_inputType, pfc::string_receiver &p_out, const char *p_data, t_size p_dataLength)
int64_t t_int64
Definition: int_types.h:2