static int _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, const char *file_name, int ignore_case, const char *mime_types[], int n_mime_types) { int n; XdgGlobHashNode *node; xdg_unichar_t character; if (glob_hash_node == NULL) return 0; character = _xdg_utf8_to_ucs4 (file_name); if (ignore_case) character = _xdg_ucs4_to_lower(character); for (node = glob_hash_node; node && character >= node->character; node = node->next) { if (character == node->character) { file_name = _xdg_utf8_next_char (file_name); if (*file_name == '\000') { n = 0; if (node->mime_type) mime_types[n++] = node->mime_type; node = node->child; while (n < n_mime_types && node && node->character == 0) { if (node->mime_type) mime_types[n++] = node->mime_type; node = node->next; } } else { n = _xdg_glob_hash_node_lookup_file_name (node->child, file_name, ignore_case, mime_types, n_mime_types); } return n; } } return 0; }
xdg_unichar_t * _xdg_convert_to_ucs4 (const char *source, int *len) { xdg_unichar_t *out; int i; const char *p; out = malloc (sizeof (xdg_unichar_t) * (strlen (source) + 1)); p = source; i = 0; while (*p) { out[i++] = _xdg_utf8_to_ucs4 (p); p = _xdg_utf8_next_char (p); } out[i] = 0; *len = i; return out; }
static int cache_glob_node_lookup_suffix (XdgMimeCache *cache, xdg_uint32_t n_entries, xdg_uint32_t offset, const char *suffix, int ignore_case, const char *mime_types[], int n_mime_types) { xdg_unichar_t character; xdg_unichar_t match_char; xdg_uint32_t mimetype_offset; xdg_uint32_t n_children; xdg_uint32_t child_offset; int min, max, mid, n, i; character = _xdg_utf8_to_ucs4 (suffix); if (ignore_case) 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; if (cache->buffer[mimetype_offset]) 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 XdgGlobHashNode * _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, const char *text, const char *mime_type) { XdgGlobHashNode *node; xdg_unichar_t character; character = _xdg_utf8_to_ucs4 (text); if ((glob_hash_node == NULL) || (character < glob_hash_node->character)) { node = _xdg_glob_hash_node_new (); node->character = character; node->next = glob_hash_node; glob_hash_node = node; } else if (character == glob_hash_node->character) { node = glob_hash_node; } else { XdgGlobHashNode *prev_node; int found_node = FALSE; /* Look for the first character of text in glob_hash_node, and insert it if we * have to.*/ prev_node = glob_hash_node; node = prev_node->next; while (node != NULL) { if (character < node->character) { node = _xdg_glob_hash_node_new (); node->character = character; node->next = prev_node->next; prev_node->next = node; found_node = TRUE; break; } else if (character == node->character) { found_node = TRUE; break; } prev_node = node; node = node->next; } if (! found_node) { node = _xdg_glob_hash_node_new (); node->character = character; node->next = prev_node->next; prev_node->next = node; } } text = _xdg_utf8_next_char (text); if (*text == '\000') { if (node->mime_type) { if (strcmp (node->mime_type, mime_type)) { XdgGlobHashNode *child; int found_node = FALSE; child = node->child; while (child && child->character == '\0') { if (strcmp (child->mime_type, mime_type) == 0) { found_node = TRUE; break; } child = child->next; } if (!found_node) { child = _xdg_glob_hash_node_new (); child->character = '\000'; child->mime_type = strdup (mime_type); child->child = NULL; child->next = node->child; node->child = child; } } } else { node->mime_type = strdup (mime_type); } } else { node->child = _xdg_glob_hash_insert_text (node->child, text, mime_type); } return glob_hash_node; }