nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2006-2007 Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Christian Kellner <gicmo@gnome.org>
19 */
20  
21 #include "config.h"
22 #include "gmemoryinputstream.h"
23 #include "gpollableinputstream.h"
24 #include "ginputstream.h"
25 #include "gseekable.h"
26 #include "string.h"
27 #include "gtask.h"
28 #include "gioerror.h"
29 #include "glibintl.h"
30  
31  
32 /**
33 * SECTION:gmemoryinputstream
34 * @short_description: Streaming input operations on memory chunks
35 * @include: gio/gio.h
36 * @see_also: #GMemoryOutputStream
37 *
38 * #GMemoryInputStream is a class for using arbitrary
39 * memory chunks as input for GIO streaming input operations.
40 *
41 * As of GLib 2.34, #GMemoryInputStream implements
42 * #GPollableInputStream.
43 */
44  
45 struct _GMemoryInputStreamPrivate {
46 GSList *chunks;
47 gsize len;
48 gsize pos;
49 };
50  
51 static gssize g_memory_input_stream_read (GInputStream *stream,
52 void *buffer,
53 gsize count,
54 GCancellable *cancellable,
55 GError **error);
56 static gssize g_memory_input_stream_skip (GInputStream *stream,
57 gsize count,
58 GCancellable *cancellable,
59 GError **error);
60 static gboolean g_memory_input_stream_close (GInputStream *stream,
61 GCancellable *cancellable,
62 GError **error);
63 static void g_memory_input_stream_skip_async (GInputStream *stream,
64 gsize count,
65 int io_priority,
66 GCancellable *cancellabl,
67 GAsyncReadyCallback callback,
68 gpointer datae);
69 static gssize g_memory_input_stream_skip_finish (GInputStream *stream,
70 GAsyncResult *result,
71 GError **error);
72 static void g_memory_input_stream_close_async (GInputStream *stream,
73 int io_priority,
74 GCancellable *cancellabl,
75 GAsyncReadyCallback callback,
76 gpointer data);
77 static gboolean g_memory_input_stream_close_finish (GInputStream *stream,
78 GAsyncResult *result,
79 GError **error);
80  
81 static void g_memory_input_stream_seekable_iface_init (GSeekableIface *iface);
82 static goffset g_memory_input_stream_tell (GSeekable *seekable);
83 static gboolean g_memory_input_stream_can_seek (GSeekable *seekable);
84 static gboolean g_memory_input_stream_seek (GSeekable *seekable,
85 goffset offset,
86 GSeekType type,
87 GCancellable *cancellable,
88 GError **error);
89 static gboolean g_memory_input_stream_can_truncate (GSeekable *seekable);
90 static gboolean g_memory_input_stream_truncate (GSeekable *seekable,
91 goffset offset,
92 GCancellable *cancellable,
93 GError **error);
94  
95 static void g_memory_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
96 static gboolean g_memory_input_stream_is_readable (GPollableInputStream *stream);
97 static GSource *g_memory_input_stream_create_source (GPollableInputStream *stream,
98 GCancellable *cancellable);
99  
100 static void g_memory_input_stream_finalize (GObject *object);
101  
102 G_DEFINE_TYPE_WITH_CODE (GMemoryInputStream, g_memory_input_stream, G_TYPE_INPUT_STREAM,
103 G_ADD_PRIVATE (GMemoryInputStream)
104 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
105 g_memory_input_stream_seekable_iface_init);
106 G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
107 g_memory_input_stream_pollable_iface_init);
108 )
109  
110  
111 static void
112 g_memory_input_stream_class_init (GMemoryInputStreamClass *klass)
113 {
114 GObjectClass *object_class;
115 GInputStreamClass *istream_class;
116  
117 object_class = G_OBJECT_CLASS (klass);
118 object_class->finalize = g_memory_input_stream_finalize;
119  
120 istream_class = G_INPUT_STREAM_CLASS (klass);
121 istream_class->read_fn = g_memory_input_stream_read;
122 istream_class->skip = g_memory_input_stream_skip;
123 istream_class->close_fn = g_memory_input_stream_close;
124  
125 istream_class->skip_async = g_memory_input_stream_skip_async;
126 istream_class->skip_finish = g_memory_input_stream_skip_finish;
127 istream_class->close_async = g_memory_input_stream_close_async;
128 istream_class->close_finish = g_memory_input_stream_close_finish;
129 }
130  
131 static void
132 g_memory_input_stream_finalize (GObject *object)
133 {
134 GMemoryInputStream *stream;
135 GMemoryInputStreamPrivate *priv;
136  
137 stream = G_MEMORY_INPUT_STREAM (object);
138 priv = stream->priv;
139  
140 g_slist_free_full (priv->chunks, (GDestroyNotify)g_bytes_unref);
141  
142 G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize (object);
143 }
144  
145 static void
146 g_memory_input_stream_seekable_iface_init (GSeekableIface *iface)
147 {
148 iface->tell = g_memory_input_stream_tell;
149 iface->can_seek = g_memory_input_stream_can_seek;
150 iface->seek = g_memory_input_stream_seek;
151 iface->can_truncate = g_memory_input_stream_can_truncate;
152 iface->truncate_fn = g_memory_input_stream_truncate;
153 }
154  
155 static void
156 g_memory_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
157 {
158 iface->is_readable = g_memory_input_stream_is_readable;
159 iface->create_source = g_memory_input_stream_create_source;
160 }
161  
162 static void
163 g_memory_input_stream_init (GMemoryInputStream *stream)
164 {
165 stream->priv = g_memory_input_stream_get_instance_private (stream);
166 }
167  
168 /**
169 * g_memory_input_stream_new:
170 *
171 * Creates a new empty #GMemoryInputStream.
172 *
173 * Returns: a new #GInputStream
174 */
175 GInputStream *
176 g_memory_input_stream_new (void)
177 {
178 GInputStream *stream;
179  
180 stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL);
181  
182 return stream;
183 }
184  
185 /**
186 * g_memory_input_stream_new_from_data:
187 * @data: (array length=len) (element-type guint8) (transfer full): input data
188 * @len: length of the data, may be -1 if @data is a nul-terminated string
189 * @destroy: (allow-none): function that is called to free @data, or %NULL
190 *
191 * Creates a new #GMemoryInputStream with data in memory of a given size.
192 *
193 * Returns: new #GInputStream read from @data of @len bytes.
194 **/
195 GInputStream *
196 g_memory_input_stream_new_from_data (const void *data,
197 gssize len,
198 GDestroyNotify destroy)
199 {
200 GInputStream *stream;
201  
202 stream = g_memory_input_stream_new ();
203  
204 g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream),
205 data, len, destroy);
206  
207 return stream;
208 }
209  
210 /**
211 * g_memory_input_stream_new_from_bytes:
212 * @bytes: a #GBytes
213 *
214 * Creates a new #GMemoryInputStream with data from the given @bytes.
215 *
216 * Returns: new #GInputStream read from @bytes
217 *
218 * Since: 2.34
219 **/
220 GInputStream *
221 g_memory_input_stream_new_from_bytes (GBytes *bytes)
222 {
223  
224 GInputStream *stream;
225  
226 stream = g_memory_input_stream_new ();
227  
228 g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (stream),
229 bytes);
230  
231 return stream;
232 }
233  
234 /**
235 * g_memory_input_stream_add_data:
236 * @stream: a #GMemoryInputStream
237 * @data: (array length=len) (element-type guint8) (transfer full): input data
238 * @len: length of the data, may be -1 if @data is a nul-terminated string
239 * @destroy: (allow-none): function that is called to free @data, or %NULL
240 *
241 * Appends @data to data that can be read from the input stream
242 */
243 void
244 g_memory_input_stream_add_data (GMemoryInputStream *stream,
245 const void *data,
246 gssize len,
247 GDestroyNotify destroy)
248 {
249 GBytes *bytes;
250  
251 if (len == -1)
252 len = strlen (data);
253  
254 /* It's safe to discard the const here because we're chaining the
255 * destroy callback.
256 */
257 bytes = g_bytes_new_with_free_func (data, len, destroy, (void*)data);
258  
259 g_memory_input_stream_add_bytes (stream, bytes);
260  
261 g_bytes_unref (bytes);
262 }
263  
264 /**
265 * g_memory_input_stream_add_bytes:
266 * @stream: a #GMemoryInputStream
267 * @bytes: input data
268 *
269 * Appends @bytes to data that can be read from the input stream.
270 *
271 * Since: 2.34
272 */
273 void
274 g_memory_input_stream_add_bytes (GMemoryInputStream *stream,
275 GBytes *bytes)
276 {
277 GMemoryInputStreamPrivate *priv;
278  
279 g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream));
280 g_return_if_fail (bytes != NULL);
281  
282 priv = stream->priv;
283  
284 priv->chunks = g_slist_append (priv->chunks, g_bytes_ref (bytes));
285 priv->len += g_bytes_get_size (bytes);
286 }
287  
288 static gssize
289 g_memory_input_stream_read (GInputStream *stream,
290 void *buffer,
291 gsize count,
292 GCancellable *cancellable,
293 GError **error)
294 {
295 GMemoryInputStream *memory_stream;
296 GMemoryInputStreamPrivate *priv;
297 GSList *l;
298 GBytes *chunk;
299 gsize len;
300 gsize offset, start, rest, size;
301  
302 memory_stream = G_MEMORY_INPUT_STREAM (stream);
303 priv = memory_stream->priv;
304  
305 count = MIN (count, priv->len - priv->pos);
306  
307 offset = 0;
308 for (l = priv->chunks; l; l = l->next)
309 {
310 chunk = (GBytes *)l->data;
311 len = g_bytes_get_size (chunk);
312  
313 if (offset + len > priv->pos)
314 break;
315  
316 offset += len;
317 }
318  
319 start = priv->pos - offset;
320 rest = count;
321  
322 for (; l && rest > 0; l = l->next)
323 {
324 const guint8* chunk_data;
325 chunk = (GBytes *)l->data;
326  
327 chunk_data = g_bytes_get_data (chunk, &len);
328  
329 size = MIN (rest, len - start);
330  
331 memcpy ((guint8 *)buffer + (count - rest), chunk_data + start, size);
332 rest -= size;
333  
334 start = 0;
335 }
336  
337 priv->pos += count;
338  
339 return count;
340 }
341  
342 static gssize
343 g_memory_input_stream_skip (GInputStream *stream,
344 gsize count,
345 GCancellable *cancellable,
346 GError **error)
347 {
348 GMemoryInputStream *memory_stream;
349 GMemoryInputStreamPrivate *priv;
350  
351 memory_stream = G_MEMORY_INPUT_STREAM (stream);
352 priv = memory_stream->priv;
353  
354 count = MIN (count, priv->len - priv->pos);
355 priv->pos += count;
356  
357 return count;
358 }
359  
360 static gboolean
361 g_memory_input_stream_close (GInputStream *stream,
362 GCancellable *cancellable,
363 GError **error)
364 {
365 return TRUE;
366 }
367  
368 static void
369 g_memory_input_stream_skip_async (GInputStream *stream,
370 gsize count,
371 int io_priority,
372 GCancellable *cancellable,
373 GAsyncReadyCallback callback,
374 gpointer user_data)
375 {
376 GTask *task;
377 gssize nskipped;
378 GError *error = NULL;
379  
380 nskipped = G_INPUT_STREAM_GET_CLASS (stream)->skip (stream, count, cancellable, &error);
381 task = g_task_new (stream, cancellable, callback, user_data);
382 if (error)
383 g_task_return_error (task, error);
384 else
385 g_task_return_int (task, nskipped);
386 g_object_unref (task);
387 }
388  
389 static gssize
390 g_memory_input_stream_skip_finish (GInputStream *stream,
391 GAsyncResult *result,
392 GError **error)
393 {
394 g_return_val_if_fail (g_task_is_valid (result, stream), -1);
395  
396 return g_task_propagate_int (G_TASK (result), error);
397 }
398  
399 static void
400 g_memory_input_stream_close_async (GInputStream *stream,
401 int io_priority,
402 GCancellable *cancellable,
403 GAsyncReadyCallback callback,
404 gpointer user_data)
405 {
406 GTask *task;
407  
408 task = g_task_new (stream, cancellable, callback, user_data);
409 g_task_return_boolean (task, TRUE);
410 g_object_unref (task);
411 }
412  
413 static gboolean
414 g_memory_input_stream_close_finish (GInputStream *stream,
415 GAsyncResult *result,
416 GError **error)
417 {
418 return TRUE;
419 }
420  
421 static goffset
422 g_memory_input_stream_tell (GSeekable *seekable)
423 {
424 GMemoryInputStream *memory_stream;
425 GMemoryInputStreamPrivate *priv;
426  
427 memory_stream = G_MEMORY_INPUT_STREAM (seekable);
428 priv = memory_stream->priv;
429  
430 return priv->pos;
431 }
432  
433 static
434 gboolean g_memory_input_stream_can_seek (GSeekable *seekable)
435 {
436 return TRUE;
437 }
438  
439 static gboolean
440 g_memory_input_stream_seek (GSeekable *seekable,
441 goffset offset,
442 GSeekType type,
443 GCancellable *cancellable,
444 GError **error)
445 {
446 GMemoryInputStream *memory_stream;
447 GMemoryInputStreamPrivate *priv;
448 goffset absolute;
449  
450 memory_stream = G_MEMORY_INPUT_STREAM (seekable);
451 priv = memory_stream->priv;
452  
453 switch (type)
454 {
455 case G_SEEK_CUR:
456 absolute = priv->pos + offset;
457 break;
458  
459 case G_SEEK_SET:
460 absolute = offset;
461 break;
462  
463 case G_SEEK_END:
464 absolute = priv->len + offset;
465 break;
466  
467 default:
468 g_set_error_literal (error,
469 G_IO_ERROR,
470 G_IO_ERROR_INVALID_ARGUMENT,
471 _("Invalid GSeekType supplied"));
472  
473 return FALSE;
474 }
475  
476 if (absolute < 0 || absolute > priv->len)
477 {
478 g_set_error_literal (error,
479 G_IO_ERROR,
480 G_IO_ERROR_INVALID_ARGUMENT,
481 _("Invalid seek request"));
482 return FALSE;
483 }
484  
485 priv->pos = absolute;
486  
487 return TRUE;
488 }
489  
490 static gboolean
491 g_memory_input_stream_can_truncate (GSeekable *seekable)
492 {
493 return FALSE;
494 }
495  
496 static gboolean
497 g_memory_input_stream_truncate (GSeekable *seekable,
498 goffset offset,
499 GCancellable *cancellable,
500 GError **error)
501 {
502 g_set_error_literal (error,
503 G_IO_ERROR,
504 G_IO_ERROR_NOT_SUPPORTED,
505 _("Cannot truncate GMemoryInputStream"));
506 return FALSE;
507 }
508  
509 static gboolean
510 g_memory_input_stream_is_readable (GPollableInputStream *stream)
511 {
512 return TRUE;
513 }
514  
515 static GSource *
516 g_memory_input_stream_create_source (GPollableInputStream *stream,
517 GCancellable *cancellable)
518 {
519 GSource *base_source, *pollable_source;
520  
521 base_source = g_timeout_source_new (0);
522 pollable_source = g_pollable_source_new_full (stream, base_source,
523 cancellable);
524 g_source_unref (base_source);
525  
526 return pollable_source;
527 }