Back to index

libcitadel  8.12
Classes | Typedefs | Functions
xdgmimeglob.c File Reference
#include "xdgmimeglob.h"
#include "xdgmimeint.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <fnmatch.h>

Go to the source code of this file.

Classes

struct  XdgGlobHashNode
struct  XdgGlobList
struct  XdgGlobHash

Typedefs

typedef struct XdgGlobHashNode
typedef struct XdgGlobList

Functions

static XdgGlobList_xdg_glob_list_new (void)
static void _xdg_glob_list_free (XdgGlobList *glob_list)
static XdgGlobList_xdg_glob_list_append (XdgGlobList *glob_list, void *data, const char *mime_type)
static XdgGlobHashNode_xdg_glob_hash_node_new (void)
static void _xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node, int depth)
static XdgGlobHashNode_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, const char *text, const char *mime_type)
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 _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, const char *file_name, const char *mime_types[], int n_mime_types)
XdgGlobHash_xdg_glob_hash_new (void)
static void _xdg_glob_hash_free_nodes (XdgGlobHashNode *node)
void _xdg_glob_hash_free (XdgGlobHash *glob_hash)
XdgGlobType _xdg_glob_determine_type (const char *glob)
void _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash, const char *glob, const char *mime_type)
void _xdg_glob_hash_dump (XdgGlobHash *glob_hash)
void _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash, const char *file_name)

Class Documentation

struct XdgGlobHashNode

Definition at line 51 of file xdgmimeglob.c.

Collaboration diagram for XdgGlobHashNode:
Class Members
xdg_unichar_t character
XdgGlobHashNode * child
const char * mime_type
XdgGlobHashNode * next
struct XdgGlobList

Definition at line 58 of file xdgmimeglob.c.

Collaboration diagram for XdgGlobList:
Class Members
const char * data
const char * mime_type
XdgGlobList * next
struct XdgGlobHash

Definition at line 65 of file xdgmimeglob.c.

Collaboration diagram for XdgGlobHash:
Class Members
XdgGlobList * full_list
XdgGlobList * literal_list
XdgGlobHashNode * simple_node

Typedef Documentation

typedef struct XdgGlobHashNode

Definition at line 48 of file xdgmimeglob.c.

typedef struct XdgGlobList

Definition at line 49 of file xdgmimeglob.c.


Function Documentation

XdgGlobType _xdg_glob_determine_type ( const char *  glob)

Definition at line 440 of file xdgmimeglob.c.

{
  const char *ptr;
  int maybe_in_simple_glob = FALSE;
  int first_char = TRUE;

  ptr = glob;

  while (*ptr != '\000')
    {
      if (*ptr == '*' && first_char)
       maybe_in_simple_glob = TRUE;
      else if (*ptr == '\\' || *ptr == '[' || *ptr == '?' || *ptr == '*')
         return XDG_GLOB_FULL;

      first_char = FALSE;
      ptr = _xdg_utf8_next_char (ptr);
    }
  if (maybe_in_simple_glob)
    return XDG_GLOB_SIMPLE;
  else
    return XDG_GLOB_LITERAL;
}

Here is the caller graph for this function:

void _xdg_glob_hash_append_glob ( XdgGlobHash glob_hash,
const char *  glob,
const char *  mime_type 
)

Definition at line 466 of file xdgmimeglob.c.

{
  XdgGlobType type;

  assert (glob_hash != NULL);
  assert (glob != NULL);

  type = _xdg_glob_determine_type (glob);

  switch (type)
    {
    case XDG_GLOB_LITERAL:
      glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type));
      break;
    case XDG_GLOB_SIMPLE:
      glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type);
      break;
    case XDG_GLOB_FULL:
      glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type));
      break;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _xdg_glob_hash_dump ( XdgGlobHash glob_hash)

Definition at line 492 of file xdgmimeglob.c.

{
  XdgGlobList *list;
  printf ("LITERAL STRINGS\n");
  if (glob_hash->literal_list == NULL)
    {
      printf ("    None\n");
    }
  else
    {
      for (list = glob_hash->literal_list; list; list = list->next)
       printf ("    %s - %s\n", (char *)list->data, list->mime_type);
    }
  printf ("\nSIMPLE GLOBS\n");
  _xdg_glob_hash_node_dump (glob_hash->simple_node, 4);

  printf ("\nFULL GLOBS\n");
  if (glob_hash->full_list == NULL)
    {
      printf ("    None\n");
    }
  else
    {
      for (list = glob_hash->full_list; list; list = list->next)
       printf ("    %s - %s\n", (char *)list->data, list->mime_type);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _xdg_glob_hash_free ( XdgGlobHash glob_hash)

Definition at line 431 of file xdgmimeglob.c.

{
  _xdg_glob_list_free (glob_hash->literal_list);
  _xdg_glob_list_free (glob_hash->full_list);
  _xdg_glob_hash_free_nodes (glob_hash->simple_node);
  free (glob_hash);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void _xdg_glob_hash_free_nodes ( XdgGlobHashNode node) [static]

Definition at line 416 of file xdgmimeglob.c.

{
  if (node)
    {
      if (node->child)
       _xdg_glob_hash_free_nodes (node->child);
      if (node->next)
       _xdg_glob_hash_free_nodes (node->next);
      if (node->mime_type)
       free ((void *) node->mime_type);
      free (node);
    }
}

Here is the caller graph for this function:

static XdgGlobHashNode* _xdg_glob_hash_insert_text ( XdgGlobHashNode glob_hash_node,
const char *  text,
const char *  mime_type 
) [static]

Definition at line 180 of file xdgmimeglob.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _xdg_glob_hash_lookup_file_name ( XdgGlobHash glob_hash,
const char *  file_name,
const char *  mime_types[],
int  n_mime_types 
)

Definition at line 340 of file xdgmimeglob.c.

{
  XdgGlobList *list;
  const char *ptr;
  char stopchars[128];
  int i, n;
  XdgGlobHashNode *node;

  /* First, check the literals */

  assert (file_name != NULL && n_mime_types > 0);

  for (list = glob_hash->literal_list; list; list = list->next)
    {
      if (strcmp ((const char *)list->data, file_name) == 0)
       {
         mime_types[0] = list->mime_type;
         return 1;
       }
    }

  i = 0;
  for (node = glob_hash->simple_node; node; node = node->next)
    {
      if (node->character < 128)
       stopchars[i++] = (char)node->character;
    }
  stopchars[i] = '\0';
 
  ptr = strpbrk (file_name, stopchars);
  while (ptr)
    {
      n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, FALSE,
                                          mime_types, n_mime_types);
      if (n > 0)
       return n;
      
      n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, TRUE,
                                          mime_types, n_mime_types);
      if (n > 0)
       return n;
      
      ptr = strpbrk (ptr + 1, stopchars);
    }

  /* FIXME: Not UTF-8 safe */
  n = 0;
  for (list = glob_hash->full_list; list && n < n_mime_types; list = list->next)
    {
      if (fnmatch ((const char *)list->data, file_name, 0) == 0)
       mime_types[n++] = list->mime_type;
    }

  return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 405 of file xdgmimeglob.c.

{
  XdgGlobHash *glob_hash;

  glob_hash = calloc (1, sizeof (XdgGlobHash));

  return glob_hash;
}

Here is the caller graph for this function:

static void _xdg_glob_hash_node_dump ( XdgGlobHashNode glob_hash_node,
int  depth 
) [static]

Definition at line 161 of file xdgmimeglob.c.

{
  int i;
  for (i = 0; i < depth; i++)
    printf (" ");

  printf ("%c", (char)glob_hash_node->character);
  if (glob_hash_node->mime_type)
    printf (" - %s\n", glob_hash_node->mime_type);
  else
    printf ("\n");
  if (glob_hash_node->child)
    _xdg_glob_hash_node_dump (glob_hash_node->child, depth + 1);
  if (glob_hash_node->next)
    _xdg_glob_hash_node_dump (glob_hash_node->next, depth);
}

Here is the caller graph for this function:

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 
) [static]

Definition at line 286 of file xdgmimeglob.c.

{
  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 != NULL)
               mime_types[n++] = node->mime_type;

             node = node->child;
             while (n < n_mime_types && node && node->character == 0)
              {
                if (node->mime_type != NULL)
                  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XdgGlobHashNode* _xdg_glob_hash_node_new ( void  ) [static]

Definition at line 151 of file xdgmimeglob.c.

{
  XdgGlobHashNode *glob_hash_node;

  glob_hash_node = calloc (1, sizeof (XdgGlobHashNode));

  return glob_hash_node;
}

Here is the caller graph for this function:

static XdgGlobList* _xdg_glob_list_append ( XdgGlobList glob_list,
void *  data,
const char *  mime_type 
) [static]

Definition at line 108 of file xdgmimeglob.c.

{
  XdgGlobList *new_element;
  XdgGlobList *tmp_element;

  new_element = _xdg_glob_list_new ();
  new_element->data = data;
  new_element->mime_type = mime_type;
  if (glob_list == NULL)
    return new_element;

  tmp_element = glob_list;
  while (tmp_element->next != NULL)
    tmp_element = tmp_element->next;

  tmp_element->next = new_element;

  return glob_list;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void _xdg_glob_list_free ( XdgGlobList glob_list) [static]

Definition at line 87 of file xdgmimeglob.c.

{
  XdgGlobList *ptr, *next;

  ptr = glob_list;

  while (ptr != NULL)
    {
      next = ptr->next;

      if (ptr->data)
       free ((void *) ptr->data);
      if (ptr->mime_type)
       free ((void *) ptr->mime_type);
      free (ptr);

      ptr = next;
    }
}

Here is the caller graph for this function:

static XdgGlobList* _xdg_glob_list_new ( void  ) [static]

Definition at line 76 of file xdgmimeglob.c.

{
  XdgGlobList *new_element;

  new_element = calloc (1, sizeof (XdgGlobList));

  return new_element;
}

Here is the caller graph for this function:

void _xdg_mime_glob_read_from_file ( XdgGlobHash glob_hash,
const char *  file_name 
)

Definition at line 522 of file xdgmimeglob.c.

{
  FILE *glob_file;
  char line[255];

  glob_file = fopen (file_name, "r");

  if (glob_file == NULL)
    return;

  /* FIXME: Not UTF-8 safe.  Doesn't work if lines are greater than 255 chars.
   * Blah */
  while (fgets (line, 255, glob_file) != NULL)
    {
      char *colon;
      if (line[0] == '#')
       continue;

      colon = strchr (line, ':');
      if (colon == NULL)
       continue;
      *(colon++) = '\000';
      colon[strlen (colon) -1] = '\000';
      _xdg_glob_hash_append_glob (glob_hash, colon, line);
    }

  fclose (glob_file);
}

Here is the call graph for this function:

Here is the caller graph for this function: