Exemplo n.º 1
0
        /// <summary>
        /// Returns true if the string is full path, like <c>@"C:\a\b.txt"</c> or <c>@"C:"</c> or <c>@"\\server\share\..."</c>:
        /// </summary>
        /// <param name="path">Any string. Can be null.</param>
        /// <remarks>
        /// Returns true if <i>path</i> matches one of these wildcard patterns:
        /// - <c>@"?:\*"</c> - local path, like <c>@"C:\a\b.txt"</c>. Here ? is A-Z, a-z.
        /// - <c>@"?:"</c> - drive name, like <c>@"C:"</c>. Here ? is A-Z, a-z.
        /// - <c>@"\\*"</c> - network path, like <c>@"\\server\share\..."</c>. Or has prefix <c>@"\\?\"</c>.
        ///
        /// Supports <c>'/'</c> characters too.
        ///
        /// Supports only file-system paths. Returns false if path is URL (<see cref="IsUrl"/>) or starts with <c>"::"</c>.
        ///
        /// If path starts with <c>"%environmentVariable%"</c>, shows warning and returns false. You should at first expand environment variables with <see cref="ExpandEnvVar"/> or instead use <see cref="IsFullPathExpandEnvVar"/>.
        /// </remarks>
        public static bool IsFullPath(string path)
        {
            var s   = path;
            int len = s.Lenn();

            if (len >= 2)
            {
                if (s[1] == ':' && AChar.IsAsciiAlpha(s[0]))
                {
                    return(len == 2 || IsSepChar_(s[2]));
                    //info: returns false if eg "c:abc" which means "abc" in current directory of drive "c:"
                }
                switch (s[0])
                {
                case '\\':
                case '/':
                    return(IsSepChar_(s[1]));

                case '%':
#if true
                    if (!ExpandEnvVar(s).Starts('%'))
                    {
                        AWarning.Write("Path starts with %environmentVariable%. Use APath.IsFullPathExpandEnvVar instead.");
                    }
#else
                    s = ExpandEnvVar(s);                     //quite fast. 70% slower than just EnvVarExists_, but reliable.
                    return(!s.Starts('%') && IsFullPath(s));
#endif
                    break;
                }
            }

            return(false);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns true if ends with ':' preceded by a drive letter, like "C:" or "more\C:", but not like "moreC:".
        /// </summary>
        /// <param name="s">Can be null.</param>
        /// <param name="length">Use when want to check drive at a middle, not at the end. Eg returns true if s is <c>@"C:\more"</c> and length is 2.</param>
        static bool _EndsWithDriveWithoutSep(string s, int length = -1)
        {
            if (s == null)
            {
                return(false);
            }
            int i = ((length < 0) ? s.Length : length) - 1;

            if (i < 1 || s[i] != ':')
            {
                return(false);
            }
            if (!AChar.IsAsciiAlpha(s[--i]))
            {
                return(false);
            }
            if (i > 0 && !IsSepChar_(s[i - 1]))
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the length of the URL protocol name (also known as URI scheme) in string, including ':'.
        /// If the string does not start with a protocol name, returns 0.
        /// </summary>
        /// <param name="s">A URL or path or any string. Can be null.</param>
        /// <remarks>
        /// URL examples: <c>"http:"</c> (returns 5), <c>"http://www.x.com"</c> (returns 5), <c>"file:///path"</c> (returns 5), <c>"shell:etc"</c> (returns 6).
        ///
        /// The protocol can be unknown. The function just checks string format, which is an ASCII alpha character followed by one or more ASCII alpha-numeric, '.', '-', '+' characters, followed by ':' character.
        /// </remarks>
        public static int GetUrlProtocolLength(string s)
        {
            int len = (s == null) ? 0 : s.Length;

            if (len > 2 && AChar.IsAsciiAlpha(s[0]) && s[1] != ':')
            {
                for (int i = 1; i < len; i++)
                {
                    var c = s[i];
                    if (c == ':')
                    {
                        return(i + 1);
                    }
                    if (!(AChar.IsAsciiAlphaDigit(c) || c == '.' || c == '-' || c == '+'))
                    {
                        break;
                    }
                }
            }
            return(0);
            //info: API PathIsURL lies, like most shlwapi.dll functions.
        }
Exemplo n.º 4
0
 /// <summary>
 /// Returns true if pathOrFilename looks like a DOS filename or path.
 /// Examples: <c>"abcde~12"</c>, <c>"abcde~12.txt"</c>, <c>@"c:\path\abcde~12.txt"</c>, <c>"c:\abcde~12\path"</c>.
 /// </summary>
 /// <param name="s">Can be null.</param>
 internal static bool IsPossiblyDos_(string s)
 {
     //AOutput.Write(s);
     if (s != null && s.Length >= 8)
     {
         for (int i = 0; (i = s.IndexOf('~', i + 1)) > 0;)
         {
             int j = i + 1, k = 0;
             for (; k < 6 && j < s.Length; k++, j++)
             {
                 if (!AChar.IsAsciiDigit(s[j]))
                 {
                     break;
                 }
             }
             if (k == 0)
             {
                 continue;
             }
             char c = j < s.Length ? s[j] : '\\';
             if (c == '\\' || c == '/' || (c == '.' && j == s.Length - 4))
             {
                 for (j = i; j > 0; j--)
                 {
                     c = s[j - 1]; if (c == '\\' || c == '/')
                     {
                         break;
                     }
                 }
                 if (j == i - (7 - k))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
Exemplo n.º 5
0
        /// <summary>
        /// Converts part of string to <see cref="KKey"/>.
        /// The substring should contain single key name, eg "Esc", "A", "=".
        /// Returns 0 if invalid key name.
        /// </summary>
        static unsafe KKey _KeynameToKey(string s, int i, int len)
        {
            //AOutput.Write(s, i, len);
            if (len < 1)
            {
                return(0);
            }

            char c = s[i];

            //character keys, like K, 9, -
            if (len == 1)
            {
                if (c >= 'a' && c <= 'z')
                {
                    return((KKey)(c - 32));
                }
                if (c >= 'A' && c <= 'Z')
                {
                    return((KKey)c);
                }
                if (c >= '0' && c <= '9')
                {
                    return((KKey)c);
                }
                switch (c)
                {
                case '=': return(KKey.OemPlus);

                case '`':
                case '~': return(KKey.OemTilde);

                case '-':
                case '_': return(KKey.OemMinus);

                case '[':
                case '{': return(KKey.OemOpenBrackets);

                case ']':
                case '}': return(KKey.OemCloseBrackets);

                case '\\':
                case '|': return(KKey.OemPipe);

                case ';':
                case ':': return(KKey.OemSemicolon);

                case '\'':
                case '\"': return(KKey.OemQuotes);

                case ',':
                case '<': return(KKey.OemComma);

                case '.':
                case '>': return(KKey.OemPeriod);

                case '/':
                case '?': return(KKey.OemQuestion);
                }
                return(0);

                //special
                //+ //eg Ctrl+A
                //* //*nTimes, *down, *up
                //( //eg Alt+(A F)
                //)
                //# //numpad keys, eg #5, #*
                //$ //Shift+

                //reserved
                //! @ % ^ &
            }

            //numpad keys
            if (c == '#')
            {
                if (len == 2)
                {
                    switch (s[i + 1])
                    {
                    case '.': return(KKey.Decimal);

                    case '+': return(KKey.Add);

                    case '/': return(KKey.Divide);

                    case '*': return(KKey.Multiply);

                    case '-': return(KKey.Subtract);

                    case '0': return(KKey.NumPad0);

                    case '1': return(KKey.NumPad1);

                    case '2': return(KKey.NumPad2);

                    case '3': return(KKey.NumPad3);

                    case '4': return(KKey.NumPad4);

                    case '5': return(KKey.NumPad5);

                    case '6': return(KKey.NumPad6);

                    case '7': return(KKey.NumPad7);

                    case '8': return(KKey.NumPad8);

                    case '9': return(KKey.NumPad9);
                    }
                }
                return(0);
            }

            //F keys
            if (c == 'F' && AChar.IsAsciiDigit(s[i + 1]))
            {
                int n = s.ToInt(i + 1, out int e, STIFlags.NoHex);
                if (n > 0 && n <= 24 && e == i + len)
                {
                    return((KKey)(0x6F + n));
                }
            }

            //named keys
            //names start with an uppercase letter and must have at least 2 other anycase letters, except: Up, AltG (RAl), PageU (PgU), PageD (PgD), some alternative names (PU, PD, PB, PS, HM, SL, CL, NL, BS).
            KKey k  = 0;
            char c1 = Char.ToLowerInvariant(s[i + 1]),             //note: Util.Tables_.LowerCase would make startup slow
                 c2 = len > 2 ? Char.ToLowerInvariant(s[i + 2]) : ' ',
                 c3 = len > 3 ? Char.ToLowerInvariant(s[i + 3]) : ' ',
                 c4 = len > 4 ? Char.ToLowerInvariant(s[i + 4]) : ' ';
            uint u  = (uint)c1 << 16 | c2;

            switch (c)
            {
            case 'A':
                if (_U('l', 't'))
                {
                    k = c3 == 'g' ? KKey.RAlt : KKey.Alt;
                }
                else if (_U('p', 'p'))
                {
                    k = KKey.Apps;
                }
                break;

            case 'B':
                if (_U('a', 'c') || _U('s', ' '))
                {
                    k = KKey.Back;
                }
                break;

            case 'C':
                if (_U('t', 'r'))
                {
                    k = KKey.Ctrl;
                }
                else if (_U('a', 'p') || _U('l', ' '))
                {
                    k = KKey.CapsLock;
                }
                break;

            case 'D':
                if (_U('e', 'l'))
                {
                    k = KKey.Delete;
                }
                else if (_U('o', 'w'))
                {
                    k = KKey.Down;
                }
                break;

            case 'E':
                if (_U('n', 't'))
                {
                    k = KKey.Enter;
                }
                else if (_U('n', 'd'))
                {
                    k = KKey.End;
                }
                else if (_U('s', 'c'))
                {
                    k = KKey.Escape;
                }
                break;

            case 'H':
                if (_U('o', 'm') || _U('m', ' '))
                {
                    k = KKey.Home;
                }
                break;

            case 'I':
                if (_U('n', 's'))
                {
                    k = KKey.Insert;
                }
                break;

            case 'L':
                if (_U('e', 'f'))
                {
                    k = KKey.Left;
                }
                //don't need LShift etc
                break;

            case 'M':
                if (_U('e', 'n'))
                {
                    k = KKey.Apps;
                }
                break;

            case 'N':
                if (_U('u', 'm') || _U('l', ' '))
                {
                    k = KKey.NumLock;
                }
                //for NumEnter use AKeys.Key((KKey.Enter, 0, true))
                break;

            case 'P':
                if (_U('a', 'g') && c3 == 'e')
                {
                    k = c4 == 'u' ? KKey.PageUp : (c4 == 'd' ? KKey.PageDown : 0);
                }
                else if (_U('g', 'u') || _U('u', ' '))
                {
                    k = KKey.PageUp;
                }
                else if (_U('g', 'd') || _U('d', ' '))
                {
                    k = KKey.PageDown;
                }
                else if (_U('a', 'u') || _U('b', ' '))
                {
                    k = KKey.Pause;
                }
                else if (_U('r', 'i') || _U('r', 't') || _U('s', ' '))
                {
                    k = KKey.PrintScreen;
                }
                break;

            case 'R':
                if (_U('i', 'g'))
                {
                    k = KKey.Right;
                }
                else if (_U('a', 'l'))
                {
                    k = KKey.RAlt;
                }
                else if (_U('c', 't'))
                {
                    k = KKey.RCtrl;
                }
                else if (_U('s', 'h'))
                {
                    k = KKey.RShift;
                }
                else if (_U('w', 'i'))
                {
                    k = KKey.RWin;
                }
                break;

            case 'S':
                if (_U('h', 'i'))
                {
                    k = KKey.Shift;
                }
                else if (_U('p', 'a'))
                {
                    k = KKey.Space;
                }
                else if (_U('c', 'r') || _U('l', ' '))
                {
                    k = KKey.ScrollLock;
                }
                //SysRq not used on Windows
                break;

            case 'T':
                if (_U('a', 'b'))
                {
                    k = KKey.Tab;
                }
                break;

            case 'U':
                if (c1 == 'p')
                {
                    k = KKey.Up;
                }
                break;

            case 'V':
                if (c1 == 'k')
                {
                    int v = s.ToInt(i + 2, out int end, STIFlags.DontSkipSpaces);
                    if (end != i + len || (uint)v > 255)
                    {
                        v = 0;
                    }
                    return((KKey)v);
                }
                break;

            case 'W':
                if (_U('i', 'n'))
                {
                    k = KKey.Win;
                }
                break;
            }
            if (k != 0)
            {
                for (int i2 = i + len; i < i2; i++)
                {
                    if (!AChar.IsAsciiAlpha(s[i]))
                    {
                        return(0);
                    }
                }
                return(k);
            }

            if (c >= 'A' && c <= 'Z')
            {
                var s1 = s.Substring(i, len);
#if false
                if (Enum.TryParse(s1, true, out KKey r1))
                {
                    return(r1);
                }
                //if(Enum.TryParse(s1, true, out System.Windows.Forms.Keys r2) && (uint)r2 <= 0xff) return (KKey)r2;
#else //20-50 times faster and less garbage. Good JIT speed.
                return(_FindKeyInEnums(s1));
#endif
            }
            return(0);

            bool _U(char cc1, char cc2)
            {
                return(u == ((uint)cc1 << 16 | cc2));
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets the length of the drive or network folder part in path, including its separator if any.
        /// If the string does not start with a drive or network folder path, returns 0 or prefix length (<c>@"\\?\"</c> or <c>@"\\?\UNC\"</c>).
        /// </summary>
        /// <param name="path">Full path or any string. Can be null. Should not be <c>@"%environmentVariable%\..."</c>.</param>
        /// <remarks>
        /// Supports prefixes <c>@"\\?\"</c> and <c>@"\\?\UNC\"</c>.
        /// Supports separators <c>'\\'</c> and <c>'/'</c>.
        /// </remarks>
        public static int GetRootLength(string path)
        {
            var s = path;
            int i = 0, len = (s == null) ? 0 : s.Length;

            if (len >= 2)
            {
                switch (s[1])
                {
                case ':':
                    if (AChar.IsAsciiAlpha(s[i]))
                    {
                        int j = i + 2;
                        if (len == j)
                        {
                            return(j);
                        }
                        if (IsSepChar_(s[j]))
                        {
                            return(j + 1);
                        }
                        //else invalid
                    }
                    break;

                case '\\':
                case '/':
                    if (IsSepChar_(s[0]))
                    {
                        i = _GetPrefixLength(s);
                        if (i == 0)
                        {
                            i = 2;                                //no prefix
                        }
                        else if (i == 4)
                        {
                            if (len >= 6 && s[5] == ':')
                            {
                                goto case ':';    //like @"\\?\C:\..."
                            }
                            break;                //invalid, no UNC
                        }                         //else like @"\\?\UNC\server\share\..."
                        int i0 = i, nSep = 0;
                        for (; i < len && nSep < 2; i++)
                        {
                            char c = s[i];
                            if (IsSepChar_(c))
                            {
                                nSep++;
                            }
                            else if (c == ':')
                            {
                                return(i0);
                            }
                            else if (c == '0')
                            {
                                break;
                            }
                        }
                    }
                    break;
                }
            }
            return(i);
        }