123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Text;
- using XUnity.AutoTranslator.Plugin.Core.Configuration;
- namespace XUnity.AutoTranslator.Plugin.Core.Extensions
- {
- public static class StringExtensions
- {
- private static readonly HashSet<char> Numbers = new HashSet<char>
- {
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9'
- };
- private static readonly HashSet<char> NumbersWithDot = new HashSet<char>
- {
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '.'
- };
- private static readonly char[] NewlinesCharacters = new char[] { '\r', '\n' };
- private static readonly char[] WhitespacesAndNewlines = new char[] { '\r', '\n', ' ', ' ' };
- public static TemplatedString TemplatizeByNumbers( this string str )
- {
- var dict = new Dictionary<string, string>();
- bool isNumber = false;
- StringBuilder carg = null;
- char arg = 'A';
- for( int i = 0 ; i < str.Length ; i++ )
- {
- var c = str[ i ];
- if( isNumber )
- {
- if( NumbersWithDot.Contains( c ) )
- {
- carg.Append( c );
- }
- else
- {
- // end current number
- var variable = carg.ToString();
- var ok = true;
- var c1 = variable[ 0 ];
- if( c1 == '.' )
- {
- if( variable.Length == 1 )
- {
- ok = false;
- }
- else
- {
- var c2 = variable[ 1 ];
- ok = Numbers.Contains( c2 );
- }
- }
- if( ok && !dict.ContainsKey( variable ) )
- {
- dict.Add( variable, "{{" + arg + "}}" );
- arg++;
- }
- carg = null;
- isNumber = false;
- }
- }
- else
- {
- if( NumbersWithDot.Contains( c ) )
- {
- isNumber = true;
- carg = new StringBuilder();
- carg.Append( c );
- }
- }
- }
- if( carg != null )
- {
- // end current number
- var variable = carg.ToString();
- var ok = true;
- var c1 = variable[ 0 ];
- if( c1 == '.' )
- {
- if( variable.Length == 1 )
- {
- ok = false;
- }
- else
- {
- var c2 = variable[ 1 ];
- ok = Numbers.Contains( c2 );
- }
- }
- if( ok && !dict.ContainsKey( variable ) )
- {
- dict.Add( variable, "{{" + arg + "}}" );
- arg++;
- }
- }
- if( dict.Count > 0 )
- {
- foreach( var kvp in dict )
- {
- str = str.Replace( kvp.Key, kvp.Value );
- }
- return new TemplatedString( str, dict.ToDictionary( x => x.Value, x => x.Key ) );
- }
- else
- {
- return null;
- }
- }
- public static string SplitToLines( this string text, int maxStringLength, params char[] splitOnCharacters )
- {
- var sb = new StringBuilder();
- var index = 0;
- while( text.Length > index )
- {
- // start a new line, unless we've just started
- if( index != 0 )
- sb.Append( '\n' );
- // get the next substring, else the rest of the string if remainder is shorter than `maxStringLength`
- var splitAt = index + maxStringLength <= text.Length
- ? text.Substring( index, maxStringLength ).LastIndexOfAny( splitOnCharacters )
- : text.Length - index;
- // if can't find split location, take `maxStringLength` characters
- splitAt = ( splitAt == -1 ) ? maxStringLength : splitAt;
- // add result to collection & increment index
- sb.Append( text.Substring( index, splitAt ).Trim() );
- index += splitAt;
- }
- return sb.ToString();
- }
- public static string TrimIfConfigured( this string text )
- {
- if( text == null ) return text;
- if( Settings.TrimAllText )
- {
- return text.Trim();
- }
- return text;
- }
- public static string RemoveWhitespaceAndNewlines( this string text )
- {
- var builder = new StringBuilder( text.Length );
- if( Settings.WhitespaceRemovalStrategy == WhitespaceHandlingStrategy.AllOccurrences )
- {
- for( int i = 0 ; i < text.Length ; i++ )
- {
- var c = text[ i ];
- switch( c )
- {
- case '\n':
- case '\r':
- case ' ':
- case ' ':
- break;
- default:
- builder.Append( c );
- break;
- }
- }
- }
- else // if( Settings.WhitespaceHandlingStrategy == WhitespaceHandlingStrategy.TrimPerNewline )
- {
- var lines = text.Split( NewlinesCharacters, StringSplitOptions.RemoveEmptyEntries );
- for( int i = 0 ; i < lines.Length ; i++ )
- {
- var line = lines[ i ].Trim( WhitespacesAndNewlines );
- for( int j = 0 ; j < line.Length ; j++ )
- {
- var c = line[ j ];
- builder.Append( c );
- }
- }
- }
- return builder.ToString();
- }
- public static bool ContainsNumbers( this string text )
- {
- foreach( var c in text )
- {
- if( Numbers.Contains( c ) )
- {
- return true;
- }
- }
- return false;
- }
- public static string UnescapeJson( this string str )
- {
- if( str == null ) return null;
- var builder = new StringBuilder( str );
- bool escapeNext = false;
- for( int i = 0 ; i < builder.Length ; i++ )
- {
- var c = builder[ i ];
- if( escapeNext )
- {
- bool found = true;
- char escapeWith = default( char );
- switch( c )
- {
- case 'b':
- escapeWith = '\b';
- break;
- case 'f':
- escapeWith = '\f';
- break;
- case 'n':
- escapeWith = '\n';
- break;
- case 'r':
- escapeWith = '\r';
- break;
- case 't':
- escapeWith = '\t';
- break;
- case '"':
- escapeWith = '\"';
- break;
- case '\\':
- escapeWith = '\\';
- break;
- case 'u':
- escapeWith = 'u';
- break;
- default:
- found = false;
- break;
- }
- // remove previous char and go one back
- if( found )
- {
- if( escapeWith == 'u' )
- {
- // unicode crap, lets handle the next 4 characters manually
- int code = int.Parse( new string( new char[] { builder[ i + 1 ], builder[ i + 2 ], builder[ i + 3 ], builder[ i + 4 ] } ), NumberStyles.HexNumber );
- var replacingChar = (char)code;
- builder.Remove( --i, 6 );
- builder.Insert( i, replacingChar );
- }
- else
- {
- // found proper escaping
- builder.Remove( --i, 2 );
- builder.Insert( i, escapeWith );
- }
- }
- else
- {
- // dont do anything
- }
- escapeNext = false;
- }
- else if( c == '\\' )
- {
- escapeNext = true;
- }
- }
- return builder.ToString();
- }
- public static string EscapeJson( this string str )
- {
- if( str == null || str.Length == 0 )
- {
- return "";
- }
- char c;
- int len = str.Length;
- StringBuilder sb = new StringBuilder( len + 4 );
- for( int i = 0 ; i < len ; i += 1 )
- {
- c = str[ i ];
- switch( c )
- {
- case '\\':
- case '"':
- sb.Append( '\\' );
- sb.Append( c );
- break;
- case '/':
- sb.Append( '\\' );
- sb.Append( c );
- break;
- case '\b':
- sb.Append( "\\b" );
- break;
- case '\t':
- sb.Append( "\\t" );
- break;
- case '\n':
- sb.Append( "\\n" );
- break;
- case '\f':
- sb.Append( "\\f" );
- break;
- case '\r':
- sb.Append( "\\r" );
- break;
- default:
- sb.Append( c );
- break;
- }
- }
- return sb.ToString();
- }
- public static string GetBetween( this string strSource, string strStart, string strEnd )
- {
- const int kNotFound = -1;
- var startIdx = strSource.IndexOf( strStart );
- if( startIdx != kNotFound )
- {
- startIdx += strStart.Length;
- var endIdx = strSource.IndexOf( strEnd, startIdx );
- if( endIdx > startIdx )
- {
- return strSource.Substring( startIdx, endIdx - startIdx );
- }
- }
- return String.Empty;
- }
- }
- }
|