00001 namespace titleformat_inputtypes {
00002 extern const GUID meta, unknown;
00003 };
00004
00005 class NOVTABLE titleformat_text_out {
00006 public:
00007 virtual void write(const GUID & p_inputtype,const char * p_data,t_size p_data_length = infinite) = 0;
00008 void write_int(const GUID & p_inputtype,t_int64 val);
00009 void write_int_padded(const GUID & p_inputtype,t_int64 val,t_int64 maxval);
00010 protected:
00011 titleformat_text_out() {}
00012 ~titleformat_text_out() {}
00013 };
00014
00015
00016 class NOVTABLE titleformat_text_filter {
00017 public:
00018 virtual void write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length) = 0;
00019 protected:
00020 titleformat_text_filter() {}
00021 ~titleformat_text_filter() {}
00022 };
00023
00024 class NOVTABLE titleformat_hook_function_params
00025 {
00026 public:
00027 virtual t_size get_param_count() = 0;
00028 virtual void get_param(t_size index,const char * & p_string,t_size & p_string_len) = 0;
00029
00030
00031 t_size get_param_uint(t_size index);
00032 };
00033
00034 class NOVTABLE titleformat_hook
00035 {
00036 public:
00037 virtual bool process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) = 0;
00038 virtual 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) = 0;
00039 };
00041 class NOVTABLE titleformat_object : public service_base
00042 {
00043 public:
00044 virtual void run(titleformat_hook * p_source,pfc::string_base & p_out,titleformat_text_filter * p_filter)=0;
00045
00046 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);
00047 void run_simple(const playable_location & p_location,const file_info * p_source,pfc::string_base & p_out);
00048
00049 FB2K_MAKE_SERVICE_INTERFACE(titleformat_object,service_base);
00050 };
00051
00054 class NOVTABLE titleformat_compiler : public service_base
00055 {
00056 public:
00058 virtual bool compile(titleformat_object::ptr & p_out,const char * p_spec) = 0;
00060 void run(titleformat_hook * p_source,pfc::string_base & p_out,const char * p_spec);
00062 void compile_safe(titleformat_object::ptr & p_out,const char * p_spec);
00063
00065 void compile_safe_ex(titleformat_object::ptr & p_out,const char * p_spec,const char * p_fallback = "<ERROR>");
00066
00068 void compile_force(titleformat_object::ptr & p_out,const char * p_spec) {if (!compile(p_out,p_spec)) throw pfc::exception_bug_check_v2();}
00069
00070
00071 static void remove_color_marks(const char * src,pfc::string_base & out);
00072 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);
00073 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);
00074 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);
00075
00076 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(titleformat_compiler);
00077 };
00078
00079
00080 class titleformat_object_wrapper {
00081 public:
00082 titleformat_object_wrapper(const char * p_script) {
00083 static_api_ptr_t<titleformat_compiler>()->compile_force(m_script,p_script);
00084 }
00085
00086 operator const service_ptr_t<titleformat_object> &() const {return m_script;}
00087
00088 private:
00089 service_ptr_t<titleformat_object> m_script;
00090 };
00091
00092
00093
00094
00095
00096 class titleformat_text_out_impl_filter_chars : public titleformat_text_out
00097 {
00098 public:
00099 inline titleformat_text_out_impl_filter_chars(titleformat_text_out * p_chain,const char * p_restricted_chars)
00100 : m_chain(p_chain), m_restricted_chars(p_restricted_chars) {}
00101 void write(const GUID & p_inputtype,const char * p_data,t_size p_data_length);
00102 private:
00103 titleformat_text_out * m_chain;
00104 const char * m_restricted_chars;
00105 };
00106
00107 class titleformat_text_out_impl_string : public titleformat_text_out {
00108 public:
00109 titleformat_text_out_impl_string(pfc::string_receiver & p_string) : m_string(p_string) {}
00110 void write(const GUID & p_inputtype,const char * p_data,t_size p_data_length) {m_string.add_string(p_data,p_data_length);}
00111 private:
00112 pfc::string_receiver & m_string;
00113 };
00114
00115 class titleformat_common_methods : public service_base {
00116 public:
00117 virtual bool process_field(const file_info & p_info,const playable_location & p_location,titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) = 0;
00118 virtual bool process_function(const file_info & p_info,const playable_location & p_location,titleformat_text_out * p_out,const char * p_name,t_size p_name_length,titleformat_hook_function_params * p_params,bool & p_found_flag) = 0;
00119 virtual bool remap_meta(const file_info & p_info,t_size & p_index, const char * p_name, t_size p_name_length) = 0;
00120
00121 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(titleformat_common_methods);
00122 };
00123
00124 class titleformat_hook_impl_file_info : public titleformat_hook
00125 {
00126 public:
00127 titleformat_hook_impl_file_info(const playable_location & p_location,const file_info * p_info) : m_location(p_location), m_info(p_info) {}
00128 bool process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag);
00129 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);
00130 protected:
00131 bool remap_meta(t_size & p_index, const char * p_name, t_size p_name_length) {return m_api->remap_meta(*m_info,p_index,p_name,p_name_length);}
00132 const file_info * m_info;
00133 private:
00134 const playable_location & m_location;
00135 static_api_ptr_t<titleformat_common_methods> m_api;
00136 };
00137
00138 class titleformat_hook_impl_splitter : public titleformat_hook {
00139 public:
00140 inline titleformat_hook_impl_splitter(titleformat_hook * p_hook1,titleformat_hook * p_hook2) : m_hook1(p_hook1), m_hook2(p_hook2) {}
00141 bool process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag);
00142 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);
00143 private:
00144 titleformat_hook * m_hook1, * m_hook2;
00145 };
00146
00147 class titleformat_text_filter_impl_reserved_chars : public titleformat_text_filter {
00148 public:
00149 titleformat_text_filter_impl_reserved_chars(const char * p_reserved_chars) : m_reserved_chars(p_reserved_chars) {}
00150 virtual void write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length);
00151 private:
00152 const char * m_reserved_chars;
00153 };
00154
00155 class titleformat_text_filter_impl_filename_chars : public titleformat_text_filter {
00156 public:
00157 void write(const GUID & p_inputType,pfc::string_receiver & p_out,const char * p_data,t_size p_dataLength);
00158 };
00159
00160 class titleformat_text_filter_nontext_chars : public titleformat_text_filter {
00161 public:
00162 inline static bool isReserved(char c) { return c >= 0 && c < 0x20; }
00163 void write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length);
00164 };
00165
00166
00167
00168
00169
00170
00171
00172 class titleformat_hook_impl_list : public titleformat_hook {
00173 public:
00174 titleformat_hook_impl_list(t_size p_index ,t_size p_total) : m_index(p_index), m_total(p_total) {}
00175
00176 bool process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) {
00177 if (
00178 stricmp_utf8_ex(p_name,p_name_length,"list_index",infinite) == 0
00179 ) {
00180 p_out->write_int_padded(titleformat_inputtypes::unknown,m_index+1, m_total);
00181 p_found_flag = true; return true;
00182 } else if (
00183 stricmp_utf8_ex(p_name,p_name_length,"list_total",infinite) == 0
00184 ) {
00185 p_out->write_int(titleformat_inputtypes::unknown,m_total);
00186 p_found_flag = true; return true;
00187 } else {
00188 p_found_flag = false; return false;
00189 }
00190 }
00191
00192 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) {return false;}
00193
00194 private:
00195 t_size m_index, m_total;
00196 };
00197
00198 class string_formatter_tf : public pfc::string_base {
00199 public:
00200 string_formatter_tf(titleformat_text_out * out, const GUID & inputType = titleformat_inputtypes::meta) : m_out(out), m_inputType(inputType) {}
00201
00202 const char * get_ptr() const {
00203 throw pfc::exception_not_implemented();
00204 }
00205 void add_string(const char * p_string,t_size p_length) {
00206 m_out->write(m_inputType,p_string,p_length);
00207 }
00208 void set_string(const char * p_string,t_size p_length) {
00209 throw pfc::exception_not_implemented();
00210 }
00211 void truncate(t_size len) {
00212 throw pfc::exception_not_implemented();
00213 }
00214 t_size get_length() const {
00215 throw pfc::exception_not_implemented();
00216 }
00217 char * lock_buffer(t_size p_requested_length) {
00218 throw pfc::exception_not_implemented();
00219 }
00220 void unlock_buffer() {
00221 throw pfc::exception_not_implemented();
00222 }
00223
00224 private:
00225 titleformat_text_out * const m_out;
00226 const GUID m_inputType;
00227 };