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

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