/Assets/Facebook/Editor/iOS/third_party/XCodeEditor-for-Unity/PBXParser.cs
C# | 470 lines | 394 code | 73 blank | 3 comment | 62 complexity | 09536cac680431336f8929fd0d84499b MD5 | raw file
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace UnityEditor.XCodeEditor
- {
- public class PBXParser
- {
- public const string PBX_HEADER_TOKEN = "// !$*UTF8*$!\n";
- public const char WHITESPACE_SPACE = ' ';
- public const char WHITESPACE_TAB = '\t';
- public const char WHITESPACE_NEWLINE = '\n';
- public const char WHITESPACE_CARRIAGE_RETURN = '\r';
- public const char ARRAY_BEGIN_TOKEN = '(';
- public const char ARRAY_END_TOKEN = ')';
- public const char ARRAY_ITEM_DELIMITER_TOKEN = ',';
- public const char DICTIONARY_BEGIN_TOKEN = '{';
- public const char DICTIONARY_END_TOKEN = '}';
- public const char DICTIONARY_ASSIGN_TOKEN = '=';
- public const char DICTIONARY_ITEM_DELIMITER_TOKEN = ';';
- public const char QUOTEDSTRING_BEGIN_TOKEN = '"';
- public const char QUOTEDSTRING_END_TOKEN = '"';
- public const char QUOTEDSTRING_ESCAPE_TOKEN = '\\';
- public const char END_OF_FILE = (char)0x1A;
- public const string COMMENT_BEGIN_TOKEN = "/*";
- public const string COMMENT_END_TOKEN = "*/";
- public const string COMMENT_LINE_TOKEN = "//";
- private const int BUILDER_CAPACITY = 20000;
- private char[] data;
- private int index;
- private int indent;
-
- public PBXDictionary Decode( string data )
- {
- if( !data.StartsWith( PBX_HEADER_TOKEN ) ) {
- Debug.Log( "Wrong file format." );
- return null;
- }
- data = data.Substring( 13 );
- this.data = data.ToCharArray();
- index = 0;
-
- return (PBXDictionary)ParseValue();
- }
- public string Encode( PBXDictionary pbxData)
- {
- indent = 0;
- StringBuilder builder = new StringBuilder( PBX_HEADER_TOKEN, BUILDER_CAPACITY );
- bool success = SerializeValue( pbxData, builder);
- return ( success ? builder.ToString() : null );
- }
- #region Move
- private char NextToken()
- {
- SkipWhitespaces();
- return StepForeward();
- }
-
- private string Peek( int step = 1 )
- {
- string sneak = string.Empty;
- for( int i = 1; i <= step; i++ ) {
- if( data.Length - 1 < index + i ) {
- break;
- }
- sneak += data[ index + i ];
- }
- return sneak;
- }
- private bool SkipWhitespaces()
- {
- bool whitespace = false;
- while( Regex.IsMatch( StepForeward().ToString(), @"\s" ) )
- whitespace = true;
- StepBackward();
-
- if( SkipComments() ) {
- whitespace = true;
- SkipWhitespaces();
- }
- return whitespace;
- }
- private bool SkipComments()
- {
- string s = string.Empty;
- string tag = Peek( 2 );
- switch( tag ) {
- case COMMENT_BEGIN_TOKEN: {
- while( Peek( 2 ).CompareTo( COMMENT_END_TOKEN ) != 0 ) {
- s += StepForeward();
- }
- s += StepForeward( 2 );
- break;
- }
- case COMMENT_LINE_TOKEN: {
- while( !Regex.IsMatch( StepForeward().ToString(), @"\n" ) )
- continue;
- break;
- }
- default:
- return false;
- }
- return true;
- }
-
- private char StepForeward( int step = 1 )
- {
- index = Math.Min( data.Length, index + step );
- return data[ index ];
- }
-
- private char StepBackward( int step = 1 )
- {
- index = Math.Max( 0, index - step );
- return data[ index ];
- }
- #endregion
- #region Parse
- private object ParseValue()
- {
- switch( NextToken() ) {
- case END_OF_FILE:
- Debug.Log( "End of file" );
- return null;
- case DICTIONARY_BEGIN_TOKEN:
- return ParseDictionary();
- case ARRAY_BEGIN_TOKEN:
- return ParseArray();
- case QUOTEDSTRING_BEGIN_TOKEN:
- return ParseString();
- default:
- StepBackward();
- return ParseEntity();
- }
- }
-
- private PBXDictionary ParseDictionary()
- {
- SkipWhitespaces();
- PBXDictionary dictionary = new PBXDictionary();
- string keyString = string.Empty;
- object valueObject = null;
- bool complete = false;
- while( !complete ) {
- switch( NextToken() ) {
- case END_OF_FILE:
- Debug.Log( "Error: reached end of file inside a dictionary: " + index );
- complete = true;
- break;
- case DICTIONARY_ITEM_DELIMITER_TOKEN:
- keyString = string.Empty;
- valueObject = null;
- break;
- case DICTIONARY_END_TOKEN:
- keyString = string.Empty;
- valueObject = null;
- complete = true;
- break;
- case DICTIONARY_ASSIGN_TOKEN:
- valueObject = ParseValue();
- dictionary.Add( keyString, valueObject );
- break;
- default:
- StepBackward();
- keyString = ParseValue() as string;
- break;
- }
- }
- return dictionary;
- }
- private PBXList ParseArray()
- {
- PBXList list = new PBXList();
- bool complete = false;
- while( !complete ) {
- switch( NextToken() ) {
- case END_OF_FILE:
- Debug.Log( "Error: Reached end of file inside a list: " + list );
- complete = true;
- break;
- case ARRAY_END_TOKEN:
- complete = true;
- break;
- case ARRAY_ITEM_DELIMITER_TOKEN:
- break;
- default:
- StepBackward();
- list.Add( ParseValue() );
- break;
- }
- }
- return list;
- }
- private object ParseString()
- {
- string s = string.Empty;
- s += "\"";
- char c = StepForeward();
- while( c != QUOTEDSTRING_END_TOKEN ) {
- s += c;
- if( c == QUOTEDSTRING_ESCAPE_TOKEN )
- s += StepForeward();
- c = StepForeward();
- }
- s += "\"";
- return s;
- }
-
- //there has got to be a better way to do this
- private string GetDataSubstring(int begin, int length)
- {
- string res = string.Empty;
-
-
- for(int i=begin; i<begin+length && i<data.Length; i++)
- {
- res += data[i];
- }
- return res;
- }
-
- private int CountWhitespace(int pos)
- {
- int i=0;
- for(int currPos=pos; currPos<data.Length && Regex.IsMatch( GetDataSubstring(currPos, 1), @"[;,\s=]" ); i++, currPos++) {}
- return i;
- }
-
- private string ParseCommentFollowingWhitespace()
- {
- int currIdx = index+1;
- int whitespaceLength = CountWhitespace(currIdx);
- currIdx += whitespaceLength;
-
- if(currIdx + 1 >= data.Length)
- return "";
-
-
-
- if(data[currIdx] == '/' && data[currIdx+1] == '*')
- {
-
- while(!GetDataSubstring(currIdx, 2).Equals(COMMENT_END_TOKEN))
- {
- if(currIdx >= data.Length)
- {
- Debug.LogError("Unterminated comment found in .pbxproj file. Bad things are probably going to start happening");
- return "";
- }
-
- currIdx++;
- }
-
- return GetDataSubstring (index+1, (currIdx-index+1));
-
- }
- else
- {
- return "";
- }
- }
-
- private object ParseEntity()
- {
- string word = string.Empty;
-
- while(!Regex.IsMatch( Peek(), @"[;,\s=]" ))
- {
- word += StepForeward();
- }
-
- string comment = ParseCommentFollowingWhitespace();
- if(comment.Length > 0)
- {
- word += comment;
- index += comment.Length;
- }
-
- if( word.Length != 24 && Regex.IsMatch( word, @"^\d+$" ) ) {
- return Int32.Parse( word );
- }
-
- return word;
- }
- #endregion
- #region Serialize
-
- private void AppendNewline(StringBuilder builder)
- {
- builder.Append(WHITESPACE_NEWLINE);
- for(int i=0; i<indent; i++)
- {
- builder.Append (WHITESPACE_TAB);
- }
- }
-
- private void AppendLineDelim(StringBuilder builder, bool newline)
- {
- if(newline)
- {
- AppendNewline(builder);
- }
- else
- {
- builder.Append(WHITESPACE_SPACE);
- }
- }
- private bool SerializeValue( object value, StringBuilder builder)
- {
- bool internalNewlines = false;
- if(value is PBXObject)
- {
- internalNewlines = ((PBXObject)value).internalNewlines;
- }
- else if(value is PBXDictionary)
- {
- internalNewlines = ((PBXDictionary)value).internalNewlines;
- }
- else if(value is PBXList)
- {
- internalNewlines = ((PBXList)value).internalNewlines;
- }
-
- if( value == null ) {
- builder.Append( "null" );
- }
- else if( value is PBXObject ) {
- SerializeDictionary( ((PBXObject)value).data, builder, internalNewlines);
- }
- else if( value is PBXDictionary ) {
- SerializeDictionary( (Dictionary<string, object>)value, builder, internalNewlines);
- }
- else if( value is Dictionary<string, object> ) {
- SerializeDictionary( (Dictionary<string, object>)value, builder, internalNewlines);
- }
- else if( value.GetType().IsArray ) {
- SerializeArray( new ArrayList( (ICollection)value ), builder, internalNewlines);
- }
- else if( value is ArrayList ) {
- SerializeArray( (ArrayList)value, builder, internalNewlines);
- }
- else if( value is string ) {
- SerializeString( (string)value, builder);
- }
- else if( value is Char ) {
- SerializeString( Convert.ToString( (char)value ), builder);
- }
- else if( value is bool ) {
- builder.Append( Convert.ToInt32( value ).ToString() );
- }
- else if( value.GetType().IsPrimitive ) {
- builder.Append( Convert.ToString( value ) );
- }
- else {
- Debug.LogWarning( "Error: unknown object of type " + value.GetType().Name );
- return false;
- }
-
- return true;
- }
- private bool SerializeDictionary( Dictionary<string, object> dictionary, StringBuilder builder, bool internalNewlines)
- {
- builder.Append( DICTIONARY_BEGIN_TOKEN );
- if(dictionary.Count > 0)
- indent++;
- if(internalNewlines)
- AppendNewline(builder);
-
- int i=0;
- foreach( KeyValuePair<string, object> pair in dictionary ) {
- SerializeString( pair.Key, builder );
- builder.Append( WHITESPACE_SPACE );
- builder.Append( DICTIONARY_ASSIGN_TOKEN );
- builder.Append( WHITESPACE_SPACE );
- SerializeValue( pair.Value, builder );
- builder.Append( DICTIONARY_ITEM_DELIMITER_TOKEN );
-
- if(i == dictionary.Count-1)
- indent--;
- AppendLineDelim(builder, internalNewlines);
- i++;
- }
-
- builder.Append( DICTIONARY_END_TOKEN );
- return true;
- }
- private bool SerializeArray( ArrayList anArray, StringBuilder builder, bool internalNewlines)
- {
- builder.Append( ARRAY_BEGIN_TOKEN );
- if(anArray.Count > 0)
- indent++;
- if(internalNewlines)
- AppendNewline(builder);
-
-
- for( int i = 0; i < anArray.Count; i++ )
- {
- object value = anArray[i];
-
- if( !SerializeValue( value, builder ) )
- {
- return false;
- }
-
- builder.Append( ARRAY_ITEM_DELIMITER_TOKEN );
-
- if(i == anArray.Count-1)
- indent--;
- AppendLineDelim(builder, internalNewlines);
- }
-
- builder.Append( ARRAY_END_TOKEN );
- return true;
- }
- private bool SerializeString( string aString, StringBuilder builder)
- {
- // Is a GUID?
- if(PBXObject.IsGuid(aString)) {
- builder.Append( aString );
- return true;
- }
- // Is an empty string?
- if( string.IsNullOrEmpty( aString ) ) {
- builder.Append( QUOTEDSTRING_BEGIN_TOKEN );
- builder.Append( QUOTEDSTRING_END_TOKEN );
- return true;
- }
- builder.Append( aString );
- return true;
- }
- #endregion
- }
- }