class ref name: directory
category-group: files
layer: 9

synopsis.
The directory object is undoubtedly the easiest way to do most any operation on a directory (Microsoft: "folder") in the file system. When making an instance of this object, the directory the object represents need not exist. The object is just a placeholder, a theoretical idea, a representation, until it does a sync().

Directory objects have a close relationship with their parent, directory_address_o . Unfortunately, the programmer desiring to use the directory object will undoubtedly need to learn this class object also. The directory class is actually very little more than the directory address class with a list of a directory's sub-contents added.

The parent, directory_address_o, focuses on the addressing aspects of a directory - that is where it isf found (eg its path). However, it is the directory class where you create, delete, rename, move, and get the contents of a directory (Microsoft: "folder").

description.
The directory object can be used without having to reference an existing directory. Thus it can be used in simulations or for other purposes. If you want the object to contain the contents of an existing directory, sync() should be called. This will build an internal list of all the sub-directories and files for that directory. Unfortunately, this can be an extremely long process. Thus, some alternatives have been provided:

  • You can set the object's mode so that it looks only in the top-level directory (and ignore contents of all sub-directories). This is done by invoking setmode_currdir_only() prior to heavy operations such as sync().
  • You can restrict the maximum "depth" (# of sub-dirs to recurse into) with set_maxdepth(). This takes a 'count_t' parameter that specifies the maximum number of sub-directory levels. A value of 0 is equivalent to calling setmode_currdir_only().
  • You can manually loop thru the contents of a directory using first_item() and next_item(). These functions return the "base name" of the "items" in the current directory (top-level only). Only files and sub-directories are returned, as a string. "." and ".." [inodes] are skipped. A sync() cannot be done while manually fetching single items ("hand mode"). To end this mode, either the last item must be returned (via next_item() call), or invoke close_itemfetch().

member functions (primary)

directory_o()
SIGNATURE: directory_o ()
SYNOPSIS: creates a a new directory object, completely devoid of path or contents.
 

directory_o(directory_o)
SIGNATURE: directory_o (const directory_o &that)
SYNOPSIS: creates a a new directory object; an exact image of the copied directory object "that".
 

operator = (directory_o)
SIGNATURE: const directory_o &operator = (const directory_o &rhs)
SYNOPSIS:
copies exactly the RHS [Right Hand Side] object "rhs". the resultant directory instance is the same as if the copy constructor was used.
 

destructor
SIGNATURE: ~directory_o ()
SYNOPSIS: virtual destructor. instance is wiped out.
 

directory_o(<args>)
SIGNATURE: directory_o (const string_o &s)
SYNOPSIS: create a new directory object. set the directory's address to the value 's' (set the path to s).
 

directory_o(<args>)
SIGNATURE: directory_o (const directory_address_o &rhs_da)
SYNOPSIS:
create a new directory object. set the directory's address to that of "rhs_da". The list of files and subdirectories is not set, and no "sync()" is done. only the path-address part is copied from "rhs_da".
 

assignment operator()
SIGNATURE: const directory_o &operator = (const string_o &s)
SYNOPSIS:
set an existing instance of a directory object to the value given by "s". If the directory object 'auto refresh' flag is set, a sync() will be done, and if the path is valid, the list of files and directories will be fulfilled.
RETURNS: a reference to the current object.
 

operator !=()
SIGNATURE: int operator != (const directory_o &rhs) const
SYNOPSIS: inverse of "==" operator; compares the address of this directory instance to "rhs".
RETURNS:
1: directories are different
0: directories are equivalent
 

operator ==()
SIGNATURE: int operator == (const directory_o &rhs) const
SYNOPSIS: tell if the current directory is the same as "rhs". the converse of directory_o::operator != (rhs).
RETURNS:
1: directories are the same (equivalent)
0: directories are different
 

dirs()
SIGNATURE: const directory_addr_list &dirs () const
SYNOPSIS:
return a reference to the internal list of sub-directories for this directory. This operation is useless unless a sync() has been done for the directory object. Otherwise, the list will be empty. The return type is "directory_addr_list", which is an alias (a typedef) for vlist_o - eg, a "virtual" list of directory addresses (vlist_o is an alias for array_o).
 

files()
SIGNATURE: const file_addr_list &files () const
SYNOPSIS:
return a reference to the list of files contained within this directory. This operation is useless unless and has no meaning unless a sync() has been done for the directory object earlier. Otherwise, the list will be empty. The files can be of any type - as long as they are classified as "files".
 

names()
SIGNATURE: const string_list &names () const
SYNOPSIS:
returns a list of the "names" of everything in the directory. This operation is useless unless and has no meaning unless a sync() has been done earlier. A "name" can be a file or a directory (or other object, such as a link).
 

exists()
SIGNATURE: boolean exists (int *pi = NULL) const
SYNOPSIS:
informs if the current directory really exists. the directory path should have been set prior (otherwise, it will default to a degenerate "", which does not exist).
PARAMETERS

  • pi: error indicator variable. The values this output parameter takes on is the same as that of [L-00] function z_directory_exists(). values:
    0: the directory specified by the object exists, and is a normal, readable directory.
    1: the directory specified by the object does not exist
    2: the path specified by this object is not a directory.
  • RETURNS:
    TRUE: the directory specified in the object is really in the current file system;
    FALSE: otherwise.
     

    exists()
    SIGNATURE: static boolean exists (const string_o &s_dir)
    SYNOPSIS: a "convenience" function, tells if the directgory path specified by "s_dir" is a valid directory.
     

    set_auto_refresh()
    SIGNATURE: void set_auto_refresh ()
    SYNOPSIS:
    a "flavoring" member function. turns on the internal "refresh" flag, which will result in a sync() being done when the directory guts are set to something else, such as by an assignment operator (::operator = (directory_o &)).
     

    unset_auto_refresh()
    SIGNATURE: void unset_auto_refresh ()
    SYNOPSIS:
    a "flavoring" member function. the converse of set_auto_refresh(). Turns off doing auto refreshing. Thus, when assigning a path to a directory object, this will prevent the object from making an inventory of it's contents.
    TRAITS:
    using this function can provide a large performance boost, as the sync() operation is a very heavy, expensive, time-consuming job.
     

    set_name()
    SIGNATURE: int set_name (const string_o &s, int *pi = NULL)
    SYNOPSIS:
    sets the "name" of the directory - that is, it sets the directory's path. The name set_name() was chosen to be the same as that of the file_o class. You can also use set_path(), which was created as an alternative name. That function simply calls this one.
    PARAMETERS

    • s: the directory's path. It is recommended to use the full path, starting from the device root. The syntax to use should match the operating system.
    • pi: [output] error indicator output variable. values:
     

    set_path()
    SIGNATURE: int set_path (const string_o &s, int *pi = NULL)
    SYNOPSIS: this function sets the path of the directory. It is exactly equivalent to set_name() (which see).
     

    reset()
    SIGNATURE: int reset (VOID)
    SYNOPSIS:
    sets the directory object instance to its at-construction state: all internal lists (subdirectories and files) are set to empty, and the auto-refresh flag is set to its default value (TRUE).
    RETURNS: 0
     

    sync()
    SIGNATURE: int sync (int *pie = NULL)
    SYNOPSIS:
    "syncing" a directory means synching the internal data members of the object instance with what's actually there. After synchronization with the actual directory, the object will have a list of files and subdirectories contained in that directory.
    DESCRIPTION:
    this function processes every file and sub-directory contained in the directory tree contained within the current directory. A sync() cannot be done if the object is in "manual mode" (also known as "single-fetch" mode). This mode is initiated by invoking first_item() and terminates when the last item is fetched, or close_itemfetch() is called.
    TRAITS:
    Since this function is CPU-intensive, this operation should be avoided if possible. It can be disabled by calling unset_auto_refresh() prior to its invocation.
     

    RETURNS:
    0: all ok; did the sync
    1: directory not valid
    -1: error occured
     

    setto_current()
    SIGNATURE: int setto_current (VOID)
    SYNOPSIS: sets the directory object to the current directory of the main program.
     

    clone()
    SIGNATURE: directory_o *clone () const
    SYNOPSIS: creates a new instance of a directory object, which is a clone of the current object.
     

    create()
    SIGNATURE: int create (int *pe = NULL)
    SYNOPSIS:
    creates a new directory in the existing file system. the directory path must have been specified prior in order for this function to create a directory.
     

    remove()
    SIGNATURE: int remove (boolean kill_always = TRUE, int *pe = NULL)
    SYNOPSIS: deletes the directory specified by the object's path-address.
     

    rename()
    SIGNATURE: int rename (const string_o &new_name, int *pe = NULL)
    SYNOPSIS:
    renames the curent directory to "new_name". the object's directory address must be set and valid, and the target name ("new_name") must be a simple name. This function DOES NOT MOVE the directory to a new location (use "relocate()" for that).
    PARAMETERS

    • new_name: new name for the directory. the string must be `a "simple" name, and valid under the rules of the operating system.
    • pe - error indicator output variable. values:
      0: rename successful
      1: directory separator found in string (not allowed)
      2: curr directory's name not set; can't rename w/out name
      3: error occured during rename attempt (perhaps target name already exists?)
     

    relocate()
    SIGNATURE: int relocate (const directory_address_o &target, int *pe = NULL)
    SYNOPSIS: moves the directory to the address given by "target", which must be a valid directory on the current file system.
    TRAITS: this function CURRENTLY DOES NOT WORK - DO NOT USE! (disabled)
     

    note.
    The idea of recursion is natural for a directory in a file system. The directory class (actually, its parent directory address) represents the extreme example of an address being recursive. Each directory component (except for root) is contained in another directory component. This approach is natural for computer disk drive (or other storage medium) file systems. Almost all computer file systems are based on the principal of recursive directories.

    As mentioned earlier, you should look first at the directory_address_o object for functions relating to mapping a directory path or component of the path to a string.

    examples.
    The following example shows how to set a directory path and cycle through its contents.

    #include "z_directory.h"
    
    void analyze_dir (const directory_o &d);
    
    
    void main (int argc, char **argv)
    {
        directory_o d("C:\\");              // create dir obj and set the path
        d.set_name ("C:\\");                // alternative way to set the path
        d.sync();
        analyze_dir(d);
    }
    
    
    void analyze_dir (const directory_o &d)
    {
        count_t n = 0;
        directory_o &rd = (directory_o &) d;
    
        const file_addr_list &fa = rd.files();
        cursor_o<file_address_o> cu_f ( (vlist_o<file_address_o> &) fa );
    
        std::cout << "files:\n";
    
        //..........................................................
        // fetch and display the files in this directory
        //..........................................................
        for (n = 0, cu_f.first(); cu_f.ok(); n++, cu_f++)
        {
            const file_address_o &fnow = cu_f.fetch();
            std::cout << "\t[" << n << "]: " << fnow << endl;
        }
    
        std::cout << "\"" << d << "\" has " << n << " files.\n\n";
    
    
        //..........................................................
        // fetch and display the sub-directories in this directory
        //..........................................................
        const directory_addr_list &da = rd.dirs();
        cursor_o<directory_address_o> cu_d ((list_o<directory_address_o> &) da);
    
        std::cout << "directories:\n";
    
        for (n = 0, cu_d.first(); cu_d.ok(); n ++, cu_d ++)
        {
            const directory_address_o &dnow = cu_d.fetch();
            std::cout << "\t[" << n << "]: " << dnow << endl;
        }
    
        std::cout << "\"" << d << "\" has " << n << " sub-directories.\n\n";
    }