| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- // Better Streaming Assets, Piotr Gwiazdowski <gwiazdorrr+github at gmail.com>, 2017
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace Better.StreamingAssets
- {
- public static partial class PathUtil
- {
- private enum NormalizeState
- {
- PrevSlash,
- PrevDot,
- PrevDoubleDot,
- NothingSpecial,
- }
- public static bool IsDirectorySeparator(char c)
- {
- return c == '/' || c == '\\';
- }
- public static string FixTrailingDirectorySeparators(string path)
- {
- if ( path.Length >= 2 )
- {
- var lastChar = path[path.Length - 1];
- var prevChar = path[path.Length - 2];
- if ( PathUtil.IsDirectorySeparator(lastChar) && PathUtil.IsDirectorySeparator(prevChar) )
- {
- return path.TrimEnd('\\', '/') + lastChar;
- }
- }
- return path;
- }
-
- public static string CombineSlash(string a, string b)
- {
- if ( a == null )
- throw new ArgumentNullException("a");
- if ( b == null )
- throw new ArgumentNullException("b");
- if ( string.IsNullOrEmpty(b) )
- return a;
- if ( string.IsNullOrEmpty(a) )
- return b;
- if (b[0] == '/')
- return b;
- if ( IsDirectorySeparator(a[a.Length -1]) )
- return a + b;
- else
- return a + '/' + b;
- }
- public static string NormalizeRelativePath(string relative, bool forceTrailingSlash = false)
- {
- if (string.IsNullOrEmpty(relative))
- throw new System.ArgumentException("Empty or null", "relative");
- StringBuilder output = new StringBuilder(relative.Length);
- NormalizeState state = NormalizeState.PrevSlash;
- output.Append('/');
- int startIndex = 0;
- int lastIndexPlus1 = relative.Length;
- if ( relative[0] == '"' && relative.Length > 2 && relative[relative.Length - 1] == '"')
- {
- startIndex++;
- lastIndexPlus1--;
- }
- for ( int i = startIndex; i <= lastIndexPlus1; ++i )
- {
- if (i == lastIndexPlus1 || relative[i] == '/' || relative[i] == '\\')
- {
- if ( state == NormalizeState.PrevSlash || state == NormalizeState.PrevDot )
- {
- // do nothing
- }
- else if ( state == NormalizeState.PrevDoubleDot )
- {
- if ( output.Length == 1 )
- throw new System.IO.IOException("Invalid path: double dot error (before " + i + ")");
- // on level up!
- int j;
- for ( j = output.Length - 2; j >= 0 && output[j] != '/'; --j)
- {
- }
- output.Remove(j + 1, output.Length - j - 1);
- }
- else if ( i < lastIndexPlus1 || forceTrailingSlash )
- {
- output.Append('/');
- }
- state = NormalizeState.PrevSlash;
- }
- else if ( relative[i] == '.' )
- {
- if ( state == NormalizeState.PrevSlash )
- {
- state = NormalizeState.PrevDot;
- }
- else if ( state == NormalizeState.PrevDot )
- {
- state = NormalizeState.PrevDoubleDot;
- }
- else if ( state == NormalizeState.PrevDoubleDot )
- {
- state = NormalizeState.NothingSpecial;
- output.Append("...");
- }
- else
- {
- output.Append('.');
- }
- }
- else
- {
- if ( state == NormalizeState.PrevDot )
- {
- output.Append('.');
- }
- else if ( state == NormalizeState.PrevDoubleDot )
- {
- output.Append("..");
- }
- if (!IsValidCharacter(relative[i]))
- throw new System.IO.IOException("Invalid characters");
- output.Append(relative[i]);
- state = NormalizeState.NothingSpecial;
- }
- }
- return output.ToString();
- }
- public static bool IsValidCharacter(char c)
- {
- if (c == '\"' || c == '<' || c == '>' || c == '|' || c < 32 || c == ':' || c == '*' || c == '?')
- return false;
- return true;
- }
- public static Regex WildcardToRegex(string pattern)
- {
- return new Regex("^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", RegexOptions.IgnoreCase);
- }
- }
- }
|