527 lines
12 KiB
C#
527 lines
12 KiB
C#
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<float>();
|
|
|
|
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<string,float>( 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<string,float>( 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<string> Split( string source, Regex regex )
|
|
{
|
|
var strings = regex.Split( source );
|
|
var list = new List<string>();
|
|
|
|
list.AddRange( strings );
|
|
|
|
return list;
|
|
}
|
|
|
|
public static List<string> Split( string source, string regex )
|
|
{
|
|
return Split( source, new Regex( regex ) );
|
|
}
|
|
|
|
public static List<string> SplitLines( string source )
|
|
{
|
|
var array = Regex.Split( source, "\r\n|\r|\n" );
|
|
var list = new List<string>();
|
|
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<string,string> 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<string> SplitPaths( string path )
|
|
{
|
|
var splittedPaths = new List<string>();
|
|
var normalizedPath = NormalizePath( path );
|
|
var splits = Split( normalizedPath, new Regex( @"\/" ) );
|
|
return splits;
|
|
}
|
|
|
|
public static string JoinPaths( List<string> paths, int startIndex = 0, int length = -1 )
|
|
{
|
|
var normalizedPaths = new List<string>();
|
|
// 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<string>();
|
|
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;
|
|
}
|
|
}
|
|
} |