[vlc-devel] [RFC 05/10] stream_extractor: add vlc_stream_extractor_CreateMRL
Rémi Denis-Courmont
remi at remlab.net
Mon Nov 28 17:46:50 CET 2016
Le maanantaina 28. marraskuuta 2016, 3.22.24 EET Filip Roséen a écrit :
> 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 );
%02hhx otherwise non-printable and non-ASCII values won´t work.
> + }
> +
> +#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
--
Rémi Denis-Courmont
https://www.remlab.net/
More information about the vlc-devel
mailing list