[vlc-devel] [RFC 05/10] stream_extractor: add vlc_stream_extractor_CreateMRL

Filip Roséen filip at atch.se
Mon Nov 28 03:22:24 CET 2016


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.
---
 include/vlc_stream_extractor.h | 18 ++++++++++
 src/input/mrl_helpers.h        | 78 ++++++++++++++++++++++++++++++++++++++++++
 src/input/stream_extractor.c   | 31 ++++++++++++++++-
 src/libvlccore.sym             |  1 +
 4 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 src/input/mrl_helpers.h

diff --git a/include/vlc_stream_extractor.h b/include/vlc_stream_extractor.h
index 1f6d01a..87be9d2 100644
--- a/include/vlc_stream_extractor.h
+++ b/include/vlc_stream_extractor.h
@@ -67,6 +67,24 @@ 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 create a stream_t where the underlying
diff --git a/src/input/mrl_helpers.h b/src/input/mrl_helpers.h
new file mode 100644
index 0000000..a3fc7a4
--- /dev/null
+++ b/src/input/mrl_helpers.h
@@ -0,0 +1,78 @@
+#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" : "%%%x"), *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 */
diff --git a/src/input/stream_extractor.c b/src/input/stream_extractor.c
index 78800e4..9d559a5 100644
--- a/src/input/stream_extractor.c
+++ b/src/input/stream_extractor.c
@@ -15,6 +15,7 @@
 #include <assert.h>
 
 #include "stream.h"
+#include "mrl_helpers.h"
 
 /**
  * \defgroup stream_extractor_Private Stream Extractor Private
@@ -146,7 +147,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
     {
@@ -196,6 +198,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;
+}
+
 /**
  * @}
  **/
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index cd8d0b5..6c66b09 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -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
-- 
2.10.2



More information about the vlc-devel mailing list