git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1757 52acb1d6-8a22-11de-b505-999d5b087335
729 lines
31 KiB
C#
729 lines
31 KiB
C#
/*
|
|
* Copyright (c) 2007-2008, Second Life Reverse Engineering Team
|
|
* All rights reserved.
|
|
*
|
|
* - Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* - Neither the name of the Second Life Reverse Engineering Team nor the names
|
|
* of its contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
namespace libsecondlife.StructuredData
|
|
{
|
|
public static partial class LLSDParser
|
|
{
|
|
private const string notationHead = "<?llsd/notation?>\n";
|
|
private const string baseIntend = " ";
|
|
|
|
private const char undefNotationValue = '!';
|
|
|
|
private const char trueNotationValueOne = '1';
|
|
private const char trueNotationValueTwo = 't';
|
|
private static char[] trueNotationValueTwoFull = { 't', 'r', 'u', 'e' };
|
|
private const char trueNotationValueThree = 'T';
|
|
private static char[] trueNotationValueThreeFull = { 'T', 'R', 'U', 'E' };
|
|
|
|
private const char falseNotationValueOne = '0';
|
|
private const char falseNotationValueTwo = 'f';
|
|
private static char[] falseNotationValueTwoFull = { 'f', 'a', 'l', 's', 'e' };
|
|
private const char falseNotationValueThree = 'F';
|
|
private static char[] falseNotationValueThreeFull = { 'F', 'A', 'L', 'S', 'E' };
|
|
|
|
private const char integerNotationMarker = 'i';
|
|
private const char realNotationMarker = 'r';
|
|
private const char uuidNotationMarker = 'u';
|
|
private const char binaryNotationMarker = 'b';
|
|
private const char stringNotationMarker = 's';
|
|
private const char uriNotationMarker = 'l';
|
|
private const char dateNotationMarker = 'd';
|
|
|
|
private const char arrayBeginNotationMarker = '[';
|
|
private const char arrayEndNotationMarker = ']';
|
|
|
|
private const char mapBeginNotationMarker = '{';
|
|
private const char mapEndNotationMarker = '}';
|
|
private const char kommaNotationDelimiter = ',';
|
|
private const char keyNotationDelimiter = ':';
|
|
|
|
private const char sizeBeginNotationMarker = '(';
|
|
private const char sizeEndNotationMarker = ')';
|
|
private const char doubleQuotesNotationMarker = '"';
|
|
private const char singleQuotesNotationMarker = '\'';
|
|
|
|
public static LLSD DeserializeNotation(string notationData)
|
|
{
|
|
StringReader reader = new StringReader( notationData );
|
|
LLSD llsd = DeserializeNotation( reader );
|
|
reader.Close();
|
|
return llsd;
|
|
}
|
|
|
|
public static LLSD DeserializeNotation( StringReader reader )
|
|
{
|
|
LLSD llsd = DeserializeNotationElement( reader );
|
|
return llsd;
|
|
}
|
|
|
|
public static string SerializeNotation(LLSD llsd)
|
|
{
|
|
StringWriter writer = SerializeNotationStream( llsd );
|
|
string s = writer.ToString();
|
|
writer.Close();
|
|
|
|
return s;
|
|
}
|
|
|
|
public static StringWriter SerializeNotationStream(LLSD llsd)
|
|
{
|
|
StringWriter writer = new StringWriter();
|
|
|
|
SerializeNotationElement( writer, llsd );
|
|
return writer;
|
|
}
|
|
|
|
public static string SerializeNotationFormatted(LLSD llsd)
|
|
{
|
|
StringWriter writer = SerializeNotationStreamFormatted(llsd);
|
|
string s = writer.ToString();
|
|
writer.Close();
|
|
|
|
return s;
|
|
}
|
|
|
|
public static StringWriter SerializeNotationStreamFormatted(LLSD llsd)
|
|
{
|
|
StringWriter writer = new StringWriter();
|
|
|
|
string intend = "";
|
|
SerializeNotationElementFormatted( writer, intend, llsd );
|
|
return writer;
|
|
}
|
|
|
|
|
|
private static LLSD DeserializeNotationElement( StringReader reader )
|
|
{
|
|
int character = ReadAndSkipWhitespace( reader );
|
|
if ( character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing:Unexpected end of stream." );
|
|
|
|
|
|
LLSD llsd;
|
|
int matching;
|
|
switch( (char)character)
|
|
{
|
|
case undefNotationValue:
|
|
llsd = new LLSD();
|
|
break;
|
|
case trueNotationValueOne:
|
|
llsd = LLSD.FromBoolean( true );
|
|
break;
|
|
case trueNotationValueTwo:
|
|
matching = BufferCharactersEqual( reader, trueNotationValueTwoFull, 1 );
|
|
if ( matching > 1 && matching < trueNotationValueTwoFull.Length )
|
|
throw new LLSDException( "Notation LLSD parsing: True value parsing error:" );
|
|
llsd = LLSD.FromBoolean( true );
|
|
break;
|
|
case trueNotationValueThree:
|
|
matching = BufferCharactersEqual( reader, trueNotationValueThreeFull, 1 );
|
|
if ( matching > 1 && matching < trueNotationValueThreeFull.Length )
|
|
throw new LLSDException( "Notation LLSD parsing: True value parsing error:" );
|
|
llsd = LLSD.FromBoolean( true );
|
|
break;
|
|
case falseNotationValueOne:
|
|
llsd = LLSD.FromBoolean( false );
|
|
break;
|
|
case falseNotationValueTwo:
|
|
matching = BufferCharactersEqual( reader, falseNotationValueTwoFull, 1 );
|
|
if ( matching > 1 && matching < falseNotationValueTwoFull.Length )
|
|
throw new LLSDException( "Notation LLSD parsing: True value parsing error:" );
|
|
llsd = LLSD.FromBoolean( false );
|
|
break;
|
|
case falseNotationValueThree:
|
|
matching = BufferCharactersEqual( reader, falseNotationValueThreeFull, 1 );
|
|
if ( matching > 1 && matching < falseNotationValueThreeFull.Length )
|
|
throw new LLSDException( "Notation LLSD parsing: True value parsing error:" );
|
|
llsd = LLSD.FromBoolean( false );
|
|
break;
|
|
case integerNotationMarker:
|
|
llsd = DeserializeNotationInteger( reader );
|
|
break;
|
|
case realNotationMarker:
|
|
llsd = DeserializeNotationReal( reader );
|
|
break;
|
|
case uuidNotationMarker:
|
|
char[] uuidBuf = new char[36];
|
|
if ( reader.Read( uuidBuf, 0, 36 ) < 36)
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in UUID." );
|
|
LLUUID lluuid;
|
|
if ( !LLUUID.TryParse( new String( uuidBuf ), out lluuid ))
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid UUID discovered." );
|
|
llsd = LLSD.FromUUID( lluuid );
|
|
break;
|
|
case binaryNotationMarker:
|
|
byte[] bytes = new byte[0];
|
|
int bChar = reader.Peek();
|
|
if ( bChar < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in binary." );
|
|
if ((char)bChar == sizeBeginNotationMarker )
|
|
{
|
|
throw new LLSDException( "Notation LLSD parsing: Raw binary encoding not supported." );
|
|
}
|
|
else if (Char.IsDigit((char)bChar))
|
|
{
|
|
char[] charsBaseEncoding = new char[2];
|
|
if (reader.Read( charsBaseEncoding, 0, 2 ) < 2 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in binary." );
|
|
int baseEncoding;
|
|
if (!Int32.TryParse( new String( charsBaseEncoding ), out baseEncoding ))
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid binary encoding base." );
|
|
if ( baseEncoding == 64 )
|
|
{
|
|
if (reader.Read() < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in binary." );
|
|
string bytes64 = GetStringDelimitedBy( reader, doubleQuotesNotationMarker );
|
|
bytes = Convert.FromBase64String( bytes64 );
|
|
}
|
|
else
|
|
{
|
|
throw new LLSDException( "Notation LLSD parsing: Encoding base" + baseEncoding + " + not supported." );
|
|
}
|
|
}
|
|
llsd = LLSD.FromBinary( bytes );
|
|
break;
|
|
case stringNotationMarker:
|
|
int numChars = GetLengthInBrackets( reader );
|
|
if ( reader.Read() < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in string." );
|
|
char[] chars = new char[numChars];
|
|
if ( reader.Read( chars, 0, numChars ) < numChars )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in string." );
|
|
if ( reader.Read() < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in string." );
|
|
llsd = LLSD.FromString( new String( chars ));
|
|
break;
|
|
case singleQuotesNotationMarker:
|
|
string sOne = GetStringDelimitedBy( reader, singleQuotesNotationMarker );
|
|
llsd = LLSD.FromString( sOne );
|
|
break;
|
|
case doubleQuotesNotationMarker:
|
|
string sTwo = GetStringDelimitedBy( reader, doubleQuotesNotationMarker );
|
|
llsd = LLSD.FromString( sTwo );
|
|
break;
|
|
case uriNotationMarker:
|
|
if ( reader.Read() < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in string." );
|
|
string sUri = GetStringDelimitedBy( reader, doubleQuotesNotationMarker );
|
|
|
|
Uri uri;
|
|
try
|
|
{
|
|
uri = new Uri( sUri, UriKind.RelativeOrAbsolute );
|
|
}
|
|
catch
|
|
{
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid Uri format detected." );
|
|
}
|
|
llsd = LLSD.FromUri( uri);
|
|
break;
|
|
case dateNotationMarker:
|
|
if (reader.Read() < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in date." );
|
|
string date = GetStringDelimitedBy( reader, doubleQuotesNotationMarker );
|
|
DateTime dt;
|
|
if ( !Helpers.TryParse( date, out dt ))
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid date discovered." );
|
|
llsd = LLSD.FromDate( dt );
|
|
break;
|
|
case arrayBeginNotationMarker:
|
|
llsd = DeserializeNotationArray( reader );
|
|
break;
|
|
case mapBeginNotationMarker:
|
|
llsd = DeserializeNotationMap( reader );
|
|
break;
|
|
default:
|
|
throw new LLSDException( "Notation LLSD parsing: Unknown type marker '" + (char)character + "'." );
|
|
}
|
|
return llsd;
|
|
}
|
|
|
|
private static LLSD DeserializeNotationInteger( StringReader reader )
|
|
{
|
|
int character;
|
|
StringBuilder s = new StringBuilder();
|
|
if ((( character = reader.Peek()) > 0 ) && ((char)character == '-' ))
|
|
{
|
|
s.Append((char)character);
|
|
reader.Read();
|
|
}
|
|
|
|
while (( character = reader.Peek()) > 0 &&
|
|
Char.IsDigit((char)character))
|
|
{
|
|
s.Append((char)character);
|
|
reader.Read();
|
|
}
|
|
int integer;
|
|
if ( !Helpers.TryParse( s.ToString(), out integer ))
|
|
throw new LLSDException( "Notation LLSD parsing: Can't parse integer value." );
|
|
|
|
return LLSD.FromInteger( integer );
|
|
}
|
|
|
|
private static LLSD DeserializeNotationReal( StringReader reader )
|
|
{
|
|
int character;
|
|
StringBuilder s = new StringBuilder();
|
|
if ((( character = reader.Peek()) > 0 ) && ((char)character == '-' ))
|
|
{
|
|
s.Append((char)character);
|
|
reader.Read();
|
|
}
|
|
while ((( character = reader.Peek()) > 0) &&
|
|
( Char.IsDigit((char)character) || (char)character == '.' ||
|
|
(char)character == 'e' || (char)character == 'E' || (char)character == '+' ))
|
|
{
|
|
s.Append((char)character);
|
|
reader.Read();
|
|
}
|
|
double dbl;
|
|
if (!Helpers.TryParse(s.ToString(), out dbl))
|
|
throw new LLSDException("Notation LLSD parsing: Can't parse real value: " + s.ToString());
|
|
|
|
return LLSD.FromReal( dbl );
|
|
}
|
|
|
|
private static LLSD DeserializeNotationArray( StringReader reader )
|
|
{
|
|
int character;
|
|
LLSDArray llsdArray = new LLSDArray();
|
|
while((( character = PeekAndSkipWhitespace( reader )) > 0) &&
|
|
((char)character != arrayEndNotationMarker))
|
|
{
|
|
llsdArray.Add( DeserializeNotationElement( reader ));
|
|
|
|
character = ReadAndSkipWhitespace( reader );
|
|
if (character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of array discovered." );
|
|
else if ((char)character == kommaNotationDelimiter )
|
|
continue;
|
|
else if ((char)character == arrayEndNotationMarker )
|
|
break;
|
|
}
|
|
if ( character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of array discovered." );
|
|
|
|
return (LLSD)llsdArray;
|
|
}
|
|
|
|
private static LLSD DeserializeNotationMap( StringReader reader )
|
|
{
|
|
int character;
|
|
LLSDMap llsdMap = new LLSDMap();
|
|
while((( character = PeekAndSkipWhitespace( reader )) > 0 ) &&
|
|
((char)character != mapEndNotationMarker ))
|
|
{
|
|
LLSD llsdKey = DeserializeNotationElement( reader );
|
|
if ( llsdKey.Type != LLSDType.String )
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid key in map" );
|
|
string key = llsdKey.AsString();
|
|
|
|
character = ReadAndSkipWhitespace( reader );
|
|
if ((char)character != keyNotationDelimiter )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of stream in map." );
|
|
if ((char)character != keyNotationDelimiter )
|
|
throw new LLSDException( "Notation LLSD parsing: Invalid delimiter in map." );
|
|
|
|
llsdMap[key] = DeserializeNotationElement( reader );
|
|
character = ReadAndSkipWhitespace( reader );
|
|
if ( character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of map discovered." );
|
|
else if ((char)character == kommaNotationDelimiter )
|
|
continue;
|
|
else if ((char)character == mapEndNotationMarker )
|
|
break;
|
|
}
|
|
if ( character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Unexpected end of map discovered." );
|
|
|
|
return (LLSD)llsdMap;
|
|
}
|
|
|
|
private static void SerializeNotationElement( StringWriter writer, LLSD llsd )
|
|
{
|
|
|
|
switch( llsd.Type )
|
|
{
|
|
case LLSDType.Unknown:
|
|
writer.Write( undefNotationValue );
|
|
break;
|
|
case LLSDType.Boolean:
|
|
if ( llsd.AsBoolean() )
|
|
writer.Write( trueNotationValueTwo );
|
|
else
|
|
writer.Write( falseNotationValueTwo );
|
|
break;
|
|
case LLSDType.Integer:
|
|
writer.Write( integerNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.Real:
|
|
writer.Write( realNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.UUID:
|
|
writer.Write( uuidNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.String:
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( llsd.AsString(), singleQuotesNotationMarker ));
|
|
writer.Write( singleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Binary:
|
|
writer.Write( binaryNotationMarker );
|
|
writer.Write( "64" );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Date:
|
|
writer.Write( dateNotationMarker );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.URI:
|
|
writer.Write( uriNotationMarker );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( llsd.AsString(), doubleQuotesNotationMarker ));
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Array:
|
|
SerializeNotationArray( writer, (LLSDArray)llsd );
|
|
break;
|
|
case LLSDType.Map:
|
|
SerializeNotationMap( writer, (LLSDMap)llsd );
|
|
break;
|
|
default:
|
|
throw new LLSDException( "Notation serialization: Not existing element discovered." );
|
|
|
|
}
|
|
}
|
|
|
|
private static void SerializeNotationArray( StringWriter writer, LLSDArray llsdArray )
|
|
{
|
|
writer.Write( arrayBeginNotationMarker );
|
|
int lastIndex = llsdArray.Count - 1;
|
|
|
|
for( int idx = 0; idx <= lastIndex; idx++ )
|
|
{
|
|
SerializeNotationElement( writer, llsdArray[idx] );
|
|
if ( idx < lastIndex )
|
|
writer.Write( kommaNotationDelimiter );
|
|
}
|
|
writer.Write( arrayEndNotationMarker );
|
|
}
|
|
|
|
private static void SerializeNotationMap( StringWriter writer, LLSDMap llsdMap )
|
|
{
|
|
writer.Write( mapBeginNotationMarker );
|
|
int lastIndex = llsdMap.Count - 1;
|
|
int idx = 0;
|
|
|
|
foreach( KeyValuePair<string, LLSD> kvp in llsdMap )
|
|
{
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( kvp.Key, singleQuotesNotationMarker ));
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( keyNotationDelimiter );
|
|
SerializeNotationElement( writer,kvp.Value );
|
|
if ( idx < lastIndex )
|
|
writer.Write( kommaNotationDelimiter );
|
|
|
|
idx++;
|
|
}
|
|
writer.Write( mapEndNotationMarker );
|
|
}
|
|
|
|
private static void SerializeNotationElementFormatted( StringWriter writer, string intend, LLSD llsd )
|
|
{
|
|
switch( llsd.Type )
|
|
{
|
|
case LLSDType.Unknown:
|
|
writer.Write( undefNotationValue );
|
|
break;
|
|
case LLSDType.Boolean:
|
|
if ( llsd.AsBoolean() )
|
|
writer.Write( trueNotationValueTwo );
|
|
else
|
|
writer.Write( falseNotationValueTwo );
|
|
break;
|
|
case LLSDType.Integer:
|
|
writer.Write( integerNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.Real:
|
|
writer.Write( realNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.UUID:
|
|
writer.Write( uuidNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
break;
|
|
case LLSDType.String:
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( llsd.AsString(), singleQuotesNotationMarker ));
|
|
writer.Write( singleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Binary:
|
|
writer.Write( binaryNotationMarker );
|
|
writer.Write( "64" );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Date:
|
|
writer.Write( dateNotationMarker );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( llsd.AsString());
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.URI:
|
|
writer.Write( uriNotationMarker );
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( llsd.AsString(), doubleQuotesNotationMarker ));
|
|
writer.Write( doubleQuotesNotationMarker );
|
|
break;
|
|
case LLSDType.Array:
|
|
SerializeNotationArrayFormatted( writer, intend + baseIntend, (LLSDArray)llsd );
|
|
break;
|
|
case LLSDType.Map:
|
|
SerializeNotationMapFormatted( writer, intend + baseIntend, (LLSDMap)llsd );
|
|
break;
|
|
default:
|
|
throw new LLSDException( "Notation serialization: Not existing element discovered." );
|
|
|
|
}
|
|
}
|
|
|
|
private static void SerializeNotationArrayFormatted( StringWriter writer, string intend, LLSDArray llsdArray )
|
|
{
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend );
|
|
writer.Write( arrayBeginNotationMarker );
|
|
int lastIndex = llsdArray.Count - 1;
|
|
|
|
for( int idx = 0; idx <= lastIndex; idx++ )
|
|
{
|
|
if ( llsdArray[idx].Type != LLSDType.Array && llsdArray[idx].Type != LLSDType.Map )
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend + baseIntend );
|
|
SerializeNotationElementFormatted( writer, intend, llsdArray[idx] );
|
|
if ( idx < lastIndex )
|
|
{
|
|
writer.Write( kommaNotationDelimiter );
|
|
}
|
|
}
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend );
|
|
writer.Write( arrayEndNotationMarker );
|
|
}
|
|
|
|
private static void SerializeNotationMapFormatted( StringWriter writer, string intend, LLSDMap llsdMap )
|
|
{
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend );
|
|
writer.Write( mapBeginNotationMarker );
|
|
writer.Write( Helpers.NewLine );
|
|
int lastIndex = llsdMap.Count - 1;
|
|
int idx = 0;
|
|
|
|
foreach( KeyValuePair<string, LLSD> kvp in llsdMap )
|
|
{
|
|
writer.Write( intend + baseIntend );
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( EscapeCharacter( kvp.Key, singleQuotesNotationMarker ));
|
|
writer.Write( singleQuotesNotationMarker );
|
|
writer.Write( keyNotationDelimiter );
|
|
SerializeNotationElementFormatted( writer, intend, kvp.Value );
|
|
if ( idx < lastIndex )
|
|
{
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend + baseIntend );
|
|
writer.Write( kommaNotationDelimiter );
|
|
writer.Write( Helpers.NewLine );
|
|
}
|
|
|
|
idx++;
|
|
}
|
|
writer.Write( Helpers.NewLine );
|
|
writer.Write( intend );
|
|
writer.Write( mapEndNotationMarker );
|
|
}
|
|
|
|
public static int PeekAndSkipWhitespace( StringReader reader )
|
|
{
|
|
int character;
|
|
while ((character = reader.Peek()) > 0 )
|
|
{
|
|
char c = (char)character;
|
|
if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' )
|
|
{
|
|
reader.Read();
|
|
continue;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return character;
|
|
}
|
|
|
|
public static int ReadAndSkipWhitespace( StringReader reader )
|
|
{
|
|
int character = PeekAndSkipWhitespace( reader );
|
|
reader.Read();
|
|
return character;
|
|
}
|
|
|
|
public static int GetLengthInBrackets( StringReader reader )
|
|
{
|
|
int character;
|
|
StringBuilder s = new StringBuilder();
|
|
if ((( character = PeekAndSkipWhitespace( reader )) > 0 ) &&
|
|
((char)character == sizeBeginNotationMarker))
|
|
{
|
|
reader.Read();
|
|
}
|
|
while((( character = reader.Read()) > 0) &&
|
|
Char.IsDigit((char)character) &&
|
|
((char) character != sizeEndNotationMarker ))
|
|
{
|
|
s.Append((char)character);
|
|
}
|
|
if ( character < 0 )
|
|
throw new LLSDException( "Notation LLSD parsing: Can't parse length value cause unexpected end of stream." );
|
|
int length;
|
|
if ( !Helpers.TryParse( s.ToString(), out length ))
|
|
throw new LLSDException( "Notation LLSD parsing: Can't parse length value." );
|
|
|
|
return length;
|
|
}
|
|
|
|
public static string GetStringDelimitedBy( StringReader reader, char delimiter )
|
|
{
|
|
int character;
|
|
bool foundEscape = false;
|
|
StringBuilder s = new StringBuilder();
|
|
while( ((character = reader.Read()) > 0 ) &&
|
|
(((char) character != delimiter ) ||
|
|
((char) character == delimiter && foundEscape )))
|
|
{
|
|
|
|
if ( foundEscape )
|
|
{
|
|
foundEscape = false;
|
|
switch((char)character)
|
|
{
|
|
case 'a':
|
|
s.Append( '\a' );
|
|
break;
|
|
case 'b':
|
|
s.Append( '\b' );
|
|
break;
|
|
case 'f':
|
|
s.Append( '\f' );
|
|
break;
|
|
case 'n':
|
|
s.Append( '\n' );
|
|
break;
|
|
case 'r':
|
|
s.Append( '\r' );
|
|
break;
|
|
case 't':
|
|
s.Append( '\t' );
|
|
break;
|
|
case 'v':
|
|
s.Append( '\v' );
|
|
break;
|
|
default:
|
|
s.Append((char)character);
|
|
break;
|
|
}
|
|
}
|
|
else if ((char)character == '\\')
|
|
foundEscape = true;
|
|
else
|
|
s.Append((char)character);
|
|
|
|
}
|
|
if ( character < 0)
|
|
throw new LLSDException( "Notation LLSD parsing: Can't parse text because unexpected end of stream while expecting a '"
|
|
+ delimiter + "' character." );
|
|
|
|
return s.ToString();
|
|
}
|
|
|
|
public static int BufferCharactersEqual( StringReader reader, char[] buffer, int offset ) {
|
|
|
|
int character;
|
|
int lastIndex = buffer.Length - 1;
|
|
int crrIndex = offset;
|
|
bool charactersEqual = true;
|
|
|
|
while (( character = reader.Peek()) > 0 &&
|
|
crrIndex <= lastIndex &&
|
|
charactersEqual )
|
|
{
|
|
if (((char) character) != buffer[crrIndex] )
|
|
{
|
|
charactersEqual = false;
|
|
break;
|
|
}
|
|
crrIndex++;
|
|
reader.Read();
|
|
}
|
|
|
|
return crrIndex;
|
|
}
|
|
|
|
public static string UnescapeCharacter( String s, char c )
|
|
{
|
|
string oldOne = "\\" + c;
|
|
string newOne = new String( c, 1 );
|
|
|
|
String sOne = s.Replace( "\\\\", "\\" ).Replace( oldOne, newOne );
|
|
return sOne;
|
|
}
|
|
|
|
public static string EscapeCharacter( String s, char c )
|
|
{
|
|
string oldOne = new String( c, 1 );
|
|
string newOne = "\\" + c;
|
|
|
|
String sOne = s.Replace( "\\", "\\\\" ).Replace( oldOne, newOne );
|
|
return sOne;
|
|
}
|
|
}
|
|
}
|