stream_extractor: add vlc_stream_extractor_CreateMRL
authorFilip Roséen <filip@atch.se>
Mon, 21 Nov 2016 23:50:52 +0000 (00:50 +0100)
committerThomas Guillem <thomas@gllm.fr>
Tue, 6 Dec 2016 14:57:19 +0000 (15:57 +0100)
Function used by stream-extractor modules to make it easy to create a
relative MRL for an entity within the data handled by the
stream-extractor.

Signed-off-by: Thomas Guillem <thomas@gllm.fr>
include/vlc_stream_extractor.h
src/Makefile.am
src/input/mrl_helpers.h [new file with mode: 0644]
src/input/stream_extractor.c
src/libvlccore.sym

index 0d0e63e..9045264 100644 (file)
@@ -86,12 +86,29 @@ struct stream_extractor_t {
 
 typedef struct stream_extractor_t stream_extractor_t;
 
+/**
+ * Create a relative MRL for the associated entity
+ *
+ * This function shall be used by stream_extractor_t's in order to
+ * generate a MRL that refers to an entity within the stream. Normally
+ * this function will only be invoked within `pf_readdir` in order to
+ * get the virtual path of the listed items.
+ *
+ * \warning the returned value is to be freed by the caller
+ *
+ * \param extractor the stream_extractor_t in which the entity belongs
+ * \param subentry the name of the entity in question
+ *
+ * \return a pointer to the resulting MRL on success, NULL on failure
+ **/
+VLC_API char* vlc_stream_extractor_CreateMRL( stream_extractor_t*,
+                                              char const* subentry );
+
 /**
  * Construct a new stream_extractor-based stream
  *
- * This function is used to attach a stream to an already existing
- * stream, where the underlying, attached, stream is a
- * stream_extractor.
+ * This function is used to attach a stream extractor to an already
+ * existing stream.
  *
  * If \p identifier is `NULL`, `*stream` is guaranteed to refer to a
  * directory, otherwise \p identifier denotes the specific subentry
index ccc8dfb..2c8800e 100644 (file)
@@ -247,6 +247,7 @@ libvlccore_la_SOURCES = \
        input/es_out_timeshift.h \
        input/event.h \
        input/item.h \
+       input/mrl_helpers.h \
        input/stream.h \
        input/input_internal.h \
        input/input_interface.h \
diff --git a/src/input/mrl_helpers.h b/src/input/mrl_helpers.h
new file mode 100644 (file)
index 0000000..f4f815c
--- /dev/null
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ * mrl_helpers.h
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef INPUT_MRL_HELPERS_H
+#define INPUT_MRL_HELPERS_H
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <vlc_common.h>
+#include <vlc_memstream.h>
+#include <vlc_arrays.h>
+
+/**
+ * \defgroup mrl_helpers MRL helpers
+ * \ingroup mrl
+ *
+ * Helper functions related to parsing, as well as generating, data
+ * related to the \link MRL-specification\endlink.
+ *
+ * @{
+ * \file
+ **/
+
+/**
+ * Escape a fragment identifier for use within an MRL
+ *
+ * The function will generate a string that follows the \link mrl
+ * MRL-specification\endlink regarding \em fragment-identifiers.
+ *
+ * See the \link mrl MRL-specification\endlink for a detailed
+ * explanation of how `payload` will be escaped.
+ *
+ * \param[out] out `*out` will refer to the created string on success,
+ *                  and an unspecified value on error.
+ * \param[in] payload the data to escape.
+ * \return VLC_SUCCESS on success, an error-code on failure.
+ **/
+static inline int
+mrl_EscapeFragmentIdentifier( char** out, char const* payload )
+{
+    struct vlc_memstream mstream;
+
+#define RFC3986_SUBDELIMS  "!" "$" "&" "'" "(" ")" \
+                           "*" "+" "," ";" "="
+#define RFC3986_ALPHA      "abcdefghijklmnopqrstuvwxyz" \
+                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define RFC3986_DIGIT      "0123456789"
+#define RFC3986_UNRESERVED RFC3986_ALPHA RFC3986_DIGIT "-" "." "_" "~"
+#define RFC3986_PCHAR      RFC3986_UNRESERVED RFC3986_SUBDELIMS ":" "@"
+#define RFC3986_FRAGMENT   RFC3986_PCHAR "/" "?"
+
+    if( vlc_memstream_open( &mstream ) )
+        return VLC_EGENERIC;
+
+    for( char const* p = payload; *p; ++p )
+    {
+        vlc_memstream_printf( &mstream,
+            ( strchr( "!?", *p ) == NULL &&
+              strchr( RFC3986_FRAGMENT, *p ) ? "%c" : "%%%02hhx"), *p );
+    }
+
+#undef RFC3986_FRAGMENT
+#undef RFC3986_PCHAR
+#undef RFC3986_UNRESERVEd
+#undef RFC3986_DIGIT
+#undef RFC3986_ALPHA
+#undef RFC3986_SUBDELIMS
+
+    if( vlc_memstream_close( &mstream ) )
+        return VLC_EGENERIC;
+
+    *out = mstream.ptr;
+    return VLC_SUCCESS;
+}
+
+/*
+ * @}
+ **/
+
+#endif /* include-guard */
index 82b04cc..573ba9d 100644 (file)
@@ -35,6 +35,7 @@
 #include <assert.h>
 
 #include "stream.h"
+#include "mrl_helpers.h"
 
 /**
  * \defgroup stream_extractor_Private Stream Extractor Private
@@ -166,7 +167,8 @@ se_InitStream( struct stream_extractor_private* priv, stream_t* source )
         else                              s->pf_block = se_StreamBlock;
 
         s->pf_seek = se_StreamSeek;
-        s->psz_url = NULL;
+        s->psz_url = vlc_stream_extractor_CreateMRL( &priv->public,
+                                                      priv->public.identifier );
     }
     else
     {
@@ -219,6 +221,33 @@ error:
     return VLC_EGENERIC;
 }
 
+char*
+vlc_stream_extractor_CreateMRL( stream_extractor_t* extractor,
+                                char const* subentry )
+{
+    struct vlc_memstream buffer;
+    char* escaped;
+
+    if( mrl_EscapeFragmentIdentifier( &escaped, subentry ) )
+        return NULL;
+
+    if( vlc_memstream_open( &buffer ) )
+    {
+        free( escaped );
+        return NULL;
+    }
+
+    vlc_memstream_puts( &buffer, extractor->source->psz_url );
+
+    if( !strstr( extractor->source->psz_url, "#" ) )
+        vlc_memstream_putc( &buffer, '#' );
+
+    vlc_memstream_printf( &buffer, "!/%s", escaped );
+
+    free( escaped );
+    return vlc_memstream_close( &buffer ) ? NULL : buffer.ptr;
+}
+
 /**
  * @}
  **/
index cdb8f31..b4e37e4 100644 (file)
@@ -396,6 +396,7 @@ spu_Render
 spu_RegisterChannel
 spu_ClearChannel
 vlc_stream_extractor_Attach
+vlc_stream_extractor_CreateMRL
 vlc_stream_Block
 vlc_stream_CommonNew
 vlc_stream_Delete