plover/inputstream.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Jun 01 17:19:01 2018 +0100 (2018-06-01)
changeset 71 bd272d15bea4
parent 61 31fb35727621
child 99 0121592e2512
permissions -rw-r--r--
Treat invalid URIs as programming errors
     1 /*
     2  * Copyright (C) 2006-2007  Red Hat, Inc
     3  * Copyright (C) 2016  J. Ali Harlow <ali@juiblex.co.uk>
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program 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
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #include <stdlib.h>
    21 #include <razor.h>
    22 #include <glib.h>
    23 #include <glib/gi18n.h>
    24 #include "plover/inputstream.h"
    25 
    26 /**
    27  * SECTION:ploverrazorinputstream
    28  * @short_description: Streaming input operations on razor files
    29  * @include: plover/inputstream.h
    30  * @see_also: #GMemoryInputStream
    31  *
    32  * #PloverRazorInputStream provides input streams that get their
    33  * content via razor's URI input routines.
    34  */
    35 
    36 struct _PloverRazorInputStreamPrivate
    37 {
    38     void *buf;
    39     gsize len;
    40     gsize pos;
    41 };
    42 
    43 static gssize plover_razor_input_stream_read(GInputStream *stream,void *buffer,
    44   gsize count,GCancellable *cancellable,GError **error);
    45 static gssize plover_razor_input_stream_skip(GInputStream *stream,gsize count,
    46   GCancellable *cancellable,GError **error);
    47 static gboolean plover_razor_input_stream_close(GInputStream *stream,
    48   GCancellable *cancellable,GError **error);
    49 static void plover_razor_input_stream_skip_async(GInputStream *stream,
    50   gsize count,int io_priority,GCancellable *cancellable,
    51   GAsyncReadyCallback callback,gpointer data);
    52 static gssize plover_razor_input_stream_skip_finish(GInputStream *stream,
    53   GAsyncResult *result,GError **error);
    54 static void plover_razor_input_stream_close_async(GInputStream *stream,
    55   int io_priority,GCancellable *cancellable,GAsyncReadyCallback callback,
    56   gpointer data);
    57 static gboolean plover_razor_input_stream_close_finish(GInputStream *stream,
    58   GAsyncResult *result,GError **error);
    59 static void
    60   plover_razor_input_stream_seekable_iface_init(GSeekableIface *iface);
    61 static goffset plover_razor_input_stream_tell(GSeekable *seekable);
    62 static gboolean plover_razor_input_stream_can_seek(GSeekable *seekable);
    63 static gboolean plover_razor_input_stream_seek(GSeekable *seekable,
    64   goffset offset,GSeekType type,GCancellable *cancellable,GError **error);
    65 static gboolean plover_razor_input_stream_can_truncate(GSeekable *seekable);
    66 static gboolean plover_razor_input_stream_truncate(GSeekable *seekable,
    67   goffset offset,GCancellable *cancellable,GError **error);
    68 static void plover_razor_input_stream_pollable_iface_init(
    69   GPollableInputStreamInterface *iface);
    70 static gboolean
    71   plover_razor_input_stream_is_readable(GPollableInputStream *stream);
    72 static GSource *
    73   plover_razor_input_stream_create_source(GPollableInputStream *stream,
    74   GCancellable *cancellable);
    75 static void plover_razor_input_stream_finalize(GObject *object);
    76 
    77 G_DEFINE_TYPE_WITH_CODE(PloverRazorInputStream,plover_razor_input_stream,
    78   G_TYPE_INPUT_STREAM,
    79   G_IMPLEMENT_INTERFACE(G_TYPE_SEEKABLE,
    80     plover_razor_input_stream_seekable_iface_init);
    81   G_IMPLEMENT_INTERFACE(G_TYPE_POLLABLE_INPUT_STREAM,
    82     plover_razor_input_stream_pollable_iface_init);
    83 )
    84 
    85 static void
    86   plover_razor_input_stream_class_init(PloverRazorInputStreamClass *klass)
    87 {
    88     GObjectClass *object_class;
    89     GInputStreamClass *istream_class;
    90     g_type_class_add_private(klass,sizeof(PloverRazorInputStreamPrivate));
    91     object_class=G_OBJECT_CLASS(klass);
    92     object_class->finalize=plover_razor_input_stream_finalize;
    93     istream_class=G_INPUT_STREAM_CLASS(klass);
    94     istream_class->read_fn=plover_razor_input_stream_read;
    95     istream_class->skip=plover_razor_input_stream_skip;
    96     istream_class->close_fn=plover_razor_input_stream_close;
    97     istream_class->skip_async=plover_razor_input_stream_skip_async;
    98     istream_class->skip_finish=plover_razor_input_stream_skip_finish;
    99     istream_class->close_async=plover_razor_input_stream_close_async;
   100     istream_class->close_finish=plover_razor_input_stream_close_finish;
   101 }
   102 
   103 static void plover_razor_input_stream_finalize(GObject *object)
   104 {
   105     PloverRazorInputStream *razor_stream;
   106     PloverRazorInputStreamPrivate *priv;
   107     razor_stream=PLOVER_RAZOR_INPUT_STREAM(object);
   108     priv=razor_stream->priv;
   109     razor_uri_free_contents(priv->buf,priv->len);
   110     G_OBJECT_CLASS(plover_razor_input_stream_parent_class)->finalize(object);
   111 }
   112 
   113 static void plover_razor_input_stream_seekable_iface_init(GSeekableIface *iface)
   114 {
   115     iface->tell=plover_razor_input_stream_tell;
   116     iface->can_seek=plover_razor_input_stream_can_seek;
   117     iface->seek=plover_razor_input_stream_seek;
   118     iface->can_truncate=plover_razor_input_stream_can_truncate;
   119     iface->truncate_fn=plover_razor_input_stream_truncate;
   120 }
   121 
   122 static void plover_razor_input_stream_pollable_iface_init(
   123   GPollableInputStreamInterface *iface)
   124 {
   125     iface->is_readable=plover_razor_input_stream_is_readable;
   126     iface->create_source=plover_razor_input_stream_create_source;
   127 }
   128 
   129 static void plover_razor_input_stream_init(PloverRazorInputStream *stream)
   130 {
   131     stream->priv=G_TYPE_INSTANCE_GET_PRIVATE(stream,
   132       PLOVER_TYPE_RAZOR_INPUT_STREAM,PloverRazorInputStreamPrivate);
   133 }
   134 
   135 GInputStream *plover_razor_input_stream_new(const char *uri,GError **error)
   136 {
   137     void *buf;
   138     size_t len;
   139     struct razor_error *tmp_error=NULL;
   140     GInputStream *stream;
   141     PloverRazorInputStreamPrivate *priv;
   142     g_return_val_if_fail(plover__uri_validate(uri),NULL);
   143     buf=razor_uri_get_contents(uri,&len,FALSE,&tmp_error);
   144     if (!buf)
   145     {
   146 	plover_propagate_razor_error(error,tmp_error);
   147 	return NULL;
   148     }
   149     stream=g_object_new(PLOVER_TYPE_RAZOR_INPUT_STREAM,NULL);
   150     priv=PLOVER_RAZOR_INPUT_STREAM(stream)->priv;
   151     priv->buf=buf;
   152     priv->len=len;
   153     return stream;
   154 }
   155 
   156 static gssize plover_razor_input_stream_read(GInputStream *stream,void *buffer,
   157   gsize count,GCancellable *cancellable,GError **error)
   158 {
   159     PloverRazorInputStream *razor_stream;
   160     PloverRazorInputStreamPrivate *priv;
   161     razor_stream=PLOVER_RAZOR_INPUT_STREAM(stream);
   162     priv=razor_stream->priv;
   163     count=MIN(count,priv->len-priv->pos);
   164     memcpy(buffer,(guint8 *)priv->buf+priv->pos,count);
   165     priv->pos+=count;
   166     return count;
   167 }
   168 
   169 static gssize plover_razor_input_stream_skip(GInputStream *stream,gsize count,
   170   GCancellable *cancellable,GError **error)
   171 {
   172     PloverRazorInputStream *razor_stream;
   173     PloverRazorInputStreamPrivate *priv;
   174     razor_stream=PLOVER_RAZOR_INPUT_STREAM(stream);
   175     priv=razor_stream->priv;
   176     count=MIN(count,priv->len-priv->pos);
   177     priv->pos+=count;
   178     return count;
   179 }
   180 
   181 static gboolean plover_razor_input_stream_close(GInputStream *stream,
   182   GCancellable *cancellable,GError **error)
   183 {
   184     return TRUE;
   185 }
   186 
   187 static void plover_razor_input_stream_skip_async(GInputStream *stream,
   188   gsize count,int io_priority,GCancellable *cancellable,
   189   GAsyncReadyCallback callback,gpointer user_data)
   190 {
   191     GTask *task;
   192     gssize nskipped;
   193     GError *error=NULL;
   194     nskipped=G_INPUT_STREAM_GET_CLASS(stream)->skip(stream,count,cancellable,
   195       &error);
   196     task=g_task_new(stream,cancellable,callback,user_data);
   197     if (error)
   198 	g_task_return_error(task,error);
   199     else
   200 	g_task_return_int(task,nskipped);
   201     g_object_unref(task);
   202 }
   203 
   204 static gssize plover_razor_input_stream_skip_finish(GInputStream *stream,
   205   GAsyncResult *result,GError **error)
   206 {
   207     g_return_val_if_fail(g_task_is_valid(result,stream),-1);
   208     return g_task_propagate_int(G_TASK(result),error);
   209 }
   210 
   211 static void plover_razor_input_stream_close_async(GInputStream *stream,
   212   int io_priority,GCancellable *cancellable,GAsyncReadyCallback callback,
   213   gpointer user_data)
   214 {
   215     GTask *task;
   216     task=g_task_new(stream,cancellable,callback,user_data);
   217     g_task_return_boolean(task,TRUE);
   218     g_object_unref (task);
   219 }
   220 
   221 static gboolean plover_razor_input_stream_close_finish(GInputStream *stream,
   222   GAsyncResult *result,GError **error)
   223 {
   224     return TRUE;
   225 }
   226 
   227 static goffset plover_razor_input_stream_tell(GSeekable *seekable)
   228 {
   229     PloverRazorInputStream *razor_stream;
   230     PloverRazorInputStreamPrivate *priv;
   231     razor_stream=PLOVER_RAZOR_INPUT_STREAM(seekable);
   232     priv=razor_stream->priv;
   233     return priv->pos;
   234 }
   235 
   236 static gboolean plover_razor_input_stream_can_seek(GSeekable *seekable)
   237 {
   238     return TRUE;
   239 }
   240 
   241 static gboolean plover_razor_input_stream_seek(GSeekable *seekable,
   242   goffset offset,GSeekType type,GCancellable *cancellable,GError **error)
   243 {
   244     PloverRazorInputStream *razor_stream;
   245     PloverRazorInputStreamPrivate *priv;
   246     goffset absolute;
   247     razor_stream=PLOVER_RAZOR_INPUT_STREAM(seekable);
   248     priv=razor_stream->priv;
   249     switch(type)
   250     {
   251 	case G_SEEK_CUR:
   252 	    absolute=priv->pos+offset;
   253 	    break;
   254 	case G_SEEK_SET:
   255 	    absolute=offset;
   256 	    break;
   257 	case G_SEEK_END:
   258 	    absolute=priv->len+offset;
   259 	    break;
   260 	default:
   261 	    g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_INVALID_ARGUMENT,
   262 	      _("Invalid GSeekType supplied"));
   263 	    return FALSE;
   264     }
   265     if (absolute<0 || absolute>priv->len)
   266     {
   267 	g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_INVALID_ARGUMENT,
   268 	  _("Invalid seek request"));
   269 	return FALSE;
   270     }
   271     priv->pos=absolute;
   272     return TRUE;
   273 }
   274 
   275 static gboolean plover_razor_input_stream_can_truncate(GSeekable *seekable)
   276 {
   277     return FALSE;
   278 }
   279 
   280 static gboolean plover_razor_input_stream_truncate(GSeekable *seekable,
   281   goffset offset,GCancellable *cancellable,GError **error)
   282 {
   283     g_set_error_literal(error,G_IO_ERROR,G_IO_ERROR_NOT_SUPPORTED,
   284       _("Cannot truncate PloverRazorInputStream"));
   285     return FALSE;
   286 }
   287 
   288 static gboolean
   289   plover_razor_input_stream_is_readable(GPollableInputStream *stream)
   290 {
   291     return TRUE;
   292 }
   293 
   294 static GSource *
   295   plover_razor_input_stream_create_source(GPollableInputStream *stream,
   296   GCancellable *cancellable)
   297 {
   298     GSource *base_source,*pollable_source;
   299     base_source=g_timeout_source_new(0);
   300     pollable_source=g_pollable_source_new_full(stream,base_source,cancellable);
   301     g_source_unref(base_source);
   302     return pollable_source;
   303 }