/*
 * --- GSMP-COPYRIGHT-NOTE-BEGIN ---
 * 
 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
 * Please add additional copyright information _after_ the line containing
 * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
 * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
 * 
 * GSMP: utility/src/File.cc
 * General Sound Manipulation Program is Copyright (C) 2000 - 2004
 *   Valentin Ziegler and René Rebe
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * --- GSMP-COPYRIGHT-NOTE-END ---
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <iostream>

#include "File.hh"

Utility::File::File () {
  c_stat_valid = false;
}

Utility::File::File (const std::string& str) {
  filename = str;
  c_stat_valid = false;
}

Utility::File::~File () {
}

void Utility::File::SetFile (const std::string& str) {
  if (str != filename) {
    reset();
    filename = str;
  }
}

const std::string& Utility::File::Dirname ()
{
  // this is slightly unoptimal if we really do not have a dirname
  // but since this is rare we keep this simple
  if (dirname == "")
    updateDirBaseExt ();
  return dirname;
}

const std::string& Utility::File::Basename ()
{
  // we always have a basename - a leading dot forms a hidden Unix file ....
  if (basename == "")
    updateDirBaseExt ();
  return basename;
}

std::string Utility::File::BasenameWOExtension ()
{
  // we always have a basename - a leading dot forms a hidden Unix file ....
  if (basename == "")
    updateDirBaseExt ();

  std::string::size_type idx = extension.size(); if (idx) ++idx;
  std::string bwoe = basename.substr(0, basename.size() - idx);
  return bwoe;
}

const std::string& Utility::File::Extension ()
{
  // this is slightly unoptimal if we really do not have an extension
  // but since this is rare we keep this simple
  if (extension == "")
    updateDirBaseExt ();
  return extension;
}

const Utility::FileType Utility::File::Type ()
{
  updateStat();
  return FileType(c_stat.st_mode);
}

void Utility::File::reset () {
  basename.clear();
  extension.clear();
  c_stat_valid = false;
}

bool Utility::File::updateStat () {
  if (c_stat_valid)
    return true;
  
  return stat (filename.c_str(), &c_stat) == 0;
}

void Utility::File::updateDirBaseExt () {
  // parse the filename extension
  std::string::size_type idx_ext = filename.rfind ('.');
  std::string::size_type idx_base = filename.rfind ('/');
  
  // ignore leading dots - they mark hidden Unix files ...
  if (idx_ext && idx_ext != std::string::npos) {
    extension = filename.substr (idx_ext + 1);
  }
  else {
    extension.clear ();
  }

  if (idx_base == std::string::npos) {
    dirname.clear ();
    basename = filename.substr (0, std::string::npos);
  }
  else {
    dirname = filename.substr (0, idx_base);
    basename = filename.substr (idx_base + 1, std::string::npos);
  }
}

std::ostream& Utility::operator<< (std::ostream& os, const File& file) {
  os << file.Name ();
  return os;
}
