includefile(include/header)

COMMENT(replace 'filesystem' by the name of the new class)

COMMENT(manpage, section, releasedate, archive, short name)
manpage(FBB::FileSystem)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_)
       (Wraps std::filesystem)

manpagename(FBB::Filesystem)(class offering std::filesystem facilities)

manpagesynopsis()
    bf(#include <bobcat/filesystem>)nl()
    Linking option: tt(-lbobcat)

    This header file also includes the tt(std::chrono) header file.

manpagedescription()
    The Bobcat class bf(FileSystem) is a plain wrapper around the facilities
offered by the bf(C++) tt(std::filesystem) namespace. bf(FileSystem) was
developed because the use of the tt(std::filesystem) facilities is considered
overly complex: too many free functions having signatures resembling bf(C),
and therefore not object-based. Its tt(std::filesystem::path) type offers
several nice features which are then usable via the tt(path) member functions,
but functions manipulating the file system aren't members, but are defined as
free functions requiring tt(path) arguments.

The class bf(FileSystem) offers almost all tt(std::filesystem) facilities via
its member functions. Except for some (static) members all facilities
operate on data stored inside bf(FileSystem) objects.

The class bf(FileSystem) is an extensive class: over-all it contains about 60
constructors, operators and members. It'll probably take a while before a
mental picture of what the class offers has been attained, but at least it
embeds all components of the tt(std::filesystem) namespace.

Note:
    itemization(
    it() The class bf(FileSystem) uses tt(std::chrono::file_clock), which is 
        available since the tt(C++-2a) standard: specify the tt(--std=c++2a)
        (or more recent) compiler option when using bf(FileSystem).
    )

includefile(include/namespace)

manpagesection(INHERITS FROM)
    tt(FBB::FS) - internally used only, covered in this man-page

manpagesection(TYPEDEFS AND ENUMS)

bf(Typedefs:)
    itemization(
    it()bf(DirEntry) - tt(std::filesystem::directory_entry)
    it()bf(DirIter) - tt(std::filesystem::directory_iterator)
    it()bf(EC) - tt(std::error_code)
    it()bf(FileClock) - tt(std::chrono::file_clock)
    it()bf(FileType) - tt(std::filesystem::file_type)
    it()bf(Path) - tt(std::filesystem::path)
    it()bf(Perms) - tt(std::filesystem::perms)
    it()bf(RecursiveIter) - tt(std::filesystem::recursive_directory_iterator)
    it()bf(FileStatus) - tt(std::filesystem::file_status)
    it()bf(SystemClock) - tt(std::chrono::system_clock)
    )

bf(FSOptions:)
    
    itemization(
    itb(enum FSOptions) contains the following values, inherited by
        tt(FileSystem). Options up to tt(CP_MASK) are primarily
        used by the tt(copy) member, options beyond tt(CP_MASK) are used by
        tt(setPermissions): 
COMMENT(
    DEFAULT     used by default when cally copy or setting 
                permission options to the specified ones
)
 verb(
    NEW             copy is only performed if the destination 
                    doesn't yet exist
    REPLACE         copy is only performed if the destination 
                    exists but it is replaced  
    UPDATE          copy is only performed if the destination 
                    is older than the filesystem entry to copy
    RECURSIVE       directories are recursively copied; can be
                    combined with CP_SYMLINKS, SKIP_SYMLINKS, 
                    ONLY_DIRS
    CP_SYMLINKS     symlinks are copied as symlinks
    SKIP_SYMLINKS   symlinks are ignored
    ONLY_DIRS       only the directory structure is copied
                    other entries in directories are ignored
    SYMLINK         with copy: define a symlink to the current 
                    entry
    HARDLINK        with copy: define a hard link to the current 
                    entry
    FILE            with copy: only files are processed, not 
                    directories
    CP_SYMLINK      copies a symlink to a symlink
    NEW_SYMLINK     defines a non-existing (directory) symlink
    NEW_LINK        create_hard-link
    CP_MASK         all the above enum values

    RESET           replace the current permissions
    ADD             add to the current permissions
    REMOVE          remove the specified permissions
 )
    )

    All bit-wise operators are available for bf(FSOptions) values.

manpagesection(STATIC DATA MEMBER)

    The class tt(FileSystem) defines one static data member:
tt(std::error_code s_errorCode). All tt(FileSystem) objects can use this
tt(error_code) object after calling their function call operator. E.g.,
 verb(
    FileSystem fs;
    fs();
 )
    Once tt(fs()) has been called members called by tt(fs) accepting
tt(error_code) arguments receive tt(s_error_code) as their argument. It's also
possible to use other tt(error_code) objects, or not to use tt(error_code)
arguments (which is the default). See also the description of the function
call operator below.
 
manpagesection(CONSTRUCTORS)

    tt(Path) arguments can also be arguments of types from which tt(Path)
objects can be constructed (e.g., tt(std::string, char const *), raw string
literal).

    tt(FileSystem) objects contain two data members: a tt(Path) and an 
tt(EC *). When tt(FileSystem) objects are initialized their tt(EC *) is set to
0. 

    itemization(
    itb(Filesystem())
       The default constructor constructs an empty object, not using the
        class's static tt(s_errorCode) object;

    itb(Filesystem(Path const &path, bool useEC = true))
       The object is initialized with a copy of tt(path). By default tt(useEC
        == true), in which case it uses the class's static tt(s_errorCode)
        object;

    itb(Filesystem(Path &&path, EC &ec))
       The object is initialized with a copy of tt(path), passing tt(ec) to
        members supporting tt(EC) arguments;

    itb(Filesystem(Path const &tmp, bool useEC = true))
       The object moves tt(tmp) to its internal tt(path). By default tt(useEC
        == true), in which case it uses the class's static tt(s_errorCode)
        object;

    itb(Filesystem(Path &&tmp, EC &ec))
       The object moves tt(tmp) to its internal tt(path), passing tt(ec) to
        members supporting tt(EC) arguments.
    )

    Copy and move constructors (and assignment operators) are available.  The
newly constructed or assigned object use the same tt(EC) specification as
their source (right-hand side) objects.

manpagesection(OVERLOADED OPERATORS)

    tt(Type) arguments can be arguments of type tt(FileSystem, Path) or types
from which tt(Path) objects can be constructed (e.g., tt(std::string, char
const *), raw string literal).

    itemization(
    itb(std::istream &operator>>(std::istream &in, FileSystem &rhs))
       extracts a tt(path) specification from tt(in), and initializes tt(rhs)
        with the extracted path;

    itb(std::ostream &operator<<(std::ostream &out, FileSystem const &rhs))
       inserts the object's tt(path) into tt(out);

    itb(bool operator==(FileSystem const &lhs, FileSystem const &rhs))
       returns tt(true) if tt(lhs) and tt(rhs) refer to the same file system
        entry. An exception is thrown if at least one argument doesn't refer
        to an existing file system entry and the tt(lhs) operand hasn't
        specified an tt(EC) (see tt(operator()()) below). This operator calls
        the member tt(sameAs) for its tt(lhs) argument;

    itb(FileSystem &operator/=(Type const &arg))
       tt(arg) is appended to the object's tt(path) data member. If the
        tt(path) data member did not already end in tt('/') then tt(/arg) is
        appended;

    itb(FileSystem &operator+=(Type const &arg))
       tt(arg) is appended to the object's tt(path) data member;

    itb(FileSystem [const] &operator()(EC &ec = s_errorCode) [const])
       this operator activates passing tt(EC) arguments to member function
        accepting such arguments. By calling this operator without argument
        member functions receive tt(FileSystem's s_errorCode). Alternatively
        another (e.g., local) tt(error_code) object can be specified  which
        will then be passed to members accepting tt(error_code)
        arguments. Example: 
 verb(
    std::error_code ec;
    FileSystem fs;
    fs(ec);
 )
       Using tt(EC) arguments is configured separately for each
        tt(FileSystem) object. The member tt(noEC) can be used to suppress 
        passing  tt(EC) arguments to tt(std::filesystem) functions;
    )

manpagesection(MEMBER FUNCTIONS)

    tt(Type) arguments can be arguments of type tt(FileSystem, Path) or types
from which tt(Path) objects can be constructed (e.g., tt(std::string, char
const *), raw string literal).

    All members can use tt(EC) objects to prevent exceptions being thrown when
the members cannot perform their tasks.

    itemization(
    itb(FileSystem absolute() const)
       returns a tt(FileSystem) object containing the absolute path of the
        calling object's tt(Path), which does not have to exist. Relative
        directory specifications are kept: tt(absolute) simply prefixes the
        current working directory to the calling object's tt(Path);

    itb(FileSystem canonical() const)
       returns a tt(FileSystem) object containing the canonical absolute path
        of the calling object's tt(Path), from which all relative
        specifications have been removed. tt(Path) must refer to an existing
        file system entry;

    itb(bool copy(Type const &dest, FSOptions cpOptions = DEFAULT))
       copies the object's file system entry to tt(dest). It is covered in
        detail in the section bf(COPYING FILE SYSTEM ENTRIES) below;

    itb(uintmax_t count() const)
       returns the number of hard-link counts of the calling tt(FileSystem)
        object. The file system entry must exist;

    itb(char const *c_str() const)
       returns the calling object's tt(PATH) specification as a NTBS;

    itb(static FileSystem cwd([EC &ec]))
       this static member returns the current working directory (cwd). If the
        cwd cannot be determined then an exception is thrown, unless an tt(EC)
        argument is specified, in which case the tt(EC) argument provides
        information about the failure;

    itb(FileSystem destination() const)
       returns a tt(FileSystem) object containing the (symlink) destination of
        the calling object, which must refer to a symlink;

    itb(DirEntry directory() const)
       returns a tt(DirEntry) for the calling object. The calling object does
        not have to refer to a directory, and not even to an existing file
        system entry;

    itb(Ranger<DirIter> dirRange() const)
       returns a pair of directory iterators non-recursively visiting all
        entries referred to by the calling object, which must specify a
        directory name (see also the member tt(recursiveRange)). Example:
 verb(
    for (auto const &entry: fs.dirRange())
        cout << entry << '\n';
 )

    itb(static std::error_code &errorCode())
       this static member returns a reference to tt(FileSystem's) static
        (modifiable) tt(EC) data member. 

    itb(bool exists() const)
       returns tt(true) if the current object's file system entry exists;

    itb(static bool exists(FileStatus status))
       returns tt(true) if tt(status) indicates that the current file system
        entry exists (see also the member tt(status) below);

    itb(std::string extension() const)
       returns the extension (including the initial dot (.) of the calling
        object); 

    itb(FileClock::time_point fcModification() const)
       returns the tt(FileClock::time_point) of the (existing) file system
        entry represented by the calling object;

    itb(std::string filename() const)
       returns the filename (i.e., the path name from which all but the last
        element has been removed). If the calling object doesn't contain a
        filename (as with tt(./) or tt(/)) then and empty tt(string) is
        returned; 

    itb(bool hasExtension() const)
       returns tt(true) if the calling object's tt(Path) has an extension;

    itb(bool hasFilename() const)
       returns tt(true) if the calling object's tt(Path) contains characters
        after its final tt(/) character;

    itb(bool isAbsolute() const)
       returns tt(true) if the calling object's tt(Path) starts with tt(/);

    itb(bool isRelative() const)
       returns tt(true) if the calling object's tt(Path) does not start with
        tt(/); 

    itb(bool knownStatus() const)
       this member only returns tt(false) for
        tt(std::filesystem::file_status{}). The member tt(status) is probably
        more useful: non-existing entries show status values
        tt(FileType::not_found) or tt(FileType::unknown).nl()
       To check for specific statuses the functions+nl()
        tt(bool is_WHATEVER(file_status status)) or+nl()
        tt(bool is_WHATEVER(path const &entry [, EC &ec]))nl()
       can also be used;

    itb(bool mkDir() const)
       returns tt(true) if the (plain) directory name stored in the calling
        oblect could be created. This member does not create nested
        sub-directories, but the directory name specified as the last
        (tt(/)-separated) component of the calling object's tt(Path) is
        created if its parent directories already exist;

    itb(bool mkDir(Type const &reference) const)
       same as the previous member, but the created directory receives the
        same attributes (permissions) as tt(reference);

    itb(bool mkDirs() const)
       returns true if the last component of the  calling object's tt(Path)
        could be created and its parent components could either be created or
        already existed as directories. Only the directories are constructed,
        not their entries. Use the tt(copy) member (see section tt(COPYING
        FILE SYSTEM ENTRIES) below) to copy directories and their file system
        entries; 

    itb(SystemClock::time_point modification() const)
       returns the tt(SystemClock::time_point) of the (existing) file system
        entry represented by the calling object;

    itb(FileSystem [const] &noEC() [const])
       if the calling object uses an tt(EC), then the tt(EC) won't be used
        anymore after calling this member;

    itb(FileSystem parent() const)
       returns a tt(FileSystem) object initialized with the parent tt(Path) of
        the calling object. The tt(parent) is equal to the calling object's
        tt(Path) from which its tt(filename) has been removed (returning an
        empty object if the calling object merely contains `tt(/)');

    itb(Path const &path() const)
       returns the current object's tt(Path) data member. When inserting
        tt(path()) into an tt(ostream) tt(Path) is surrounded by double
        quotes. If that's not required call the tt(string) member;

    itb(Perms permissions() const)
       returns the permissions of the calling object, which must refer to an
        existing file system entry. The returned tt(Perms) value consists of
        bitwise or-ed values of the tt(std::filesystem::perms enum class), but
        can be statically cast to tt(mode_t) values which are used as argument
        to bf(chmod)(2);

    itb(Ranger<[Const]Iter> range() [const])
       returns a pair of iterators visiting all components of the calling
        object's tt(Path).Example:
 verb(
    for (auto const &comp: fs.range())
        cout << comp << '\n';
 )

    itb(FileSystem relative() const)
       returns a copy of the calling object from which an initial `tt(/)' has
        been removed;

    itb(bool remove() const)
       returns tt(true) if the current object's file system entry has been
        removed;

    itb(size_t removeAll() const)
       returns the number of (recursively) removed file system entries
        starting at the calling object's tt(Path). The calling object doesn't
        have to specify a directory;

    itb(bool rename(Type const &newName) const)
       returns tt(true) if the current file system entry could be renamed to
        tt(newName). The calling object's tt(Path) is not altered;

    itb(bool resize(std::uintmax_t size) const)
       returns tt(true) if the current file system entry could be resized to
        tt(size); 

    itb(bool sameAs(Type const &other) const)
       returns tt(true) if tt(other) refers to the same file system entry as
        the calling object. It is called by tt(operator==) as its tt(lhs)
        member; 

    itb(FileSystem &setCwd())
       changes the current process's current working directory to the
        directory specified by the calling object;

    itb(static FileSystem setCwd(Path const &path [, EC &ec]))
       this static member changes the current process's current working
        directory to the directory specified by its tt(Path) argument;

    itb(FileSystem &setExtension(std::string const &ext))
       changes the filename extension of the current object to tt(ext). A dot
        (tt(.)) is used to separate the current object's tt(stem) (see below)
        and the extension. The resulting file name only has a single dot;

    itb(FileSystem &setFilename(std::string const &newName))
       changes the current object's file name (including its extension) to
        tt(newName). If the current object refers to an existing file system
        entry then that file system entry is kept as-is;

    itb(bool setModification(FBB::DateTime const &time))
       changes the modification time of the current file system entry to the
        tt(time) time-specification;

    itb(bool setModification(SystemClock::time_point const &time))
       changes the modification time of the current file system entry to the
        tt(time) time-specification;

    itb(FileSystem [const] &setPermissions(PermType perms, 
        FSOptions opt = RESET) [const])
       changes the permissions of the current file system entry to tt(perms),
        which must be statically castable to tt(Perms). Example:
 verb(
            // change "entry's" permissions to -rw-------
    FileSystem{ "entry" }.setPermissions(0600); 
 )

    itb(bool setType(FileType type, bool destination = true))
       it's unclear what this function is used for. It calls
        tt(filesystem::(symlink_)status), using tt(symlink_status) when called
        as tt(type(false)). It returns tt(false) if tt(type) doesn't match the
        current file system entry referred, but the type itself isn't
        modified;
        
    itb(uintmax_t size() const)
       returns the size in bytes of the current file system entry;

    itb(FileStatus status(bool destination = true) const)
       returns the tt(filesystem::status) of the current file system entry. If
        the current object is a symlink and the symlink's status is requested
        then call tt(status(false));

    itb(FileSystem stem() const)
       returns the file name of the current object without its extension;

    itb(std::string string() const)
       returns the current object's tt(Path) data member as a tt(std::string);

    itb(static FileSystem tmpDir(Type arg [= true]))
       this static member returns the file system's directory which is by
        default used for temporary files. By default tt(tmpDir) uses
        tt(FileSystem::s_errorCode) objct, when calling tt(tmpDir(false)) no
        tt(EC) object is used;

    itb(static FileSystem tmpDir(EC &ec))
       this static member returns the file system's directory  using the
        specified tt(EC) object when determining the temporay directory;

    itb(FileType type(bool destination = true) const)
       returns the tt(FileType) of the current file system entry. If the
        current object refers to a symlink call tt(type(false)) to receive the
        symlink's type.
    )

manpagesection(COPYING FILE SYSTEM ENTRIES)
    The member tt(copy(Type const &dest, FSOptions cpOptions = DEFAULT)'s)
first argument specifies the name of the copied file or directory. It's second
argument specifies the type of the copy-operation. Options can be combined
using binary operators (usually tt(bit_or)). The following combinations are
valid: 
    itemization(
    itt(FILE) - unconditionally copies the current entry to tt(dest);
    itt(FILE | NEW) - the current entry is copied to tt(dest) if tt(dest) 
        does not yet exist; 
    itt(FILE | REPLACE) - the current entry is copied to tt(dest) if tt(dest)
        already exists;
    itt(FILE | UPDATE) - the current entry is only copied to tt(dest) if it is
        younger than tt(dest);
    itt(CP_SYMLINK) - the current entry must be a symlink, tt(dest) may not
        yet exist and becomes a symlink to the same destination as the
        current entry's destination;
    itt(NEW_LINK) - tt(dest) may not yet exist. It becomes a hard-link to the
        current entry. The current object must exist;
    itt(NEW_SYMLINK) - tt(dest) may not yet exist. It becomes a symlink to the
        current entry. If the current entry is itself a symlink then tt(dest)
        becomes a symlink to the current entry, and not to the entry the
        current object refers to. The current object does not have to be an
        existing file system entry;
    itt(RECURSIVE) - the current entry is recursively copied to tt(dest). If
        the current entry isn't a directory then the entry itself is copied as
        if tt(RECURSIVE) was not specified;
    itt(RECURSIVE | CP_SYMLINKS) - like using tt(RECURSIVE) but existing
        symlinks are copied as symlinks;
    itt(RECURSIVE | ONLY_DIRS) - like using tt(RECURSIVE) but only the
        directory structure is copied;
    itt(RECURSIVE | SKIP_SYMLINKS) - like using tt(RECURSIVE) but existing
        symlinks are not copied;
    )

manpagesection(EXAMPLE)
    verbinclude(../../filesystem/driver/main.cc)

manpagefiles()
    em(bobcat/filesystem) - defines the class interface

manpageseealso()
    bf(bobcat)(7), bf(chmod)(2), bf(datetime)(3bobcat), bf(ranger)(3bobcat)

manpagebugs()
    None Reported.

includefile(include/trailer)
