1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_DETAIL_PATH_HPP
10  
#ifndef BOOST_URL_DETAIL_PATH_HPP
11  
#define BOOST_URL_DETAIL_PATH_HPP
11  
#define BOOST_URL_DETAIL_PATH_HPP
12  

12  

13  
#include <boost/url/detail/config.hpp>
13  
#include <boost/url/detail/config.hpp>
14  
#include <boost/core/detail/string_view.hpp>
14  
#include <boost/core/detail/string_view.hpp>
15  

15  

16  
namespace boost {
16  
namespace boost {
17  
namespace urls {
17  
namespace urls {
18  
namespace detail {
18  
namespace detail {
19  

19  

20  
// Return the number of characters at
20  
// Return the number of characters at
21  
// the front of the path that are reserved
21  
// the front of the path that are reserved
22  
inline
22  
inline
23  
std::size_t
23  
std::size_t
24  
path_prefix(
24  
path_prefix(
25  
    char const* p,
25  
    char const* p,
26  
    std::size_t n) noexcept
26  
    std::size_t n) noexcept
27  
{
27  
{
28  
    switch(n)
28  
    switch(n)
29  
    {
29  
    {
30  
    case 0:
30  
    case 0:
31  
        return 0;
31  
        return 0;
32  

32  

33  
    case 1:
33  
    case 1:
34  
        if(p[0] == '/')
34  
        if(p[0] == '/')
35  
            return 1;
35  
            return 1;
36  
        return 0;
36  
        return 0;
37  

37  

38  
    case 2:
38  
    case 2:
39  
        if(p[0] == '/')
39  
        if(p[0] == '/')
40  
            return 1;
40  
            return 1;
41  
        if( p[0] == '.' &&
41  
        if( p[0] == '.' &&
42  
            p[1] == '/')
42  
            p[1] == '/')
43  
            return 2;
43  
            return 2;
44  
        return 0;
44  
        return 0;
45  

45  

46  
    default:
46  
    default:
47  
        if(p[0] == '/')
47  
        if(p[0] == '/')
48  
        {
48  
        {
49  
            if( p[1] == '.' &&
49  
            if( p[1] == '.' &&
50  
                p[2] == '/')
50  
                p[2] == '/')
51  
                return 3;
51  
                return 3;
52  
            return 1;
52  
            return 1;
53  
        }
53  
        }
54  
        if( p[0] == '.' &&
54  
        if( p[0] == '.' &&
55  
            p[1] == '/')
55  
            p[1] == '/')
56  
            return 2;
56  
            return 2;
57  
        break;
57  
        break;
58  
    }
58  
    }
59  
    return 0;
59  
    return 0;
60  
}
60  
}
61  

61  

62  
// VFALCO DEPRECATED
62  
// VFALCO DEPRECATED
63  
inline
63  
inline
64  
std::size_t
64  
std::size_t
65  
path_prefix(
65  
path_prefix(
66  
    core::string_view s) noexcept
66  
    core::string_view s) noexcept
67  
{
67  
{
68  
    return path_prefix(
68  
    return path_prefix(
69  
        s.data(), s.size());
69  
        s.data(), s.size());
70  
}
70  
}
71  

71  

72  
// returns the number of adjusted
72  
// returns the number of adjusted
73  
// segments based on the malleable prefix.
73  
// segments based on the malleable prefix.
74  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
74  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
75  
std::size_t
75  
std::size_t
76  
path_segments(
76  
path_segments(
77  
    core::string_view s,
77  
    core::string_view s,
78  
    std::size_t nseg) noexcept
78  
    std::size_t nseg) noexcept
79  
{
79  
{
80  
    switch(s.size())
80  
    switch(s.size())
81  
    {
81  
    {
82  
    case 0:
82  
    case 0:
83  
        BOOST_ASSERT(nseg == 0);
83  
        BOOST_ASSERT(nseg == 0);
84  
        return 0;
84  
        return 0;
85  

85  

86  
    case 1:
86  
    case 1:
87  
        BOOST_ASSERT(nseg == 1);
87  
        BOOST_ASSERT(nseg == 1);
88  
        if(s[0] == '/')
88  
        if(s[0] == '/')
89  
            return 0;
89  
            return 0;
90  
        return 1;
90  
        return 1;
91  

91  

92  
    case 2:
92  
    case 2:
93  
        if(s[0] == '/')
93  
        if(s[0] == '/')
94  
            return nseg;
94  
            return nseg;
95  
        if( s[0] == '.' &&
95  
        if( s[0] == '.' &&
96  
            s[1] == '/')
96  
            s[1] == '/')
97  
        {
97  
        {
98  
            BOOST_ASSERT(nseg > 1);
98  
            BOOST_ASSERT(nseg > 1);
99  
            return nseg - 1;
99  
            return nseg - 1;
100  
        }
100  
        }
101  
        return nseg;
101  
        return nseg;
102  

102  

103  
    default:
103  
    default:
104  
        if(s[0] == '/')
104  
        if(s[0] == '/')
105  
        {
105  
        {
106  
            if( s[1] == '.' &&
106  
            if( s[1] == '.' &&
107  
                s[2] == '/')
107  
                s[2] == '/')
108  
            {
108  
            {
109  
                BOOST_ASSERT(nseg > 1);
109  
                BOOST_ASSERT(nseg > 1);
110  
                return nseg - 1;
110  
                return nseg - 1;
111  
            }
111  
            }
112  
            return nseg;
112  
            return nseg;
113  
        }
113  
        }
114  
        if( s[0] == '.' &&
114  
        if( s[0] == '.' &&
115  
            s[1] == '/')
115  
            s[1] == '/')
116  
        {
116  
        {
117  
            BOOST_ASSERT(nseg > 1);
117  
            BOOST_ASSERT(nseg > 1);
118  
            return nseg - 1;
118  
            return nseg - 1;
119  
        }
119  
        }
120  
        break;
120  
        break;
121  
    }
121  
    }
122  
    return nseg;
122  
    return nseg;
123  
}
123  
}
124  

124  

125  
// Trim reserved characters from
125  
// Trim reserved characters from
126  
// the front of the path.
126  
// the front of the path.
127  
inline
127  
inline
128  
core::string_view
128  
core::string_view
129  
clean_path(
129  
clean_path(
130  
    core::string_view s) noexcept
130  
    core::string_view s) noexcept
131  
{
131  
{
132  
    s.remove_prefix(
132  
    s.remove_prefix(
133  
        path_prefix(s));
133  
        path_prefix(s));
134  
    return s;
134  
    return s;
135  
}
135  
}
136  

136  

137  
} // detail
137  
} // detail
138  
} // urls
138  
} // urls
139  
} // boost
139  
} // boost
140  

140  

141  
#endif
141  
#endif