(root)/
glib-2.79.0/
gio/
gmemoryoutputstream.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   * Authors:
      21   *   Christian Kellner <gicmo@gnome.org>
      22   *   Krzysztof KosiƄski <tweenk.pl@gmail.com>
      23   */
      24  
      25  #include "config.h"
      26  #include "gmemoryoutputstream.h"
      27  #include "goutputstream.h"
      28  #include "gpollableoutputstream.h"
      29  #include "gseekable.h"
      30  #include "gtask.h"
      31  #include "gioerror.h"
      32  #include "string.h"
      33  #include "glibintl.h"
      34  #include "gutilsprivate.h"
      35  
      36  
      37  /**
      38   * GMemoryOutputStream:
      39   *
      40   * `GMemoryOutputStream` is a class for using arbitrary
      41   * memory chunks as output for GIO streaming output operations.
      42   *
      43   * As of GLib 2.34, `GMemoryOutputStream` trivially implements
      44   * [iface@Gio.PollableOutputStream]: it always polls as ready.
      45   */
      46  
      47  #define MIN_ARRAY_SIZE  16
      48  
      49  enum {
      50    PROP_0,
      51    PROP_DATA,
      52    PROP_SIZE,
      53    PROP_DATA_SIZE,
      54    PROP_REALLOC_FUNCTION,
      55    PROP_DESTROY_FUNCTION
      56  };
      57  
      58  struct _GMemoryOutputStreamPrivate
      59  {
      60    gpointer       data; /* Write buffer */
      61    gsize          len; /* Current length of the data buffer. Can change with resizing. */
      62    gsize          valid_len; /* The part of data that has been written to */
      63    gsize          pos; /* Current position in the stream. Distinct from valid_len,
      64                           because the stream is seekable. */
      65  
      66    GReallocFunc   realloc_fn;
      67    GDestroyNotify destroy;
      68  };
      69  
      70  static void     g_memory_output_stream_set_property (GObject      *object,
      71                                                       guint         prop_id,
      72                                                       const GValue *value,
      73                                                       GParamSpec   *pspec);
      74  static void     g_memory_output_stream_get_property (GObject      *object,
      75                                                       guint         prop_id,
      76                                                       GValue       *value,
      77                                                       GParamSpec   *pspec);
      78  static void     g_memory_output_stream_finalize     (GObject      *object);
      79  
      80  static gssize   g_memory_output_stream_write       (GOutputStream *stream,
      81                                                      const void    *buffer,
      82                                                      gsize          count,
      83                                                      GCancellable  *cancellable,
      84                                                      GError       **error);
      85  
      86  static gboolean g_memory_output_stream_close       (GOutputStream  *stream,
      87                                                      GCancellable   *cancellable,
      88                                                      GError        **error);
      89  
      90  static void     g_memory_output_stream_close_async  (GOutputStream        *stream,
      91                                                       int                   io_priority,
      92                                                       GCancellable         *cancellable,
      93                                                       GAsyncReadyCallback   callback,
      94                                                       gpointer              data);
      95  static gboolean g_memory_output_stream_close_finish (GOutputStream        *stream,
      96                                                       GAsyncResult         *result,
      97                                                       GError              **error);
      98  
      99  static void     g_memory_output_stream_seekable_iface_init (GSeekableIface  *iface);
     100  static goffset  g_memory_output_stream_tell                (GSeekable       *seekable);
     101  static gboolean g_memory_output_stream_can_seek            (GSeekable       *seekable);
     102  static gboolean g_memory_output_stream_seek                (GSeekable       *seekable,
     103                                                             goffset          offset,
     104                                                             GSeekType        type,
     105                                                             GCancellable    *cancellable,
     106                                                             GError         **error);
     107  static gboolean g_memory_output_stream_can_truncate        (GSeekable       *seekable);
     108  static gboolean g_memory_output_stream_truncate            (GSeekable       *seekable,
     109                                                             goffset          offset,
     110                                                             GCancellable    *cancellable,
     111                                                             GError         **error);
     112  
     113  static gboolean g_memory_output_stream_is_writable       (GPollableOutputStream *stream);
     114  static GSource *g_memory_output_stream_create_source     (GPollableOutputStream *stream,
     115                                                            GCancellable          *cancellable);
     116  
     117  static void g_memory_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface);
     118  
     119  G_DEFINE_TYPE_WITH_CODE (GMemoryOutputStream, g_memory_output_stream, G_TYPE_OUTPUT_STREAM,
     120                           G_ADD_PRIVATE (GMemoryOutputStream)
     121                           G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
     122                                                  g_memory_output_stream_seekable_iface_init);
     123                           G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM,
     124                                                  g_memory_output_stream_pollable_iface_init))
     125  
     126  
     127  static void
     128  g_memory_output_stream_class_init (GMemoryOutputStreamClass *klass)
     129  {
     130    GOutputStreamClass *ostream_class;
     131    GObjectClass *gobject_class;
     132  
     133    gobject_class = G_OBJECT_CLASS (klass);
     134    gobject_class->set_property = g_memory_output_stream_set_property;
     135    gobject_class->get_property = g_memory_output_stream_get_property;
     136    gobject_class->finalize     = g_memory_output_stream_finalize;
     137  
     138    ostream_class = G_OUTPUT_STREAM_CLASS (klass);
     139  
     140    ostream_class->write_fn = g_memory_output_stream_write;
     141    ostream_class->close_fn = g_memory_output_stream_close;
     142    ostream_class->close_async  = g_memory_output_stream_close_async;
     143    ostream_class->close_finish = g_memory_output_stream_close_finish;
     144  
     145    /**
     146     * GMemoryOutputStream:data:
     147     *
     148     * Pointer to buffer where data will be written.
     149     *
     150     * Since: 2.24
     151     **/
     152    g_object_class_install_property (gobject_class,
     153                                     PROP_DATA,
     154                                     g_param_spec_pointer ("data", NULL, NULL,
     155                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     156                                                           G_PARAM_STATIC_STRINGS));
     157  
     158    /**
     159     * GMemoryOutputStream:size:
     160     *
     161     * Current size of the data buffer.
     162     *
     163     * Since: 2.24
     164     **/
     165    g_object_class_install_property (gobject_class,
     166                                     PROP_SIZE,
     167                                     g_param_spec_ulong ("size", NULL, NULL,
     168                                                         0, G_MAXULONG, 0,
     169                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     170                                                         G_PARAM_STATIC_STRINGS));
     171  
     172    /**
     173     * GMemoryOutputStream:data-size:
     174     *
     175     * Size of data written to the buffer.
     176     *
     177     * Since: 2.24
     178     **/
     179    g_object_class_install_property (gobject_class,
     180                                     PROP_DATA_SIZE,
     181                                     g_param_spec_ulong ("data-size", NULL, NULL,
     182                                                         0, G_MAXULONG, 0,
     183                                                         G_PARAM_READABLE |
     184                                                         G_PARAM_STATIC_STRINGS));
     185  
     186    /**
     187     * GMemoryOutputStream:realloc-function: (skip)
     188     *
     189     * Function with realloc semantics called to enlarge the buffer.
     190     *
     191     * Since: 2.24
     192     **/
     193    g_object_class_install_property (gobject_class,
     194                                     PROP_REALLOC_FUNCTION,
     195                                     g_param_spec_pointer ("realloc-function", NULL, NULL,
     196                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     197                                                           G_PARAM_STATIC_STRINGS));
     198  
     199    /**
     200     * GMemoryOutputStream:destroy-function: (skip)
     201     *
     202     * Function called with the buffer as argument when the stream is destroyed.
     203     *
     204     * Since: 2.24
     205     **/
     206    g_object_class_install_property (gobject_class,
     207                                     PROP_DESTROY_FUNCTION,
     208                                     g_param_spec_pointer ("destroy-function", NULL, NULL,
     209                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     210                                                           G_PARAM_STATIC_STRINGS));
     211  }
     212  
     213  static void
     214  g_memory_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface)
     215  {
     216    iface->is_writable = g_memory_output_stream_is_writable;
     217    iface->create_source = g_memory_output_stream_create_source;
     218  }
     219  
     220  static void
     221  g_memory_output_stream_set_property (GObject      *object,
     222                                       guint         prop_id,
     223                                       const GValue *value,
     224                                       GParamSpec   *pspec)
     225  {
     226    GMemoryOutputStream        *stream;
     227    GMemoryOutputStreamPrivate *priv;
     228  
     229    stream = G_MEMORY_OUTPUT_STREAM (object);
     230    priv = stream->priv;
     231  
     232    switch (prop_id)
     233      {
     234      case PROP_DATA:
     235        priv->data = g_value_get_pointer (value);
     236        break;
     237      case PROP_SIZE:
     238        priv->len = g_value_get_ulong (value);
     239        break;
     240      case PROP_REALLOC_FUNCTION:
     241        priv->realloc_fn = g_value_get_pointer (value);
     242        break;
     243      case PROP_DESTROY_FUNCTION:
     244        priv->destroy = g_value_get_pointer (value);
     245        break;
     246      default:
     247        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     248        break;
     249      }
     250  }
     251  
     252  static void
     253  g_memory_output_stream_get_property (GObject      *object,
     254                                       guint         prop_id,
     255                                       GValue       *value,
     256                                       GParamSpec   *pspec)
     257  {
     258    GMemoryOutputStream        *stream;
     259    GMemoryOutputStreamPrivate *priv;
     260  
     261    stream = G_MEMORY_OUTPUT_STREAM (object);
     262    priv = stream->priv;
     263  
     264    switch (prop_id)
     265      {
     266      case PROP_DATA:
     267        g_value_set_pointer (value, priv->data);
     268        break;
     269      case PROP_SIZE:
     270        g_value_set_ulong (value, priv->len);
     271        break;
     272      case PROP_DATA_SIZE:
     273        g_value_set_ulong (value, priv->valid_len);
     274        break;
     275      case PROP_REALLOC_FUNCTION:
     276        g_value_set_pointer (value, priv->realloc_fn);
     277        break;
     278      case PROP_DESTROY_FUNCTION:
     279        g_value_set_pointer (value, priv->destroy);
     280        break;
     281      default:
     282        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     283        break;
     284      }
     285  }
     286  
     287  static void
     288  g_memory_output_stream_finalize (GObject *object)
     289  {
     290    GMemoryOutputStream        *stream;
     291    GMemoryOutputStreamPrivate *priv;
     292  
     293    stream = G_MEMORY_OUTPUT_STREAM (object);
     294    priv = stream->priv;
     295    
     296    if (priv->destroy)
     297      priv->destroy (priv->data);
     298  
     299    G_OBJECT_CLASS (g_memory_output_stream_parent_class)->finalize (object);
     300  }
     301  
     302  static void
     303  g_memory_output_stream_seekable_iface_init (GSeekableIface *iface)
     304  {
     305    iface->tell         = g_memory_output_stream_tell;
     306    iface->can_seek     = g_memory_output_stream_can_seek;
     307    iface->seek         = g_memory_output_stream_seek;
     308    iface->can_truncate = g_memory_output_stream_can_truncate;
     309    iface->truncate_fn  = g_memory_output_stream_truncate;
     310  }
     311  
     312  
     313  static void
     314  g_memory_output_stream_init (GMemoryOutputStream *stream)
     315  {
     316    stream->priv = g_memory_output_stream_get_instance_private (stream);
     317    stream->priv->pos = 0;
     318    stream->priv->valid_len = 0;
     319  }
     320  
     321  /**
     322   * g_memory_output_stream_new: (skip)
     323   * @data: (nullable): pointer to a chunk of memory to use, or %NULL
     324   * @size: the size of @data
     325   * @realloc_function: (nullable): a function with realloc() semantics (like g_realloc())
     326   *     to be called when @data needs to be grown, or %NULL
     327   * @destroy_function: (nullable): a function to be called on @data when the stream is
     328   *     finalized, or %NULL
     329   *
     330   * Creates a new #GMemoryOutputStream.
     331   *
     332   * In most cases this is not the function you want.  See
     333   * g_memory_output_stream_new_resizable() instead.
     334   *
     335   * If @data is non-%NULL, the stream will use that for its internal storage.
     336   *
     337   * If @realloc_fn is non-%NULL, it will be used for resizing the internal
     338   * storage when necessary and the stream will be considered resizable.
     339   * In that case, the stream will start out being (conceptually) empty.
     340   * @size is used only as a hint for how big @data is.  Specifically,
     341   * seeking to the end of a newly-created stream will seek to zero, not
     342   * @size.  Seeking past the end of the stream and then writing will
     343   * introduce a zero-filled gap.
     344   *
     345   * If @realloc_fn is %NULL then the stream is fixed-sized.  Seeking to
     346   * the end will seek to @size exactly.  Writing past the end will give
     347   * an 'out of space' error.  Attempting to seek past the end will fail.
     348   * Unlike the resizable case, seeking to an offset within the stream and
     349   * writing will preserve the bytes passed in as @data before that point
     350   * and will return them as part of g_memory_output_stream_steal_data().
     351   * If you intend to seek you should probably therefore ensure that @data
     352   * is properly initialised.
     353   *
     354   * It is probably only meaningful to provide @data and @size in the case
     355   * that you want a fixed-sized stream.  Put another way: if @realloc_fn
     356   * is non-%NULL then it makes most sense to give @data as %NULL and
     357   * @size as 0 (allowing #GMemoryOutputStream to do the initial
     358   * allocation for itself).
     359   *
     360   * |[<!-- language="C" -->
     361   * // a stream that can grow
     362   * stream = g_memory_output_stream_new (NULL, 0, realloc, free);
     363   *
     364   * // another stream that can grow
     365   * stream2 = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     366   *
     367   * // a fixed-size stream
     368   * data = malloc (200);
     369   * stream3 = g_memory_output_stream_new (data, 200, NULL, free);
     370   * ]|
     371   *
     372   * Returns: A newly created #GMemoryOutputStream object.
     373   **/
     374  GOutputStream *
     375  g_memory_output_stream_new (gpointer       data,
     376                              gsize          size,
     377                              GReallocFunc   realloc_function,
     378                              GDestroyNotify destroy_function)
     379  {
     380    GOutputStream *stream;
     381  
     382    stream = g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
     383                           "data", data,
     384                           "size", size,
     385                           "realloc-function", realloc_function,
     386                           "destroy-function", destroy_function,
     387                           NULL);
     388  
     389    return stream;
     390  }
     391  
     392  /**
     393   * g_memory_output_stream_new_resizable:
     394   *
     395   * Creates a new #GMemoryOutputStream, using g_realloc() and g_free()
     396   * for memory allocation.
     397   *
     398   * Since: 2.36
     399   */
     400  GOutputStream *
     401  g_memory_output_stream_new_resizable (void)
     402  {
     403    return g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     404  }
     405  
     406  /**
     407   * g_memory_output_stream_get_data:
     408   * @ostream: a #GMemoryOutputStream
     409   *
     410   * Gets any loaded data from the @ostream.
     411   *
     412   * Note that the returned pointer may become invalid on the next
     413   * write or truncate operation on the stream.
     414   *
     415   * Returns: (transfer none): pointer to the stream's data, or %NULL if the data
     416   *    has been stolen
     417   **/
     418  gpointer
     419  g_memory_output_stream_get_data (GMemoryOutputStream *ostream)
     420  {
     421    g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), NULL);
     422  
     423    return ostream->priv->data;
     424  }
     425  
     426  /**
     427   * g_memory_output_stream_get_size:
     428   * @ostream: a #GMemoryOutputStream
     429   *
     430   * Gets the size of the currently allocated data area (available from
     431   * g_memory_output_stream_get_data()).
     432   *
     433   * You probably don't want to use this function on resizable streams.
     434   * See g_memory_output_stream_get_data_size() instead.  For resizable
     435   * streams the size returned by this function is an implementation
     436   * detail and may be change at any time in response to operations on the
     437   * stream.
     438   *
     439   * If the stream is fixed-sized (ie: no realloc was passed to
     440   * g_memory_output_stream_new()) then this is the maximum size of the
     441   * stream and further writes will return %G_IO_ERROR_NO_SPACE.
     442   *
     443   * In any case, if you want the number of bytes currently written to the
     444   * stream, use g_memory_output_stream_get_data_size().
     445   *
     446   * Returns: the number of bytes allocated for the data buffer
     447   */
     448  gsize
     449  g_memory_output_stream_get_size (GMemoryOutputStream *ostream)
     450  {
     451    g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), 0);
     452  
     453    return ostream->priv->len;
     454  }
     455  
     456  /**
     457   * g_memory_output_stream_get_data_size:
     458   * @ostream: a #GMemoryOutputStream
     459   *
     460   * Returns the number of bytes from the start up to including the last
     461   * byte written in the stream that has not been truncated away.
     462   *
     463   * Returns: the number of bytes written to the stream
     464   *
     465   * Since: 2.18
     466   */
     467  gsize
     468  g_memory_output_stream_get_data_size (GMemoryOutputStream *ostream)
     469  {
     470    g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), 0);
     471  
     472    return ostream->priv->valid_len;
     473  }
     474  
     475  /**
     476   * g_memory_output_stream_steal_data:
     477   * @ostream: a #GMemoryOutputStream
     478   *
     479   * Gets any loaded data from the @ostream. Ownership of the data
     480   * is transferred to the caller; when no longer needed it must be
     481   * freed using the free function set in @ostream's
     482   * #GMemoryOutputStream:destroy-function property.
     483   *
     484   * @ostream must be closed before calling this function.
     485   *
     486   * Returns: (transfer full): the stream's data, or %NULL if it has previously
     487   *    been stolen
     488   *
     489   * Since: 2.26
     490   **/
     491  gpointer
     492  g_memory_output_stream_steal_data (GMemoryOutputStream *ostream)
     493  {
     494    gpointer data;
     495  
     496    g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), NULL);
     497    g_return_val_if_fail (g_output_stream_is_closed (G_OUTPUT_STREAM (ostream)), NULL);
     498  
     499    data = ostream->priv->data;
     500    ostream->priv->data = NULL;
     501  
     502    return data;
     503  }
     504  
     505  /**
     506   * g_memory_output_stream_steal_as_bytes:
     507   * @ostream: a #GMemoryOutputStream
     508   *
     509   * Returns data from the @ostream as a #GBytes. @ostream must be
     510   * closed before calling this function.
     511   *
     512   * Returns: (transfer full): the stream's data
     513   *
     514   * Since: 2.34
     515   **/
     516  GBytes *
     517  g_memory_output_stream_steal_as_bytes (GMemoryOutputStream *ostream)
     518  {
     519    GBytes *result;
     520  
     521    g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), NULL);
     522    g_return_val_if_fail (g_output_stream_is_closed (G_OUTPUT_STREAM (ostream)), NULL);
     523  
     524    result = g_bytes_new_with_free_func (ostream->priv->data,
     525                                         ostream->priv->valid_len,
     526                                         ostream->priv->destroy,
     527                                         ostream->priv->data);
     528    ostream->priv->data = NULL;
     529  
     530    return result;
     531  }
     532  
     533  static gboolean
     534  array_resize (GMemoryOutputStream  *ostream,
     535                gsize                 size,
     536                gboolean              allow_partial,
     537                GError              **error)
     538  {
     539    GMemoryOutputStreamPrivate *priv;
     540    gpointer data;
     541    gsize len;
     542  
     543    priv = ostream->priv;
     544  
     545    if (priv->len == size)
     546      return TRUE;
     547  
     548    if (!priv->realloc_fn)
     549      {
     550        if (allow_partial &&
     551            priv->pos < priv->len)
     552          return TRUE; /* Short write */
     553  
     554        g_set_error_literal (error,
     555                             G_IO_ERROR,
     556                             G_IO_ERROR_NO_SPACE,
     557                             _("Memory output stream not resizable"));
     558        return FALSE;
     559      }
     560  
     561    len = priv->len;
     562    data = priv->realloc_fn (priv->data, size);
     563  
     564    if (size > 0 && !data)
     565      {
     566        if (allow_partial &&
     567            priv->pos < priv->len)
     568          return TRUE; /* Short write */
     569  
     570        g_set_error_literal (error,
     571                             G_IO_ERROR,
     572                             G_IO_ERROR_NO_SPACE,
     573                             _("Failed to resize memory output stream"));
     574        return FALSE;
     575      }
     576  
     577    if (size > len)
     578      memset ((guint8 *)data + len, 0, size - len);
     579  
     580    priv->data = data;
     581    priv->len = size;
     582  
     583    if (priv->len < priv->valid_len)
     584      priv->valid_len = priv->len;
     585  
     586    return TRUE;
     587  }
     588  
     589  static gssize
     590  g_memory_output_stream_write (GOutputStream  *stream,
     591                                const void     *buffer,
     592                                gsize           count,
     593                                GCancellable   *cancellable,
     594                                GError        **error)
     595  {
     596    GMemoryOutputStream        *ostream;
     597    GMemoryOutputStreamPrivate *priv;
     598    guint8   *dest;
     599    gsize new_size;
     600  
     601    ostream = G_MEMORY_OUTPUT_STREAM (stream);
     602    priv = ostream->priv;
     603  
     604    if (count == 0)
     605      return 0;
     606  
     607    /* Check for address space overflow, but only if the buffer is resizable.
     608       Otherwise we just do a short write and don't worry. */
     609    if (priv->realloc_fn && priv->pos + count < priv->pos)
     610      goto overflow;
     611  
     612    if (priv->pos + count > priv->len)
     613      {
     614        /* At least enough to fit the write, rounded up for greater than
     615         * linear growth.
     616         *
     617         * Assuming that we're using something like realloc(), the kernel
     618         * will overcommit memory to us, so doubling the size each time
     619         * will keep the number of realloc calls low without wasting too
     620         * much memory.
     621         */
     622        new_size = g_nearest_pow (priv->pos + count);
     623        /* Check for overflow again. We have checked if
     624           pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
     625           overflowed */
     626        if (new_size == 0)
     627          goto overflow;
     628  
     629        new_size = MAX (new_size, MIN_ARRAY_SIZE);
     630        if (!array_resize (ostream, new_size, TRUE, error))
     631          return -1;
     632      }
     633  
     634    /* Make sure we handle short writes if the array_resize
     635       only added part of the required memory */
     636    count = MIN (count, priv->len - priv->pos);
     637  
     638    dest = (guint8 *)priv->data + priv->pos;
     639    memcpy (dest, buffer, count);
     640    priv->pos += count;
     641  
     642    if (priv->pos > priv->valid_len)
     643      priv->valid_len = priv->pos;
     644  
     645    return count;
     646  
     647   overflow:
     648    /* Overflow: buffer size would need to be bigger than G_MAXSIZE. */
     649    g_set_error_literal (error,
     650                         G_IO_ERROR,
     651                         G_IO_ERROR_NO_SPACE,
     652                         _("Amount of memory required to process the write is "
     653                           "larger than available address space"));
     654    return -1;
     655  }
     656  
     657  static gboolean
     658  g_memory_output_stream_close (GOutputStream  *stream,
     659                                GCancellable   *cancellable,
     660                                GError        **error)
     661  {
     662    return TRUE;
     663  }
     664  
     665  static void
     666  g_memory_output_stream_close_async (GOutputStream       *stream,
     667                                      int                  io_priority,
     668                                      GCancellable        *cancellable,
     669                                      GAsyncReadyCallback  callback,
     670                                      gpointer             data)
     671  {
     672    GTask *task;
     673  
     674    task = g_task_new (stream, cancellable, callback, data);
     675    g_task_set_source_tag (task, g_memory_output_stream_close_async);
     676  
     677    /* will always return TRUE */
     678    g_memory_output_stream_close (stream, cancellable, NULL);
     679  
     680    g_task_return_boolean (task, TRUE);
     681    g_object_unref (task);
     682  }
     683  
     684  static gboolean
     685  g_memory_output_stream_close_finish (GOutputStream  *stream,
     686                                       GAsyncResult   *result,
     687                                       GError        **error)
     688  {
     689    g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
     690  
     691    return g_task_propagate_boolean (G_TASK (result), error);
     692  }
     693  
     694  static goffset
     695  g_memory_output_stream_tell (GSeekable *seekable)
     696  {
     697    GMemoryOutputStream *stream;
     698    GMemoryOutputStreamPrivate *priv;
     699  
     700    stream = G_MEMORY_OUTPUT_STREAM (seekable);
     701    priv = stream->priv;
     702  
     703    return priv->pos;
     704  }
     705  
     706  static gboolean
     707  g_memory_output_stream_can_seek (GSeekable *seekable)
     708  {
     709    return TRUE;
     710  }
     711  
     712  static gboolean
     713  g_memory_output_stream_seek (GSeekable    *seekable,
     714                               goffset        offset,
     715                               GSeekType      type,
     716                               GCancellable  *cancellable,
     717                               GError       **error)
     718  {
     719    GMemoryOutputStream        *stream;
     720    GMemoryOutputStreamPrivate *priv;
     721    goffset absolute;
     722  
     723    stream = G_MEMORY_OUTPUT_STREAM (seekable);
     724    priv = stream->priv;
     725  
     726    switch (type)
     727      {
     728      case G_SEEK_CUR:
     729        absolute = priv->pos + offset;
     730        break;
     731  
     732      case G_SEEK_SET:
     733        absolute = offset;
     734        break;
     735  
     736      case G_SEEK_END:
     737        /* For resizable streams, we consider the end to be the data
     738         * length.  For fixed-sized streams, we consider the end to be the
     739         * size of the buffer.
     740         */
     741        if (priv->realloc_fn)
     742          absolute = priv->valid_len + offset;
     743        else
     744          absolute = priv->len + offset;
     745        break;
     746  
     747      default:
     748        g_set_error_literal (error,
     749                             G_IO_ERROR,
     750                             G_IO_ERROR_INVALID_ARGUMENT,
     751                             _("Invalid GSeekType supplied"));
     752  
     753        return FALSE;
     754      }
     755  
     756    if (absolute < 0)
     757      {
     758        g_set_error_literal (error,
     759                             G_IO_ERROR,
     760                             G_IO_ERROR_INVALID_ARGUMENT,
     761                             _("Requested seek before the beginning of the stream"));
     762        return FALSE;
     763      }
     764  
     765    /* Can't seek past the end of a fixed-size stream.
     766     *
     767     * Note: seeking to the non-existent byte at the end of a fixed-sized
     768     * stream is valid (eg: a 1-byte fixed sized stream can have position
     769     * 0 or 1).  Therefore '>' is what we want.
     770     * */
     771    if (priv->realloc_fn == NULL && (gsize) absolute > priv->len)
     772      {
     773        g_set_error_literal (error,
     774                             G_IO_ERROR,
     775                             G_IO_ERROR_INVALID_ARGUMENT,
     776                             _("Requested seek beyond the end of the stream"));
     777        return FALSE;
     778      }
     779  
     780    priv->pos = absolute;
     781  
     782    return TRUE;
     783  }
     784  
     785  static gboolean
     786  g_memory_output_stream_can_truncate (GSeekable *seekable)
     787  {
     788    GMemoryOutputStream *ostream;
     789    GMemoryOutputStreamPrivate *priv;
     790  
     791    ostream = G_MEMORY_OUTPUT_STREAM (seekable);
     792    priv = ostream->priv;
     793  
     794    /* We do not allow truncation of fixed-sized streams */
     795    return priv->realloc_fn != NULL;
     796  }
     797  
     798  static gboolean
     799  g_memory_output_stream_truncate (GSeekable     *seekable,
     800                                   goffset        offset,
     801                                   GCancellable  *cancellable,
     802                                   GError       **error)
     803  {
     804    GMemoryOutputStream *ostream = G_MEMORY_OUTPUT_STREAM (seekable);
     805  
     806    if (!array_resize (ostream, offset, FALSE, error))
     807      return FALSE;
     808  
     809    ostream->priv->valid_len = offset;
     810  
     811    return TRUE;
     812  }
     813  
     814  static gboolean
     815  g_memory_output_stream_is_writable (GPollableOutputStream *stream)
     816  {
     817    return TRUE;
     818  }
     819  
     820  static GSource *
     821  g_memory_output_stream_create_source (GPollableOutputStream *stream,
     822                                        GCancellable          *cancellable)
     823  {
     824    GSource *base_source, *pollable_source;
     825  
     826    base_source = g_timeout_source_new (0);
     827    pollable_source = g_pollable_source_new_full (stream, base_source, cancellable);
     828    g_source_unref (base_source);
     829  
     830    return pollable_source;
     831  }