text: /** @file
    Helper functions for mangling file names in UDF/ECMA-167 file systems.
  
    Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
  
    SPDX-License-Identifier: BSD-2-Clause-Patent
  **/
  
  #include "Udf.h"
  
  /**
    Trim the leading and trailing spaces for a give Unicode string.
  
    @param[in]  String              The Unicode string to trim.
  
    @return  A pointer to the trimmed string.
  
  **/
  CHAR16 *
  TrimString (
    IN CHAR16  *String
    )
  {
    CHAR16  *TempString;
  
    for ( ; *String != L'\0' && *String == L' '; String++) {
    }
  
    TempString = String + StrLen (String) - 1;
    while ((TempString >= String) && (*TempString == L' ')) {
      TempString--;
    }
  
    *(TempString + 1) = L'\0';
  
    return String;
  }
  
  /**
    Replace the content of a Unicode string with the content of another Unicode
    string.
  
    @param[in]  Destination         A pointer to a Unicode string.
    @param[in]  Source              A pointer to a Unicode string.
  
  **/
  VOID
  ReplaceLeft (
    IN CHAR16        *Destination,
    IN CONST CHAR16  *Source
    )
  {
    CONST CHAR16  *EndString;
  
    EndString = Source + StrLen (Source);
    while (Source <= EndString) {
      *Destination++ = *Source++;
    }
  }
  
  /**
    Remove one or more consecutive backslashes starting from the second character
    of a given Unicode string.
  
    @param[in]  String              A pointer to a Unicode string.
  
    @return  A pointer to the modified string.
  
  **/
  CHAR16 *
  ExcludeTrailingBackslashes (
    IN CHAR16  *String
    )
  {
    CHAR16  *TempString;
  
    switch (*(String + 1)) {
      case L'\\':
        break;
      case L'\0':
      default:
        String++;
        goto Exit;
    }
  
    TempString = String;
    while (*TempString != L'\0' && *TempString == L'\\') {
      TempString++;
    }
  
    if (TempString - 1 > String) {
      ReplaceLeft (String + 1, TempString);
    }
  
    String++;
  
  Exit:
    return String;
  }
  
  /**
    Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
  
    @param[in] FileName Filename.
  
    @retval The mangled Filename.
  
  **/
  CHAR16 *
  MangleFileName (
    IN CHAR16  *FileName
    )
  {
    CHAR16  *FileNameSavedPointer;
    CHAR16  *TempFileName;
    UINTN   BackslashesNo;
  
    if ((FileName == NULL) || (*FileName == L'\0')) {
      FileName = NULL;
      goto Exit;
    }
  
    FileName = TrimString (FileName);
    if (*FileName == L'\0') {
      goto Exit;
    }
  
    if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
      FileName[StrLen (FileName) - 1] = L'\0';
    }
  
    FileNameSavedPointer = FileName;
  
    if (FileName[0] == L'.') {
      if (FileName[1] == L'.') {
        if (FileName[2] == L'\0') {
          goto Exit;
        } else {
          FileName += 2;
        }
      } else if (FileName[1] == L'\0') {
        goto Exit;
      }
    }
  
    while (*FileName != L'\0') {
      if (*FileName == L'\\') {
        FileName = ExcludeTrailingBackslashes (FileName);
      } else if (*FileName == L'.') {
        switch (*(FileName + 1)) {
          case L'\0':
            *FileName = L'\0';
            break;
          case L'\\':
            TempFileName = FileName + 1;
            TempFileName = ExcludeTrailingBackslashes (TempFileName);
            ReplaceLeft (FileName, TempFileName);
            break;
          case '.':
            if ((*(FileName - 1) != L'\\') && ((*(FileName + 2) != L'\\') ||
                                               (*(FileName + 2) != L'\0')))
            {
              FileName++;
              continue;
            }
  
            BackslashesNo = 0;
            TempFileName  = FileName - 1;
            while (TempFileName >= FileNameSavedPointer) {
              if (*TempFileName == L'\\') {
                if (++BackslashesNo == 2) {
                  break;
                }
              }
  
              TempFileName--;
            }
  
            TempFileName++;
  
            if ((*TempFileName == L'.') && (*(TempFileName + 1) == L'.')) {
              FileName += 2;
            } else {
              if (*(FileName + 2) != L'\0') {
                ReplaceLeft (TempFileName, FileName + 3);
                if (*(TempFileName - 1) == L'\\') {
                  FileName = TempFileName;
                  ExcludeTrailingBackslashes (TempFileName - 1);
                  TempFileName = FileName;
                }
              } else {
                *TempFileName = L'\0';
              }
  
              FileName = TempFileName;
            }
  
            break;
          default:
            FileName++;
        }
      } else {
        FileName++;
      }
    }
  
    FileName = FileNameSavedPointer;
    if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
      FileName[StrLen (FileName) - 1] = L'\0';
    }
  
  Exit:
    return FileName;
  }
  