Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
probe-buffer.c
Go to the documentation of this file.
1 /*
2  * probe-buffer.c
3  * Copyright 2010-2011 John Lindgren
4  *
5  * This file is part of Audacious.
6  *
7  * Audacious is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation, version 2 or version 3 of the License.
10  *
11  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Audacious. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * The Audacious team does not consider modular code linking to Audacious or
19  * using our public API to be a derived work.
20  */
21 
22 #include <glib.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "debug.h"
27 #include "probe-buffer.h"
28 
29 typedef struct
30 {
32  unsigned char buffer[16384];
33  int filled, at;
34 }
36 
37 static int probe_buffer_fclose (VFSFile * file)
38 {
39  ProbeBuffer * p = vfs_get_handle (file);
40 
41  int ret = vfs_fclose (p->file);
42  g_slice_free (ProbeBuffer, p);
43  return ret;
44 }
45 
46 static void increase_buffer (ProbeBuffer * p, int64_t size)
47 {
48  size = (size + 0xFF) & ~0xFF;
49 
50  if (size > sizeof p->buffer)
51  size = sizeof p->buffer;
52 
53  if (p->filled < size)
54  p->filled += vfs_fread (p->buffer + p->filled, 1, size - p->filled,
55  p->file);
56 }
57 
58 static int64_t probe_buffer_fread (void * buffer, int64_t size, int64_t count,
59  VFSFile * file)
60 {
61  ProbeBuffer * p = vfs_get_handle (file);
62 
63  increase_buffer (p, p->at + size * count);
64  int readed = (size > 0) ? MIN (count, (p->filled - p->at) / size) : 0;
65  memcpy (buffer, p->buffer + p->at, size * readed);
66 
67  p->at += size * readed;
68  return readed;
69 }
70 
71 static int64_t probe_buffer_fwrite (const void * data, int64_t size, int64_t count,
72  VFSFile * file)
73 {
74  /* not implemented */
75  return 0;
76 }
77 
78 static int probe_buffer_getc (VFSFile * file)
79 {
80  unsigned char c;
81  return (probe_buffer_fread (& c, 1, 1, file) == 1) ? c : EOF;
82 }
83 
84 static int probe_buffer_fseek (VFSFile * file, int64_t offset, int whence)
85 {
86  ProbeBuffer * p = vfs_get_handle (file);
87 
88  if (whence == SEEK_END)
89  return -1;
90 
91  if (whence == SEEK_CUR)
92  offset += p->at;
93 
94  g_return_val_if_fail (offset >= 0, -1);
95  increase_buffer (p, offset);
96 
97  if (offset > p->filled)
98  return -1;
99 
100  p->at = offset;
101  return 0;
102 }
103 
104 static int probe_buffer_ungetc (int c, VFSFile * file)
105 {
106  return (! probe_buffer_fseek (file, -1, SEEK_CUR)) ? c : EOF;
107 }
108 
109 static void probe_buffer_rewind (VFSFile * file)
110 {
111  probe_buffer_fseek (file, 0, SEEK_SET);
112 }
113 
114 static int64_t probe_buffer_ftell (VFSFile * file)
115 {
116  return ((ProbeBuffer *) vfs_get_handle (file))->at;
117 }
118 
120 {
121  ProbeBuffer * p = vfs_get_handle (file);
122  return (p->at < p->filled) ? FALSE : vfs_feof (p->file);
123 }
124 
125 static int probe_buffer_ftruncate (VFSFile * file, int64_t size)
126 {
127  /* not implemented */
128  return -1;
129 }
130 
131 static int64_t probe_buffer_fsize (VFSFile * file)
132 {
133  return vfs_fsize (((ProbeBuffer *) vfs_get_handle (file))->file);
134 }
135 
136 static char * probe_buffer_get_metadata (VFSFile * file, const char * field)
137 {
138  return vfs_get_metadata (((ProbeBuffer *) vfs_get_handle (file))->file, field);
139 }
140 
142 {
143  .vfs_fopen_impl = NULL,
144  .vfs_fclose_impl = probe_buffer_fclose,
145  .vfs_fread_impl = probe_buffer_fread,
146  .vfs_fwrite_impl = probe_buffer_fwrite,
147  .vfs_getc_impl = probe_buffer_getc,
148  .vfs_ungetc_impl = probe_buffer_ungetc,
149  .vfs_fseek_impl = probe_buffer_fseek,
150  .vfs_rewind_impl = probe_buffer_rewind,
151  .vfs_ftell_impl = probe_buffer_ftell,
152  .vfs_feof_impl = probe_buffer_feof,
153  .vfs_ftruncate_impl = probe_buffer_ftruncate,
154  .vfs_fsize_impl = probe_buffer_fsize,
155  .vfs_get_metadata_impl = probe_buffer_get_metadata,
156 };
157 
159 {
160  VFSFile * file = vfs_fopen (filename, "r");
161 
162  if (! file)
163  return NULL;
164 
165  ProbeBuffer * p = g_slice_new (ProbeBuffer);
166  p->file = file;
167  p->filled = 0;
168  p->at = 0;
169 
170  return vfs_new (filename, & probe_buffer_table, p);
171 }