rj-action-library/Runtime/Text/JSON/JSONStringConverter.cs

215 lines
5.0 KiB
C#

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;
}
}
}