source: trunk/third/gnome-vfs/libgnomevfs/gnome-vfs-file-info.c @ 15497

Revision 15497, 9.8 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15496, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* gnome-vfs-file-info.c - Handling of file information for the GNOME
3   Virtual File System.
4
5   Copyright (C) 1999 Free Software Foundation
6
7   The Gnome Library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Library General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   The Gnome Library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   Library General Public License for more details.
16
17   You should have received a copy of the GNU Library General Public
18   License along with the Gnome Library; see the file COPYING.LIB.  If not,
19   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.
21
22   Author: Ettore Perazzoli <ettore@comm2000.it>
23*/
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <string.h>
30#include <glib.h>
31#include "gnome-vfs.h"
32#include "gnome-vfs-private.h"
33
34/* Special refcount used on stack-allocated file_info's */
35#define FILE_INFO_REFCOUNT_STACK ((guint)(-1))
36
37/* Mutex for making GnomeVFSFileInfo ref's/unref's atomic */
38/* Note that an atomic increment function (such as is present in NSPR) is preferable */
39static GStaticMutex file_info_ref_lock = G_STATIC_MUTEX_INIT;
40
41
42/**
43 * gnome_vfs_file_info_new:
44 *
45 * Allocate and initialize a new file information struct.
46 *
47 * Return value: A pointer to the new file information struct.
48 **/
49GnomeVFSFileInfo *
50gnome_vfs_file_info_new (void)
51{
52        GnomeVFSFileInfo *new;
53
54        new = g_new0 (GnomeVFSFileInfo, 1);
55
56        /* `g_new0()' is enough to initialize everything (we just want
57           all the members to be set to zero).  */
58
59        new->refcount = 1;
60       
61        return new;
62}
63
64/**
65 * gnome_vfs_file_info_init:
66 * @info:
67 *
68 * Initialize @info.  This is different from %gnome_vfs_file_info_clear,
69 * because it will not de-allocate any memory.  This is supposed to be used
70 * when a new %GnomeVFSFileInfo struct is allocated on the stack, and you want
71 * to initialize it.
72 **/
73void
74gnome_vfs_file_info_init (GnomeVFSFileInfo *info)
75{
76        g_return_if_fail (info != NULL);
77
78        /* This is enough to initialize everything (we just want all
79           the members to be set to zero).  */
80        memset (info, 0, sizeof (*info));
81
82        info->refcount = FILE_INFO_REFCOUNT_STACK;
83}
84
85/**
86 * gnome_vfs_file_info_clear:
87 * @info: Pointer to a file information struct
88 *
89 * Clear @info so that it's ready to accept new data.  This is different from
90 * %gnome_vfs_file_info_init as it will free associated memory too.  This is
91 * supposed to be used when @info already contains meaningful information which
92 * we want to get rid of.
93 **/
94void
95gnome_vfs_file_info_clear (GnomeVFSFileInfo *info)
96{
97        guint old_refcount;
98       
99        g_return_if_fail (info != NULL);
100
101        g_free (info->name);
102        g_free (info->symlink_name);
103        g_free (info->mime_type);
104
105        /* Ensure the ref count is maintained correctly */
106        g_static_mutex_lock (&file_info_ref_lock);
107
108        old_refcount = info->refcount;
109        memset (info, 0, sizeof (*info));
110        info->refcount = old_refcount;
111
112        g_static_mutex_unlock (&file_info_ref_lock);
113
114}
115
116
117/**
118 * gnome_vfs_file_info_ref:
119 * @info: Pointer to a file information struct
120 *
121 * Increment reference count
122 **/
123void
124gnome_vfs_file_info_ref (GnomeVFSFileInfo *info)
125{
126        g_return_if_fail (info != NULL);
127        g_return_if_fail (info->refcount != FILE_INFO_REFCOUNT_STACK);
128        g_return_if_fail (info->refcount > 0);
129
130        g_static_mutex_lock (&file_info_ref_lock);
131        info->refcount += 1;
132        g_static_mutex_unlock (&file_info_ref_lock);
133       
134}
135
136/**
137 * gnome_vfs_file_info_unref:
138 * @info: Pointer to a file information struct
139 *
140 * Destroy @info
141 **/
142void
143gnome_vfs_file_info_unref (GnomeVFSFileInfo *info)
144{
145        g_return_if_fail (info != NULL);
146        g_return_if_fail (info->refcount != FILE_INFO_REFCOUNT_STACK);
147        g_return_if_fail (info->refcount > 0);
148
149        g_static_mutex_lock (&file_info_ref_lock);
150        info->refcount -= 1;
151        g_static_mutex_unlock (&file_info_ref_lock);
152
153        if (info->refcount == 0) {
154                gnome_vfs_file_info_clear (info);
155                g_free (info);
156        }
157}
158
159
160
161/**
162 * gnome_vfs_file_info_get_mime_type:
163 * @info: A pointer to a file information struct
164 *
165 * Retrieve MIME type from @info.
166 *
167 * Return value: A pointer to a string representing the MIME type.
168 **/
169const gchar *
170gnome_vfs_file_info_get_mime_type (GnomeVFSFileInfo *info)
171{
172        g_return_val_if_fail (info != NULL, NULL);
173
174        return info->mime_type;
175}
176
177
178/**
179 * gnome_vfs_file_info_copy:
180 * @dest: Pointer to a struct to copy @src's information into
181 * @src: Pointer to the information to be copied into @dest
182 *
183 * Copy information from @src into @dest.
184 **/
185void
186gnome_vfs_file_info_copy (GnomeVFSFileInfo *dest,
187                          const GnomeVFSFileInfo *src)
188{
189        guint old_refcount;
190
191        g_return_if_fail (dest != NULL);
192        g_return_if_fail (src != NULL);
193
194        /* The primary purpose of this lock is to guarentee that the
195         * refcount is correctly maintained, not to make the copy
196         * atomic.  If you want to make the copy atomic, you probably
197         * want serialize access differently (or perhaps you shouldn't
198         * use copy)
199         */
200        g_static_mutex_lock (&file_info_ref_lock);
201
202        old_refcount = dest->refcount;
203
204        /* Copy basic information all at once; we will fix pointers later.  */
205
206        memcpy (dest, src, sizeof (*src));
207
208        /* Duplicate dynamically allocated strings.  */
209
210        dest->name = g_strdup (src->name);
211        dest->symlink_name = g_strdup (src->symlink_name);
212        dest->mime_type = g_strdup (src->mime_type);
213
214        dest->refcount = old_refcount;
215
216        g_static_mutex_unlock (&file_info_ref_lock);
217
218}
219
220/**
221 * gnome_vfs_file_info_dup:
222 * @orig: Pointer to a file information structure to duplicate
223 *
224 * Returns a new file information struct that duplicates the information in @orig.
225 **/
226
227GnomeVFSFileInfo *
228gnome_vfs_file_info_dup         (const GnomeVFSFileInfo *orig)
229{
230        GnomeVFSFileInfo * ret;
231
232        g_return_val_if_fail (orig != NULL, NULL);
233
234        ret = gnome_vfs_file_info_new();
235
236        gnome_vfs_file_info_copy (ret, orig);
237
238        return ret;
239}
240
241
242/**
243 * gnome_vfs_file_info_matches:
244 *
245 * Compare the two file info structs, return TRUE if they match.
246 **/
247gboolean
248gnome_vfs_file_info_matches (const GnomeVFSFileInfo *a,
249                             const GnomeVFSFileInfo *b)
250{
251        if (a->type != b->type
252            || a->size != b->size
253            || a->block_count != b->block_count
254            || a->atime != b->atime
255            || a->mtime != b->mtime
256            || a->ctime != b->ctime
257            || strcmp (a->name, b->name) != 0) {
258                return FALSE;
259        }
260
261        if (a->mime_type == NULL || b->mime_type == NULL) {
262                return a->mime_type == b->mime_type;
263        }
264
265        g_assert (a->mime_type != NULL && b->mime_type != NULL);
266        return g_strcasecmp (a->mime_type, b->mime_type) == 0;
267}
268
269gint
270gnome_vfs_file_info_compare_for_sort (const GnomeVFSFileInfo *a,
271                                      const GnomeVFSFileInfo *b,
272                                      const GnomeVFSDirectorySortRule *sort_rules)
273{
274        guint i;
275        gint retval;
276
277        /* Note that the sort direction is determined by a
278         * "natural order" rather than a logical "small" to "large"
279         * order. For instance, large sizes come before small ones,
280         * because that is what the user probably cares about.
281         */
282
283        for (i = 0; sort_rules[i] != GNOME_VFS_DIRECTORY_SORT_NONE; i++) {
284                switch (sort_rules[i]) {
285                case GNOME_VFS_DIRECTORY_SORT_DIRECTORYFIRST:
286                        if (a->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
287                                if (b->type != GNOME_VFS_FILE_TYPE_DIRECTORY)
288                                        return -1;
289                        } else if (b->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
290                                return +1;
291                        }
292                        break;
293                case GNOME_VFS_DIRECTORY_SORT_BYNAME:
294                        retval = strcmp (a->name, b->name);
295                        if (retval != 0)
296                                return retval;
297                        break;
298                case GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE:
299                        retval = g_strcasecmp (a->name, b->name);
300                        if (retval != 0)
301                                return retval;
302                        break;
303                case GNOME_VFS_DIRECTORY_SORT_BYSIZE:
304                        /* Natural order of sorting by size is largest first */
305                        if (a->size != b->size)
306                                return (a->size > b->size) ? -1 : +1;
307                        break;
308                case GNOME_VFS_DIRECTORY_SORT_BYBLOCKCOUNT:
309                        /* Natural order of sorting by block count is largest first */
310                        if (a->block_count != b->block_count)
311                                return ((a->block_count > b->block_count)
312                                        ? -1 : +1);
313                        break;
314                case GNOME_VFS_DIRECTORY_SORT_BYATIME:
315                        /* Natural order of sorting by date is most recent first */
316                        if (a->atime != b->atime)
317                                return (a->atime > b->atime) ? -1 : +1;
318                        break;
319                case GNOME_VFS_DIRECTORY_SORT_BYMTIME:
320                        /* Natural order of sorting by date is most recent first */
321                        if (a->mtime != b->mtime)
322                                return (a->mtime > b->mtime) ? -1 : +1;
323                        break;
324                case GNOME_VFS_DIRECTORY_SORT_BYCTIME:
325                        /* Natural order of sorting by date is most recent first */
326                        if (a->ctime != b->ctime)
327                                return (a->ctime > b->ctime) ? -1 : +1;
328                        break;
329                case GNOME_VFS_DIRECTORY_SORT_BYMIMETYPE:
330                        /* Directories (e.g.) don't have mime types, so
331                         * we have to check the NULL case.
332                         */
333                        if (a->mime_type != b->mime_type) {
334                                if (a->mime_type == NULL)
335                                        return -1;
336                                if (b->mime_type == NULL)
337                                        return +1;
338                                return g_strcasecmp (a->mime_type, b->mime_type);
339                        }
340                        break;
341                default:
342                        g_warning (_("Unknown sort rule %d"), sort_rules[i]);
343                }
344        }
345
346        return 0;
347}
348
349gint
350gnome_vfs_file_info_compare_for_sort_reversed (const GnomeVFSFileInfo *a,
351                                               const GnomeVFSFileInfo *b,
352                                               const GnomeVFSDirectorySortRule *sort_rules)
353{
354        return 0 - gnome_vfs_file_info_compare_for_sort (a, b, sort_rules);
355}
356
357GList *
358gnome_vfs_file_info_list_ref (GList *list)
359{
360        g_list_foreach (list, (GFunc) gnome_vfs_file_info_ref, NULL);
361        return list;
362}
363
364GList *
365gnome_vfs_file_info_list_unref (GList *list)
366{
367        g_list_foreach (list, (GFunc) gnome_vfs_file_info_unref, NULL);
368        return list;
369}
370
371GList *
372gnome_vfs_file_info_list_copy (GList *list)
373{
374        return g_list_copy (gnome_vfs_file_info_list_ref (list));
375}
376
377void
378gnome_vfs_file_info_list_free (GList *list)
379{
380        g_list_free (gnome_vfs_file_info_list_unref (list));
381}
Note: See TracBrowser for help on using the repository browser.