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