/** @file
Functions useful to operate file directories by parsing file path.

Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

**/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CommonLib.h"
#include "OsPath.h"

//
// Functions implementations
//

#if 0
  //
  // BUGBUG: Not fully implemented yet.
  //
CHAR8*
OsPathDirName (
  IN CHAR8    *FilePath
  )
/*++

Routine Description:

  This function returns the directory path which contains the particular path.
  Some examples:
    "a/b/c"  -> "a/b"
    "a/b/c/" -> "a/b"
    "a"      -> "."
    "."      -> ".."
    "/"      -> NULL

  This function does not check for the existence of the file.

  The caller must free the string returned.

Arguments:

  FilePath     Path name of file to get the parent directory for.

Returns:

  NULL if error

--*/
{
  CHAR8 *Return;
  CHAR8 *Pos;
  CHAR8 Char;
  UINTN Length;
  INTN  Offset;

  Length = strlen (FilePath);

  if (Length == 0) {
    return NULL;
  }

  //
  // Check for the root directory case
  //
  if (
    (Length == 3 && isalpha (FilePath[0]) && (strcmp(FilePath + 1, ":\\") == 0)) ||
    (strcmp(FilePath, "/") == 0)
    ) {
    return NULL;
  }

  //
  // If the path ends with a path separator, then just append ".."
  //
  Char = FilePath[Length - 1];
  if (Char == '/' || Char == '\\') {
    return OsPathJoin (FilePath, "..");
  }

  //
  // 
  //
  for (Offset = Length; Offset > 0; Offset--) {
    if ((Return[Offset] == '/') || (Return[Offset] == '\\')) {
      Return[Offset] = '\0';
      return Return;
    }
  }
}
#endif


#if 0
  //
  // BUGBUG: Not fully implemented yet.
  //
VOID
OsPathNormPathInPlace (
  IN CHAR8    *Path
  )
/*++

Routine Description:

  This function returns the directory path which contains the particular path.
  Some examples:
    "a/b/../c" -> "a/c"
    "a/b//c"   -> "a/b/c"
    "a/./b"    -> "a/b"

  This function does not check for the existence of the file.

Arguments:

  Path     Path name of file to normalize

Returns:

  The string is altered in place.

--*/
{
  CHAR8   *Pos;
  INTN    Offset;
  BOOLEAN TryAgain;
  UINTN   Length;
  UINTN   Remaining;
  UINTN   SubLength;

  do {
    TryAgain = FALSE;
    Length = strlen (Path);

    for (Offset = 0; Offset < Length; Offset++) {
      Remaining = Length - Offset;

      //
      // Collapse '//' -> '/'
      //
      if (
          (Remaining >= 2) &&
          ((Offset > 0) || (Path[0] != '\\')) &&
          IsDirSep (Path[Offset]) && IsDirSep (Path[Offset + 1])
         ) {
        memmove (&Path[Offset], &Path[Offset + 1], Remaining);
        TryAgain = TRUE;
        break;
      }

      //
      // Collapse '/./' -> '/'
      //
      if ((Remaining >= 3) && IsDirSep (Path[Offset]) &&
           (Path[Offset + 1] == '.') && IsDirSep (Path[Offset + 2])
         ) {
        memmove (&Path[Offset], &Path[Offset + 1], Remaining);
        TryAgain = TRUE;
        break;
      }

      //
      // Collapse 'a/../b' -> 'b'
      //
      // BUGBUG: Not implemented yet

    }

  } while (TryAgain);

  Return = CloneString (FilePath);
  if (Return == NULL) {
    return NULL;
  }

  Length = strlen (Return);

  //
  // Check for the root directory case
  //
  if (
    (Length == 3 && isalpha (Return[0]) && (strcmp(Return + 1, ":\\") == 0)) ||
    (strcmp(Return, "/") == 0)
    ) {
    free (Return);
    return NULL;
  }

  //
  // 
  //
  for (Offset = Length; Offset > 0; Offset--) {
    if ((Return[Offset] == '/') || (Return[Offset] == '\\')) {
      Return[Offset] = '\0';
      return Return;
    }
  }
}
#endif


CHAR8*
OsPathPeerFilePath (
  IN CHAR8    *OldPath,
  IN CHAR8    *Peer
  )
/*++

Routine Description:

  This function replaces the final portion of a path with an alternative
  'peer' filename.  For example:
    "a/b/../c", "peer" -> "a/b/../peer"
    "a/b/", "peer"     -> "a/b/peer"
    "/a", "peer"       -> "/peer"
    "a", "peer"        -> "peer"

  This function does not check for the existence of the file.

Arguments:

  OldPath     Path name of replace the final segment
  Peer        The new path name to concatinate to become the peer path

Returns:

  A CHAR8* string, which must be freed by the caller

--*/
{
  CHAR8 *Result;
  INTN    Offset;

  Result = (CHAR8 *) malloc (strlen (OldPath) + strlen (Peer) + 1);
  if (Result == NULL) {
    return NULL;
  }

  strcpy (Result, OldPath);

  //
  // Search for the last '/' or '\' in the string.  If found, replace
  // everything following it with Peer
  //
  for (Offset = strlen (Result); Offset >= 0; Offset--) {
    if ((Result[Offset] == '/') || (Result[Offset] == '\\')) {
      Result[Offset + 1] = '\0';
      strcat (Result, Peer);
      return Result;
    }
  }

  //
  // Neither a '/' nor a '\' was found.  Therefore, we simply return Peer.
  //
  strcpy (Result, Peer);
  return Result;
}


BOOLEAN
OsPathExists (
  IN CHAR8    *InputFileName
  )
/*++

Routine Description:

  Checks if a file exists

Arguments:

  InputFileName     The name of the file to check for existence

Returns:

  TRUE              The file exists
  FALSE             The file does not exist

--*/
{
  FILE    *InputFile;
  InputFile = fopen (LongFilePath (InputFileName), "rb");
  if (InputFile == NULL) {
    return FALSE;
  } else {
    fclose (InputFile);
    return TRUE;
  }
}



