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/core/detail/string_view.hpp>
13  
#include <boost/core/detail/string_view.hpp>
14  

14  

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

18  

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

31  

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

36  

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

44  

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

60  

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

70  

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

84  

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

90  

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

101  

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

123  

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

135  

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

139  

140  
#endif
140  
#endif