using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Text; using System.Globalization; using Godot; namespace Rokojori { public class RegexUtility { public static Regex MakeSticky( Regex regex ) { var source = MakeSourceSticky( regex + "" ); return new Regex( source, regex.Options ); } public static string MakeSourceSticky( string source ) { if ( ! source.StartsWith( "\\G" ) ) { source = "\\G(?:" + source + ")"; } return source; } public static string NumberToString( double value ) { try { var specifier = "G"; return value.ToString( specifier, CultureInfo.InvariantCulture ); } catch( System.Exception e ) { RJLog.Log(e ); } return "0"; } public static double ParseDouble( string source, double alternative = 0 ) { try { double newValue = System.Double.Parse( source, CultureInfo.InvariantCulture ); return newValue; } catch ( System.Exception e ) { if ( e != null ) { } return alternative; } } public static float ParseFloat( string source, float alternative = 0 ) { return ( float ) ParseDouble( source, alternative ); } public static int ParseInt( string source, int alternative = 0 ) { var multiply = 1; var value = 0; for ( int i = source.Length - 1; i >= 0 ; i-- ) { var symbol = source[ i ]; if ( i == 0 ) { if ( symbol == '-' ) { return - value; } if ( symbol == '+' ) { return value; } } var digitValue = ParseDigit( symbol ); if ( digitValue == -1 ) { return alternative; } value += digitValue * multiply; multiply *= 10; } return value; } public static int ParseDigit( char c ) { switch ( c ) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; } return -1; } public static bool Matching( string source, string regex ) { return new Regex( regex ).Match( source ).Success; } public static string Substring( string source, string regex ) { return new Regex( regex ).Match( source ).Value; } public static string EscapeForRegex( string source ) { var sb = new StringBuilder(); var escapes = "+*?^$\\.[]{}()|/"; for ( int i = 0; i < source.Length; i++ ) { var character = source[ i ]; if ( escapes.IndexOf( character ) != -1 ) { sb.Append( "\\" ); } sb.Append( character ); } return sb.ToString(); } public static string LeadingZeros( int value, int minDigits = 2) { var stringValue = value + ""; while ( stringValue.Length < minDigits ) { stringValue = "0" + stringValue; } return stringValue; } public static string NumberWithThousandsSeperator( int value, string seperator = "." ) { var isNegative = value < 0; if ( isNegative ){ value = - value; } var stringValue = value + ""; var builder = new StringBuilder(); for ( int i = 0; i < stringValue.Length; i++ ) { var index = ( stringValue.Length - 1 ) - i ; if ( i % 4 == 3 ) { builder.Append( seperator ); } builder.Append( stringValue[ index ] ); } var seperatorValue = builder.ToString(); return Reverse( seperatorValue ); } public static string Reverse( string source ) { char[] characters = source.ToCharArray(); System.Array.Reverse( characters ); return new string( characters ); } public static Regex EscapedOrRegex( string first, params string[] other ) { var value = EscapeForRegex( first ); for ( var i = 0; i < other.Length; i++ ) { value += "|" + EscapeForRegex( other[ i ] ); /* if ( i == 0 ) { value = "(" + value; } value += ")|(" + EscapeForRegex( other[ i ] ); if ( i == ( other.Length - 1 ) ) { value += ")"; } */ } //Logs.Log("EscapedOrRegex:", "'" + value + "'"); return new Regex( value ); } public static Color ParseColor( string source, Color alternative ) { if ( Matching( source, @"#\d+" ) ) { return ParseHexColor( source, alternative ); } else if ( Matching( source, @"^rgb" ) ) { return ParseRGBColor( source, alternative ); } else if ( Matching( source, @"^hsl" ) ) { return ParseHSLColor( source, alternative ); } return alternative; } public static double ParsePercentage( string source ) { source = Remove( source, @"\s*%" ); return ParseDouble( source.Trim(), 0 ) / 100.0; } public static int ParseHexCharacter( char hexCharacter ) { if ( '0' <= hexCharacter && hexCharacter <= '9' ) { return (int) (hexCharacter - '0' ); } if ( 'a' <= hexCharacter && hexCharacter <= 'f' ) { return (int) (hexCharacter - 'a') + 10; } if ( 'A' <= hexCharacter && hexCharacter <= 'F' ) { return (int) (hexCharacter - 'A') + 10; } return 0; } public static int ParseHex( string source ) { var value = 0; var shift = 0; for ( var i = source.Length - 1; i < source.Length; i++ ) { var hexValue = ParseHexCharacter( source[ i ] ) << shift; shift += 4; } return value; } public static Color ParseHexColor( string source, Color alternative ) { source = RegexUtility.Remove( source, @"^#" ); var numbers = new List(); for ( var i = 0; i < 3; i++ ) { var value = source.Substring( i * 2, 2 ); var numberValue = ParseHex( value ) / 255f; numbers.Add( numberValue ); } if ( numbers.Count == 3 ) { numbers.Add( 1f ); } return new Color( numbers[ 0 ], numbers[ 1 ], numbers[ 2 ] , numbers[ 3 ] ); } public static Color ParseRGBColor( string source, Color alternative ) { source = RegexUtility.Remove( source, @"^rgba?\(" ); source = RegexUtility.Remove( source, @"\)$" ); var splits = Split( source, @"\," ); var numbers = Lists.Map( splits, ( string value, int index ) => { if ( value.Contains( "%" ) ) { return (float) ParsePercentage( value ); } return ParseFloat( value ); } ); if ( numbers.Count == 3 ) { numbers.Add( 1f ); } return new Color( numbers[ 0 ], numbers[ 1 ], numbers[ 2 ] , numbers[ 3 ] ); } public static HSLColor ParseHSLColor( string source, HSLColor alternative ) { source = RegexUtility.Remove( source, @"^hsl\(" ); source = RegexUtility.Remove( source, @"\)$" ); var splits = Split( source, @"\," ); var numbers =Lists.Map( splits, ( string value, int index ) => { if ( value.Contains( "%" ) ) { return (float) ParsePercentage( value ); } return ParseFloat( value ); } ); if ( numbers.Count < 3 ) { RJLog.Log("Not enough numbers parsed: ", source, ">>", numbers.Count, Lists.Join( numbers, "," ) ); } if ( numbers.Count == 3 ) { numbers.Add( 1f ); } return new HSLColor( numbers[ 0 ], numbers[ 1 ], numbers[ 2 ] , numbers[ 3 ] ); } public static List Split( string source, Regex regex ) { var strings = regex.Split( source ); var list = new List(); list.AddRange( strings ); return list; } public static List Split( string source, string regex ) { return Split( source, new Regex( regex ) ); } public static List SplitLines( string source ) { var array = Regex.Split( source, "\r\n|\r|\n" ); var list = new List(); list.AddRange( array ); return list; } public static string Remove( string source, string regex ) { return Replace( source, regex, "" ); } public static string Replace( string source, Regex regex, string replacement ) { return regex.Replace( source, replacement ); } public static string Remove( string source, Regex regex ) { return Replace( source, regex, "" ); } public static string Replace( string source, string regex, string replacement ) { return new Regex( regex ).Replace( source, replacement ); } public static string ReplaceMultiple( string source, Dictionary replacements ) { var replaced = source; foreach ( var vk in replacements ) { replaced = replaced.Replace( vk.Key, vk.Value ); } return replaced; } public static string ParentPathOrLastFragment( string path ) { var splits = SplitPaths( path ); return splits[ splits.Count - 1 ]; } public static List SplitPaths( string path ) { var splittedPaths = new List(); var normalizedPath = NormalizePath( path ); var splits = Split( normalizedPath, new Regex( @"\/" ) ); return splits; } public static string JoinPaths( List paths, int startIndex = 0, int length = -1 ) { var normalizedPaths = new List(); // normalizedPaths.AddRange( paths ); var endIndex = startIndex + length; var end = ( length < 0 || ( length + startIndex ) >= paths.Count ) ? paths.Count : endIndex; for ( var i = startIndex; i < end; i++ ) { normalizedPaths.Add( _NormalizePath( paths[ i ] ) ); } return Lists.Join( normalizedPaths, "/" ); } public static string Join( string pathA, string pathB, params string[] paths ) { var normalizedPaths = new List(); normalizedPaths.Add( pathA ); normalizedPaths.Add( pathB ); normalizedPaths.AddRange( paths ); for ( var i = 0; i < normalizedPaths.Count; i++ ) { normalizedPaths[ i ] = _NormalizePath( normalizedPaths[ i ] ); } return Lists.Join( normalizedPaths, "/" ); } private static string _EnsureForwardSlashes( string path ) { if ( path.IndexOf( "\\" ) == -1 ) { return path; } var correctedPath = ""; for ( int i = 0; i < path.Length; i++ ) { if ( path[ i ] == '\\' ) { correctedPath += "/"; } else { correctedPath += path[ i ]; } } return correctedPath; } public static string NormalizePath( string path ) { return _NormalizePath( path ); } public static string WindowsPath( string path ) { path = _NormalizePath( path ); var slashes = @"\/"; path = Regex.Replace( path, slashes, "\\" ); return path; } private static string _NormalizePath( string path ) { path = _EnsureForwardSlashes( path ); var startSlashes = @"^\/+"; var endSlashes = @"\/+$"; var multiples = @"\/\/+"; path = Regex.Replace( path, startSlashes, "" ); path = Regex.Replace( path, endSlashes, "" ); path = Regex.Replace( path, multiples, "/" ); return path; } } }