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

Revision 17128, 5.9 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17127, 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#include <config.h>
25#include "gnome-vfs-iobuf.h"
26
27#include <unistd.h>
28#include <string.h>
29
30#include "gnome-vfs.h"
31#include "gnome-vfs-private.h"
32
33
34#define BUFFER_SIZE 4096
35
36struct Buffer {
37        gchar data[BUFFER_SIZE];
38        guint offset;
39        guint byte_count;
40        GnomeVFSResult last_error;
41};
42typedef struct Buffer Buffer;
43
44struct GnomeVFSIOBuf {
45        gint fd;
46
47        Buffer input_buffer;
48        Buffer output_buffer;
49};
50
51
52static void
53buffer_init (Buffer *buffer)
54{
55        buffer->byte_count = 0;
56        buffer->offset = 0;
57        buffer->last_error = GNOME_VFS_OK;
58}
59
60GnomeVFSIOBuf *
61gnome_vfs_iobuf_new (gint fd)
62{
63        GnomeVFSIOBuf *new;
64
65        g_return_val_if_fail (fd >= 0, NULL);
66
67        new = g_new (GnomeVFSIOBuf, 1);
68
69        new->fd = fd;
70
71        buffer_init (&new->input_buffer);
72        buffer_init (&new->output_buffer);
73
74        return new;
75}
76
77void
78gnome_vfs_iobuf_destroy (GnomeVFSIOBuf *iobuf)
79{
80        g_free (iobuf);
81}
82
83static gboolean
84refill_input_buffer (GnomeVFSIOBuf *iobuf)
85{
86        Buffer *input_buffer;
87        gint r;
88
89        input_buffer = &iobuf->input_buffer;
90        if (input_buffer->last_error != GNOME_VFS_OK
91            || input_buffer->byte_count > 0)
92                return FALSE;
93
94        input_buffer->offset = 0;
95
96        r = read (iobuf->fd, &input_buffer->data, BUFFER_SIZE);
97        if (r == -1) {
98                input_buffer->last_error = gnome_vfs_result_from_errno ();
99                return FALSE;
100        }
101        if (r == 0) {
102                input_buffer->last_error = GNOME_VFS_ERROR_EOF;
103                return FALSE;
104        }
105
106        input_buffer->byte_count = r;
107
108        return TRUE;
109}
110
111GnomeVFSResult
112gnome_vfs_iobuf_read (GnomeVFSIOBuf *iobuf,
113                      gpointer buffer,
114                      GnomeVFSFileSize bytes,
115                      GnomeVFSFileSize *bytes_read)
116{
117        Buffer *input_buffer;
118        GnomeVFSResult result;
119        GnomeVFSFileSize n;
120
121        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
122        g_return_val_if_fail (buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
123
124        /* Quote from UNIX 98:
125           "If nbyte is 0, read() will return 0 and have no other results."
126        */
127        if (bytes == 0) {
128                *bytes_read = 0;
129                return GNOME_VFS_OK;
130        }
131               
132        input_buffer = &iobuf->input_buffer;
133
134        result = GNOME_VFS_OK;
135
136        if (input_buffer->byte_count == 0) {
137                if (! refill_input_buffer (iobuf)) {
138                        /* The buffer is empty but we had an error last time we
139                           filled it, so we report the error.  */
140                        result = input_buffer->last_error;
141                        input_buffer->last_error = GNOME_VFS_OK;
142                }
143        }
144
145        if (input_buffer->byte_count != 0) {
146                n = MIN (bytes, input_buffer->byte_count);
147                memcpy (buffer, input_buffer->data + input_buffer->offset, n);
148                input_buffer->byte_count -= n;
149                input_buffer->offset += n;
150                if (bytes_read != NULL)
151                        *bytes_read = n;
152        } else {
153                if (bytes_read != NULL)
154                        *bytes_read = 0;
155        }
156
157        if (result == GNOME_VFS_ERROR_EOF)
158                result = GNOME_VFS_OK;
159        return result;
160}
161
162GnomeVFSResult
163gnome_vfs_iobuf_peekc (GnomeVFSIOBuf *iobuf,
164                       gchar *c)
165{
166        GnomeVFSResult result;
167        Buffer *input_buffer;
168
169        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
170        g_return_val_if_fail (c != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
171
172        input_buffer = &iobuf->input_buffer;
173        result = GNOME_VFS_OK;
174
175        if (input_buffer->byte_count == 0) {
176                if (! refill_input_buffer (iobuf)) {
177                        /* The buffer is empty but we had an error last time we
178                           filled it, so we report the error.  */
179                        result = input_buffer->last_error;
180                        input_buffer->last_error = GNOME_VFS_OK;
181                }
182        }
183
184        if (result == GNOME_VFS_OK)
185                *c = *input_buffer->data;
186
187        return result;
188}
189
190static GnomeVFSResult
191flush (GnomeVFSIOBuf *iobuf)
192{
193        Buffer *output_buffer;
194        gint r;
195
196        output_buffer = &iobuf->output_buffer;
197
198        while (output_buffer->byte_count > 0) {
199                r = write (iobuf->fd, output_buffer->data,
200                           output_buffer->byte_count);
201                if (r == -1) {
202                        output_buffer->last_error =
203                                gnome_vfs_result_from_errno ();
204                        return output_buffer->last_error;
205                } else {
206                        output_buffer->byte_count -= r;
207                }
208        }
209
210        return GNOME_VFS_OK;
211}
212
213GnomeVFSResult
214gnome_vfs_iobuf_write (GnomeVFSIOBuf *iobuf,
215                       gconstpointer buffer,
216                       GnomeVFSFileSize bytes,
217                       GnomeVFSFileSize *bytes_written)
218{
219        Buffer *output_buffer;
220        GnomeVFSFileSize write_count;
221        GnomeVFSResult result;
222        const gchar *p;
223
224        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
225        g_return_val_if_fail (buffer != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
226        g_return_val_if_fail (bytes_written != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
227
228        output_buffer = &iobuf->output_buffer;
229
230        result = GNOME_VFS_OK;
231
232        p = buffer;
233        write_count = 0;
234        while (write_count < bytes) {
235                if (output_buffer->byte_count < BUFFER_SIZE) {
236                        GnomeVFSFileSize n;
237
238                        n = MIN (BUFFER_SIZE - output_buffer->byte_count,
239                                 bytes);
240                        memcpy (output_buffer->data + output_buffer->byte_count,
241                                p, n);
242                        p += n;
243                        write_count += n;
244                        output_buffer->byte_count += n;
245                } else {
246                        result = flush (iobuf);
247                        if (result != GNOME_VFS_OK)
248                                break;
249                }
250        }
251
252        if (bytes_written != NULL)
253                *bytes_written = write_count;
254
255        return result;
256}
257
258GnomeVFSResult
259gnome_vfs_iobuf_flush (GnomeVFSIOBuf *iobuf)
260{
261        g_return_val_if_fail (iobuf != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
262
263        return flush (iobuf);
264}
Note: See TracBrowser for help on using the repository browser.