using System.Collections; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace Rokojori { public class JSONStringConverter { static bool ContainsBackslash( string dataFromFile, int start, int length ) { var end = start + length; for ( var i = start; i < end; i++ ) { if ( dataFromFile[ i ] == '\\' ) { return true; } } return false; } public static string Read( string dataFromFile ) { var output = new StringBuilder(); Read( output, dataFromFile, 0, dataFromFile.Length ); return output.ToString(); } public static void Read( StringBuilder output, string dataFromFile, int start, int length ) { ReadWithoutQuotes( output, dataFromFile, start + 1, length - 2 ); } public static void Read( StringBuilder output, string dataFromFile ) { Read( output, dataFromFile, 0, dataFromFile.Length ); } public static void ReadWithoutQuotes( StringBuilder output, string dataFromFile, int start, int length ) { if ( ! JSONStringConverter.ContainsBackslash( dataFromFile, start, length ) ) { output.Append( dataFromFile.Substring( start, length ) ); return; } var end = start + length; for ( var i = start ; i < end; i++ ) { var rawCharacter = dataFromFile[ i ]; if ( rawCharacter == '\\' ) { if ( i == end - 1 ) { return; } var nextRawCharacter = dataFromFile[ i + 1 ]; if ( nextRawCharacter == 'u' ) { var hexStringStart = i + 2; var hexString = dataFromFile.Substring( hexStringStart, 4 ); var unicodeValue = ReadUnicodeFromHexString( hexString ); output.Append( unicodeValue ); i += 5; } else { var escapedCharacter = ReadSingleEscaped( nextRawCharacter ); output.Append( escapedCharacter ); i ++; } } else { output.Append( rawCharacter ); } } } static char ReadSingleEscaped( char character ) { switch ( character ) { case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; default: return character; } } static char ReadUnicodeFromHexString( string hexString ) { return (char) int.Parse( hexString, System.Globalization.NumberStyles.HexNumber ); } static readonly char[] ESCAPE_CHARACTERS = new char[] { '\"', '\\', '/', '\b', '\f', '\n', '\r', '\t' }; static readonly string[] ESCAPING_SEQUENCES = new string[] { "\\\"", "\\\\", "\\/", "\\b", "\\f", "\\n", "\\r", "\\t" }; public static string Write( string dataFromMemory ) { var output = new StringBuilder(); Write( output, dataFromMemory, 0, dataFromMemory.Length ); return output.ToString(); } public static void Write( StringBuilder output, string dataFromMemory, int start, int length ) { output.Append( "\"" ); WriteWithoutQuotes( output, dataFromMemory, start, length ); output.Append( "\"" ); } public static void Write( StringBuilder output, string dataFromMemory ) { Write( output, dataFromMemory, 0, dataFromMemory.Length ); } public static void WriteWithoutQuotes( StringBuilder output, string dataFromMemory, int start, int length ) { var end = start + length; var index = IndexOfEscapeCharacter( dataFromMemory, start, end ); if ( index == -1 ) { output.Append( dataFromMemory.Substring( start, length ) ); return; } for ( var i = 0; i < end; i++ ) { var intValue = ( int ) dataFromMemory[ i ]; if ( intValue > 127 ) { var escapedUnicodeValue = "\\u" + intValue.ToString( "x4" ); output.Append( escapedUnicodeValue ); continue; } var escapeIndex = GetEscapeIndex( dataFromMemory[ i ] ); if ( escapeIndex != -1 ) { output.Append( ESCAPING_SEQUENCES[ escapeIndex ] ); } else { output.Append( dataFromMemory[ i ] ); } } } static int IndexOfEscapeCharacter( string dataFromMemory, int start, int end ) { for ( var i = start; i < end; i++ ) { var intValue = ( int ) dataFromMemory[ i ]; if ( intValue > 127 ) { return i; } var escapeIndex = GetEscapeIndex( dataFromMemory[ i ] ); if ( escapeIndex != -1 ) { return i; } } return -1; } static int GetEscapeIndex( char c ) { for ( int i = 0; i < ESCAPE_CHARACTERS.Length; i++ ) { if ( ESCAPE_CHARACTERS[ i ] == c ) { return i; } } return -1; } } }