📄 xdgmimecache.c
字号:
character = _xdg_ucs4_to_lower ( character ); min = 0; max = n_entries - 1; while ( max >= min ) { mid = ( min + max ) / 2; match_char = GET_UINT32 ( cache->buffer, offset + 16 * mid ); if ( match_char < character ) min = mid + 1; else if ( match_char > character ) max = mid - 1; else { suffix = _xdg_utf8_next_char ( suffix ); if ( *suffix == '\0' ) { mimetype_offset = GET_UINT32 ( cache->buffer, offset + 16 * mid + 4 ); n = 0; mime_types[ n++ ] = cache->buffer + mimetype_offset; n_children = GET_UINT32 ( cache->buffer, offset + 16 * mid + 8 ); child_offset = GET_UINT32 ( cache->buffer, offset + 16 * mid + 12 ); i = 0; while ( n < n_mime_types && i < n_children ) { match_char = GET_UINT32 ( cache->buffer, child_offset + 16 * i ); mimetype_offset = GET_UINT32 ( cache->buffer, offset + 16 * i + 4 ); if ( match_char != 0 ) break; mime_types[ n++ ] = cache->buffer + mimetype_offset; i++; } return n; } else { n_children = GET_UINT32 ( cache->buffer, offset + 16 * mid + 8 ); child_offset = GET_UINT32 ( cache->buffer, offset + 16 * mid + 12 ); return cache_glob_node_lookup_suffix ( cache, n_children, child_offset, suffix, ignore_case, mime_types, n_mime_types ); } } } return 0;}static intcache_glob_lookup_suffix ( const char *suffix, int ignore_case, const char *mime_types[], int n_mime_types ){ int i, n; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; xdg_uint32_t list_offset = GET_UINT32 ( cache->buffer, 16 ); xdg_uint32_t n_entries = GET_UINT32 ( cache->buffer, list_offset ); xdg_uint32_t offset = GET_UINT32 ( cache->buffer, list_offset + 4 ); n = cache_glob_node_lookup_suffix ( cache, n_entries, offset, suffix, ignore_case, mime_types, n_mime_types ); if ( n > 0 ) return n; } return 0;}static voidfind_stopchars ( char *stopchars ){ int i, j, k, l; k = 0; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; xdg_uint32_t list_offset = GET_UINT32 ( cache->buffer, 16 ); xdg_uint32_t n_entries = GET_UINT32 ( cache->buffer, list_offset ); xdg_uint32_t offset = GET_UINT32 ( cache->buffer, list_offset + 4 ); for ( j = 0; j < n_entries; j++ ) { xdg_uint32_t match_char = GET_UINT32 ( cache->buffer, offset ); if ( match_char < 128 ) { for ( l = 0; l < k; l++ ) if ( stopchars[ l ] == match_char ) break; if ( l == k ) { stopchars[ k ] = ( char ) match_char; k++; } } offset += 16; } } stopchars[ k ] = '\0';}static intcache_glob_lookup_file_name ( const char *file_name, const char *mime_types[], int n_mime_types ){ const char * ptr; char stopchars[ 128 ]; int n; assert ( file_name != NULL ); /* First, check the literals */ n = cache_glob_lookup_literal ( file_name, mime_types, n_mime_types ); if ( n > 0 ) return n; find_stopchars ( stopchars ); /* Next, check suffixes */ ptr = strpbrk ( file_name, stopchars ); while ( ptr ) { n = cache_glob_lookup_suffix ( ptr, FALSE, mime_types, n_mime_types ); if ( n > 0 ) return n; n = cache_glob_lookup_suffix ( ptr, TRUE, mime_types, n_mime_types ); if ( n > 0 ) return n; ptr = strpbrk ( ptr + 1, stopchars ); } /* Last, try fnmatch */ return cache_glob_lookup_fnmatch ( file_name, mime_types, n_mime_types );}int_xdg_mime_cache_get_max_buffer_extents ( void ){ xdg_uint32_t offset; xdg_uint32_t max_extent; int i; max_extent = 0; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; offset = GET_UINT32 ( cache->buffer, 24 ); max_extent = MAX ( max_extent, GET_UINT32 ( cache->buffer, offset + 4 ) ); } return max_extent;}static const char *cache_get_mime_type_for_data ( const void *data, size_t len, const char *mime_types[], int n_mime_types ){ const char * mime_type; int i, n, priority; priority = 0; mime_type = NULL; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; int prio; const char *match; match = cache_magic_lookup_data ( cache, data, len, &prio, mime_types, n_mime_types ); if ( prio > priority ) { priority = prio; mime_type = match; } } if ( priority > 0 ) return mime_type; for ( n = 0; n < n_mime_types; n++ ) { if ( mime_types[ n ] ) return mime_types[ n ]; } return XDG_MIME_TYPE_UNKNOWN;}const char *_xdg_mime_cache_get_mime_type_for_data ( const void *data, size_t len ){ return cache_get_mime_type_for_data ( data, len, NULL, 0 );}const char *_xdg_mime_cache_get_mime_type_for_file ( const char *file_name, struct stat *statbuf ){ const char *mime_type; const char *mime_types[ 2 ]; FILE *file; unsigned char *data; int max_extent; int bytes_read; struct stat buf; const char *base_name; int n; if ( file_name == NULL ) return NULL; if ( ! _xdg_utf8_validate ( file_name ) ) return NULL; base_name = _xdg_get_base_name ( file_name ); n = cache_glob_lookup_file_name ( base_name, mime_types, 2 ); if ( n == 1 ) return mime_types[ 0 ]; if ( !statbuf ) { if ( stat ( file_name, &buf ) != 0 ) return XDG_MIME_TYPE_UNKNOWN; statbuf = &buf; } if ( !S_ISREG ( statbuf->st_mode ) ) return XDG_MIME_TYPE_UNKNOWN; /* FIXME: Need to make sure that max_extent isn't totally broken. This could * be large and need getting from a stream instead of just reading it all * in. */ max_extent = _xdg_mime_cache_get_max_buffer_extents (); data = malloc ( max_extent ); if ( data == NULL ) return XDG_MIME_TYPE_UNKNOWN; file = fopen ( file_name, "r" ); if ( file == NULL ) { free ( data ); return XDG_MIME_TYPE_UNKNOWN; } bytes_read = fread ( data, 1, max_extent, file ); if ( ferror ( file ) ) { free ( data ); fclose ( file ); return XDG_MIME_TYPE_UNKNOWN; } mime_type = cache_get_mime_type_for_data ( data, bytes_read, mime_types, n ); free ( data ); fclose ( file ); return mime_type;}const char *_xdg_mime_cache_get_mime_type_from_file_name ( const char *file_name ){ const char * mime_types[ 2 ]; if ( cache_glob_lookup_file_name ( file_name, mime_types, 2 ) == 1 ) return mime_types[ 0 ]; else return XDG_MIME_TYPE_UNKNOWN;}#if 1static intis_super_type ( const char *mime ){ int length; const char *type; length = strlen ( mime ); type = &( mime[ length - 2 ] ); if ( strcmp ( type, "/*" ) == 0 ) return 1; return 0;}#endifint_xdg_mime_cache_mime_type_subclass ( const char *mime, const char *base ){ const char * umime, *ubase; int i, j, min, max, med, cmp; umime = _xdg_mime_cache_unalias_mime_type ( mime ); ubase = _xdg_mime_cache_unalias_mime_type ( base ); if ( strcmp ( umime, ubase ) == 0 ) return 1; /* We really want to handle text/ * in GtkFileFilter, so we just * turn on the supertype matching */#if 1 /* Handle supertypes */ if ( is_super_type ( ubase ) && xdg_mime_media_type_equal ( umime, ubase ) ) return 1;#endif /* Handle special cases text/plain and application/octet-stream */ if ( strcmp ( ubase, XDG_MIME_TYPE_PLAIN_TEXT ) == 0 && strncmp ( umime, "text/", 5 ) == 0 ) return 1; if ( strcmp ( ubase, XDG_MIME_TYPE_UNKNOWN ) == 0 ) return 1; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; xdg_uint32_t list_offset = GET_UINT32 ( cache->buffer, 8 ); xdg_uint32_t n_entries = GET_UINT32 ( cache->buffer, list_offset ); xdg_uint32_t offset, n_parents, parent_offset; min = 0; max = n_entries - 1; while ( max >= min ) { med = ( min + max ) / 2; offset = GET_UINT32 ( cache->buffer, list_offset + 4 + 8 * med ); cmp = strcmp ( cache->buffer + offset, umime ); if ( cmp < 0 ) min = med + 1; else if ( cmp > 0 ) max = med - 1; else { offset = GET_UINT32 ( cache->buffer, list_offset + 4 + 8 * med + 4 ); n_parents = GET_UINT32 ( cache->buffer, offset ); for ( j = 0; j < n_parents; j++ ) { parent_offset = GET_UINT32 ( cache->buffer, offset + 4 + 4 * j ); if ( _xdg_mime_cache_mime_type_subclass ( cache->buffer + parent_offset, ubase ) ) return 1; } break; } } } return 0;}const char *_xdg_mime_cache_unalias_mime_type ( const char *mime ){ const char * lookup; lookup = cache_alias_lookup ( mime ); if ( lookup ) return lookup; return mime;}char **_xdg_mime_cache_list_mime_parents ( const char *mime ){ int i, j, p; char *all_parents[ 128 ]; /* we'll stop at 128 */ char **result; p = 0; for ( i = 0; _caches[ i ]; i++ ) { XdgMimeCache *cache = _caches[ i ]; xdg_uint32_t list_offset = GET_UINT32 ( cache->buffer, 8 ); xdg_uint32_t n_entries = GET_UINT32 ( cache->buffer, list_offset ); for ( j = 0; j < n_entries; j++ ) { xdg_uint32_t mimetype_offset = GET_UINT32 ( cache->buffer, list_offset + 4 + 8 * i ); xdg_uint32_t parents_offset = GET_UINT32 ( cache->buffer, list_offset + 4 + 8 * i + 4 ); if ( strcmp ( cache->buffer + mimetype_offset, mime ) == 0 ) { xdg_uint32_t n_parents = GET_UINT32 ( cache->buffer, parents_offset ); for ( j = 0; j < n_parents; j++ ) all_parents[ p++ ] = cache->buffer + parents_offset + 4 + 4 * j; break; } } } all_parents[ p++ ] = 0; result = ( char ** ) malloc ( p * sizeof ( char * ) ); memcpy ( result, all_parents, p * sizeof ( char * ) ); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -