VLC 4.0.0-dev
mrl_helpers.h
Go to the documentation of this file.
1/*****************************************************************************
2 * mrl_helpers.h
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
20
21#ifndef INPUT_MRL_HELPERS_H
22#define INPUT_MRL_HELPERS_H
23
24#include <string.h>
25#include <stdlib.h>
26
27#include <vlc_common.h>
28#include <vlc_memstream.h>
29#include <vlc_arrays.h>
30#include <vlc_url.h>
31
32/**
33 * \defgroup mrl_helpers MRL helpers
34 * \ingroup mrl
35 *
36 * Helper functions related to parsing, as well as generating, data
37 * related to the \link mrl MRL-specification\endlink.
38 *
39 * @{
40 * \file
41 **/
42
43/**
44 * Escape a fragment identifier for use within an MRL
45 *
46 * The function will generate a string that follows the \link mrl
47 * MRL-specification\endlink regarding \em fragment-identifiers.
48 *
49 * See the \link mrl MRL-specification\endlink for a detailed
50 * explanation of how `payload` will be escaped.
51 *
52 * \param[out] out `*out` will refer to the created string on success,
53 * and an unspecified value on error.
54 * \param[in] payload the data to escape.
55 * \return VLC_SUCCESS on success, an error-code on failure.
56 **/
57static inline int
58mrl_EscapeFragmentIdentifier( char** out, char const* payload )
59{
60 struct vlc_memstream mstream;
61
62#define RFC3986_SUBDELIMS "!" "$" "&" "'" "(" ")" \
63 "*" "+" "," ";" "="
64#define RFC3986_ALPHA "abcdefghijklmnopqrstuvwxyz" \
65 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
66#define RFC3986_DIGIT "0123456789"
67#define RFC3986_UNRESERVED RFC3986_ALPHA RFC3986_DIGIT "-" "." "_" "~"
68#define RFC3986_PCHAR RFC3986_UNRESERVED RFC3986_SUBDELIMS ":" "@"
69#define RFC3986_FRAGMENT RFC3986_PCHAR "/" "?"
70
71 if( vlc_memstream_open( &mstream ) )
72 return VLC_EGENERIC;
73
74 for( char const* p = payload; *p; ++p )
75 {
76 vlc_memstream_printf( &mstream,
77 ( strchr( "!?", *p ) == NULL &&
78 strchr( RFC3986_FRAGMENT, *p ) ? "%c" : "%%%02hhx"), *p );
79 }
80
81#undef RFC3986_FRAGMENT
82#undef RFC3986_PCHAR
83#undef RFC3986_UNRESERVEd
84#undef RFC3986_DIGIT
85#undef RFC3986_ALPHA
86#undef RFC3986_SUBDELIMS
87
88 if( vlc_memstream_close( &mstream ) )
89 return VLC_EGENERIC;
90
91 *out = mstream.ptr;
92 return VLC_SUCCESS;
93}
94
95/**
96 * Split an \link mrl_technical_fragment MRL-fragment\endlink into identifiers
97 *
98 * Function used to split the fragment-data (also referred to as
99 * anchor-data) into an array containing each of the files specified.
100 *
101 * See the \link mrl MRL-specification\endlink for detailed
102 * information regarding how `payload` will be interpreted.
103 *
104 * \warning On success, the caller has ownership of the contents of *out_items
105 * which means that it is responsible for freeing the individual
106 * elements, as well as cleaning the array itself.
107 *
108 * \param[out] out_items storage for a vlc_array_t that will contain the
109 * parsed identifiers on success.
110 * \param[out] out_extra `*out_extra` will point to any remaining data (if any)
111 * \param[in] payload the data to parse
112 * \return VLC_SUCCESS on success, an error-code on failure
113 **/
114static inline int
116 char const** out_extra,
117 char const* payload )
118{
119 char const* extra = NULL;
120
121 vlc_array_init( out_items );
122
123 while( strncmp( payload, "!/", 2 ) == 0 )
124 {
125 payload += 2;
126
127 int len = strcspn( payload, "!?" );
128 char* decoded = strndup( payload, len );
129
130 if( unlikely( !decoded ) || !vlc_uri_decode( decoded ) )
131 goto error;
132
133 if( vlc_array_append( out_items, decoded ) )
134 {
135 free( decoded );
136 goto error;
137 }
138 payload += len;
139 }
140
141 if( *payload )
142 {
143 if( *payload == '!' )
144 goto error;
145
146 if( *payload == '?' && vlc_array_count( out_items ) )
147 ++payload;
148
149 extra = payload;
150 }
151
152 *out_extra = extra;
153 return VLC_SUCCESS;
154
155error:
156 for( size_t i = 0; i < vlc_array_count( out_items ); ++i )
157 free( vlc_array_item_at_index( out_items, i ) );
158 vlc_array_clear( out_items );
159 return VLC_EGENERIC;
160}
161
162/** @} */
163
164#endif /* include-guard */
#define p(t)
#define unlikely(p)
Predicted false condition.
Definition: vlc_common.h:257
#define VLC_EGENERIC
Unspecified error.
Definition: vlc_common.h:505
#define VLC_SUCCESS
No error.
Definition: vlc_common.h:503
int vlc_memstream_open(struct vlc_memstream *ms)
Initializes a byte stream object.
Definition: memstream.c:105
int vlc_memstream_printf(struct vlc_memstream *ms, const char *fmt,...)
Appends a formatted string to a byte stream.
Definition: memstream.c:194
int vlc_memstream_close(struct vlc_memstream *ms)
Closes a byte stream object.
Definition: memstream.c:120
static int mrl_EscapeFragmentIdentifier(char **out, char const *payload)
Escape a fragment identifier for use within an MRL.
Definition: mrl_helpers.h:58
static int mrl_FragmentSplit(vlc_array_t *out_items, char const **out_extra, char const *payload)
Split an MRL-fragment into identifiers.
Definition: mrl_helpers.h:115
char * vlc_uri_decode(char *str)
Decodes an URI component in place.
Definition: url.c:74
#define RFC3986_FRAGMENT
Definition: vlc_arrays.h:257
In-memory stream object.
Definition: vlc_memstream.h:42
char * ptr
Buffer start address.
Definition: vlc_memstream.h:48
int error
Definition: vlc_memstream.h:46
This file defines functions, structures and macros for handling arrays in vlc.
static int vlc_array_append(vlc_array_t *ar, void *elem)
Definition: vlc_arrays.h:333
static void vlc_array_init(vlc_array_t *p_array)
Definition: vlc_arrays.h:262
static void vlc_array_clear(vlc_array_t *p_array)
Definition: vlc_arrays.h:268
#define vlc_array_item_at_index(ar, idx)
Definition: vlc_arrays.h:281
static size_t vlc_array_count(vlc_array_t *p_array)
Definition: vlc_arrays.h:275
This file is a collection of common definitions and types.
char * strndup(const char *, size_t)