Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / camel / camel-stream.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-stream.c : abstract class for a stream */
3
4 /*
5  * Author:
6  *  Bertrand Guiheneuf <bertrand@helixcode.com>
7  *
8  * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of version 2 of the GNU Lesser General Public
12  * License as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
22  * USA
23  */
24
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <string.h>
31
32 #include "camel-stream.h"
33
34 static CamelObjectClass *parent_class = NULL;
35
36 /* Returns the class for a CamelStream */
37 #define CS_CLASS(so) CAMEL_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so))
38
39 /* default implementations, do very little */
40 static ssize_t   stream_read       (CamelStream *stream, char *buffer, size_t n) { return 0; }
41 static ssize_t   stream_write      (CamelStream *stream, const char *buffer, size_t n) { return n; }
42 static int       stream_close      (CamelStream *stream) { return 0; }
43 static int       stream_flush      (CamelStream *stream) { return 0; }
44 static gboolean  stream_eos        (CamelStream *stream) { return stream->eos; }
45 static int       stream_reset      (CamelStream *stream) { return 0; }
46
47 static void
48 camel_stream_class_init (CamelStreamClass *camel_stream_class)
49 {
50         parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE );
51
52         /* virtual method definition */
53         camel_stream_class->read = stream_read;
54         camel_stream_class->write = stream_write;
55         camel_stream_class->close = stream_close;
56         camel_stream_class->flush = stream_flush;
57         camel_stream_class->eos = stream_eos;
58         camel_stream_class->reset = stream_reset;
59 }
60
61 CamelType
62 camel_stream_get_type (void)
63 {
64         static CamelType camel_stream_type = CAMEL_INVALID_TYPE;
65
66         if (camel_stream_type == CAMEL_INVALID_TYPE) {
67                 camel_stream_type = camel_type_register( CAMEL_OBJECT_TYPE,
68                                                          "CamelStream",
69                                                          sizeof( CamelStream ),
70                                                          sizeof( CamelStreamClass ),
71                                                          (CamelObjectClassInitFunc) camel_stream_class_init,
72                                                          NULL,
73                                                          NULL,
74                                                          NULL );
75         }
76
77         return camel_stream_type;
78 }
79
80
81 /**
82  * camel_stream_read:
83  * @stream: a #CamelStream object.
84  * @buffer: output buffer
85  * @n: max number of bytes to read.
86  *
87  * Attempts to read up to @len bytes from @stream into @buf.
88  *
89  * Returns the number of bytes actually read, or %-1 on error and set
90  * errno.
91  **/
92 ssize_t
93 camel_stream_read (CamelStream *stream, char *buffer, size_t n)
94 {
95         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
96         g_return_val_if_fail (n == 0 || buffer, -1);
97         
98         return (CS_CLASS (stream)->read) (stream, buffer, n);
99 }
100
101
102 /**
103  * camel_stream_write:
104  * @stream: a #CamelStream object
105  * @buffer: buffer to write.
106  * @n: number of bytes to write
107  *
108  * Attempts to write up to @n bytes of @buffer into @stream.
109  *
110  * Returns the number of bytes written to the stream, or %-1 on error
111  * along with setting errno.
112  **/
113 ssize_t
114 camel_stream_write (CamelStream *stream, const char *buffer, size_t n)
115 {
116         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
117         g_return_val_if_fail (n == 0 || buffer, -1);
118
119         return CS_CLASS (stream)->write (stream, buffer, n);
120 }
121
122
123 /**
124  * camel_stream_flush:
125  * @stream: a #CamelStream object
126  *
127  * Flushes any buffered data to the stream's backing store.  Only
128  * meaningful for writable streams.
129  *
130  * Returns %0 on success or %-1 on fail along with setting errno.
131  **/
132 int
133 camel_stream_flush (CamelStream *stream)
134 {
135         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
136
137         return CS_CLASS (stream)->flush (stream);
138 }
139
140
141 /**
142  * camel_stream_close:
143  * @stream: a #CamelStream object
144  * 
145  * Closes the stream.
146  * 
147  * Returns %0 on success or %-1 on error.
148  **/
149 int
150 camel_stream_close (CamelStream *stream)
151 {
152         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
153         
154         return CS_CLASS (stream)->close (stream);
155 }
156
157
158 /**
159  * camel_stream_eos:
160  * @stream: a #CamelStream object
161  *
162  * Tests if there are bytes left to read on the @stream object.
163  *
164  * Returns %TRUE on EOS or %FALSE otherwise.
165  **/
166 gboolean
167 camel_stream_eos (CamelStream *stream)
168 {
169         g_return_val_if_fail (CAMEL_IS_STREAM (stream), TRUE);
170         
171         return CS_CLASS (stream)->eos (stream);
172 }
173
174
175 /**
176  * camel_stream_reset:
177  * @stream: a #CamelStream object
178  *
179  * Resets the stream. That is, put it in a state where it can be read
180  * from the beginning again. Not all streams in Camel are seekable,
181  * but they must all be resettable.
182  *
183  * Returns %0 on success or %-1 on error along with setting errno.
184  **/
185 int
186 camel_stream_reset (CamelStream *stream)
187 {
188         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
189         
190         return CS_CLASS (stream)->reset (stream);
191 }
192
193 /***************** Utility functions ********************/
194
195 /**
196  * camel_stream_write_string:
197  * @stream: a #CamelStream object
198  * @string: a string
199  *
200  * Writes the string to the stream.
201  *
202  * Returns the number of characters written or %-1 on error.
203  **/
204 ssize_t
205 camel_stream_write_string (CamelStream *stream, const char *string)
206 {
207         return camel_stream_write (stream, string, strlen (string));
208 }
209
210
211 /**
212  * camel_stream_printf:
213  * @stream: a #CamelStream object
214  * @fmt: a printf-style format string
215  *
216  * Write formatted output to a stream.
217  *
218  * Returns the number of characters written or %-1 on error.
219  **/
220 ssize_t
221 camel_stream_printf (CamelStream *stream, const char *fmt, ... )
222 {
223         va_list args;
224         char *string;
225         ssize_t ret;
226         
227         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
228         
229         va_start (args, fmt);
230         string = g_strdup_vprintf (fmt, args);
231         va_end (args);
232         
233         if (!string)
234                 return -1;
235         
236         ret = camel_stream_write (stream, string, strlen (string));
237         g_free (string);
238         return ret;
239 }
240
241
242 /**
243  * camel_stream_write_to_stream:
244  * @stream: source #CamelStream object
245  * @output_stream: destination #CamelStream object
246  *
247  * Write all of a stream (until eos) into another stream, in a
248  * blocking fashion.
249  *
250  * Returns %-1 on error, or the number of bytes succesfully
251  * copied across streams.
252  **/
253 ssize_t
254 camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream)
255 {
256         char tmp_buf[4096];
257         ssize_t total = 0;
258         ssize_t nb_read;
259         ssize_t nb_written;
260
261         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
262         g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1);
263
264         while (!camel_stream_eos (stream)) {
265                 nb_read = camel_stream_read (stream, tmp_buf, sizeof (tmp_buf));
266                 if (nb_read < 0)
267                         return -1;
268                 else if (nb_read > 0) {
269                         nb_written = 0;
270
271                         while (nb_written < nb_read) {
272                                 ssize_t len = camel_stream_write (output_stream, tmp_buf + nb_written,
273                                                                   nb_read - nb_written);
274                                 if (len < 0)
275                                         return -1;
276                                 nb_written += len;
277                         }
278                         total += nb_written;
279                 }
280         }
281         return total;
282 }