1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4 * gnome-vfs-mime-sniff-buffer.c
5 * Utility for implementing gnome_vfs_mime_type_from_magic, and other
6 * mime-type sniffing calls.
8 * Copyright (C) 2000 Eazel, Inc.
11 * This file is part of the Gnome Library.
13 * The Gnome Library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) any later version.
18 * The Gnome Library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public
24 * License along with the Gnome Library; see the file COPYING.LIB. If not,
25 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 * Boston, MA 02111-1307, USA.
30 #include "gnome-vfs-mime-sniff-buffer.h"
32 #include "gnome-vfs-handle.h"
33 #include "gnome-vfs-mime-sniff-buffer-private.h"
34 #include "gnome-vfs-ops.h"
38 handle_seek_glue (gpointer context, GnomeVFSSeekPosition whence,
39 GnomeVFSFileOffset offset)
41 GnomeVFSHandle *handle = (GnomeVFSHandle *)context;
42 return gnome_vfs_seek (handle, whence, offset);
46 handle_read_glue (gpointer context, gpointer buffer,
47 GnomeVFSFileSize bytes, GnomeVFSFileSize *bytes_read)
49 GnomeVFSHandle *handle = (GnomeVFSHandle *)context;
50 return gnome_vfs_read (handle, buffer, bytes, bytes_read);
53 GnomeVFSMimeSniffBuffer *
54 _gnome_vfs_mime_sniff_buffer_new_from_handle (GnomeVFSHandle *file)
56 GnomeVFSMimeSniffBuffer *result;
58 result = g_new0 (GnomeVFSMimeSniffBuffer, 1);
59 result->owning = TRUE;
60 result->context = file;
61 result->seek = handle_seek_glue;
62 result->read = handle_read_glue;
67 GnomeVFSMimeSniffBuffer *
68 _gnome_vfs_mime_sniff_buffer_new_generic (GnomeVFSSniffBufferSeekCall seek_callback,
69 GnomeVFSSniffBufferReadCall read_callback,
72 GnomeVFSMimeSniffBuffer * result;
74 result = g_new0 (GnomeVFSMimeSniffBuffer, 1);
76 result->owning = TRUE;
77 result->seek = seek_callback;
78 result->read = read_callback;
79 result->context = context;
84 GnomeVFSMimeSniffBuffer *
85 _gnome_vfs_mime_sniff_buffer_new_from_memory (const guchar *buffer,
88 GnomeVFSMimeSniffBuffer *result;
90 result = g_new0 (GnomeVFSMimeSniffBuffer, 1);
91 result->owning = TRUE;
92 result->buffer = g_malloc (buffer_length);
93 result->buffer_length = buffer_length;
94 memcpy (result->buffer, buffer, buffer_length);
95 result->read_whole_file = TRUE;
100 GnomeVFSMimeSniffBuffer *
101 gnome_vfs_mime_sniff_buffer_new_from_existing_data (const guchar *buffer,
102 gssize buffer_length)
104 GnomeVFSMimeSniffBuffer *result;
106 result = g_new0 (GnomeVFSMimeSniffBuffer, 1);
107 result->owning = FALSE;
108 result->buffer = (guchar *)buffer;
109 result->buffer_length = buffer_length;
110 result->read_whole_file = TRUE;
116 gnome_vfs_mime_sniff_buffer_free (GnomeVFSMimeSniffBuffer *buffer)
119 g_free (buffer->buffer);
124 GNOME_VFS_SNIFF_BUFFER_INITIAL_CHUNK = 256,
125 GNOME_VFS_SNIFF_BUFFER_MIN_CHUNK = 128
129 _gnome_vfs_mime_sniff_buffer_get (GnomeVFSMimeSniffBuffer *buffer,
132 GnomeVFSResult result;
133 GnomeVFSFileSize bytes_to_read, bytes_read;
135 /* check to see if we already have enough data */
136 if (buffer->buffer_length >= size) {
140 /* if we've read the whole file, don't try to read any more */
141 if (buffer->read_whole_file) {
142 return GNOME_VFS_ERROR_EOF;
145 /* figure out how much to read */
146 bytes_to_read = size - buffer->buffer_length;
148 /* don't bother to read less than this */
149 if (bytes_to_read < GNOME_VFS_SNIFF_BUFFER_MIN_CHUNK) {
150 bytes_to_read = GNOME_VFS_SNIFF_BUFFER_MIN_CHUNK;
153 /* make room in buffer for new data */
154 buffer->buffer = g_realloc (buffer->buffer,
155 buffer->buffer_length + bytes_to_read);
157 /* read in more data */
158 result = (* buffer->read) (buffer->context,
159 buffer->buffer + buffer->buffer_length,
162 if (result == GNOME_VFS_ERROR_EOF) {
163 /* only happens with 0-byte files, due to other logic */
164 buffer->read_whole_file = TRUE;
166 if (result != GNOME_VFS_OK) {
169 if (bytes_read < bytes_to_read) {
170 buffer->read_whole_file = TRUE;
172 buffer->buffer_length += bytes_read;
174 /* check to see if we have enough data */
175 if (buffer->buffer_length >= size) {
179 /* not enough data */
180 return GNOME_VFS_ERROR_EOF;