📄 path.hpp
字号:
typename String::size_type pos(
str.find_last_of( slash<path_type>::value, end_pos-1 ) );
# ifdef BOOST_WINDOWS_PATH
if ( pos == String::npos )
pos = str.find_last_of( path_alt_separator<path_type>::value, end_pos-1 );
if ( pos == String::npos )
pos = str.find_last_of( colon<path_type>::value, end_pos-2 );
# endif
return ( pos == String::npos // path itself must be a leaf (or empty)
|| (pos == 1 && str[0] == slash<path_type>::value) ) // or net
? 0 // so leaf is entire string
: pos + 1; // or starts after delimiter
}
// first_element helper -----------------------------------------------//
// sets pos and len of first element, excluding extra separators
// if src.empty(), sets pos,len, to 0,0.
template<class String, class Traits>
void first_element(
const String & src, // precondition: portable generic path grammar
typename String::size_type & element_pos,
typename String::size_type & element_size,
# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1
typename String::size_type size = String::npos
# else
typename String::size_type size = -1
# endif
)
{
if ( size == String::npos ) size = src.size();
element_pos = 0;
element_size = 0;
if ( src.empty() ) return;
typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
typename String::size_type cur(0);
// deal with // [network]
if ( size >= 2 && src[0] == slash<path_type>::value
&& src[1] == slash<path_type>::value
&& (size == 2
|| src[2] != slash<path_type>::value) )
{
cur += 2;
element_size += 2;
}
// leading (not non-network) separator
else if ( src[0] == slash<path_type>::value )
{
++element_size;
// bypass extra leading separators
while ( cur+1 < size
&& src[cur+1] == slash<path_type>::value )
{
++cur;
++element_pos;
}
return;
}
// at this point, we have either a plain name, a network name,
// or (on Windows only) a device name
// find the end
while ( cur < size
# ifdef BOOST_WINDOWS_PATH
&& src[cur] != colon<path_type>::value
# endif
&& src[cur] != slash<path_type>::value )
{
++cur;
++element_size;
}
# ifdef BOOST_WINDOWS_PATH
if ( cur == size ) return;
// include device delimiter
if ( src[cur] == colon<path_type>::value )
{ ++element_size; }
# endif
return;
}
// root_directory_start helper ----------------------------------------//
template<class String, class Traits>
typename String::size_type root_directory_start(
const String & s, // precondition: portable generic path grammar
typename String::size_type size )
// return npos if no root_directory found
{
typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits> path_type;
# ifdef BOOST_WINDOWS_PATH
// case "c:/"
if ( size > 2
&& s[1] == colon<path_type>::value
&& s[2] == slash<path_type>::value ) return 2;
# endif
// case "//"
if ( size == 2
&& s[0] == slash<path_type>::value
&& s[1] == slash<path_type>::value ) return String::npos;
// case "//net {/}"
if ( size > 3
&& s[0] == slash<path_type>::value
&& s[1] == slash<path_type>::value
&& s[2] != slash<path_type>::value )
{
typename String::size_type pos(
s.find( slash<path_type>::value, 2 ) );
return pos < size ? pos : String::npos;
}
// case "/"
if ( size > 0 && s[0] == slash<path_type>::value ) return 0;
return String::npos;
}
// is_non_root_slash helper -------------------------------------------//
template<class String, class Traits>
bool is_non_root_slash( const String & str,
typename String::size_type pos ) // pos is position of the slash
{
typedef typename
boost::BOOST_FILESYSTEM_NAMESPACE::basic_path<String, Traits>
path_type;
assert( !str.empty() && str[pos] == slash<path_type>::value
&& "precondition violation" );
// subsequent logic expects pos to be for leftmost slash of a set
while ( pos > 0 && str[pos-1] == slash<path_type>::value )
--pos;
return pos != 0
&& (pos <= 2 || str[1] != slash<path_type>::value
|| str.find( slash<path_type>::value, 2 ) != pos)
# ifdef BOOST_WINDOWS_PATH
&& (pos !=2 || str[1] != colon<path_type>::value)
# endif
;
}
} // namespace detail
// decomposition functions ----------------------------------------------//
template<class String, class Traits>
String basic_path<String, Traits>::leaf() const
{
typename String::size_type end_pos(
detail::leaf_pos<String, Traits>( m_path, m_path.size() ) );
return (m_path.size()
&& end_pos
&& m_path[end_pos] == slash<path_type>::value
&& detail::is_non_root_slash< String, Traits >(m_path, end_pos))
? String( 1, dot<path_type>::value )
: m_path.substr( end_pos );
}
template<class String, class Traits>
basic_path<String, Traits> basic_path<String, Traits>::branch_path() const
{
typename String::size_type end_pos(
detail::leaf_pos<String, Traits>( m_path, m_path.size() ) );
bool leaf_was_separator( m_path.size()
&& m_path[end_pos] == slash<path_type>::value );
// skip separators unless root directory
typename string_type::size_type root_dir_pos( detail::root_directory_start
<string_type, traits_type>( m_path, end_pos ) );
for ( ;
end_pos > 0
&& (end_pos-1) != root_dir_pos
&& m_path[end_pos-1] == slash<path_type>::value
;
--end_pos ) {}
return (end_pos == 1 && root_dir_pos == 0 && leaf_was_separator)
? path_type()
: path_type( m_path.substr( 0, end_pos ) );
}
template<class String, class Traits>
basic_path<String, Traits> basic_path<String, Traits>::relative_path() const
{
iterator itr( begin() );
for ( ; itr.m_pos != m_path.size()
&& (itr.m_name[0] == slash<path_type>::value
# ifdef BOOST_WINDOWS_PATH
|| itr.m_name[itr.m_name.size()-1]
== colon<path_type>::value
# endif
); ++itr ) {}
return basic_path<String, Traits>( m_path.substr( itr.m_pos ) );
}
template<class String, class Traits>
String basic_path<String, Traits>::root_name() const
{
iterator itr( begin() );
return ( itr.m_pos != m_path.size()
&& (
( itr.m_name.size() > 1
&& itr.m_name[0] == slash<path_type>::value
&& itr.m_name[1] == slash<path_type>::value
)
# ifdef BOOST_WINDOWS_PATH
|| itr.m_name[itr.m_name.size()-1]
== colon<path_type>::value
# endif
) )
? *itr
: String();
}
template<class String, class Traits>
String basic_path<String, Traits>::root_directory() const
{
typename string_type::size_type start(
detail::root_directory_start<String, Traits>( m_path, m_path.size() ) );
return start == string_type::npos
? string_type()
: m_path.substr( start, 1 );
}
template<class String, class Traits>
basic_path<String, Traits> basic_path<String, Traits>::root_path() const
{
// even on POSIX, root_name() is non-empty() on network paths
return basic_path<String, Traits>( root_name() ) /= root_directory();
}
// path query functions -------------------------------------------------//
template<class String, class Traits>
inline bool basic_path<String, Traits>::is_complete() const
{
# ifdef BOOST_WINDOWS_PATH
return has_root_name() && has_root_directory();
# else
return has_root_directory();
# endif
}
template<class String, class Traits>
inline bool basic_path<String, Traits>::has_root_path() const
{
return !root_path().empty();
}
template<class String, class Traits>
inline bool basic_path<String, Traits>::has_root_name() const
{
return !root_name().empty();
}
template<class String, class Traits>
inline bool basic_path<String, Traits>::has_root_directory() const
{
return !root_directory().empty();
}
// append ---------------------------------------------------------------//
template<class String, class Traits>
void basic_path<String, Traits>::m_append_separator_if_needed()
// requires: !empty()
{
if (
# ifdef BOOST_WINDOWS_PATH
*(m_path.end()-1) != colon<path_type>::value &&
# endif
*(m_path.end()-1) != slash<path_type>::value )
{
m_path += slash<path_type>::value;
}
}
template<class String, class Traits>
void basic_path<String, Traits>::m_append( value_type value )
{
# ifdef BOOST_CYGWIN_PATH
if ( m_path.empty() ) m_cygwin_root = (value == slash<path_type>::value);
# endif
# ifdef BOOST_WINDOWS_PATH
// for BOOST_WINDOWS_PATH, convert alt_separator ('\') to separator ('/')
m_path += ( value == path_alt_separator<path_type>::value
? slash<path_type>::value
: value );
# else
m_path += value;
# endif
}
// except that it wouldn't work for BOOST_NO_MEMBER_TEMPLATES compilers,
// the append() member template could replace this code.
template<class String, class Traits>
basic_path<String, Traits> & basic_path<String, Traits>::operator /=
( const value_type * next_p )
{
// ignore escape sequence on POSIX or Windows
if ( *next_p == slash<path_type>::value
&& *(next_p+1) == slash<path_type>::value
&& *(next_p+2) == colon<path_type>::value ) next_p += 3;
// append slash<path_type>::value if needed
if ( !empty() && *next_p != 0
&& !detail::is_separator<path_type>( *next_p ) )
{ m_append_separator_if_needed(); }
for ( ; *next_p != 0; ++next_p ) m_append( *next_p );
return *this;
}
# ifndef BOOST_NO_MEMBER_TEMPLATES
template<class String, class Traits> template <class InputIterator>
basic_path<String, Traits> & basic_path<String, Traits>::append(
InputIterator first, InputIterator last )
{
// append slash<path_type>::value if needed
if ( !empty() && first != last
&& !detail::is_separator<path_type>( *first ) )
{ m_append_separator_if_needed(); }
// song-and-dance to avoid violating InputIterator requirements
// (which prohibit lookahead) in detecting a possible escape sequence
// (escape sequences are simply ignored on POSIX and Windows)
bool was_escape_sequence(true);
std::size_t append_count(0);
typename String::size_type initial_pos( m_path.size() );
for ( ; first != last && *first; ++first )
{
if ( append_count == 0 && *first != slash<path_type>::value )
was_escape_sequence = false;
if ( append_count == 1 && *first != slash<path_type>::value )
was_escape_sequence = false;
if ( append_count == 2 && *first != colon<path_type>::value )
was_escape_sequence = false;
m_append( *first );
++append_count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -