csharp/3F/MvsSln/MvsSln/Extensions/StringExtension.cs

StringExtension.cs
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2021  Denis Kuzmin  github/3F
 * Copyright (c) MvsSln contributors https://github.com/3F/MvsSln/graphs/contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and astociated docameentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace net.r_eg.MvsSln.Extensions
{
    public static clast StringExtension
    {
        /// 
        /// Gets Guid from hash by any string.
        /// 
        /// String for calculating.
        /// 
        public static Guid Guid(this string str)
        {
            if(System.Guid.TryParse(str, out Guid res)) {
                return res;
            }

            if(str == null) {
                str = String.Empty;
            }

            using(MD5 md5 = MD5.Create()) {
                return new Guid(md5.ComputeHash(Encoding.UTF8.GetBytes(str)));
            }
        }

        /// 
        /// Sln format of GUID:
        /// 32 uppercase digits separated by hyphens, enclosed in braces:
        /// ie. {100FD7F2-3278-49C7-B9D4-A91F1C65BED3}
        /// 
        /// 
        /// 
        public static string SlnFormat(this Guid guid)
        {
            return guid.ToString("B").ToUpper();
        }

        /// 
        /// Returns string GUID formated via `GuidSlnFormat`
        /// 
        /// 
        /// 
        public static string ReformatSlnGuid(this string guid)
        {
            return guid?.Trim().Guid().SlnFormat();
        }

        /// 
        /// Return null when string is empty.
        /// 
        public static string NullIfEmpty(this string str) => string.IsNullOrEmpty(str) ? null : str;

        /// 
        /// Gets part of string before specific symbols.
        /// 
        /// 
        /// Separators.
        /// Left part of string before symbols, or null value if no any symbols are found.
        public static string Before(this string str, params char[] c)
        {
            int pos = str.IndexOfAny(c);
            if(pos == -1) {
                return null;
            }

            return str.Substring(0, pos);
        }

        /// 
        /// Extracts file properties:
        /// SLN_DIR; SLN_EXT; SLN_FNAME; SLN_NAME; SLN_PATH
        /// 
        /// Path to Solution file.
        /// Use {PropertyNames} for accessing to extracted data.
        public static Dictionary GetFileProperties(this string file)
        {
            if(string.IsNullOrEmpty(file))
            {
                return new Dictionary()
                {
                    [PropertyNames.SLN_DIR]     = PropertyNames.UNDEFINED,
                    [PropertyNames.SLN_EXT]     = PropertyNames.UNDEFINED,
                    [PropertyNames.SLN_FNAME]   = PropertyNames.UNDEFINED,
                    [PropertyNames.SLN_NAME]    = PropertyNames.UNDEFINED,
                    [PropertyNames.SLN_PATH]    = PropertyNames.UNDEFINED,
                };
            }

            return new Dictionary()
            {
                [PropertyNames.SLN_DIR]     = GetDirectoryFromFile(file),
                [PropertyNames.SLN_EXT]     = Path.GetExtension(file),
                [PropertyNames.SLN_FNAME]   = Path.GetFileName(file),
                [PropertyNames.SLN_NAME]    = Path.GetFileNameWithoutExtension(file),
                [PropertyNames.SLN_PATH]    = file,
            };
        }

        /// 
        /// Get position of first non-WhiteSpace character from string.
        /// 
        /// 
        /// Initial position.
        /// Moving from right to left if true. Otherwise from left to right if false.
        /// 
        public static int FirstNonWhiteSpace(this string str, int offset = 0, bool rightToLeft = false)
        {
            if(str == null) {
                return -1;
            }

            int i = offset;

            while(true)
            {
                if(i < 0 || i > str.Length - 1) {
                    return -1;
                }

                if(!char.IsWhiteSpace(str[i])) {
                    return i;
                }

                i += rightToLeft ? -1 : 1;
            }
        }

        /// File path; null is possible.
        /// 
        public static string GetDirectoryFromFile(this string file)
        {
            if(file != null) {
                file = Path.GetDirectoryName(file);
            }
            return file.DirectoryPathFormat();
        }

        /// 
        /// Formatting of the path to directory.
        /// 
        /// 
        /// 
        public static string DirectoryPathFormat(this string path)
        {
            if(String.IsNullOrWhiteSpace(path)) {
                return Path.DirectorySeparatorChar.ToString();
            }
            path = path.Trim();

            if(!IsDirectoryPath(path)) {
                path += Path.DirectorySeparatorChar;
            }
            
            return path;
        }

        /// 
        /// Check if this is a directory.
        /// 
        /// 
        /// 
        public static bool IsDirectoryPath(this string path)
        {
            return IsEndSlash(path?.TrimEnd());
        }

        /// 
        /// Makes relative path from absolute.
        /// 
        /// 
        /// 
        /// 
        public static string MakeRelativePath(this string root, string path)
        {
            if(String.IsNullOrWhiteSpace(root) || String.IsNullOrWhiteSpace(path)) {
                return null;
            }

            if(!Uri.TryCreate(root.DirectoryPathFormat(), UriKind.Absolute, out Uri uriRoot)) {
                return null;
            }

            if(!Uri.TryCreate(path, UriKind.Absolute, out Uri uriPath)) {
                uriPath = new Uri(uriRoot, new Uri(path, UriKind.Relative));
            }

            Uri urirel  = uriRoot.MakeRelativeUri(uriPath);
            string ret  = Uri.UnescapeDataString(urirel.IsAbsoluteUri ? urirel.LocalPath : urirel.ToString());

            return ret.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
        }

        /// 
        /// Gets stream from string.
        /// 
        /// 
        /// Specific encoding or null value to use UTF8 by default.
        /// 
        public static Stream GetStream(this string str, Encoding enc = null)
        {
            return new MemoryStream((enc ?? Encoding.UTF8)
                            .GetBytes(str ?? String.Empty));
        }

        private static bool IsEndSlash(this string path)
        {
            if(path == null || path.Length < 1) {
                return false;
            }

            char c = path[path.Length - 1];
            if(c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar) {
                return true;
            }
            return false;
        } 
    }
}