Skip to content

Commit

Permalink
Parser and serializer worksfine on a pbxproj file.
Browse files Browse the repository at this point in the history
  • Loading branch information
dcariola committed Sep 19, 2012
1 parent 773587d commit 21ed82e
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 12 deletions.
198 changes: 195 additions & 3 deletions PBXParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
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';
Expand All @@ -26,16 +29,18 @@ public class PBXParser
public const string COMMENT_BEGIN_TOKEN = "/*";
public const string COMMENT_END_TOKEN = "*/";
public const string COMMENT_LINE_TOKEN = "//";
private const int BUILDER_CAPACITY = 10000;

//
private char[] data;
private int index;
// private bool success;
// public bool success;
private int indent;

public object Decode( string data )
{
// success = true;
if( !data.StartsWith( "// !$*UTF8*$!" ) ) {
if( !data.StartsWith( PBX_HEADER_TOKEN ) ) {
Debug.Log( "Wrong file format." );
return null;
}
Expand All @@ -45,6 +50,16 @@ public object Decode( string data )
return Parse();
}

public string Encode( Dictionary<string, object> pbxData, bool readable = false )
{
indent = 0;

StringBuilder builder = new StringBuilder( PBX_HEADER_TOKEN, BUILDER_CAPACITY );
bool success = SerializeValue( pbxData, builder, readable );

return ( success ? builder.ToString() : null );
}

#region Move

private char NextToken()
Expand Down Expand Up @@ -218,7 +233,8 @@ private object ParseValue()
private object ParseDictionary()
{
SkipWhitespaces();
Hashtable dictionary = new Hashtable();
// Hashtable dictionary = new Hashtable();
Dictionary<string, object> dictionary = new Dictionary<string, object>();
string keyString = string.Empty;
object valueObject = null;

Expand Down Expand Up @@ -345,6 +361,7 @@ private object ParseString()

c = StepForeward();
}

return s;

// def parse_string(self):
Expand Down Expand Up @@ -394,6 +411,181 @@ private object ParseEntity()
}

#endregion
#region Serialize

private bool SerializeValue( object value, StringBuilder builder, bool readable = false )
{
if( value == null ) {
builder.Append( "null" );
}
else if( value is Dictionary<string, object> ) {
SerializeDictionary( (Dictionary<string, object> )value, builder, readable );
}
else if( value.GetType().IsArray ) {
SerializeArray( new ArrayList( (ICollection)value ), builder, readable );
}
else if( value is ArrayList ) {
SerializeArray( (ArrayList)value, builder, readable );
}
else if( value is string ) {
SerializeString( (string)value, builder, readable );
}
else if( value is Char ) {
SerializeString( Convert.ToString( (char)value ), builder, readable );
}
else if( value.GetType().IsPrimitive ) {
// SerializeNumber( Convert.ToDouble( value ), builder );
builder.Append( Convert.ToString( value ) );
}
// else if( value is Hashtable )
// {
// serializeObject( (Hashtable)value, builder );
// }
// else if( ( value is Boolean ) && ( (Boolean)value == true ) )
// {
// builder.Append( "true" );
// }
// else if( ( value is Boolean ) && ( (Boolean)value == false ) )
// {
// builder.Append( "false" );
// }
else {
return false;
}

return true;
}

private bool SerializeDictionary( Dictionary<string, object> dictionary, StringBuilder builder, bool readable = false )
{

builder.Append( DICTIONARY_BEGIN_TOKEN );

// bool first = true;
foreach( KeyValuePair<string, object> pair in dictionary ) {
// if( !first )
// builder.Append( DICTIONARY_ITEM_DELIMITER_TOKEN );

SerializeString( pair.Key, builder );
builder.Append( DICTIONARY_ASSIGN_TOKEN );
SerializeValue( pair.Value, builder );
builder.Append( DICTIONARY_ITEM_DELIMITER_TOKEN );
// first = false;
}

builder.Append( DICTIONARY_END_TOKEN );
return true;
}

private bool SerializeArray( ArrayList anArray, StringBuilder builder, bool readable = false )
{
builder.Append( ARRAY_BEGIN_TOKEN );

// bool first = true;
for( int i = 0; i < anArray.Count; i++ )
{
object value = anArray[i];

// if( !first )
// {
// builder.Append( ARRAY_ITEM_DELIMITER_TOKEN );
// }

if( !SerializeValue( value, builder ) )
{
return false;
}

builder.Append( ARRAY_ITEM_DELIMITER_TOKEN );
// first = false;
}

builder.Append( ARRAY_END_TOKEN );
return true;
}

private bool SerializeString( string aString, StringBuilder builder, bool useQuotes = false, bool readable = false )
{
// Is a GUID?
if( Regex.IsMatch( aString, @"^[A-F0-9]{24}$" ) ) {
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;
}

if( !Regex.IsMatch( aString, @"^[A-Za-z0-9_.]+$" ) ) {
useQuotes = true;
}

if( useQuotes )
builder.Append( QUOTEDSTRING_BEGIN_TOKEN );

builder.Append( aString );

// char[] charArray = aString.ToCharArray();
// for( int i = 0; i < charArray.Length; i++ )
// {
// char c = charArray[i];
// if( c == '"' )
// {
// builder.Append( "\"" );
// }
// else if( c == '\\' )
// {
// builder.Append( "\\\\" );
// }
// else if( c == '\b' )
// {
// builder.Append( "\\b" );
// }
// else if( c == '\f' )
// {
// builder.Append( "\\f" );
// }
// else if( c == '\n' )
// {
// builder.Append( "\\n" );
// }
// else if( c == '\r' )
// {
// builder.Append( "\\r" );
// }
// else if( c == '\t' )
// {
// builder.Append( "\\t" );
// }
// else
// {
// int codepoint = Convert.ToInt32( c );
// if( ( codepoint >= 32 ) && ( codepoint <= 126 ) )
// {
// builder.Append( c );
// }
// else
// {
// builder.Append( "\\u" + Convert.ToString( codepoint, 16 ).PadLeft( 4, '0' ) );
// }
// }
// }

if( useQuotes )
builder.Append( QUOTEDSTRING_END_TOKEN );

return true;
}

// private bool SerializeNumber( int number, StringBuilder builder )
// {
// builder.Append( Convert.ToString( number ) ); // , CultureInfo.InvariantCulture));
// return true;
// }

#endregion
}
}
21 changes: 13 additions & 8 deletions XCProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ namespace UnityEditor.XCodeEditor
{
public class XCProject : System.IDisposable
{
//private XCFileOperationQueue _fileOperrationQueue;
private XCFileOperationQueue _fileOperrationQueue;

// private string _filePath;
private Dictionary<string, string> _datastore;
private Dictionary<string, string> _groups;
private Dictionary<string, string> _configurations;
private Dictionary<string, object> _datastore;
private Dictionary<string, object> _groups;
private Dictionary<string, object> _configurations;
private string _defaultConfigurationName;
private string _rootObjectKey;

Expand Down Expand Up @@ -48,10 +48,15 @@ public XCProject( string filePath ) : this()
string projPath = System.IO.Path.Combine( this.filePath, "project.pbxproj" );
string contents = System.IO.File.OpenText( projPath ).ReadToEnd();
// Debug.Log( System.IO.File.OpenText( projPath ).ReadToEnd );

IDictionary dictionary = (Hashtable)MiniJSON.jsonDecode( contents );

Debug.Log( dictionary );

PBXParser parser = new PBXParser();
_datastore = (Dictionary<string, object>)parser.Decode( contents );
if( _datastore == null ) {
throw new System.Exception( "Project file not found at file path " + filePath );
}

_fileOperrationQueue = new XCFileOperationQueue();
_groups = new Dictionary<string, object>();

// if ((self = [super init])) {
// _filePath = [filePath copy];
Expand Down
6 changes: 5 additions & 1 deletion XCodeEditorMenu.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace UnityEditor.XCodeEditor
Expand Down Expand Up @@ -32,8 +33,11 @@ static void DebugTest2()
// Debug.Log( System.IO.File.OpenText( projPath ).ReadToEnd );

PBXParser parser = new PBXParser();
Hashtable test = (Hashtable)parser.Decode( contents );
// Hashtable test = (Hashtable)parser.Decode( contents );
Dictionary<string, object> test = (Dictionary<string, object>)parser.Decode( contents );
Debug.Log( MiniJSON.jsonEncode( test ) );
Debug.Log( test + " - " + test.Count );
Debug.Log( parser.Encode( test ) );
}

}
Expand Down

0 comments on commit 21ed82e

Please sign in to comment.