Extending test-client-custom-summary to try e_book_client_get_contacts_uids()
[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 (C) 1999-2008 Novell, Inc. (www.novell.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 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <string.h>
31
32 #include "camel-debug.h"
33 #include "camel-stream.h"
34
35 G_DEFINE_ABSTRACT_TYPE (CamelStream, camel_stream, CAMEL_TYPE_OBJECT)
36
37 static gssize
38 stream_read (CamelStream *stream,
39              gchar *buffer,
40              gsize n,
41              GCancellable *cancellable,
42              GError **error)
43 {
44         return 0;
45 }
46
47 static gssize
48 stream_write (CamelStream *stream,
49               const gchar *buffer,
50               gsize n,
51               GCancellable *cancellable,
52               GError **error)
53 {
54         return n;
55 }
56
57 static gint
58 stream_close (CamelStream *stream,
59               GCancellable *cancellable,
60               GError **error)
61 {
62         return 0;
63 }
64
65 static gint
66 stream_flush (CamelStream *stream,
67               GCancellable *cancellable,
68               GError **error)
69 {
70         return 0;
71 }
72
73 static gboolean
74 stream_eos (CamelStream *stream)
75 {
76         return stream->eos;
77 }
78
79 static void
80 camel_stream_class_init (CamelStreamClass *class)
81 {
82         class->read = stream_read;
83         class->write = stream_write;
84         class->close = stream_close;
85         class->flush = stream_flush;
86         class->eos = stream_eos;
87 }
88
89 static void
90 camel_stream_init (CamelStream *stream)
91 {
92 }
93
94 /**
95  * camel_stream_read:
96  * @stream: a #CamelStream object.
97  * @buffer: output buffer
98  * @n: max number of bytes to read.
99  * @cancellable: optional #GCancellable object, or %NULL
100  * @error: return location for a #GError, or %NULL
101  *
102  * Attempts to read up to @len bytes from @stream into @buf.
103  *
104  * Returns: the number of bytes actually read, or %-1 on error and set
105  * errno.
106  **/
107 gssize
108 camel_stream_read (CamelStream *stream,
109                    gchar *buffer,
110                    gsize n,
111                    GCancellable *cancellable,
112                    GError **error)
113 {
114         CamelStreamClass *class;
115         gssize n_bytes;
116
117         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
118         g_return_val_if_fail (n == 0 || buffer, -1);
119
120         class = CAMEL_STREAM_GET_CLASS (stream);
121         g_return_val_if_fail (class->read != NULL, -1);
122
123         n_bytes = class->read (stream, buffer, n, cancellable, error);
124         CAMEL_CHECK_GERROR (stream, read, n_bytes >= 0, error);
125
126         return n_bytes;
127 }
128
129 /**
130  * camel_stream_write:
131  * @stream: a #CamelStream object
132  * @buffer: buffer to write.
133  * @n: number of bytes to write
134  * @cancellable: optional #GCancellable object, or %NULL
135  * @error: return location for a #GError, or %NULL
136  *
137  * Attempts to write up to @n bytes of @buffer into @stream.
138  *
139  * Returns: the number of bytes written to the stream, or %-1 on error
140  * along with setting errno.
141  **/
142 gssize
143 camel_stream_write (CamelStream *stream,
144                     const gchar *buffer,
145                     gsize n,
146                     GCancellable *cancellable,
147                     GError **error)
148 {
149         CamelStreamClass *class;
150         gssize n_bytes;
151
152         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
153         g_return_val_if_fail (n == 0 || buffer, -1);
154
155         class = CAMEL_STREAM_GET_CLASS (stream);
156         g_return_val_if_fail (class->write != NULL, -1);
157
158         n_bytes = class->write (stream, buffer, n, cancellable, error);
159         CAMEL_CHECK_GERROR (stream, write, n_bytes >= 0, error);
160
161         return n_bytes;
162 }
163
164 /**
165  * camel_stream_flush:
166  * @stream: a #CamelStream object
167  * @cancellable: optional #GCancellable object, or %NULL
168  * @error: return location for a #GError, or %NULL
169  *
170  * Flushes any buffered data to the stream's backing store.  Only
171  * meaningful for writable streams.
172  *
173  * Returns: %0 on success or %-1 on fail along with setting @error
174  **/
175 gint
176 camel_stream_flush (CamelStream *stream,
177                     GCancellable *cancellable,
178                     GError **error)
179 {
180         CamelStreamClass *class;
181         gint retval;
182
183         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
184
185         class = CAMEL_STREAM_GET_CLASS (stream);
186         g_return_val_if_fail (class->flush != NULL, -1);
187
188         retval = class->flush (stream, cancellable, error);
189         CAMEL_CHECK_GERROR (stream, flush, retval == 0, error);
190
191         return retval;
192 }
193
194 /**
195  * camel_stream_close:
196  * @stream: a #CamelStream object
197  * @cancellable: optional #GCancellable object, or %NULL
198  * @error: return location for a #GError, or %NULL
199  *
200  * Closes the stream.
201  *
202  * Returns: %0 on success or %-1 on error.
203  **/
204 gint
205 camel_stream_close (CamelStream *stream,
206                     GCancellable *cancellable,
207                     GError **error)
208 {
209         CamelStreamClass *class;
210         gint retval;
211
212         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
213
214         class = CAMEL_STREAM_GET_CLASS (stream);
215         g_return_val_if_fail (class->close != NULL, -1);
216
217         retval = class->close (stream, cancellable, error);
218         CAMEL_CHECK_GERROR (stream, close, retval == 0, error);
219
220         return retval;
221 }
222
223 /**
224  * camel_stream_eos:
225  * @stream: a #CamelStream object
226  *
227  * Tests if there are bytes left to read on the @stream object.
228  *
229  * Returns: %TRUE on EOS or %FALSE otherwise.
230  **/
231 gboolean
232 camel_stream_eos (CamelStream *stream)
233 {
234         CamelStreamClass *class;
235
236         g_return_val_if_fail (CAMEL_IS_STREAM (stream), TRUE);
237
238         class = CAMEL_STREAM_GET_CLASS (stream);
239         g_return_val_if_fail (class->eos != NULL, TRUE);
240
241         return class->eos (stream);
242 }
243
244 /***************** Utility functions ********************/
245
246 /**
247  * camel_stream_write_string:
248  * @stream: a #CamelStream object
249  * @string: a string
250  * @error: return location for a #GError, or %NULL
251  *
252  * Writes the string to the stream.
253  *
254  * Returns: the number of characters written or %-1 on error.
255  **/
256 gssize
257 camel_stream_write_string (CamelStream *stream,
258                            const gchar *string,
259                            GCancellable *cancellable,
260                            GError **error)
261 {
262         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
263         g_return_val_if_fail (string != NULL, -1);
264
265         return camel_stream_write (
266                 stream, string, strlen (string), cancellable, error);
267 }
268
269 /**
270  * camel_stream_write_to_stream:
271  * @stream: source #CamelStream object
272  * @output_stream: destination #CamelStream object
273  * @cancellable: optional #GCancellable object, or %NULL
274  * @error: return location for a #GError, or %NULL
275  *
276  * Write all of a stream (until eos) into another stream, in a
277  * blocking fashion.
278  *
279  * Returns: %-1 on error, or the number of bytes succesfully
280  * copied across streams.
281  **/
282 gssize
283 camel_stream_write_to_stream (CamelStream *stream,
284                               CamelStream *output_stream,
285                               GCancellable *cancellable,
286                               GError **error)
287 {
288         gchar tmp_buf[4096];
289         gssize total = 0;
290         gssize nb_read;
291         gssize nb_written;
292
293         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
294         g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1);
295
296         while (!camel_stream_eos (stream)) {
297                 nb_read = camel_stream_read (
298                         stream, tmp_buf, sizeof (tmp_buf),
299                         cancellable, error);
300                 if (nb_read < 0)
301                         return -1;
302                 else if (nb_read > 0) {
303                         nb_written = 0;
304
305                         while (nb_written < nb_read) {
306                                 gssize len = camel_stream_write (
307                                         output_stream,
308                                         tmp_buf + nb_written,
309                                         nb_read - nb_written,
310                                         cancellable, error);
311                                 if (len < 0)
312                                         return -1;
313                                 nb_written += len;
314                         }
315                         total += nb_written;
316                 }
317         }
318         return total;
319 }