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

Revision 15497, 5.9 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-iobuf.c - Buffered I/O for the GNOME Virtual File System.
3
4   Copyright (C) 1999 Free Software Foundation
5
6   The Gnome Library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Library General Public License as
8   published by the Free Software Foundation; either version 2 of the
9   License, or (at your option) any later version.
10
11   The Gnome Library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15
16   You should have received a copy of the GNU Library General Public
17   License along with the Gnome Library; see the file COPYING.LIB.  If not,
18   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.
20
21   Author: Ettore Perazzoli <ettore@gnu.org>
22*/
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <unistd.h>
29#include <string.h>
30
31#include "gnome-vfs.h"
32#include "gnome-vfs-private.h"
33
34
35#define BUFFER_SIZE 4096
36
37struct Buffer {
38        gchar data[BUFFER_SIZE];
39        guint offset;
40        guint byte_count;
41        GnomeVFSResult last_error;
42};
43typedef struct Buffer Buffer;
44
45struct GnomeVFSIOBuf {
46        gint fd;
47
48        Buffer input_buffer;
49        Buffer output_buffer;
50};
51
52
53static void
54buffer_init (Buffer *buffer)
55{
56        buffer->byte_count = 0;
57        buffer->offset = 0;
58        buffer->last_error = GNOME_VFS_OK;
59}
60
61GnomeVFSIOBuf *
62gnome_vfs_iobuf_new (gint fd)
63{
64        GnomeVFSIOBuf *new;
65
66        g_return_val_if_fail (fd >= 0, NULL);
67
68        new = g_new (GnomeVFSIOBuf, 1);
69
70        new->fd = fd;
71
72        buffer_init (&new->input_buffer);
73        buffer_init (&new->output_buffer);
74
75        return new;
76}
77
78void
79gnome_vfs_iobuf_destroy (GnomeVFSIOBuf *iobuf)
80{
81        g_free (iobuf);
82}
83
84static gboolean
85refill_input_buffer (GnomeVFSIOBuf *iobuf)
86{
87        Buffer *input_buffer;
88        gint r;
89
90        input_buffer = &iobuf->input_buffer;
91        if (input_buffer->last_error != GNOME_VFS_OK
92            || input_buffer->byte_count > 0)
93                return FALSE;
94
95        input_buffer->offset = 0;
96
97        r = read (iobuf->fd, &input_buffer->data, BUFFER_SIZE);
98        if (r == -1) {
99                input_buffer->last_error = gnome_vfs_result_from_errno ();
100                return FALSE;
101        }
102        if (r == 0) {
103                input_buffer->last_error = GNOME_VFS_ERROR_EOF;
104                return FALSE;
105        }
106
107        input_buffer->byte_count = r;
108
109        return TRUE;
110}
111
112GnomeVFSResult
113gnome_vfs_iobuf_read (GnomeVFSIOBuf *iobuf,
114                      gpointer buffer,
115                      GnomeVFSFileSize bytes,
116                      GnomeVFSFileSize *bytes_read)
117{
118        Buffer *input_buffer;
119        GnomeVFSResult result;
120        GnomeVFSFileSize n;
121
122        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
123        g_return_val_if_fail (buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
124
125        /* Quote from UNIX 98:
126           "If nbyte is 0, read() will return 0 and have no other results."
127        */
128        if (bytes == 0) {
129                *bytes_read = 0;
130                return GNOME_VFS_OK;
131        }
132               
133        input_buffer = &iobuf->input_buffer;
134
135        result = GNOME_VFS_OK;
136
137        if (input_buffer->byte_count == 0) {
138                if (! refill_input_buffer (iobuf)) {
139                        /* The buffer is empty but we had an error last time we
140                           filled it, so we report the error.  */
141                        result = input_buffer->last_error;
142                        input_buffer->last_error = GNOME_VFS_OK;
143                }
144        }
145
146        if (input_buffer->byte_count != 0) {
147                n = MIN (bytes, input_buffer->byte_count);
148                memcpy (buffer, input_buffer->data + input_buffer->offset, n);
149                input_buffer->byte_count -= n;
150                input_buffer->offset += n;
151                if (bytes_read != NULL)
152                        *bytes_read = n;
153        } else {
154                if (bytes_read != NULL)
155                        *bytes_read = 0;
156        }
157
158        if (result == GNOME_VFS_ERROR_EOF)
159                result = GNOME_VFS_OK;
160        return result;
161}
162
163GnomeVFSResult
164gnome_vfs_iobuf_peekc (GnomeVFSIOBuf *iobuf,
165                       gchar *c)
166{
167        GnomeVFSResult result;
168        Buffer *input_buffer;
169
170        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
171        g_return_val_if_fail (c != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
172
173        input_buffer = &iobuf->input_buffer;
174        result = GNOME_VFS_OK;
175
176        if (input_buffer->byte_count == 0) {
177                if (! refill_input_buffer (iobuf)) {
178                        /* The buffer is empty but we had an error last time we
179                           filled it, so we report the error.  */
180                        result = input_buffer->last_error;
181                        input_buffer->last_error = GNOME_VFS_OK;
182                }
183        }
184
185        if (result == GNOME_VFS_OK)
186                *c = *input_buffer->data;
187
188        return result;
189}
190
191static GnomeVFSResult
192flush (GnomeVFSIOBuf *iobuf)
193{
194        Buffer *output_buffer;
195        gint r;
196
197        output_buffer = &iobuf->output_buffer;
198
199        while (output_buffer->byte_count > 0) {
200                r = write (iobuf->fd, output_buffer->data,
201                           output_buffer->byte_count);
202                if (r == -1) {
203                        output_buffer->last_error =
204                                gnome_vfs_result_from_errno ();
205                        return output_buffer->last_error;
206                } else {
207                        output_buffer->byte_count -= r;
208                }
209        }
210
211        return GNOME_VFS_OK;
212}
213
214GnomeVFSResult
215gnome_vfs_iobuf_write (GnomeVFSIOBuf *iobuf,
216                       gconstpointer buffer,
217                       GnomeVFSFileSize bytes,
218                       GnomeVFSFileSize *bytes_written)
219{
220        Buffer *output_buffer;
221        GnomeVFSFileSize write_count;
222        GnomeVFSResult result;
223        const gchar *p;
224
225        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
226        g_return_val_if_fail (buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
227        g_return_val_if_fail (bytes_written != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
228
229        output_buffer = &iobuf->output_buffer;
230
231        result = GNOME_VFS_OK;
232
233        p = buffer;
234        write_count = 0;
235        while (write_count < bytes) {
236                if (output_buffer->byte_count < BUFFER_SIZE) {
237                        GnomeVFSFileSize n;
238
239                        n = MIN (BUFFER_SIZE - output_buffer->byte_count,
240                                 bytes);
241                        memcpy (output_buffer->data + output_buffer->byte_count,
242                                p, n);
243                        p += n;
244                        write_count += n;
245                        output_buffer->byte_count += n;
246                } else {
247                        result = flush (iobuf);
248                        if (result != GNOME_VFS_OK)
249                                break;
250                }
251        }
252
253        if (bytes_written != NULL)
254                *bytes_written = write_count;
255
256        return result;
257}
258
259GnomeVFSResult
260gnome_vfs_iobuf_flush (GnomeVFSIOBuf *iobuf)
261{
262        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
263
264        return flush (iobuf);
265}
266
Note: See TracBrowser for help on using the repository browser.