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