// file: $isip/class/shell/Filename/Filename.h
// version: $Id: Filename.h 9209 2003-06-15 03:41:40Z picone $
//

// make sure definitions are only made once
//
#ifndef ISIP_FILENAME
#define ISIP_FILENAME

// isip include files
//
#ifndef ISIP_STRING
#include <String.h>
#endif

// Filename: hold and manipulate the name of a file. note that since this
// class actually holds a filename, we don't want to overload this class
// with a lot of internal data. hence, we implement the operating system
// specific methods as private methods.
//
class Filename : public String {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  // define operating system choices
  //
  enum OS { UNIX = 0, WINDOWS, MACINTOSH,
	    DEF_OS = UNIX };

  // delimiters for a Unix filename
  //
  static const String SLASH;
  static const String DOT;
  static const String UNDERSCORE;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------
  
  // define the default value(s) of the class data:
  //  note we inherit DEF_CAPACITY and DEF_VALUE from SysString class
  //
  
  // default arguments to methods:
  //  note we inherit DEF_PARAM from the String class
  //
  static const String DEF_EXTENSION;
  static const String DEF_SUFFIX;
  static const long DEF_DIR_PRES = 0;
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = 45200;

  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // this section contains data common to all operating systems
  //

  // operating system name
  //
  OS os_d;
  
  // a static memory manager
  //
  static MemoryManager mgr_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // method: setDebug
  //  this method is inherited from the SysString class
  //

  // other debug methods
  //
  boolean debug(const unichar* message) const;

  // method: destructor
  //
  ~Filename() {}

  // method: default constructor
  //
  Filename(long arg = DEF_CAPACITY) {
    setOS(DEF_OS);
    setCapacity(arg);
  }

  // method: copy constructor
  //
  Filename(const Filename& arg) {
    assign(arg);
  }
  
  // method: assign
  //
  boolean assign(const Filename& arg) {
    setOS(arg.os_d);
    return String::assign(arg);
  }

  // method: operator=
  //
   Filename& operator=(const Filename& arg) {
     assign(arg);
     return *this;
  }
  
  // i/o methods:
  //  the sofSize, readData, and writeData methods are inherited from String
  //
  boolean read(Sof& sof, long tag, const String& name = CLASS_NAME);
  boolean write(Sof& sof, long tag, const String& name = CLASS_NAME) const;

  // equality methods:
  //  this method is inherited from the SysString class
  //
  
  // memory management methods:
  //  clear method is inherited from the SysString class
  //

  // method: new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  extensions to required methods
  //
  //---------------------------------------------------------------------------

  // method: constructor
  //
  Filename(const unichar* arg, OS os = DEF_OS) {
    setOS(os);
    String temp(arg);
    assign(temp);
  }

  // method: constructor
  //
  Filename(const String& arg, OS os = DEF_OS) {
    setOS(os);
    assign(arg);
  }
  
  // method: assign
  //  because we need to have an overload of the assign method
  //  for a Filename object, and Filename inherits a SysString,
  //  we must define an overload for SysString as well (or you get
  //  a seg fault).
  //
  boolean assign(const String& arg) {
    return String::assign(arg);
  }

  // method: assign
  //  we also need a String assignment for the same reason
  //
  boolean assign(const unichar* arg) {
    return String::assign(arg);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  set and get methods
  //
  //---------------------------------------------------------------------------
  
  // method: setOS
  //
  boolean setOS(OS os) {
    os_d = os;
    return true;
  }
  
  // method: getOS
  //
  OS getOS() const {
    return os_d;
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  filename parsing methods
  //
  //---------------------------------------------------------------------------

  // define the basic transform command
  //
  boolean transform(const String& new_dir, 
		    const String& new_ext,
		    const String& new_suffix,
		    long dir_preserve = DEF_DIR_PRES);
  
  // method: transform (without a directory)
  //
  boolean transform(const String& new_ext,
		    const String& new_suffix) {
    String old_dir;
    getDir(old_dir);
    return transform(old_dir, new_ext, new_suffix);
  }

  // method: transform (with a filename argument)
  //
  boolean transform(const String& old_name,
		    const String& new_dir, const String& new_ext,
		    const String& new_suffix,
		    long dir_preserve = DEF_DIR_PRES) {
    assign(old_name);
    return transform(new_dir, new_ext, new_suffix, dir_preserve);
  }

  // define a basic command to generate a new, unique filename
  // from an existing one
  //
  boolean transformUniquely();  

  // method: transformUniquely (with the filename as an argument)
  //
  boolean transformUniquely(const String& old_name) {
    assign(old_name);
    return transformUniquely();
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  get methods. note that there is not getSuffix because by definition
  //  a suffix is only added to a filename.
  //
  //---------------------------------------------------------------------------
  
  // method: getDir
  //
  boolean getDir(String& dir) const;

  // method: getBase
  //
  boolean getBase(String& base) const;

  // method: getExt
  //
  boolean getExt(String& ext) const;

  // method: getName
  //
  boolean getName(String& filename) const;
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  temporary filename methods
  //
  //---------------------------------------------------------------------------
  
  // method: makeTemp
  //
  boolean makeTemp() {
    return Integral::makeTemp(*this);
  }

  // method: makeTemp
  //
  boolean makeTemp(const String& basename) {
    return Integral::makeTemp(*this, basename);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  methods to build necessary subdirectories for the output file
  //
  //---------------------------------------------------------------------------
  
  // pathfinding method
  //
  static boolean buildPath(const String& pathname);
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // directory merging methods
  //
  boolean preserveDirName(String& mod_dir, const String& new_dir,
			  const String& old_dir, long dir_preserve);

  // delimiter methods
  //
  boolean getDirDelim(String& arg) const;
  boolean getFileDelim(String& arg) const;

  // UNIX filename parsing methods
  //
  boolean getDirUnix(String& dir) const;
  boolean getBaseUnix(String& base) const;
  boolean getExtUnix(String& ext) const;
  boolean getNameUnix(String& filename) const;
  boolean getDirDelimUnix(String& arg) const;
  boolean getFileDelimUnix(String& arg) const;

  // WINDOWS filename parsing methods
  //
  boolean getBaseWin(String& base) const;
  boolean getExtWin(String& ext) const;
  boolean getDirWin(String& dir) const;
  boolean getNameWin(String& filename) const;
  boolean getDirDelimWin(String& arg) const;
  boolean getFileDelimWin(String& arg) const;

  // MACINTOSH filename parsing methods
  //
  boolean getBaseMac(String& base) const;
  boolean getExtMac(String& ext) const;
  boolean getDirMac(String& dir) const;
  boolean getNameMac(String& filename) const;
  boolean getDirDelimMac(String& arg) const;
  boolean getFileDelimMac(String& arg) const;
};

// end of include file
//
#endif
