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  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "debug.h"
25 #include "probe-buffer.h"
26 
27 typedef struct
28 {
30  unsigned char buffer[16384];
31  int filled, at;
32 }
34 
35 static int probe_buffer_fclose (VFSFile * file)
36 {
37  ProbeBuffer * p = vfs_get_handle (file);
38 
39  int ret = vfs_fclose (p->file);
40  g_slice_free (ProbeBuffer, p);
41  return ret;
42 }
43 
44 static void increase_buffer (ProbeBuffer * p, int64_t size)
45 {
46  size = (size + 0xFF) & ~0xFF;
47 
48  if (size > sizeof p->buffer)
49  size = sizeof p->buffer;
50 
51  if (p->filled < size)
52  p->filled += vfs_fread (p->buffer + p->filled, 1, size - p->filled,
53  p->file);
54 }
55 
56 static int64_t probe_buffer_fread (void * buffer, int64_t size, int64_t count,
57  VFSFile * file)
58 {
59  ProbeBuffer * p = vfs_get_handle (file);
60 
61  increase_buffer (p, p->at + size * count);
62  int readed = (size > 0) ? MIN (count, (p->filled - p->at) / size) : 0;
63  memcpy (buffer, p->buffer + p->at, size * readed);
64 
65  p->at += size * readed;
66  return readed;
67 }
68 
69 static int64_t probe_buffer_fwrite (const void * data, int64_t size, int64_t count,
70  VFSFile * file)
71 {
72  return 0; /* not allowed */
73 }
74 
75 static int probe_buffer_getc (VFSFile * file)
76 {
77  unsigned char c;
78  return (probe_buffer_fread (& c, 1, 1, file) == 1) ? c : EOF;
79 }
80 
81 static int probe_buffer_fseek (VFSFile * file, int64_t offset, int whence)
82 {
83  ProbeBuffer * p = vfs_get_handle (file);
84 
85  if (whence == SEEK_END)
86  return -1; /* not allowed */
87 
88  if (whence == SEEK_CUR)
89  offset += p->at;
90 
91  g_return_val_if_fail (offset >= 0, -1);
92  increase_buffer (p, offset);
93 
94  if (offset > p->filled)
95  return -1;
96 
97  p->at = offset;
98  return 0;
99 }
100 
101 static int probe_buffer_ungetc (int c, VFSFile * file)
102 {
103  return (! probe_buffer_fseek (file, -1, SEEK_CUR)) ? c : EOF;
104 }
105 
106 static void probe_buffer_rewind (VFSFile * file)
107 {
108  probe_buffer_fseek (file, 0, SEEK_SET);
109 }
110 
111 static int64_t probe_buffer_ftell (VFSFile * file)
112 {
113  return ((ProbeBuffer *) vfs_get_handle (file))->at;
114 }
115 
117 {
118  ProbeBuffer * p = vfs_get_handle (file);
119 
120  if (p->at < p->filled)
121  return FALSE;
122  if (p->at == sizeof p->buffer)
123  return TRUE;
124 
125  return vfs_feof (p->file);
126 }
127 
128 static int probe_buffer_ftruncate (VFSFile * file, int64_t size)
129 {
130  return -1; /* not allowed */
131 }
132 
133 static int64_t probe_buffer_fsize (VFSFile * file)
134 {
135  ProbeBuffer * p = vfs_get_handle (file);
136 
137  int64_t size = vfs_fsize (p->file);
138  return MIN (size, sizeof p->buffer);
139 }
140 
141 static char * probe_buffer_get_metadata (VFSFile * file, const char * field)
142 {
143  return vfs_get_metadata (((ProbeBuffer *) vfs_get_handle (file))->file, field);
144 }
145 
147 {
148  .vfs_fopen_impl = NULL,
149  .vfs_fclose_impl = probe_buffer_fclose,
150  .vfs_fread_impl = probe_buffer_fread,
151  .vfs_fwrite_impl = probe_buffer_fwrite,
152  .vfs_getc_impl = probe_buffer_getc,
153  .vfs_ungetc_impl = probe_buffer_ungetc,
154  .vfs_fseek_impl = probe_buffer_fseek,
155  .vfs_rewind_impl = probe_buffer_rewind,
156  .vfs_ftell_impl = probe_buffer_ftell,
157  .vfs_feof_impl = probe_buffer_feof,
158  .vfs_ftruncate_impl = probe_buffer_ftruncate,
159  .vfs_fsize_impl = probe_buffer_fsize,
160  .vfs_get_metadata_impl = probe_buffer_get_metadata,
161 };
162 
164 {
165  VFSFile * file = vfs_fopen (filename, "r");
166 
167  if (! file)
168  return NULL;
169 
170  ProbeBuffer * p = g_slice_new (ProbeBuffer);
171  p->file = file;
172  p->filled = 0;
173  p->at = 0;
174 
175  return vfs_new (filename, & probe_buffer_table, p);
176 }