1 #include <ctype.h>
2 #include "gskstream.h"
3 #include "gskstreamconnection.h"
4 #include "gskerror.h"
5 #include "gskmacros.h"
6 #include "gskutils.h" /* for gsk_escape_memory() */
7 #include "debug.h"
8
9 /* parent classes */
10 static GObjectClass *parent_class = NULL;
11
12 /* ugh... */
13 #define DEBUG_PRINT_HEADER_FLAGS(flags, fctname) \
14 _GSK_DEBUG_PRINTF((flags), \
15 ("running %s on %s[%p]", \
16 fctname, \
17 g_type_name(G_OBJECT_TYPE(stream)), \
18 stream))
19 #define DEBUG_PRINT_HEADER(fctname) DEBUG_PRINT_HEADER_FLAGS(GSK_DEBUG_STREAM, fctname)
20
21
22 /* ========== GskStream =========== */
23
24 /* --- i/o methods --- */
25
26 /**
27 * gsk_stream_read:
28 * @stream: the stream to attempt to read data from.
29 * @buffer: the buffer to fill with data.
30 * @buffer_length: the maximum data to copy into the buffer.
31 * @error: optional place to store a GError if something goes wrong.
32 *
33 * Read up to @buffer_length bytes into @buffer,
34 * returning the amount read. It may return 0;
35 * this does not indicate an end-of-file.
36 *
37 * returns: the number of bytes read into @buffer.
38 */
39 gsize
gsk_stream_read(GskStream * stream,gpointer buffer,gsize buffer_length,GError ** error)40 gsk_stream_read (GskStream *stream,
41 gpointer buffer,
42 gsize buffer_length,
43 GError **error)
44 {
45 GskStreamClass *class = GSK_STREAM_GET_CLASS (stream);
46 gsize rv;
47 DEBUG_PRINT_HEADER ("gsk_stream_read");
48 if (error != NULL && *error != NULL)
49 return 0;
50 if (gsk_io_get_is_connecting (stream))
51 return 0;
52 g_object_ref (stream);
53 rv = (*class->raw_read) (stream, buffer, buffer_length, error);
54 if (stream->never_partial_reads)
55 g_return_val_if_fail (rv == buffer_length, rv);
56 if (GSK_IS_DEBUGGING (STREAM_DATA))
57 {
58 char *text = gsk_escape_memory (buffer, rv);
59 g_printerr ("%s::read() = \"%s\"\n", G_OBJECT_TYPE_NAME (stream), text);
60 g_free (text);
61 }
62 g_object_unref (stream);
63 return rv;
64 }
65
66 /**
67 * gsk_stream_write:
68 * @stream: the stream to attempt to write data to.
69 * @buffer: the buffer to write from.
70 * @buffer_length: the number of bytes in buffer.
71 * @error: optional place to store a GError if something goes wrong.
72 *
73 * Write up to @buffer_length bytes into @buffer,
74 * returning the amount written. It may return 0;
75 * this does not indicate an error by itself.
76 *
77 * returns: the number of bytes written.
78 */
79 gsize
gsk_stream_write(GskStream * stream,gconstpointer buffer,gsize buffer_length,GError ** error)80 gsk_stream_write (GskStream *stream,
81 gconstpointer buffer,
82 gsize buffer_length,
83 GError **error)
84 {
85 guint written = 0;
86 GskStreamClass *class = GSK_STREAM_GET_CLASS (stream);
87 _GSK_DEBUG_PRINTF(GSK_DEBUG_STREAM,
88 ("running %s on %s[%p]. buffer_length=%u.",
89 "gsk_stream_write",
90 g_type_name(G_OBJECT_TYPE(stream)),
91 stream, (guint)buffer_length));
92 if (error != NULL && *error != NULL)
93 return 0;
94 if (buffer_length == 0)
95 return 0;
96 if (gsk_io_get_is_connecting (stream))
97 {
98 _GSK_DEBUG_PRINTF(GSK_DEBUG_STREAM,
99 ("gsk_stream_write: returning 0 because stream is still connecting"));
100 return 0;
101 }
102 g_object_ref (stream);
103 g_return_val_if_fail (class->raw_write != NULL, 0);
104 written = (*class->raw_write) (stream, buffer, buffer_length, error);
105 if (GSK_IS_DEBUGGING (STREAM_DATA))
106 {
107 char *text = gsk_escape_memory (buffer, written);
108 g_printerr ("%s::write() = \"%s\"\n", G_OBJECT_TYPE_NAME (stream), text);
109 g_free (text);
110 }
111 g_assert (written <= buffer_length);
112 if (stream->never_partial_writes)
113 g_return_val_if_fail (written == buffer_length, buffer_length);
114 g_object_unref (stream);
115 return written;
116 }
117
118 /* read into buffer */
119 /**
120 * gsk_stream_read_buffer:
121 * @stream: the stream to attempt to read data from.
122 * @buffer: the buffer to copy data into.
123 * @error: optional place to store a GError if something goes wrong.
124 *
125 * Read data from the stream directly into a #GskBuffer.
126 *
127 * returns: the number of bytes read into @buffer.
128 */
129 gsize
gsk_stream_read_buffer(GskStream * stream,GskBuffer * buffer,GError ** error)130 gsk_stream_read_buffer (GskStream *stream,
131 GskBuffer *buffer,
132 GError **error)
133 {
134 GskStreamClass *class = GSK_STREAM_GET_CLASS (stream);
135 gboolean debug_data = GSK_IS_DEBUGGING (STREAM_DATA);
136 if (gsk_io_get_is_connecting (stream))
137 return 0;
138 if (!debug_data && class->raw_read_buffer)
139 return (*class->raw_read_buffer) (stream, buffer, error);
140 else
141 {
142 char tmp_area[8192];
143 guint size = 8192;
144 gsize read;
145 /* tmp_area = g_alloca (size); */
146 g_object_ref (stream);
147 read = gsk_stream_read (stream, tmp_area, size, error);
148 if (read > 0)
149 gsk_buffer_append (buffer, tmp_area, read);
150 if (debug_data)
151 {
152 char *str = gsk_escape_memory (tmp_area, read);
153 g_printerr ("gsk_stream_read_buffer: \"%s\"\n", str);
154 g_free (str);
155 }
156 g_object_unref (stream);
157 return read;
158 }
159 }
160
161 /* write from buffer */
162 /**
163 * gsk_stream_write_buffer:
164 * @stream: the stream to attempt to write data to.
165 * @buffer: the buffer to get data from.
166 * @error: optional place to store a GError if something goes wrong.
167 *
168 * Write data to the stream directly from a #GskBuffer.
169 * Data written from the buffer is removed from it.
170 *
171 * returns: the number of bytes written from @buffer.
172 */
173 gsize
gsk_stream_write_buffer(GskStream * stream,GskBuffer * buffer,GError ** error)174 gsk_stream_write_buffer (GskStream *stream,
175 GskBuffer *buffer,
176 GError **error)
177 {
178 GskStreamClass *class = GSK_STREAM_GET_CLASS (stream);
179 gboolean debug_data = GSK_IS_DEBUGGING (STREAM_DATA);
180 if (gsk_io_get_is_connecting (stream))
181 return 0;
182 if (!debug_data && class->raw_write_buffer)
183 return (*class->raw_write_buffer) (stream, buffer, error);
184 else
185 {
186 char *tmp_area;
187 guint size = 8192;
188 guint read;
189 tmp_area = g_alloca (size);
190 g_object_ref (stream);
191 read = gsk_buffer_peek (buffer, tmp_area, size);
192 if (read > 0)
193 {
194 gsize written = gsk_stream_write (stream, tmp_area, read, error);
195 if (written > 0)
196 gsk_buffer_discard (buffer, written);
197 if (debug_data)
198 {
199 char *text = gsk_escape_memory (tmp_area, written);
200 g_printerr ("gsk_stream_write_buffer[%s]: \"%s\"\n",
201 G_OBJECT_TYPE_NAME (stream), text);
202 g_free (text);
203 }
204 g_object_unref (stream);
205 return written;
206 }
207 else
208 {
209 if (debug_data)
210 g_printerr ("gsk_stream_write_buffer[%s]: source buffer was empty\n",
211 G_OBJECT_TYPE_NAME (stream));
212 }
213 g_object_unref (stream);
214 return read;
215 }
216 }
217
218 /* --- functions --- */
219 static void
gsk_stream_init(GskStream * stream)220 gsk_stream_init (GskStream *stream)
221 {
222 }
223
224 static void
gsk_stream_class_init(GskStreamClass * class)225 gsk_stream_class_init (GskStreamClass *class)
226 {
227 GObjectClass *object_class = G_OBJECT_CLASS (class);
228 parent_class = g_type_class_peek_parent (object_class);
229 }
230
231
gsk_stream_get_type()232 GType gsk_stream_get_type()
233 {
234 static GType stream_type = 0;
235 if (!stream_type)
236 {
237 static const GTypeInfo stream_info =
238 {
239 sizeof(GskStreamClass),
240 (GBaseInitFunc) NULL,
241 (GBaseFinalizeFunc) NULL,
242 (GClassInitFunc) gsk_stream_class_init,
243 NULL, /* class_finalize */
244 NULL, /* class_data */
245 sizeof (GskStream),
246 0, /* n_preallocs */
247 (GInstanceInitFunc) gsk_stream_init,
248 NULL /* value_table */
249 };
250 stream_type = g_type_register_static (GSK_TYPE_IO,
251 "GskStream",
252 &stream_info,
253 G_TYPE_FLAG_ABSTRACT);
254 }
255 return stream_type;
256 }
257
258 /**
259 * gsk_stream_attach:
260 * @input_stream: the input stream whose read-end will be trapped.
261 * @output_stream: the output stream whose write-end will be trapped.
262 * @error: optional error return location.
263 *
264 * Attach the read end of @input_stream
265 * to the write end of @output_stream,
266 * returning an error if anything goes wrong.
267 *
268 * returns: whether the connection was successful.
269 */
270 gboolean
gsk_stream_attach(GskStream * input_stream,GskStream * output_stream,GError ** error)271 gsk_stream_attach (GskStream *input_stream,
272 GskStream *output_stream,
273 GError **error)
274 {
275 GskStreamConnection *connection = gsk_stream_connection_new (input_stream, output_stream, error);
276 if (connection != NULL)
277 {
278 g_object_unref (connection);
279 return TRUE;
280 }
281 return FALSE;
282 }
283
284
285 /**
286 * gsk_stream_attach_pair:
287 * @stream_a: one of the two streams to attach together.
288 * @stream_b: one of the two streams to attach together.
289 * @error: optional error return location.
290 *
291 * Attach a's input to b's output and vice versa.
292 *
293 * returns: whether the connection was successful.
294 */
gsk_stream_attach_pair(GskStream * stream_a,GskStream * stream_b,GError ** error)295 gboolean gsk_stream_attach_pair (GskStream *stream_a,
296 GskStream *stream_b,
297 GError **error)
298 {
299 GskStreamConnection *ab = gsk_stream_connection_new (stream_a, stream_b, error);
300 GskStreamConnection *ba;
301 if (ab == NULL)
302 return FALSE;
303 ba = gsk_stream_connection_new (stream_b, stream_a, error);
304 if (ba == NULL)
305 {
306 gsk_stream_connection_detach (ab);
307 g_object_unref (ab);
308 return FALSE;
309 }
310 g_object_unref (ab);
311 g_object_unref (ba);
312 return TRUE;
313 }
314