1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
2 /* camel-stream.c : abstract class for a stream
3 *
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5 *
6 * This library is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authors: Michael Zucchi <notzed@ximian.com>
19 */
20
21 #include "evolution-data-server-config.h"
22
23 #include <glib/gi18n-lib.h>
24
25 #include "camel-stream-null.h"
26
27 struct _CamelStreamNullPrivate {
28 gsize written;
29 gboolean ends_with_crlf;
30 gboolean ends_with_cr; /* Just for cases when the CRLF is split into two writes, CR and LF */
31 };
32
33 static void camel_stream_null_seekable_init (GSeekableIface *iface);
34
G_DEFINE_TYPE_WITH_CODE(CamelStreamNull,camel_stream_null,CAMEL_TYPE_STREAM,G_ADD_PRIVATE (CamelStreamNull)G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,camel_stream_null_seekable_init))35 G_DEFINE_TYPE_WITH_CODE (CamelStreamNull, camel_stream_null, CAMEL_TYPE_STREAM,
36 G_ADD_PRIVATE (CamelStreamNull)
37 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, camel_stream_null_seekable_init))
38
39 static gssize
40 stream_null_write (CamelStream *stream,
41 const gchar *buffer,
42 gsize n,
43 GCancellable *cancellable,
44 GError **error)
45 {
46 CamelStreamNull *stream_null = CAMEL_STREAM_NULL (stream);
47
48 stream_null->priv->written += n;
49
50 if (n >= 2) {
51 stream_null->priv->ends_with_crlf = buffer[n - 2] == '\r' && buffer[n - 1] == '\n';
52 stream_null->priv->ends_with_cr = buffer[n - 1] == '\r';
53 } else if (n == 1) {
54 stream_null->priv->ends_with_crlf = stream_null->priv->ends_with_cr && buffer[n - 1] == '\n';
55 stream_null->priv->ends_with_cr = buffer[n - 1] == '\r';
56 }
57
58 return n;
59 }
60
61 static gboolean
stream_null_eos(CamelStream * stream)62 stream_null_eos (CamelStream *stream)
63 {
64 return TRUE;
65 }
66
67 static goffset
stream_null_tell(GSeekable * seekable)68 stream_null_tell (GSeekable *seekable)
69 {
70 return 0;
71 }
72
73 static gboolean
stream_null_can_seek(GSeekable * seekable)74 stream_null_can_seek (GSeekable *seekable)
75 {
76 return TRUE;
77 }
78
79 static gboolean
stream_null_seek(GSeekable * seekable,goffset offset,GSeekType type,GCancellable * cancellable,GError ** error)80 stream_null_seek (GSeekable *seekable,
81 goffset offset,
82 GSeekType type,
83 GCancellable *cancellable,
84 GError **error)
85 {
86 if (type != G_SEEK_SET || offset != 0) {
87 g_set_error_literal (
88 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
89 _("Only reset to beginning is supported with CamelHttpStream"));
90 return FALSE;
91 }
92
93 CAMEL_STREAM_NULL (seekable)->priv->written = 0;
94
95 return TRUE;
96 }
97
98 static gboolean
stream_null_can_truncate(GSeekable * seekable)99 stream_null_can_truncate (GSeekable *seekable)
100 {
101 return FALSE;
102 }
103
104 static gboolean
stream_null_truncate_fn(GSeekable * seekable,goffset offset,GCancellable * cancellable,GError ** error)105 stream_null_truncate_fn (GSeekable *seekable,
106 goffset offset,
107 GCancellable *cancellable,
108 GError **error)
109 {
110 /* XXX Don't bother translating this. Camel never calls it. */
111 g_set_error_literal (
112 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
113 "Truncation is not supported");
114
115 return FALSE;
116 }
117
118 static void
camel_stream_null_class_init(CamelStreamNullClass * class)119 camel_stream_null_class_init (CamelStreamNullClass *class)
120 {
121 CamelStreamClass *stream_class;
122
123 stream_class = CAMEL_STREAM_CLASS (class);
124 stream_class->write = stream_null_write;
125 stream_class->eos = stream_null_eos;
126 }
127
128 static void
camel_stream_null_seekable_init(GSeekableIface * iface)129 camel_stream_null_seekable_init (GSeekableIface *iface)
130 {
131 iface->tell = stream_null_tell;
132 iface->can_seek = stream_null_can_seek;
133 iface->seek = stream_null_seek;
134 iface->can_truncate = stream_null_can_truncate;
135 iface->truncate_fn = stream_null_truncate_fn;
136 }
137
138 static void
camel_stream_null_init(CamelStreamNull * stream_null)139 camel_stream_null_init (CamelStreamNull *stream_null)
140 {
141 stream_null->priv = camel_stream_null_get_instance_private (stream_null);
142 stream_null->priv->ends_with_crlf = FALSE;
143 stream_null->priv->ends_with_cr = FALSE;
144 }
145
146 /**
147 * camel_stream_null_new:
148 *
149 * Returns a null stream. A null stream is always at eof, and
150 * always returns success for all reads and writes.
151 *
152 * Returns: (transfer full): a new #CamelStreamNull
153 **/
154 CamelStream *
camel_stream_null_new(void)155 camel_stream_null_new (void)
156 {
157 return g_object_new (CAMEL_TYPE_STREAM_NULL, NULL);
158 }
159
160 /**
161 * camel_stream_null_get_bytes_written:
162 * @stream_null: a #CamelStreamNull
163 *
164 * Returns: how many bytes had been written to the @stream_null since
165 * it was created or rewind to the beginning.
166 *
167 * Since: 3.24
168 **/
169 gsize
camel_stream_null_get_bytes_written(CamelStreamNull * stream_null)170 camel_stream_null_get_bytes_written (CamelStreamNull *stream_null)
171 {
172 g_return_val_if_fail (CAMEL_IS_STREAM_NULL (stream_null), -1);
173
174 return stream_null->priv->written;
175 }
176
177 /**
178 * camel_stream_null_get_ends_with_crlf:
179 * @stream_null: a #CamelStreamNull
180 *
181 * Returns: Whether the data being written to @stream_null ended with CRLF.
182 *
183 * Since: 3.30
184 **/
185 gboolean
camel_stream_null_get_ends_with_crlf(CamelStreamNull * stream_null)186 camel_stream_null_get_ends_with_crlf (CamelStreamNull *stream_null)
187 {
188 g_return_val_if_fail (CAMEL_IS_STREAM_NULL (stream_null), FALSE);
189
190 return stream_null->priv->ends_with_crlf;
191 }
192