//===- Path.cpp -----------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/Support/FileSystem.h"
#include "mcld/Support/Path.h"
#include <llvm/ADT/StringRef.h>

#include <locale>
#include <stdio.h>
#include <string.h>

#include <iostream>

using namespace mcld;
using namespace mcld::sys::fs;

//===--------------------------------------------------------------------===//
// Path
Path::Path()
  : m_PathName() {
}

Path::Path(const Path::ValueType* s )
  : m_PathName(s) {
}

Path::Path(const Path::StringType &s )
  : m_PathName(s) {
}

Path::Path(const Path& pCopy)
 : m_PathName(pCopy.m_PathName) {
}

Path::~Path()
{
}

bool Path::isFromRoot() const
{
  if (m_PathName.empty())
    return false;
  return (separator == m_PathName[0]);
}

bool Path::isFromPWD() const
{
  if (2 > m_PathName.size())
    return false;
  return ('.' == m_PathName[0] && separator == m_PathName[1]);
}

Path& Path::assign(const Path::StringType &s)
{
  m_PathName.assign(s);
  return *this;
}

Path& Path::assign(const Path::ValueType* s, unsigned int length)
{
  if (0 == s || 0 == length)
    assert(0 && "assign a null or empty string to Path");
  m_PathName.assign(s, length);
  return *this;
}

//a,/b a/,b a/,b/ a,b is a/b
Path& Path::append(const Path& pPath)
{
  //first path is a/,second path is /b
  if(m_PathName[m_PathName.length()-1] == separator &&
     pPath.native()[0] == separator) {
    unsigned int old_size = m_PathName.size()-1;
    unsigned int new_size = old_size + pPath.native().size();

    m_PathName.resize(new_size);
    strcpy(const_cast<char*>(m_PathName.data()+old_size), pPath.native().data());
  }
  //first path is a,second path is b
  else if(this->string()[this->native().size()-1] != separator &&
          pPath.string()[0] != separator) {
    m_PathName.append("/");
    m_PathName.append(pPath.native());
  }
  // a/,b or a,/b just append
  else {
    m_PathName.append(pPath.native());
  }
  return *this;
}

bool Path::empty() const
{
  return m_PathName.empty();
}

std::string Path::string() const
{
  return m_PathName;
}

Path::StringType Path::generic_string() const
{
  std::string result = m_PathName;
  detail::canonicalize(result);
  return result;
}

bool Path::canonicalize()
{
  return detail::canonicalize(m_PathName);
}

Path::StringType::size_type Path::m_append_separator_if_needed()
{
  if (!m_PathName.empty() &&
#ifdef LLVM_ON_WIN32
      *(m_PathName.end()-1) != colon &&
#endif
      !is_separator(*(m_PathName.end()-1))) {
        StringType::size_type tmp(m_PathName.size());
        m_PathName += preferred_separator;
        return tmp;
  }
  return 0;
}

void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos)
{
  size_t begin=pSepPos;
  // skip '/'
  while(separator == m_PathName[pSepPos])
    ++pSepPos;

  if(begin!=pSepPos)
    m_PathName.erase(begin+1,pSepPos-begin-1);
}

Path Path::stem() const
{
  size_t begin_pos = m_PathName.find_last_of(separator)+1;
  size_t end_pos   = m_PathName.find_first_of(".", begin_pos);
  Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
  return result_path;
}

Path Path::extension() const
{
  size_t begin_pos = m_PathName.find_last_of('.');
  Path result_path(m_PathName.substr(begin_pos));
  return result_path;
}

//===--------------------------------------------------------------------===//
// non-member functions
bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
{
  return (pLHS.generic_string()==pRHS.generic_string());
}

bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
{
  return !(pLHS==pRHS);
}

bool mcld::sys::fs::is_separator(char value)
{
  return (value == separator
#ifdef LLVM_ON_WIN32
          || value == preferred_separator
#endif
          );
}

bool mcld::sys::fs::exists(const Path &pPath)
{
  FileStatus pFileStatus;
  detail::status(pPath, pFileStatus);
  return exists(pFileStatus);
}

bool mcld::sys::fs::is_directory(const Path &pPath)
{
  FileStatus pFileStatus;
  detail::status(pPath, pFileStatus);
  return is_directory(pFileStatus);
}

std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS,
                                        const Path& pPath)
{
  return pOS << pPath.native();
}

std::istream &mcld::sys::fs::operator>>(std::istream& pOS,
                                        Path& pPath)
{
  return pOS >> pPath.native();
}

llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS,
                                             const Path &pPath)
{
  return pOS << pPath.native();
}

