Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/file_info_const_impl.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "foobar2000-sdk-pch.h" | |
| 2 | |
| 3 #include "file_info_const_impl.h" | |
| 4 | |
| 5 // presorted - do not change without a proper strcmp resort | |
| 6 static const char * const standard_fieldnames[] = { | |
| 7 "ALBUM","ALBUM ARTIST","ARTIST","Album","Album Artist","Artist","COMMENT","Comment","DATE","DISCNUMBER","Date", | |
| 8 "Discnumber","GENRE","Genre","TITLE","TOTALTRACKS","TRACKNUMBER","Title","TotalTracks","Totaltracks","TrackNumber", | |
| 9 "Tracknumber","album","album artist","artist","comment","date","discnumber","genre","title","totaltracks","tracknumber", | |
| 10 }; | |
| 11 | |
| 12 // presorted - do not change without a proper strcmp resort | |
| 13 static const char * const standard_infonames[] = { | |
| 14 "bitrate","bitspersample","channels","codec","codec_profile","encoding","samplerate","tagtype","tool", | |
| 15 }; | |
| 16 | |
| 17 static const char * optimize_fieldname(const char * p_string) { | |
| 18 t_size index; | |
| 19 if (!pfc::binarySearch<pfc::comparator_strcmp>::run(standard_fieldnames,0,PFC_TABSIZE(standard_fieldnames),p_string,index)) return NULL; | |
| 20 return standard_fieldnames[index]; | |
| 21 } | |
| 22 | |
| 23 static const char * optimize_infoname(const char * p_string) { | |
| 24 t_size index; | |
| 25 if (!pfc::binarySearch<pfc::comparator_strcmp>::run(standard_infonames,0,PFC_TABSIZE(standard_infonames),p_string,index)) return NULL; | |
| 26 return standard_infonames[index]; | |
| 27 } | |
| 28 | |
| 29 /* | |
| 30 order of things | |
| 31 | |
| 32 meta entries | |
| 33 meta value map | |
| 34 info entries | |
| 35 string buffer | |
| 36 | |
| 37 */ | |
| 38 | |
| 39 inline static char* stringbuffer_append(char * & buffer,const char * value) | |
| 40 { | |
| 41 char * ret = buffer; | |
| 42 while(*value) *(buffer++) = *(value++); | |
| 43 *(buffer++) = 0; | |
| 44 return ret; | |
| 45 } | |
| 46 | |
| 47 #ifdef __file_info_const_impl_have_hintmap__ | |
| 48 | |
| 49 namespace { | |
| 50 class sort_callback_hintmap_impl : public pfc::sort_callback | |
| 51 { | |
| 52 public: | |
| 53 sort_callback_hintmap_impl(const file_info_const_impl::meta_entry * p_meta,file_info_const_impl::t_index * p_hintmap) | |
| 54 : m_meta(p_meta), m_hintmap(p_hintmap) | |
| 55 { | |
| 56 } | |
| 57 | |
| 58 int compare(t_size p_index1, t_size p_index2) const | |
| 59 { | |
| 60 // profiler(sort_callback_hintmap_impl_compare); | |
| 61 return pfc::stricmp_ascii(m_meta[m_hintmap[p_index1]].m_name,m_meta[m_hintmap[p_index2]].m_name); | |
| 62 } | |
| 63 | |
| 64 void swap(t_size p_index1, t_size p_index2) | |
| 65 { | |
| 66 pfc::swap_t<file_info_const_impl::t_index>(m_hintmap[p_index1],m_hintmap[p_index2]); | |
| 67 } | |
| 68 private: | |
| 69 const file_info_const_impl::meta_entry * m_meta; | |
| 70 file_info_const_impl::t_index * m_hintmap; | |
| 71 }; | |
| 72 | |
| 73 class bsearch_callback_hintmap_impl// : public pfc::bsearch_callback | |
| 74 { | |
| 75 public: | |
| 76 bsearch_callback_hintmap_impl( | |
| 77 const file_info_const_impl::meta_entry * p_meta, | |
| 78 const file_info_const_impl::t_index * p_hintmap, | |
| 79 const char * p_name, | |
| 80 t_size p_name_length) | |
| 81 : m_meta(p_meta), m_hintmap(p_hintmap), m_name(p_name), m_name_length(p_name_length) | |
| 82 { | |
| 83 } | |
| 84 | |
| 85 inline int test(t_size p_index) const | |
| 86 { | |
| 87 return pfc::stricmp_ascii_ex(m_meta[m_hintmap[p_index]].m_name,SIZE_MAX,m_name,m_name_length); | |
| 88 } | |
| 89 | |
| 90 private: | |
| 91 const file_info_const_impl::meta_entry * m_meta; | |
| 92 const file_info_const_impl::t_index * m_hintmap; | |
| 93 const char * m_name; | |
| 94 t_size m_name_length; | |
| 95 }; | |
| 96 } | |
| 97 | |
| 98 #endif//__file_info_const_impl_have_hintmap__ | |
| 99 | |
| 100 void file_info_const_impl::copy(const file_info & p_source) | |
| 101 { | |
| 102 // profiler(file_info_const_impl__copy); | |
| 103 t_size meta_size = 0; | |
| 104 t_size info_size = 0; | |
| 105 t_size valuemap_size = 0; | |
| 106 t_size stringbuffer_size = 0; | |
| 107 #ifdef __file_info_const_impl_have_hintmap__ | |
| 108 t_size hintmap_size = 0; | |
| 109 #endif | |
| 110 | |
| 111 const char * optbuf[64]; | |
| 112 size_t optwalk = 0; | |
| 113 | |
| 114 { | |
| 115 // profiler(file_info_const_impl__copy__pass1); | |
| 116 t_size index; | |
| 117 m_meta_count = pfc::downcast_guarded<t_index>(p_source.meta_get_count()); | |
| 118 meta_size = m_meta_count * sizeof(meta_entry); | |
| 119 #ifdef __file_info_const_impl_have_hintmap__ | |
| 120 hintmap_size = (m_meta_count > hintmap_cutoff) ? m_meta_count * sizeof(t_index) : 0; | |
| 121 #endif//__file_info_const_impl_have_hintmap__ | |
| 122 for(index = 0; index < m_meta_count; index++ ) | |
| 123 { | |
| 124 { | |
| 125 const char * name = p_source.meta_enum_name(index); | |
| 126 const char * opt = optimize_fieldname(name); | |
| 127 if (optwalk < PFC_TABSIZE(optbuf)) optbuf[optwalk++] = opt; | |
| 128 if (opt == NULL) stringbuffer_size += strlen(name) + 1; | |
| 129 } | |
| 130 | |
| 131 t_size val; const t_size val_max = p_source.meta_enum_value_count(index); | |
| 132 | |
| 133 if (val_max == 1) | |
| 134 { | |
| 135 stringbuffer_size += strlen(p_source.meta_enum_value(index,0)) + 1; | |
| 136 } | |
| 137 else | |
| 138 { | |
| 139 valuemap_size += val_max * sizeof(char*); | |
| 140 | |
| 141 for(val = 0; val < val_max; val++ ) | |
| 142 { | |
| 143 stringbuffer_size += strlen(p_source.meta_enum_value(index,val)) + 1; | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 m_info_count = pfc::downcast_guarded<t_index>(p_source.info_get_count()); | |
| 149 info_size = m_info_count * sizeof(info_entry); | |
| 150 for(index = 0; index < m_info_count; index++ ) | |
| 151 { | |
| 152 const char * name = p_source.info_enum_name(index); | |
| 153 const char * opt = optimize_infoname(name); | |
| 154 if (optwalk < PFC_TABSIZE(optbuf)) optbuf[optwalk++] = opt; | |
| 155 if (opt == NULL) stringbuffer_size += strlen(name) + 1; | |
| 156 stringbuffer_size += strlen(p_source.info_enum_value(index)) + 1; | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 | |
| 161 { | |
| 162 // profiler(file_info_const_impl__copy__alloc); | |
| 163 m_buffer.set_size( | |
| 164 #ifdef __file_info_const_impl_have_hintmap__ | |
| 165 hintmap_size + | |
| 166 #endif | |
| 167 meta_size + info_size + valuemap_size + stringbuffer_size); | |
| 168 } | |
| 169 | |
| 170 char * walk = m_buffer.get_ptr(); | |
| 171 | |
| 172 #ifdef __file_info_const_impl_have_hintmap__ | |
| 173 t_index* hintmap = (hintmap_size > 0) ? (t_index*) walk : NULL; | |
| 174 walk += hintmap_size; | |
| 175 #endif | |
| 176 meta_entry * meta = (meta_entry*) walk; | |
| 177 walk += meta_size; | |
| 178 char ** valuemap = (char**) walk; | |
| 179 walk += valuemap_size; | |
| 180 info_entry * info = (info_entry*) walk; | |
| 181 walk += info_size; | |
| 182 char * stringbuffer = walk; | |
| 183 | |
| 184 m_meta = meta; | |
| 185 m_info = info; | |
| 186 #ifdef __file_info_const_impl_have_hintmap__ | |
| 187 m_hintmap = hintmap; | |
| 188 #endif | |
| 189 | |
| 190 optwalk = 0; | |
| 191 { | |
| 192 // profiler(file_info_const_impl__copy__pass2); | |
| 193 t_size index; | |
| 194 for( index = 0; index < m_meta_count; index ++ ) | |
| 195 { | |
| 196 t_size val; const t_size val_max = p_source.meta_enum_value_count(index); | |
| 197 | |
| 198 { | |
| 199 const char * name = p_source.meta_enum_name(index); | |
| 200 const char * name_opt; | |
| 201 | |
| 202 if (optwalk < PFC_TABSIZE(optbuf)) name_opt = optbuf[optwalk++]; | |
| 203 else name_opt = optimize_fieldname(name); | |
| 204 | |
| 205 if (name_opt == NULL) | |
| 206 meta[index].m_name = stringbuffer_append(stringbuffer, name ); | |
| 207 else | |
| 208 meta[index].m_name = name_opt; | |
| 209 } | |
| 210 | |
| 211 meta[index].m_valuecount = val_max; | |
| 212 | |
| 213 if (val_max == 1) | |
| 214 { | |
| 215 meta[index].m_valuemap = reinterpret_cast<const char * const *>(stringbuffer_append(stringbuffer, p_source.meta_enum_value(index,0) )); | |
| 216 } | |
| 217 else | |
| 218 { | |
| 219 meta[index].m_valuemap = valuemap; | |
| 220 for( val = 0; val < val_max ; val ++ ) | |
| 221 *(valuemap ++ ) = stringbuffer_append(stringbuffer, p_source.meta_enum_value(index,val) ); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 for( index = 0; index < m_info_count; index ++ ) | |
| 226 { | |
| 227 const char * name = p_source.info_enum_name(index); | |
| 228 const char * name_opt; | |
| 229 | |
| 230 if (optwalk < PFC_TABSIZE(optbuf)) name_opt = optbuf[optwalk++]; | |
| 231 else name_opt = optimize_infoname(name); | |
| 232 | |
| 233 if (name_opt == NULL) | |
| 234 info[index].m_name = stringbuffer_append(stringbuffer, name ); | |
| 235 else | |
| 236 info[index].m_name = name_opt; | |
| 237 info[index].m_value = stringbuffer_append(stringbuffer, p_source.info_enum_value(index) ); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 m_length = p_source.get_length(); | |
| 242 m_replaygain = p_source.get_replaygain(); | |
| 243 #ifdef __file_info_const_impl_have_hintmap__ | |
| 244 if (hintmap != NULL) { | |
| 245 // profiler(file_info_const_impl__copy__hintmap); | |
| 246 for(t_size n=0;n<m_meta_count;n++) hintmap[n]= (t_index) n; | |
| 247 sort_callback_hintmap_impl cb(meta,hintmap); | |
| 248 pfc::sort(cb,m_meta_count); | |
| 249 } | |
| 250 #endif//__file_info_const_impl_have_hintmap__ | |
| 251 } | |
| 252 | |
| 253 | |
| 254 void file_info_const_impl::reset() | |
| 255 { | |
| 256 m_meta_count = m_info_count = 0; m_length = 0; m_replaygain.reset(); | |
| 257 } | |
| 258 | |
| 259 t_size file_info_const_impl::meta_find_ex(const char * p_name,t_size p_name_length) const | |
| 260 { | |
| 261 #ifdef __file_info_const_impl_have_hintmap__ | |
| 262 if (m_hintmap != NULL) { | |
| 263 t_size result = SIZE_MAX; | |
| 264 if (!pfc::bsearch_inline_t(m_meta_count,bsearch_callback_hintmap_impl(m_meta,m_hintmap,p_name,p_name_length),result)) return SIZE_MAX; | |
| 265 else return m_hintmap[result]; | |
| 266 } else { | |
| 267 return file_info::meta_find_ex(p_name,p_name_length); | |
| 268 } | |
| 269 #else | |
| 270 return file_info::meta_find_ex(p_name,p_name_length); | |
| 271 #endif | |
| 272 } | |
| 273 | |
| 274 | |
| 275 t_size file_info_const_impl::meta_enum_value_count(t_size p_index) const | |
| 276 { | |
| 277 return m_meta[p_index].m_valuecount; | |
| 278 } | |
| 279 | |
| 280 const char* file_info_const_impl::meta_enum_value(t_size p_index,t_size p_value_number) const | |
| 281 { | |
| 282 const meta_entry & entry = m_meta[p_index]; | |
| 283 if (entry.m_valuecount == 1) | |
| 284 return reinterpret_cast<const char*>(entry.m_valuemap); | |
| 285 else | |
| 286 return entry.m_valuemap[p_value_number]; | |
| 287 } |
