* add xdgmime from freedesktop.org
[citadel.git] / libcitadel / lib / xdgmime / xdgmimeparent.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* xdgmimealias.c: Private file.  Datastructure for storing the hierarchy.
3  *
4  * More info can be found at http://www.freedesktop.org/standards/
5  *
6  * Copyright (C) 2004  Red Hat, Inc.
7  * Copyright (C) 2004  Matthias Clasen <mclasen@redhat.com>
8  *
9  * Licensed under the Academic Free License version 2.0
10  * Or under the following terms:
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the
24  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "xdgmimeparent.h"
33 #include "xdgmimeint.h"
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <assert.h>
37 #include <string.h>
38 #include <fnmatch.h>
39
40 #ifndef FALSE
41 #define FALSE   (0)
42 #endif
43
44 #ifndef TRUE
45 #define TRUE    (!FALSE)
46 #endif
47
48 typedef struct XdgMimeParents XdgMimeParents;
49
50 struct XdgMimeParents
51 {
52   char *mime;
53   char **parents;
54   int n_parents;
55 };
56
57 struct XdgParentList
58 {
59   struct XdgMimeParents *parents;
60   int n_mimes;
61 };
62
63 XdgParentList *
64 _xdg_mime_parent_list_new (void)
65 {
66   XdgParentList *list;
67
68   list = malloc (sizeof (XdgParentList));
69
70   list->parents = NULL;
71   list->n_mimes = 0;
72
73   return list;
74 }
75
76 void         
77 _xdg_mime_parent_list_free (XdgParentList *list)
78 {
79   int i;
80   char **p;
81
82   if (list->parents)
83     {
84       for (i = 0; i < list->n_mimes; i++)
85         {
86           for (p = list->parents[i].parents; *p; p++)
87             free (*p);
88
89           free (list->parents[i].parents);
90           free (list->parents[i].mime);
91         }
92       free (list->parents);
93     }
94   free (list);
95 }
96
97 static int
98 parent_entry_cmp (const void *v1, const void *v2)
99 {
100   return strcmp (((XdgMimeParents *)v1)->mime, ((XdgMimeParents *)v2)->mime);
101 }
102
103 const char **
104 _xdg_mime_parent_list_lookup (XdgParentList *list,
105                               const char    *mime)
106 {
107   XdgMimeParents *entry;
108   XdgMimeParents key;
109
110   if (list->n_mimes > 0)
111     {
112       key.mime = (char *)mime;
113       key.parents = NULL;
114
115       entry = bsearch (&key, list->parents, list->n_mimes,
116                        sizeof (XdgMimeParents), &parent_entry_cmp);
117       if (entry)
118         return (const char **)entry->parents;
119     }
120
121   return NULL;
122 }
123
124 void
125 _xdg_mime_parent_read_from_file (XdgParentList *list,
126                                  const char    *file_name)
127 {
128   FILE *file;
129   char line[255];
130   int i, alloc;
131   XdgMimeParents *entry;
132
133   file = fopen (file_name, "r");
134
135   if (file == NULL)
136     return;
137
138   /* FIXME: Not UTF-8 safe.  Doesn't work if lines are greater than 255 chars.
139    * Blah */
140   alloc = list->n_mimes + 16;
141   list->parents = realloc (list->parents, alloc * sizeof (XdgMimeParents));
142   while (fgets (line, 255, file) != NULL)
143     {
144       char *sep;
145       if (line[0] == '#')
146         continue;
147
148       sep = strchr (line, ' ');
149       if (sep == NULL)
150         continue;
151       *(sep++) = '\000';
152       sep[strlen (sep) -1] = '\000';
153       entry = NULL;
154       for (i = 0; i < list->n_mimes; i++)
155         {
156           if (strcmp (list->parents[i].mime, line) == 0)
157             {
158               entry = &(list->parents[i]);
159               break;
160             }
161         }
162       
163       if (!entry)
164         {
165           if (list->n_mimes == alloc)
166             {
167               alloc <<= 1;
168               list->parents = realloc (list->parents, 
169                                        alloc * sizeof (XdgMimeParents));
170             }
171           list->parents[list->n_mimes].mime = strdup (line);
172           list->parents[list->n_mimes].parents = NULL;
173           entry = &(list->parents[list->n_mimes]);
174           list->n_mimes++;
175         }
176
177       if (!entry->parents)
178         {
179           entry->n_parents = 1;
180           entry->parents = malloc ((entry->n_parents + 1) * sizeof (char *));
181         }
182       else
183         {
184           entry->n_parents += 1;
185           entry->parents = realloc (entry->parents, 
186                                     (entry->n_parents + 2) * sizeof (char *));
187         }
188       entry->parents[entry->n_parents - 1] = strdup (sep);
189       entry->parents[entry->n_parents] = NULL;
190     }
191
192   list->parents = realloc (list->parents, 
193                            list->n_mimes * sizeof (XdgMimeParents));
194
195   fclose (file);  
196   
197   if (list->n_mimes > 1)
198     qsort (list->parents, list->n_mimes, 
199            sizeof (XdgMimeParents), &parent_entry_cmp);
200 }
201
202
203 void         
204 _xdg_mime_parent_list_dump (XdgParentList *list)
205 {
206   int i;
207   char **p;
208
209   if (list->parents)
210     {
211       for (i = 0; i < list->n_mimes; i++)
212         {
213           for (p = list->parents[i].parents; *p; p++)
214             printf ("%s %s\n", list->parents[i].mime, *p);
215         }
216     }
217 }
218
219