2020-01-18 11:38:21 +03:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2021-06-29 14:11:03 +03:00
* Copyright ( c ) 2021 , Max Wipfli < max . wipfli @ serenityos . org >
2020-01-18 11:38:21 +03:00
*
2021-04-22 11:24:48 +03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 11:38:21 +03:00
*/
2018-10-28 10:54:20 +03:00
# pragma once
2023-12-16 17:19:34 +03:00
# include <AK/ByteString.h>
2020-02-14 23:41:10 +03:00
# include <AK/Vector.h>
2018-10-28 10:54:20 +03:00
2022-09-25 21:53:46 +03:00
// On Linux distros that use mlibc `basename` is defined as a macro that expands to `__mlibc_gnu_basename` or `__mlibc_gnu_basename_c`, so we undefine it.
# if defined(AK_OS_LINUX) && defined(basename)
# undef basename
# endif
2018-10-28 10:54:20 +03:00
namespace AK {
2020-05-26 14:52:44 +03:00
class LexicalPath {
2018-10-28 10:54:20 +03:00
public :
2023-07-28 19:48:17 +03:00
enum StripExtension {
No ,
Yes
} ;
2023-12-16 17:19:34 +03:00
explicit LexicalPath ( ByteString ) ;
2018-10-28 10:54:20 +03:00
AK+Everywhere: Use mostly StringView in LexicalPath
This changes the m_parts, m_dirname, m_basename, m_title and m_extension
member variables to StringViews onto the m_string String. It also
removes the m_is_absolute member in favour of computing if a path is
absolute in the is_absolute() getter. Due to this, the canonicalize()
method has been completely rewritten.
The parts() getter still returns a Vector<String>, although it is no
longer a const reference as m_parts is no longer a Vector<String>.
Rather, it is constructed from the StringViews in m_parts upon request.
The parts_view() getter has been added, which returns Vector<StringView>
const&. Most previous users of parts() have been changed to use
parts_view(), except where Strings are required.
Due to this change, it's is now no longer allow to create temporary
LexicalPath objects to call the dirname, basename, title, or extension
getters on them because the returned StringViews will point to possible
freed memory.
2021-06-29 18:06:21 +03:00
bool is_absolute ( ) const { return ! m_string . is_empty ( ) & & m_string [ 0 ] = = ' / ' ; }
2023-12-16 17:19:34 +03:00
ByteString const & string ( ) const { return m_string ; }
2018-10-28 10:54:20 +03:00
2021-11-11 02:55:02 +03:00
StringView dirname ( ) const { return m_dirname ; }
2023-07-28 19:48:17 +03:00
StringView basename ( StripExtension s = StripExtension : : No ) const { return s = = StripExtension : : No ? m_basename : m_basename . substring_view ( 0 , m_basename . length ( ) - m_extension . length ( ) - 1 ) ; }
2021-11-11 02:55:02 +03:00
StringView title ( ) const { return m_title ; }
StringView extension ( ) const { return m_extension ; }
2018-11-18 16:57:41 +03:00
AK+Everywhere: Use mostly StringView in LexicalPath
This changes the m_parts, m_dirname, m_basename, m_title and m_extension
member variables to StringViews onto the m_string String. It also
removes the m_is_absolute member in favour of computing if a path is
absolute in the is_absolute() getter. Due to this, the canonicalize()
method has been completely rewritten.
The parts() getter still returns a Vector<String>, although it is no
longer a const reference as m_parts is no longer a Vector<String>.
Rather, it is constructed from the StringViews in m_parts upon request.
The parts_view() getter has been added, which returns Vector<StringView>
const&. Most previous users of parts() have been changed to use
parts_view(), except where Strings are required.
Due to this change, it's is now no longer allow to create temporary
LexicalPath objects to call the dirname, basename, title, or extension
getters on them because the returned StringViews will point to possible
freed memory.
2021-06-29 18:06:21 +03:00
Vector < StringView > const & parts_view ( ) const { return m_parts ; }
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] Vector < ByteString > parts ( ) const ;
2019-03-30 05:27:25 +03:00
2021-11-11 02:55:02 +03:00
bool has_extension ( StringView ) const ;
2022-06-24 01:40:21 +03:00
bool is_child_of ( LexicalPath const & possible_parent ) const ;
2019-05-26 23:33:30 +03:00
2021-11-11 02:55:02 +03:00
[ [ nodiscard ] ] LexicalPath append ( StringView ) const ;
2021-11-21 21:55:44 +03:00
[ [ nodiscard ] ] LexicalPath prepend ( StringView ) const ;
2021-06-29 18:55:12 +03:00
[ [ nodiscard ] ] LexicalPath parent ( ) const ;
2021-05-12 22:17:39 +03:00
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] static ByteString canonicalized_path ( ByteString ) ;
[ [ nodiscard ] ] static ByteString absolute_path ( ByteString dir_path , ByteString target ) ;
[ [ nodiscard ] ] static ByteString relative_path ( StringView absolute_path , StringView prefix ) ;
2020-05-26 14:52:44 +03:00
2021-05-12 22:17:39 +03:00
template < typename . . . S >
2021-09-28 07:02:32 +03:00
[ [ nodiscard ] ] static LexicalPath join ( StringView first , S & & . . . rest )
2021-05-12 22:17:39 +03:00
{
StringBuilder builder ;
builder . append ( first ) ;
( ( builder . append ( ' / ' ) , builder . append ( forward < S > ( rest ) ) ) , . . . ) ;
2023-12-16 17:19:34 +03:00
return LexicalPath { builder . to_byte_string ( ) } ;
2021-05-12 22:17:39 +03:00
}
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] static ByteString dirname ( ByteString path )
2021-06-29 17:46:16 +03:00
{
auto lexical_path = LexicalPath ( move ( path ) ) ;
return lexical_path . dirname ( ) ;
}
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] static ByteString basename ( ByteString path , StripExtension s = StripExtension : : No )
2021-06-29 17:46:16 +03:00
{
auto lexical_path = LexicalPath ( move ( path ) ) ;
2023-07-28 19:48:17 +03:00
return lexical_path . basename ( s ) ;
2021-06-29 17:46:16 +03:00
}
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] static ByteString title ( ByteString path )
2021-06-29 17:46:16 +03:00
{
auto lexical_path = LexicalPath ( move ( path ) ) ;
return lexical_path . title ( ) ;
}
2023-12-16 17:19:34 +03:00
[ [ nodiscard ] ] static ByteString extension ( ByteString path )
2021-06-29 17:46:16 +03:00
{
auto lexical_path = LexicalPath ( move ( path ) ) ;
return lexical_path . extension ( ) ;
}
2018-10-28 10:54:20 +03:00
private :
AK+Everywhere: Use mostly StringView in LexicalPath
This changes the m_parts, m_dirname, m_basename, m_title and m_extension
member variables to StringViews onto the m_string String. It also
removes the m_is_absolute member in favour of computing if a path is
absolute in the is_absolute() getter. Due to this, the canonicalize()
method has been completely rewritten.
The parts() getter still returns a Vector<String>, although it is no
longer a const reference as m_parts is no longer a Vector<String>.
Rather, it is constructed from the StringViews in m_parts upon request.
The parts_view() getter has been added, which returns Vector<StringView>
const&. Most previous users of parts() have been changed to use
parts_view(), except where Strings are required.
Due to this change, it's is now no longer allow to create temporary
LexicalPath objects to call the dirname, basename, title, or extension
getters on them because the returned StringViews will point to possible
freed memory.
2021-06-29 18:06:21 +03:00
Vector < StringView > m_parts ;
2023-12-16 17:19:34 +03:00
ByteString m_string ;
AK+Everywhere: Use mostly StringView in LexicalPath
This changes the m_parts, m_dirname, m_basename, m_title and m_extension
member variables to StringViews onto the m_string String. It also
removes the m_is_absolute member in favour of computing if a path is
absolute in the is_absolute() getter. Due to this, the canonicalize()
method has been completely rewritten.
The parts() getter still returns a Vector<String>, although it is no
longer a const reference as m_parts is no longer a Vector<String>.
Rather, it is constructed from the StringViews in m_parts upon request.
The parts_view() getter has been added, which returns Vector<StringView>
const&. Most previous users of parts() have been changed to use
parts_view(), except where Strings are required.
Due to this change, it's is now no longer allow to create temporary
LexicalPath objects to call the dirname, basename, title, or extension
getters on them because the returned StringViews will point to possible
freed memory.
2021-06-29 18:06:21 +03:00
StringView m_dirname ;
StringView m_basename ;
StringView m_title ;
StringView m_extension ;
2018-10-28 10:54:20 +03:00
} ;
2020-10-08 15:09:38 +03:00
template < >
struct Formatter < LexicalPath > : Formatter < StringView > {
2021-11-16 03:15:21 +03:00
ErrorOr < void > format ( FormatBuilder & builder , LexicalPath const & value )
2020-10-08 15:09:38 +03:00
{
2021-11-16 03:15:21 +03:00
return Formatter < StringView > : : format ( builder , value . string ( ) ) ;
2020-10-08 15:09:38 +03:00
}
} ;
2018-10-28 10:54:20 +03:00
} ;
2022-11-26 14:18:30 +03:00
# if USING_AK_GLOBALLY
2020-05-26 14:52:44 +03:00
using AK : : LexicalPath ;
2022-11-26 14:18:30 +03:00
# endif