//=-- MSFilename.h - Class for managing filenames ----------------------------=
//
//  This class automatically dereferences ~'s for users when it is converted to a const char *.
//
//=---------------------------------------------------------------------------=
//  This file is copyright (c) 1997-1999 Chris Lattner
//=---------------------------------------------------------------------------=

#include <string.h>     // strlen, memcpy, strchr...
#include "MSFilename.h"
#include "Date.h"
#include "PlatformAbstraction.h"

#include <sys/types.h>       // Needed for sys/stat.h
#include <sys/stat.h>        // stat


// DecodeFilename - Decode filename from a possible tilde representation.
// For example, convert ~sabre to /home/sabre or ~/.MagicStats to
// /home/sabre/.MagicStats/ etc.
//
String MSFilename::DecodeFilename(const char *Data) {
  String Result(Data);
  PlatformAbstraction::DecodeFilename(Result);
  return Result;
}

// EvaluateTokens - Because the output filename may take to form 
// "OutputManager%d.html", we must now replace all occurances of %d with the 
// current numeric date.
//
MSFilename MSFilename::EvaluateTokens(const Date &D) const {
  String DayDate, MonthDate, YearDate, Temp;
  int i = 0;
  
  D.strftime(DayDate  , "%Y%m%d");
  D.strftime(MonthDate, "%Y%m");
  D.strftime(YearDate , "%Y");

  String ThisFN = DecodedFilename;
  
  i = ThisFN.strchr('%', i);
  while (i != -1) {
    switch (ThisFN[i+1]) {
    case 'd':
    case 'D':
      Temp = ThisFN;                         // Handle %d/%D
      ThisFN.Left(i);
      Temp.Right(Temp.Length()-i-2);
      ThisFN.cat(DayDate);
      ThisFN.cat(Temp);
      break;
      
    case 'm':
    case 'M':
      Temp = ThisFN;                         // Handle %m/%M
      ThisFN.Left(i);
      Temp.Right(Temp.Length()-i-2);
      ThisFN.cat(MonthDate);
      ThisFN.cat(Temp);
      break;
      
    case 'y':
    case 'Y':
      Temp = ThisFN;                         // Handle %m/%M
      ThisFN.Left(i);
      Temp.Right(Temp.Length()-i-2);
      ThisFN.cat(YearDate);
      ThisFN.cat(Temp);
      break;

    case '%':                                // Handle %%
      Temp = ThisFN;
      ThisFN.Left(i);
      Temp.Right(Temp.Length()-i-1);
      ThisFN.cat(Temp);
      i++;
      break;
      
    default:
      cout << "Unrecognized token in output filename (%" << ThisFN[i+1] << "), ignoring..."
           << endl;
    }
    
    i = ThisFN.strchr('%', i);
  }

  return ThisFN;
}

// FilenamePortion - Return the part of this filename that corresponds to the
// filename of the file, without the directory prepended to it.
//
String MSFilename::FilenamePortion() const {
  String Filename = DecodedFilename;

  int SlashIdx  = Filename.strrchr(PlatformAbstraction::DirectorySeperator);
  if (SlashIdx != -1) 
    Filename.Right(Filename.Length()-SlashIdx-1);
  return Filename;
}

// DirectoryPortion - Returns the part of this filename that corresponds to
// the directory that the file resides in.
//
String MSFilename::DirectoryPortion() const {
  String DirName = DecodedFilename;

  int SlashIdx  = DirName.strrchr(PlatformAbstraction::DirectorySeperator);
  if (SlashIdx != -1) 
    DirName.Left(SlashIdx);
  return DirName;
}

// Exists - Returns true if the file or directory corresponding to this name 
// exists...
//
int MSFilename::Exists() const {
  struct stat StatBuf;
  if (!Valid()) return 0;

  return !stat(DecodedFilename, &StatBuf);
}

// Valid - Returns true if the filename is valid.  Currently, this returns 
// false if the filename has a zero length.
//
int MSFilename::Valid() const {
  return DecodedFilename.Length() != 0;
}

