FilePath.h

// FilePath.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2013

#pragma once
#ifndef Ceda_cxUtils_FilePath_H
#define Ceda_cxUtils_FilePath_H

#include "cxUtils.h"
#include "xstring.h"
#include "SubString.h"

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// Functions to extract different components of a given path

/*
The following functions assume forward slashes are used for delimiters in the path

Let the given path be "c:/temp/blah.txt"
*/

cxUtils_API SubString ExtractContainingDirPath(SubString path);                  // "c:/temp"
cxUtils_API SubString ExtractContainingDirName(SubString path);                  // "temp"
cxUtils_API SubString ExtractExtensionFromPath(SubString path);                  // "txt"
cxUtils_API SubString ExtractFilenameWithExtensionFromPath(SubString path);      // "blah.txt"
cxUtils_API SubString ExtractFilenameWithoutExtensionFromPath(SubString path);   // "blah"

// Test whether the given path ends with the given extension. The test is case insensitve.
cxUtils_API bool PathHasExtension(SubString path, SubString extension);

// Example:  "c:/a/b/c/d"   -->  "d"
cxUtils_API SubString ExtractLastDirNameFromDirPath(SubString path);

///////////////////////////////////////////////////////////////////////////////////////////////////

cxUtils_API void WritePathWithBackSlashes(xostream& os, SubString path);

///////////////////////////////////////////////////////////////////////////////////////////////////
// Deprecated

cxUtils_API void ExtractUpperCaseExtensionFromPath(SubString path, xstring& extension);
cxUtils_API void ExtractLowerCaseExtensionFromPath(SubString path, xstring& extension);

// Extract the file component from a full path string
// Eg. "C:\temp\blah.txt" returns "blah.txt"
// Works correctly for both forward slash and back slash delimiters in the path
cxUtils_API xstring ExtractFileFromFullPath(const xstring& path);

cxUtils_API void ExtractLastDirectoryFromPath(const xstring& path, xstring& lastDir);

// path = c:\temp\blah.txt  --->  filename = blah
cxUtils_API bool GetFilenameFromPath(const xstring& path, xstring& filename);

cxUtils_API xstring GetExtensionFromPath(const xstring& path);

// Test whether the given path ends with the given extension. The test is case insensitve.
cxUtils_API bool PathHasExtension(const xstring& path, const xstring& extension);

// Let path2 be path1 with the new extension
cxUtils_API bool ReplaceExtension(SubString path1, SubString extension, xstring& path2);

///////////////////////////////////////////////////////////////////////////////////////////////////
// Making paths

cxUtils_API bool IsAbsolutePath(SubString path);

// Assumes that p1 and p2 use forward slashes to delimit directories.
// Typically returns the string formed by writing p1 then a forward slash then p2.
// If p1 = "." then returns p2
// If p2 begins with ".." then it is removed from the result, together with the last directory in p1.
//   unless p1 begins with ".." also
cxUtils_API xstring MakePath(SubString p1, SubString p2);
cxUtils_API xstring MakePath(SubString p1, SubString p2, SubString p3);
cxUtils_API xstring MakePath(SubString p1, SubString p2, SubString p3, SubString p4);

/*
Let relativePath = p1-p2  (i.e. p1 = p2 + relativePath)

Examples:

          p1                           p2                                relativePath
 -------------------------------------------------------------------------------------------------
  c:/developer/_root_   c:/developer/build_utils/build                   ../../_root_
  c:/developer/_root_   d:/developer/build_utils/build                   c:/developer/_root_
  c:/developer/_root_   c:/developer/_root_                              .
  c:/developer/_root_   c:/developer                                     _root_
*/
cxUtils_API void CalcRelativePath(SubString p1, SubString p2, xstring& relativePath);

// Replace backslashes with forward slashes and remove any trailing slash
cxUtils_API void NormalisePath(xstring& path);

} // namespace ceda

#endif // include guard