22using System ;
33using System . Collections ;
44using System . Collections . Generic ;
5+ using System . Text ;
56using System . Text . RegularExpressions ;
67
8+
79namespace UnityEditor . XCodeEditor
810{
911 public class PBXParser
1012 {
13+ public const string PBX_HEADER_TOKEN = "// !$*UTF8*$!\n " ;
1114 public const char WHITESPACE_SPACE = ' ' ;
1215 public const char WHITESPACE_TAB = '\t ' ;
1316 public const char WHITESPACE_NEWLINE = '\n ' ;
@@ -26,16 +29,18 @@ public class PBXParser
2629 public const string COMMENT_BEGIN_TOKEN = "/*" ;
2730 public const string COMMENT_END_TOKEN = "*/" ;
2831 public const string COMMENT_LINE_TOKEN = "//" ;
32+ private const int BUILDER_CAPACITY = 10000 ;
2933
3034 //
3135 private char [ ] data ;
3236 private int index ;
33- // private bool success;
37+ // public bool success;
38+ private int indent ;
3439
3540 public object Decode ( string data )
3641 {
3742// success = true;
38- if ( ! data . StartsWith ( "// !$*UTF8*$!" ) ) {
43+ if ( ! data . StartsWith ( PBX_HEADER_TOKEN ) ) {
3944 Debug . Log ( "Wrong file format." ) ;
4045 return null ;
4146 }
@@ -45,6 +50,16 @@ public object Decode( string data )
4550 return Parse ( ) ;
4651 }
4752
53+ public string Encode ( Dictionary < string , object > pbxData , bool readable = false )
54+ {
55+ indent = 0 ;
56+
57+ StringBuilder builder = new StringBuilder ( PBX_HEADER_TOKEN , BUILDER_CAPACITY ) ;
58+ bool success = SerializeValue ( pbxData , builder , readable ) ;
59+
60+ return ( success ? builder . ToString ( ) : null ) ;
61+ }
62+
4863 #region Move
4964
5065 private char NextToken ( )
@@ -218,7 +233,8 @@ private object ParseValue()
218233 private object ParseDictionary ( )
219234 {
220235 SkipWhitespaces ( ) ;
221- Hashtable dictionary = new Hashtable ( ) ;
236+ // Hashtable dictionary = new Hashtable();
237+ Dictionary < string , object > dictionary = new Dictionary < string , object > ( ) ;
222238 string keyString = string . Empty ;
223239 object valueObject = null ;
224240
@@ -345,6 +361,7 @@ private object ParseString()
345361
346362 c = StepForeward ( ) ;
347363 }
364+
348365 return s ;
349366
350367// def parse_string(self):
@@ -394,6 +411,181 @@ private object ParseEntity()
394411 }
395412
396413 #endregion
414+ #region Serialize
415+
416+ private bool SerializeValue ( object value , StringBuilder builder , bool readable = false )
417+ {
418+ if ( value == null ) {
419+ builder . Append ( "null" ) ;
420+ }
421+ else if ( value is Dictionary < string , object > ) {
422+ SerializeDictionary ( ( Dictionary < string , object > ) value , builder , readable ) ;
423+ }
424+ else if ( value . GetType ( ) . IsArray ) {
425+ SerializeArray ( new ArrayList ( ( ICollection ) value ) , builder , readable ) ;
426+ }
427+ else if ( value is ArrayList ) {
428+ SerializeArray ( ( ArrayList ) value , builder , readable ) ;
429+ }
430+ else if ( value is string ) {
431+ SerializeString ( ( string ) value , builder , readable ) ;
432+ }
433+ else if ( value is Char ) {
434+ SerializeString ( Convert . ToString ( ( char ) value ) , builder , readable ) ;
435+ }
436+ else if ( value . GetType ( ) . IsPrimitive ) {
437+ // SerializeNumber( Convert.ToDouble( value ), builder );
438+ builder . Append ( Convert . ToString ( value ) ) ;
439+ }
440+ // else if( value is Hashtable )
441+ // {
442+ // serializeObject( (Hashtable)value, builder );
443+ // }
444+ // else if( ( value is Boolean ) && ( (Boolean)value == true ) )
445+ // {
446+ // builder.Append( "true" );
447+ // }
448+ // else if( ( value is Boolean ) && ( (Boolean)value == false ) )
449+ // {
450+ // builder.Append( "false" );
451+ // }
452+ else {
453+ return false ;
454+ }
455+
456+ return true ;
457+ }
458+
459+ private bool SerializeDictionary ( Dictionary < string , object > dictionary , StringBuilder builder , bool readable = false )
460+ {
461+
462+ builder . Append ( DICTIONARY_BEGIN_TOKEN ) ;
463+
464+ // bool first = true;
465+ foreach ( KeyValuePair < string , object > pair in dictionary ) {
466+ // if( !first )
467+ // builder.Append( DICTIONARY_ITEM_DELIMITER_TOKEN );
468+
469+ SerializeString ( pair . Key , builder ) ;
470+ builder . Append ( DICTIONARY_ASSIGN_TOKEN ) ;
471+ SerializeValue ( pair . Value , builder ) ;
472+ builder . Append ( DICTIONARY_ITEM_DELIMITER_TOKEN ) ;
473+ // first = false;
474+ }
475+
476+ builder . Append ( DICTIONARY_END_TOKEN ) ;
477+ return true ;
478+ }
479+
480+ private bool SerializeArray ( ArrayList anArray , StringBuilder builder , bool readable = false )
481+ {
482+ builder . Append ( ARRAY_BEGIN_TOKEN ) ;
483+
484+ // bool first = true;
485+ for ( int i = 0 ; i < anArray . Count ; i ++ )
486+ {
487+ object value = anArray [ i ] ;
488+
489+ // if( !first )
490+ // {
491+ // builder.Append( ARRAY_ITEM_DELIMITER_TOKEN );
492+ // }
493+
494+ if ( ! SerializeValue ( value , builder ) )
495+ {
496+ return false ;
497+ }
498+
499+ builder . Append ( ARRAY_ITEM_DELIMITER_TOKEN ) ;
500+ // first = false;
501+ }
502+
503+ builder . Append ( ARRAY_END_TOKEN ) ;
504+ return true ;
505+ }
397506
507+ private bool SerializeString ( string aString , StringBuilder builder , bool useQuotes = false , bool readable = false )
508+ {
509+ // Is a GUID?
510+ if ( Regex . IsMatch ( aString , @"^[A-F0-9]{24}$" ) ) {
511+ builder . Append ( aString ) ;
512+ return true ;
513+ }
514+
515+ // Is an empty string?
516+ if ( string . IsNullOrEmpty ( aString ) ) {
517+ builder . Append ( QUOTEDSTRING_BEGIN_TOKEN ) ;
518+ builder . Append ( QUOTEDSTRING_END_TOKEN ) ;
519+ return true ;
520+ }
521+
522+ if ( ! Regex . IsMatch ( aString , @"^[A-Za-z0-9_.]+$" ) ) {
523+ useQuotes = true ;
524+ }
525+
526+ if ( useQuotes )
527+ builder . Append ( QUOTEDSTRING_BEGIN_TOKEN ) ;
528+
529+ builder . Append ( aString ) ;
530+
531+ // char[] charArray = aString.ToCharArray();
532+ // for( int i = 0; i < charArray.Length; i++ )
533+ // {
534+ // char c = charArray[i];
535+ // if( c == '"' )
536+ // {
537+ // builder.Append( "\"" );
538+ // }
539+ // else if( c == '\\' )
540+ // {
541+ // builder.Append( "\\\\" );
542+ // }
543+ // else if( c == '\b' )
544+ // {
545+ // builder.Append( "\\b" );
546+ // }
547+ // else if( c == '\f' )
548+ // {
549+ // builder.Append( "\\f" );
550+ // }
551+ // else if( c == '\n' )
552+ // {
553+ // builder.Append( "\\n" );
554+ // }
555+ // else if( c == '\r' )
556+ // {
557+ // builder.Append( "\\r" );
558+ // }
559+ // else if( c == '\t' )
560+ // {
561+ // builder.Append( "\\t" );
562+ // }
563+ // else
564+ // {
565+ // int codepoint = Convert.ToInt32( c );
566+ // if( ( codepoint >= 32 ) && ( codepoint <= 126 ) )
567+ // {
568+ // builder.Append( c );
569+ // }
570+ // else
571+ // {
572+ // builder.Append( "\\u" + Convert.ToString( codepoint, 16 ).PadLeft( 4, '0' ) );
573+ // }
574+ // }
575+ // }
576+
577+ if ( useQuotes )
578+ builder . Append ( QUOTEDSTRING_END_TOKEN ) ;
579+
580+ return true ;
581+ }
582+
583+ // private bool SerializeNumber( int number, StringBuilder builder )
584+ // {
585+ // builder.Append( Convert.ToString( number ) ); // , CultureInfo.InvariantCulture));
586+ // return true;
587+ // }
588+
589+ #endregion
398590 }
399591}
0 commit comments