Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
probe-buffer.c
Go to the documentation of this file.
00001 /*
00002  * probe-buffer.c
00003  * Copyright 2010-2011 John Lindgren
00004  *
00005  * This file is part of Audacious.
00006  *
00007  * Audacious is free software: you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License as published by the Free Software
00009  * Foundation, version 2 or version 3 of the License.
00010  *
00011  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00013  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * Audacious. If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The Audacious team does not consider modular code linking to Audacious or
00019  * using our public API to be a derived work.
00020  */
00021 
00022 #include <glib.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #include "debug.h"
00027 #include "probe-buffer.h"
00028 
00029 typedef struct
00030 {
00031     VFSFile * file;
00032     unsigned char buffer[16384];
00033     int filled, at;
00034 }
00035 ProbeBuffer;
00036 
00037 static int probe_buffer_fclose (VFSFile * file)
00038 {
00039     ProbeBuffer * p = vfs_get_handle (file);
00040 
00041     int ret = vfs_fclose (p->file);
00042     g_slice_free (ProbeBuffer, p);
00043     return ret;
00044 }
00045 
00046 static void increase_buffer (ProbeBuffer * p, int64_t size)
00047 {
00048     size = (size + 0xFF) & ~0xFF;
00049 
00050     if (size > sizeof p->buffer)
00051         size = sizeof p->buffer;
00052 
00053     if (p->filled < size)
00054         p->filled += vfs_fread (p->buffer + p->filled, 1, size - p->filled,
00055          p->file);
00056 }
00057 
00058 static int64_t probe_buffer_fread (void * buffer, int64_t size, int64_t count,
00059  VFSFile * file)
00060 {
00061     ProbeBuffer * p = vfs_get_handle (file);
00062 
00063     increase_buffer (p, p->at + size * count);
00064     int readed = (size > 0) ? MIN (count, (p->filled - p->at) / size) : 0;
00065     memcpy (buffer, p->buffer + p->at, size * readed);
00066 
00067     p->at += size * readed;
00068     return readed;
00069 }
00070 
00071 static int64_t probe_buffer_fwrite (const void * data, int64_t size, int64_t count,
00072  VFSFile * file)
00073 {
00074     /* not implemented */
00075     return 0;
00076 }
00077 
00078 static int probe_buffer_getc (VFSFile * file)
00079 {
00080     unsigned char c;
00081     return (probe_buffer_fread (& c, 1, 1, file) == 1) ? c : EOF;
00082 }
00083 
00084 static int probe_buffer_fseek (VFSFile * file, int64_t offset, int whence)
00085 {
00086     ProbeBuffer * p = vfs_get_handle (file);
00087 
00088     if (whence == SEEK_END)
00089         return -1;
00090 
00091     if (whence == SEEK_CUR)
00092         offset += p->at;
00093 
00094     g_return_val_if_fail (offset >= 0, -1);
00095     increase_buffer (p, offset);
00096 
00097     if (offset > p->filled)
00098         return -1;
00099 
00100     p->at = offset;
00101     return 0;
00102 }
00103 
00104 static int probe_buffer_ungetc (int c, VFSFile * file)
00105 {
00106     return (! probe_buffer_fseek (file, -1, SEEK_CUR)) ? c : EOF;
00107 }
00108 
00109 static void probe_buffer_rewind (VFSFile * file)
00110 {
00111     probe_buffer_fseek (file, 0, SEEK_SET);
00112 }
00113 
00114 static int64_t probe_buffer_ftell (VFSFile * file)
00115 {
00116     return ((ProbeBuffer *) vfs_get_handle (file))->at;
00117 }
00118 
00119 static bool_t probe_buffer_feof (VFSFile * file)
00120 {
00121     ProbeBuffer * p = vfs_get_handle (file);
00122     return (p->at < p->filled) ? FALSE : vfs_feof (p->file);
00123 }
00124 
00125 static int probe_buffer_ftruncate (VFSFile * file, int64_t size)
00126 {
00127     /* not implemented */
00128     return -1;
00129 }
00130 
00131 static int64_t probe_buffer_fsize (VFSFile * file)
00132 {
00133     return vfs_fsize (((ProbeBuffer *) vfs_get_handle (file))->file);
00134 }
00135 
00136 static char * probe_buffer_get_metadata (VFSFile * file, const char * field)
00137 {
00138     return vfs_get_metadata (((ProbeBuffer *) vfs_get_handle (file))->file, field);
00139 }
00140 
00141 static VFSConstructor probe_buffer_table =
00142 {
00143         .vfs_fopen_impl = NULL,
00144         .vfs_fclose_impl = probe_buffer_fclose,
00145         .vfs_fread_impl = probe_buffer_fread,
00146         .vfs_fwrite_impl = probe_buffer_fwrite,
00147         .vfs_getc_impl = probe_buffer_getc,
00148         .vfs_ungetc_impl = probe_buffer_ungetc,
00149         .vfs_fseek_impl = probe_buffer_fseek,
00150         .vfs_rewind_impl = probe_buffer_rewind,
00151         .vfs_ftell_impl = probe_buffer_ftell,
00152         .vfs_feof_impl = probe_buffer_feof,
00153         .vfs_ftruncate_impl = probe_buffer_ftruncate,
00154         .vfs_fsize_impl = probe_buffer_fsize,
00155         .vfs_get_metadata_impl = probe_buffer_get_metadata,
00156 };
00157 
00158 VFSFile * probe_buffer_new (const char * filename)
00159 {
00160     VFSFile * file = vfs_fopen (filename, "r");
00161 
00162     if (! file)
00163         return NULL;
00164 
00165     ProbeBuffer * p = g_slice_new (ProbeBuffer);
00166     p->file = file;
00167     p->filled = 0;
00168     p->at = 0;
00169 
00170     return vfs_new (filename, & probe_buffer_table, p);
00171 }