AR骑行人物控制代码重构&build混淆代码
This commit is contained in:
1 parent
7822584cdd
commit
2c9440f656
78 files changed
+562
-8031
No files matched your search
@@ -1,106 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
|
||||
class PBXElement
|
||||
{
|
||||
protected PBXElement() {}
|
||||
|
||||
// convenience methods
|
||||
public string AsString() { return ((PBXElementString)this).value; }
|
||||
public PBXElementArray AsArray() { return (PBXElementArray)this; }
|
||||
public PBXElementDict AsDict() { return (PBXElementDict)this; }
|
||||
|
||||
public PBXElement this[string key]
|
||||
{
|
||||
get { return AsDict()[key]; }
|
||||
set { AsDict()[key] = value; }
|
||||
}
|
||||
}
|
||||
|
||||
class PBXElementString : PBXElement
|
||||
{
|
||||
public PBXElementString(string v) { value = v; }
|
||||
|
||||
public string value;
|
||||
}
|
||||
|
||||
class PBXElementDict : PBXElement
|
||||
{
|
||||
public PBXElementDict() : base() {}
|
||||
|
||||
private Dictionary<string, PBXElement> m_PrivateValue = new Dictionary<string, PBXElement>();
|
||||
public IDictionary<string, PBXElement> values { get { return m_PrivateValue; }}
|
||||
|
||||
new public PBXElement this[string key]
|
||||
{
|
||||
get {
|
||||
if (values.ContainsKey(key))
|
||||
return values[key];
|
||||
return null;
|
||||
}
|
||||
set { this.values[key] = value; }
|
||||
}
|
||||
|
||||
public bool Contains(string key)
|
||||
{
|
||||
return values.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
values.Remove(key);
|
||||
}
|
||||
|
||||
public void SetString(string key, string val)
|
||||
{
|
||||
values[key] = new PBXElementString(val);
|
||||
}
|
||||
|
||||
public PBXElementArray CreateArray(string key)
|
||||
{
|
||||
var v = new PBXElementArray();
|
||||
values[key] = v;
|
||||
return v;
|
||||
}
|
||||
|
||||
public PBXElementDict CreateDict(string key)
|
||||
{
|
||||
var v = new PBXElementDict();
|
||||
values[key] = v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
class PBXElementArray : PBXElement
|
||||
{
|
||||
public PBXElementArray() : base() {}
|
||||
public List<PBXElement> values = new List<PBXElement>();
|
||||
|
||||
// convenience methods
|
||||
public void AddString(string val)
|
||||
{
|
||||
values.Add(new PBXElementString(val));
|
||||
}
|
||||
|
||||
public PBXElementArray AddArray()
|
||||
{
|
||||
var v = new PBXElementArray();
|
||||
values.Add(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
public PBXElementDict AddDict()
|
||||
{
|
||||
var v = new PBXElementDict();
|
||||
values.Add(v);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UnityEditor.iOS.Xcode
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83cffec4be0e045258109e9714cdaa5f
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,243 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
enum TokenType
|
||||
{
|
||||
EOF,
|
||||
Invalid,
|
||||
String,
|
||||
QuotedString,
|
||||
Comment,
|
||||
|
||||
Semicolon, // ;
|
||||
Comma, // ,
|
||||
Eq, // =
|
||||
LParen, // (
|
||||
RParen, // )
|
||||
LBrace, // {
|
||||
RBrace, // }
|
||||
}
|
||||
|
||||
class Token
|
||||
{
|
||||
public TokenType type;
|
||||
|
||||
// the line of the input stream the token starts in (0-based)
|
||||
public int line;
|
||||
|
||||
// start and past-the-end positions of the token in the input stream
|
||||
public int begin, end;
|
||||
}
|
||||
|
||||
class TokenList : List<Token>
|
||||
{
|
||||
}
|
||||
|
||||
class Lexer
|
||||
{
|
||||
string text;
|
||||
int pos;
|
||||
int length;
|
||||
int line;
|
||||
|
||||
public static TokenList Tokenize(string text)
|
||||
{
|
||||
var lexer = new Lexer();
|
||||
lexer.SetText(text);
|
||||
return lexer.ScanAll();
|
||||
}
|
||||
|
||||
public void SetText(string text)
|
||||
{
|
||||
this.text = text + " "; // to prevent out-of-bounds access during look ahead
|
||||
pos = 0;
|
||||
length = text.Length;
|
||||
line = 0;
|
||||
}
|
||||
|
||||
public TokenList ScanAll()
|
||||
{
|
||||
var tokens = new TokenList();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var tok = new Token();
|
||||
ScanOne(tok);
|
||||
tokens.Add(tok);
|
||||
if (tok.type == TokenType.EOF)
|
||||
break;
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
void UpdateNewlineStats(char ch)
|
||||
{
|
||||
if (ch == '\n')
|
||||
line++;
|
||||
}
|
||||
|
||||
// tokens list is modified in the case when we add BrokenLine token and need to remove already
|
||||
// added tokens for the current line
|
||||
void ScanOne(Token tok)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
while (pos < length && Char.IsWhiteSpace(text[pos]))
|
||||
{
|
||||
UpdateNewlineStats(text[pos]);
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos >= length)
|
||||
{
|
||||
tok.type = TokenType.EOF;
|
||||
break;
|
||||
}
|
||||
|
||||
char ch = text[pos];
|
||||
char ch2 = text[pos+1];
|
||||
|
||||
if (ch == '\"')
|
||||
ScanQuotedString(tok);
|
||||
else if (ch == '/' && ch2 == '*')
|
||||
ScanMultilineComment(tok);
|
||||
else if (ch == '/' && ch2 == '/')
|
||||
ScanComment(tok);
|
||||
else if (IsOperator(ch))
|
||||
ScanOperator(tok);
|
||||
else
|
||||
ScanString(tok); // be more robust and accept whatever is left
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanString(Token tok)
|
||||
{
|
||||
tok.type = TokenType.String;
|
||||
tok.begin = pos;
|
||||
while (pos < length)
|
||||
{
|
||||
char ch = text[pos];
|
||||
char ch2 = text[pos+1];
|
||||
|
||||
if (Char.IsWhiteSpace(ch))
|
||||
break;
|
||||
else if (ch == '\"')
|
||||
break;
|
||||
else if (ch == '/' && ch2 == '*')
|
||||
break;
|
||||
else if (ch == '/' && ch2 == '/')
|
||||
break;
|
||||
else if (IsOperator(ch))
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
tok.end = pos;
|
||||
tok.line = line;
|
||||
}
|
||||
|
||||
void ScanQuotedString(Token tok)
|
||||
{
|
||||
tok.type = TokenType.QuotedString;
|
||||
tok.begin = pos;
|
||||
pos++;
|
||||
|
||||
while (pos < length)
|
||||
{
|
||||
// ignore escaped quotes
|
||||
if (text[pos] == '\\' && text[pos+1] == '\"')
|
||||
{
|
||||
pos += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// note that we close unclosed quotes
|
||||
if (text[pos] == '\"')
|
||||
break;
|
||||
|
||||
UpdateNewlineStats(text[pos]);
|
||||
pos++;
|
||||
}
|
||||
pos++;
|
||||
tok.end = pos;
|
||||
tok.line = line;
|
||||
}
|
||||
|
||||
void ScanMultilineComment(Token tok)
|
||||
{
|
||||
tok.type = TokenType.Comment;
|
||||
tok.begin = pos;
|
||||
pos += 2;
|
||||
|
||||
while (pos < length)
|
||||
{
|
||||
if (text[pos] == '*' && text[pos+1] == '/')
|
||||
break;
|
||||
|
||||
// we support multiline comments
|
||||
UpdateNewlineStats(text[pos]);
|
||||
pos++;
|
||||
}
|
||||
pos += 2;
|
||||
tok.end = pos;
|
||||
tok.line = line;
|
||||
}
|
||||
|
||||
void ScanComment(Token tok)
|
||||
{
|
||||
tok.type = TokenType.Comment;
|
||||
tok.begin = pos;
|
||||
pos += 2;
|
||||
|
||||
while (pos < length)
|
||||
{
|
||||
if (text[pos] == '\n')
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
UpdateNewlineStats(text[pos]);
|
||||
pos++;
|
||||
tok.end = pos;
|
||||
tok.line = line;
|
||||
}
|
||||
|
||||
bool IsOperator(char ch)
|
||||
{
|
||||
if (ch == ';' || ch == ',' || ch == '=' || ch == '(' || ch == ')' || ch == '{' || ch == '}')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScanOperator(Token tok)
|
||||
{
|
||||
switch (text[pos])
|
||||
{
|
||||
case ';': ScanOperatorSpecific(tok, TokenType.Semicolon); return;
|
||||
case ',': ScanOperatorSpecific(tok, TokenType.Comma); return;
|
||||
case '=': ScanOperatorSpecific(tok, TokenType.Eq); return;
|
||||
case '(': ScanOperatorSpecific(tok, TokenType.LParen); return;
|
||||
case ')': ScanOperatorSpecific(tok, TokenType.RParen); return;
|
||||
case '{': ScanOperatorSpecific(tok, TokenType.LBrace); return;
|
||||
case '}': ScanOperatorSpecific(tok, TokenType.RBrace); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanOperatorSpecific(Token tok, TokenType type)
|
||||
{
|
||||
tok.type = type;
|
||||
tok.begin = pos;
|
||||
pos++;
|
||||
tok.end = pos;
|
||||
tok.line = line;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace UnityEditor.iOS.Xcode
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9766f6c4eb5ef42f99c0d5f86e34ba84
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67cf10cf994604c719f706525399f867
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,171 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
|
||||
class ValueAST {}
|
||||
|
||||
// IdentifierAST := <quoted string> \ <string>
|
||||
class IdentifierAST : ValueAST
|
||||
{
|
||||
public int value = 0; // token id
|
||||
}
|
||||
|
||||
// TreeAST := '{' KeyValuePairList '}'
|
||||
// KeyValuePairList := KeyValuePair ',' KeyValuePairList
|
||||
// KeyValuePair ','
|
||||
// (empty)
|
||||
class TreeAST : ValueAST
|
||||
{
|
||||
public List<KeyValueAST> values = new List<KeyValueAST>();
|
||||
}
|
||||
|
||||
// ListAST := '(' ValueList ')'
|
||||
// ValueList := ValueAST ',' ValueList
|
||||
// ValueAST ','
|
||||
// (empty)
|
||||
class ArrayAST : ValueAST
|
||||
{
|
||||
public List<ValueAST> values = new List<ValueAST>();
|
||||
}
|
||||
|
||||
// KeyValueAST := IdentifierAST '=' ValueAST ';'
|
||||
// ValueAST := IdentifierAST | TreeAST | ListAST
|
||||
class KeyValueAST
|
||||
{
|
||||
public IdentifierAST key = null;
|
||||
public ValueAST value = null; // either IdentifierAST, TreeAST or ListAST
|
||||
}
|
||||
|
||||
class Parser
|
||||
{
|
||||
TokenList tokens;
|
||||
int currPos;
|
||||
|
||||
public Parser(TokenList tokens)
|
||||
{
|
||||
this.tokens = tokens;
|
||||
currPos = SkipComments(0);
|
||||
}
|
||||
|
||||
int SkipComments(int pos)
|
||||
{
|
||||
while (pos < tokens.Count && tokens[pos].type == TokenType.Comment)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
// returns new position
|
||||
int IncInternal(int pos)
|
||||
{
|
||||
if (pos >= tokens.Count)
|
||||
return pos;
|
||||
pos++;
|
||||
|
||||
return SkipComments(pos);
|
||||
}
|
||||
|
||||
// Increments current pointer if not past the end, returns previous pos
|
||||
int Inc()
|
||||
{
|
||||
int prev = currPos;
|
||||
currPos = IncInternal(currPos);
|
||||
return prev;
|
||||
}
|
||||
|
||||
// Returns the token type of the current token
|
||||
TokenType Tok()
|
||||
{
|
||||
if (currPos >= tokens.Count)
|
||||
return TokenType.EOF;
|
||||
return tokens[currPos].type;
|
||||
}
|
||||
|
||||
void SkipIf(TokenType type)
|
||||
{
|
||||
if (Tok() == type)
|
||||
Inc();
|
||||
}
|
||||
|
||||
string GetErrorMsg()
|
||||
{
|
||||
return "Invalid PBX project (parsing line " + tokens[currPos].line + ")";
|
||||
}
|
||||
|
||||
public IdentifierAST ParseIdentifier()
|
||||
{
|
||||
if (Tok() != TokenType.String && Tok() != TokenType.QuotedString)
|
||||
throw new Exception(GetErrorMsg());
|
||||
var ast = new IdentifierAST();
|
||||
ast.value = Inc();
|
||||
return ast;
|
||||
}
|
||||
|
||||
public TreeAST ParseTree()
|
||||
{
|
||||
if (Tok() != TokenType.LBrace)
|
||||
throw new Exception(GetErrorMsg());
|
||||
Inc();
|
||||
|
||||
var ast = new TreeAST();
|
||||
while (Tok() != TokenType.RBrace && Tok() != TokenType.EOF)
|
||||
{
|
||||
ast.values.Add(ParseKeyValue());
|
||||
}
|
||||
SkipIf(TokenType.RBrace);
|
||||
return ast;
|
||||
}
|
||||
|
||||
public ArrayAST ParseList()
|
||||
{
|
||||
if (Tok() != TokenType.LParen)
|
||||
throw new Exception(GetErrorMsg());
|
||||
Inc();
|
||||
|
||||
var ast = new ArrayAST();
|
||||
while (Tok() != TokenType.RParen && Tok() != TokenType.EOF)
|
||||
{
|
||||
ast.values.Add(ParseValue());
|
||||
SkipIf(TokenType.Comma);
|
||||
}
|
||||
SkipIf(TokenType.RParen);
|
||||
return ast;
|
||||
}
|
||||
|
||||
// throws on error
|
||||
public KeyValueAST ParseKeyValue()
|
||||
{
|
||||
var ast = new KeyValueAST();
|
||||
ast.key = ParseIdentifier();
|
||||
|
||||
if (Tok() != TokenType.Eq)
|
||||
throw new Exception(GetErrorMsg());
|
||||
Inc(); // skip '='
|
||||
|
||||
ast.value = ParseValue();
|
||||
SkipIf(TokenType.Semicolon);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
// throws on error
|
||||
public ValueAST ParseValue()
|
||||
{
|
||||
if (Tok() == TokenType.String || Tok() == TokenType.QuotedString)
|
||||
return ParseIdentifier();
|
||||
else if (Tok() == TokenType.LBrace)
|
||||
return ParseTree();
|
||||
else if (Tok() == TokenType.LParen)
|
||||
return ParseList();
|
||||
throw new Exception(GetErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UnityEditor.iOS.Xcode
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ce5a244bc4e04a668ab097db4456665
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,122 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
// Basr classes for section handling
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
|
||||
// common base
|
||||
internal abstract class SectionBase
|
||||
{
|
||||
public abstract void AddObject(string key, PBXElementDict value);
|
||||
public abstract void WriteSection(StringBuilder sb, GUIDToCommentMap comments);
|
||||
}
|
||||
|
||||
// known section: contains objects that we care about
|
||||
internal class KnownSectionBase<T> : SectionBase where T : PBXObjectData, new()
|
||||
{
|
||||
private Dictionary<string, T> m_Entries = new Dictionary<string, T>();
|
||||
|
||||
private string m_Name;
|
||||
|
||||
public KnownSectionBase(string sectionName)
|
||||
{
|
||||
m_Name = sectionName;
|
||||
}
|
||||
|
||||
public IEnumerable<KeyValuePair<string, T>> GetEntries()
|
||||
{
|
||||
return m_Entries;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetGuids()
|
||||
{
|
||||
return m_Entries.Keys;
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetObjects()
|
||||
{
|
||||
return m_Entries.Values;
|
||||
}
|
||||
|
||||
public override void AddObject(string key, PBXElementDict value)
|
||||
{
|
||||
T obj = new T();
|
||||
obj.guid = key;
|
||||
obj.SetPropertiesWhenSerializing(value);
|
||||
obj.UpdateVars();
|
||||
m_Entries[obj.guid] = obj;
|
||||
}
|
||||
|
||||
public override void WriteSection(StringBuilder sb, GUIDToCommentMap comments)
|
||||
{
|
||||
if (m_Entries.Count == 0)
|
||||
return; // do not write empty sections
|
||||
|
||||
sb.AppendFormat("\n\n/* Begin {0} section */", m_Name);
|
||||
var keys = new List<string>(m_Entries.Keys);
|
||||
keys.Sort(StringComparer.Ordinal);
|
||||
foreach (string key in keys)
|
||||
{
|
||||
T obj = m_Entries[key];
|
||||
obj.UpdateProps();
|
||||
sb.Append("\n\t\t");
|
||||
comments.WriteStringBuilder(sb, obj.guid);
|
||||
sb.Append(" = ");
|
||||
Serializer.WriteDict(sb, obj.GetPropertiesWhenSerializing(), 2,
|
||||
obj.shouldCompact, obj.checker, comments);
|
||||
sb.Append(";");
|
||||
}
|
||||
sb.AppendFormat("\n/* End {0} section */", m_Name);
|
||||
}
|
||||
|
||||
// returns null if not found
|
||||
public T this[string guid]
|
||||
{
|
||||
get {
|
||||
if (m_Entries.ContainsKey(guid))
|
||||
return m_Entries[guid];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasEntry(string guid)
|
||||
{
|
||||
return m_Entries.ContainsKey(guid);
|
||||
}
|
||||
|
||||
public void AddEntry(T obj)
|
||||
{
|
||||
m_Entries[obj.guid] = obj;
|
||||
}
|
||||
|
||||
public void RemoveEntry(string guid)
|
||||
{
|
||||
if (m_Entries.ContainsKey(guid))
|
||||
m_Entries.Remove(guid);
|
||||
}
|
||||
}
|
||||
|
||||
// we assume there is only one PBXProject entry
|
||||
internal class PBXProjectSection : KnownSectionBase<PBXProjectObjectData>
|
||||
{
|
||||
public PBXProjectSection() : base("PBXProject")
|
||||
{
|
||||
}
|
||||
|
||||
public PBXProjectObjectData project
|
||||
{
|
||||
get {
|
||||
foreach (var kv in GetEntries())
|
||||
return kv.Value;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // UnityEditor.iOS.Xcode
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60639b138b83f4ce9b2448c38a6ba285
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,259 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
class PropertyCommentChecker
|
||||
{
|
||||
private int m_Level;
|
||||
private bool m_All;
|
||||
private List<List<string>> m_Props;
|
||||
|
||||
/* The argument is an array of matcher strings each of which determine
|
||||
whether a property with a certain path needs to be decorated with a
|
||||
comment.
|
||||
|
||||
A path is a number of path elements concatenated by '/'. The last path
|
||||
element is either:
|
||||
the key if we're referring to a dict key
|
||||
the value if we're referring to a value in an array
|
||||
the value if we're referring to a value in a dict
|
||||
All other path elements are either:
|
||||
the key if the container is dict
|
||||
'*' if the container is array
|
||||
|
||||
Path matcher has the same structure as a path, except that any of the
|
||||
elements may be '*'. Matcher matches a path if both have the same number
|
||||
of elements and for each pair matcher element is the same as path element
|
||||
or is '*'.
|
||||
|
||||
a/b/c matches a/b/c but not a/b nor a/b/c/d
|
||||
a/* /c matches a/d/c but not a/b nor a/b/c/d
|
||||
* /* /* matches any path from three elements
|
||||
*/
|
||||
protected PropertyCommentChecker(int level, List<List<string>> props)
|
||||
{
|
||||
m_Level = level;
|
||||
m_All = false;
|
||||
m_Props = props;
|
||||
}
|
||||
|
||||
public PropertyCommentChecker()
|
||||
{
|
||||
m_Level = 0;
|
||||
m_All = false;
|
||||
m_Props = new List<List<string>>();
|
||||
}
|
||||
|
||||
public PropertyCommentChecker(IEnumerable<string> props)
|
||||
{
|
||||
m_Level = 0;
|
||||
m_All = false;
|
||||
m_Props = new List<List<string>>();
|
||||
foreach (var prop in props)
|
||||
{
|
||||
m_Props.Add(new List<string>(prop.Split('/')));
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckContained(string prop)
|
||||
{
|
||||
if (m_All)
|
||||
return true;
|
||||
foreach (var list in m_Props)
|
||||
{
|
||||
if (list.Count == m_Level+1)
|
||||
{
|
||||
if (list[m_Level] == prop)
|
||||
return true;
|
||||
if (list[m_Level] == "*")
|
||||
{
|
||||
m_All = true; // short-circuit all at this level
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CheckStringValueInArray(string value) { return CheckContained(value); }
|
||||
public bool CheckKeyInDict(string key) { return CheckContained(key); }
|
||||
|
||||
public bool CheckStringValueInDict(string key, string value)
|
||||
{
|
||||
foreach (var list in m_Props)
|
||||
{
|
||||
if (list.Count == m_Level + 2)
|
||||
{
|
||||
if ((list[m_Level] == "*" || list[m_Level] == key) &&
|
||||
list[m_Level+1] == "*" || list[m_Level+1] == value)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public PropertyCommentChecker NextLevel(string prop)
|
||||
{
|
||||
var newList = new List<List<string>>();
|
||||
foreach (var list in m_Props)
|
||||
{
|
||||
if (list.Count <= m_Level+1)
|
||||
continue;
|
||||
if (list[m_Level] == "*" || list[m_Level] == prop)
|
||||
newList.Add(list);
|
||||
}
|
||||
return new PropertyCommentChecker(m_Level + 1, newList);
|
||||
}
|
||||
}
|
||||
|
||||
class Serializer
|
||||
{
|
||||
public static PBXElementDict ParseTreeAST(TreeAST ast, TokenList tokens, string text)
|
||||
{
|
||||
var el = new PBXElementDict();
|
||||
foreach (var kv in ast.values)
|
||||
{
|
||||
PBXElementString key = ParseIdentifierAST(kv.key, tokens, text);
|
||||
PBXElement value = ParseValueAST(kv.value, tokens, text);
|
||||
el[key.value] = value;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
public static PBXElementArray ParseArrayAST(ArrayAST ast, TokenList tokens, string text)
|
||||
{
|
||||
var el = new PBXElementArray();
|
||||
foreach (var v in ast.values)
|
||||
{
|
||||
el.values.Add(ParseValueAST(v, tokens, text));
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
public static PBXElement ParseValueAST(ValueAST ast, TokenList tokens, string text)
|
||||
{
|
||||
if (ast is TreeAST)
|
||||
return ParseTreeAST((TreeAST)ast, tokens, text);
|
||||
if (ast is ArrayAST)
|
||||
return ParseArrayAST((ArrayAST)ast, tokens, text);
|
||||
if (ast is IdentifierAST)
|
||||
return ParseIdentifierAST((IdentifierAST)ast, tokens, text);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PBXElementString ParseIdentifierAST(IdentifierAST ast, TokenList tokens, string text)
|
||||
{
|
||||
Token tok = tokens[ast.value];
|
||||
string value;
|
||||
switch (tok.type)
|
||||
{
|
||||
case TokenType.String:
|
||||
value = text.Substring(tok.begin, tok.end - tok.begin);
|
||||
return new PBXElementString(value);
|
||||
case TokenType.QuotedString:
|
||||
value = text.Substring(tok.begin, tok.end - tok.begin);
|
||||
value = PBXStream.UnquoteString(value);
|
||||
return new PBXElementString(value);
|
||||
default:
|
||||
throw new Exception("Internal parser error");
|
||||
}
|
||||
}
|
||||
|
||||
static string k_Indent = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
||||
|
||||
static string GetIndent(int indent)
|
||||
{
|
||||
return k_Indent.Substring(0, indent);
|
||||
}
|
||||
|
||||
static void WriteStringImpl(StringBuilder sb, string s, bool comment, GUIDToCommentMap comments)
|
||||
{
|
||||
if (comment)
|
||||
comments.WriteStringBuilder(sb, s);
|
||||
else
|
||||
sb.Append(PBXStream.QuoteStringIfNeeded(s));
|
||||
}
|
||||
|
||||
public static void WriteDictKeyValue(StringBuilder sb, string key, PBXElement value, int indent, bool compact,
|
||||
PropertyCommentChecker checker, GUIDToCommentMap comments)
|
||||
{
|
||||
if (!compact)
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(GetIndent(indent));
|
||||
}
|
||||
WriteStringImpl(sb, key, checker.CheckKeyInDict(key), comments);
|
||||
sb.Append(" = ");
|
||||
|
||||
if (value is PBXElementString)
|
||||
WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInDict(key, value.AsString()), comments);
|
||||
else if (value is PBXElementDict)
|
||||
WriteDict(sb, value.AsDict(), indent, compact, checker.NextLevel(key), comments);
|
||||
else if (value is PBXElementArray)
|
||||
WriteArray(sb, value.AsArray(), indent, compact, checker.NextLevel(key), comments);
|
||||
sb.Append(";");
|
||||
if (compact)
|
||||
sb.Append(" ");
|
||||
}
|
||||
|
||||
public static void WriteDict(StringBuilder sb, PBXElementDict el, int indent, bool compact,
|
||||
PropertyCommentChecker checker, GUIDToCommentMap comments)
|
||||
{
|
||||
sb.Append("{");
|
||||
|
||||
if (el.Contains("isa"))
|
||||
WriteDictKeyValue(sb, "isa", el["isa"], indent+1, compact, checker, comments);
|
||||
var keys = new List<string>(el.values.Keys);
|
||||
keys.Sort(StringComparer.Ordinal);
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (key != "isa")
|
||||
WriteDictKeyValue(sb, key, el[key], indent+1, compact, checker, comments);
|
||||
}
|
||||
if (!compact)
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(GetIndent(indent));
|
||||
}
|
||||
sb.Append("}");
|
||||
}
|
||||
|
||||
public static void WriteArray(StringBuilder sb, PBXElementArray el, int indent, bool compact,
|
||||
PropertyCommentChecker checker, GUIDToCommentMap comments)
|
||||
{
|
||||
sb.Append("(");
|
||||
foreach (var value in el.values)
|
||||
{
|
||||
if (!compact)
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(GetIndent(indent+1));
|
||||
}
|
||||
|
||||
if (value is PBXElementString)
|
||||
WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInArray(value.AsString()), comments);
|
||||
else if (value is PBXElementDict)
|
||||
WriteDict(sb, value.AsDict(), indent+1, compact, checker.NextLevel("*"), comments);
|
||||
else if (value is PBXElementArray)
|
||||
WriteArray(sb, value.AsArray(), indent+1, compact, checker.NextLevel("*"), comments);
|
||||
sb.Append(",");
|
||||
if (compact)
|
||||
sb.Append(" ");
|
||||
}
|
||||
|
||||
if (!compact)
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(GetIndent(indent));
|
||||
}
|
||||
sb.Append(")");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UnityEditor.iOS.Xcode
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afe8316bf614347729fac3466d7c77f2
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,300 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace ChillyRoom.UnityEditor.iOS.Xcode.PBX
|
||||
{
|
||||
internal class GUIDToCommentMap
|
||||
{
|
||||
private Dictionary<string, string> m_Dict = new Dictionary<string, string>();
|
||||
|
||||
public string this[string guid]
|
||||
{
|
||||
get {
|
||||
if (m_Dict.ContainsKey(guid))
|
||||
return m_Dict[guid];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string guid, string comment)
|
||||
{
|
||||
if (m_Dict.ContainsKey(guid))
|
||||
return;
|
||||
m_Dict.Add(guid, comment);
|
||||
}
|
||||
|
||||
public void Remove(string guid)
|
||||
{
|
||||
m_Dict.Remove(guid);
|
||||
}
|
||||
|
||||
public string Write(string guid)
|
||||
{
|
||||
string comment = this[guid];
|
||||
if (comment == null)
|
||||
return guid;
|
||||
return String.Format("{0} /* {1} */", guid, comment);
|
||||
}
|
||||
|
||||
public void WriteStringBuilder(StringBuilder sb, string guid)
|
||||
{
|
||||
string comment = this[guid];
|
||||
if (comment == null)
|
||||
sb.Append(guid);
|
||||
else
|
||||
{
|
||||
// {0} /* {1} */
|
||||
sb.Append(guid).Append(" /* ").Append(comment).Append(" */");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class PBXGUID
|
||||
{
|
||||
internal delegate string GuidGenerator();
|
||||
|
||||
// We allow changing Guid generator to make testing of PBXProject possible
|
||||
private static GuidGenerator guidGenerator = DefaultGuidGenerator;
|
||||
|
||||
internal static string DefaultGuidGenerator()
|
||||
{
|
||||
return Guid.NewGuid().ToString("N").Substring(8).ToUpper();
|
||||
}
|
||||
|
||||
internal static void SetGuidGenerator(GuidGenerator generator)
|
||||
{
|
||||
guidGenerator = generator;
|
||||
}
|
||||
|
||||
// Generates a GUID.
|
||||
public static string Generate()
|
||||
{
|
||||
return guidGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
internal class PBXRegex
|
||||
{
|
||||
public static string GuidRegexString = "[A-Fa-f0-9]{24}";
|
||||
}
|
||||
|
||||
internal class PBXStream
|
||||
{
|
||||
static bool DontNeedQuotes(string src)
|
||||
{
|
||||
// using a regex instead of explicit matching slows down common cases by 40%
|
||||
if (src.Length == 0)
|
||||
return false;
|
||||
|
||||
bool hasSlash = false;
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
char c = src[i];
|
||||
if (Char.IsLetterOrDigit(c) || c == '.' || c == '*' || c == '_')
|
||||
continue;
|
||||
if (c == '/')
|
||||
{
|
||||
hasSlash = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (hasSlash)
|
||||
{
|
||||
if (src.Contains("//") || src.Contains("/*") || src.Contains("*/"))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Quotes the given string if it contains special characters. Note: if the string already
|
||||
// contains quotes, then they are escaped and the entire string quoted again
|
||||
public static string QuoteStringIfNeeded(string src)
|
||||
{
|
||||
if (DontNeedQuotes(src))
|
||||
return src;
|
||||
return "\"" + src.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\"";
|
||||
}
|
||||
|
||||
// If the given string is quoted, removes the quotes and unescapes any quotes within the string
|
||||
public static string UnquoteString(string src)
|
||||
{
|
||||
if (!src.StartsWith("\"") || !src.EndsWith("\""))
|
||||
return src;
|
||||
return src.Substring(1, src.Length - 2).Replace("\\\\", "\u569f").Replace("\\\"", "\"")
|
||||
.Replace("\\n", "\n").Replace("\u569f", "\\"); // U+569f is a rarely used Chinese character
|
||||
}
|
||||
}
|
||||
|
||||
internal enum PBXFileType
|
||||
{
|
||||
NotBuildable,
|
||||
Framework,
|
||||
Source,
|
||||
Resource,
|
||||
CopyFile
|
||||
}
|
||||
|
||||
internal class FileTypeUtils
|
||||
{
|
||||
internal class FileTypeDesc
|
||||
{
|
||||
public FileTypeDesc(string typeName, PBXFileType type)
|
||||
{
|
||||
this.name = typeName;
|
||||
this.type = type;
|
||||
this.isExplicit = false;
|
||||
}
|
||||
|
||||
public FileTypeDesc(string typeName, PBXFileType type, bool isExplicit)
|
||||
{
|
||||
this.name = typeName;
|
||||
this.type = type;
|
||||
this.isExplicit = isExplicit;
|
||||
}
|
||||
|
||||
public string name;
|
||||
public PBXFileType type;
|
||||
public bool isExplicit;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, FileTypeDesc> types =
|
||||
new Dictionary<string, FileTypeDesc>
|
||||
{
|
||||
{ "a", new FileTypeDesc("archive.ar", PBXFileType.Framework) },
|
||||
{ "app", new FileTypeDesc("wrapper.application", PBXFileType.NotBuildable, true) },
|
||||
{ "appex", new FileTypeDesc("wrapper.app-extension", PBXFileType.CopyFile) },
|
||||
{ "bin", new FileTypeDesc("archive.macbinary", PBXFileType.Resource) },
|
||||
{ "s", new FileTypeDesc("sourcecode.asm", PBXFileType.Source) },
|
||||
{ "c", new FileTypeDesc("sourcecode.c.c", PBXFileType.Source) },
|
||||
{ "cc", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) },
|
||||
{ "cpp", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) },
|
||||
{ "swift", new FileTypeDesc("sourcecode.swift", PBXFileType.Source) },
|
||||
{ "dll", new FileTypeDesc("file", PBXFileType.NotBuildable) },
|
||||
{ "framework", new FileTypeDesc("wrapper.framework", PBXFileType.Framework) },
|
||||
{ "h", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) },
|
||||
{ "pch", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) },
|
||||
{ "icns", new FileTypeDesc("image.icns", PBXFileType.Resource) },
|
||||
{ "xcassets", new FileTypeDesc("folder.assetcatalog", PBXFileType.Resource) },
|
||||
{ "inc", new FileTypeDesc("sourcecode.inc", PBXFileType.NotBuildable) },
|
||||
{ "m", new FileTypeDesc("sourcecode.c.objc", PBXFileType.Source) },
|
||||
{ "mm", new FileTypeDesc("sourcecode.cpp.objcpp", PBXFileType.Source ) },
|
||||
{ "nib", new FileTypeDesc("wrapper.nib", PBXFileType.Resource) },
|
||||
{ "plist", new FileTypeDesc("text.plist.xml", PBXFileType.Resource) },
|
||||
{ "png", new FileTypeDesc("image.png", PBXFileType.Resource) },
|
||||
{ "rtf", new FileTypeDesc("text.rtf", PBXFileType.Resource) },
|
||||
{ "tiff", new FileTypeDesc("image.tiff", PBXFileType.Resource) },
|
||||
{ "txt", new FileTypeDesc("text", PBXFileType.Resource) },
|
||||
{ "json", new FileTypeDesc("text.json", PBXFileType.Resource) },
|
||||
{ "xcodeproj", new FileTypeDesc("wrapper.pb-project", PBXFileType.NotBuildable) },
|
||||
{ "xib", new FileTypeDesc("file.xib", PBXFileType.Resource) },
|
||||
{ "strings", new FileTypeDesc("text.plist.strings", PBXFileType.Resource) },
|
||||
{ "storyboard",new FileTypeDesc("file.storyboard", PBXFileType.Resource) },
|
||||
{ "bundle", new FileTypeDesc("wrapper.plug-in", PBXFileType.Resource) },
|
||||
{ "dylib", new FileTypeDesc("compiled.mach-o.dylib", PBXFileType.Framework) },
|
||||
{ "tbd", new FileTypeDesc("sourcecode.text-based-dylib-definition", PBXFileType.Framework) }
|
||||
};
|
||||
|
||||
public static string TrimExtension(string ext)
|
||||
{
|
||||
return ext.TrimStart('.');
|
||||
}
|
||||
|
||||
public static bool IsKnownExtension(string ext)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
return types.ContainsKey(ext);
|
||||
}
|
||||
|
||||
internal static bool IsFileTypeExplicit(string ext)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
if (types.ContainsKey(ext))
|
||||
return types[ext].isExplicit;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PBXFileType GetFileType(string ext, bool isFolderRef)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
if (isFolderRef)
|
||||
return PBXFileType.Resource;
|
||||
if (!types.ContainsKey(ext))
|
||||
return PBXFileType.Resource;
|
||||
return types[ext].type;
|
||||
}
|
||||
|
||||
public static string GetTypeName(string ext)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
if (types.ContainsKey(ext))
|
||||
return types[ext].name;
|
||||
// Xcode actually checks the file contents to determine the file type.
|
||||
// Text files have "text" type and all other files have "file" type.
|
||||
// Since we can't reasonably determine whether the file in question is
|
||||
// a text file, we just take the safe route and return "file" type.
|
||||
return "file";
|
||||
}
|
||||
|
||||
public static bool IsBuildableFile(string ext)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
if (!types.ContainsKey(ext))
|
||||
return true;
|
||||
if (types[ext].type != PBXFileType.NotBuildable)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsBuildable(string ext, bool isFolderReference)
|
||||
{
|
||||
ext = TrimExtension(ext);
|
||||
if (isFolderReference)
|
||||
return true;
|
||||
return IsBuildableFile(ext);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<PBXSourceTree, string> sourceTree = new Dictionary<PBXSourceTree, string>
|
||||
{
|
||||
{ PBXSourceTree.Absolute, "<absolute>" },
|
||||
{ PBXSourceTree.Group, "<group>" },
|
||||
{ PBXSourceTree.Build, "BUILT_PRODUCTS_DIR" },
|
||||
{ PBXSourceTree.Developer, "DEVELOPER_DIR" },
|
||||
{ PBXSourceTree.Sdk, "SDKROOT" },
|
||||
{ PBXSourceTree.Source, "SOURCE_ROOT" },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, PBXSourceTree> stringToSourceTreeMap = new Dictionary<string, PBXSourceTree>
|
||||
{
|
||||
{ "<absolute>", PBXSourceTree.Absolute },
|
||||
{ "<group>", PBXSourceTree.Group },
|
||||
{ "BUILT_PRODUCTS_DIR", PBXSourceTree.Build },
|
||||
{ "DEVELOPER_DIR", PBXSourceTree.Developer },
|
||||
{ "SDKROOT", PBXSourceTree.Sdk },
|
||||
{ "SOURCE_ROOT", PBXSourceTree.Source },
|
||||
};
|
||||
|
||||
internal static string SourceTreeDesc(PBXSourceTree tree)
|
||||
{
|
||||
return sourceTree[tree];
|
||||
}
|
||||
|
||||
// returns PBXSourceTree.Source on error
|
||||
internal static PBXSourceTree ParseSourceTree(string tree)
|
||||
{
|
||||
if (stringToSourceTreeMap.ContainsKey(tree))
|
||||
return stringToSourceTreeMap[tree];
|
||||
return PBXSourceTree.Source;
|
||||
}
|
||||
|
||||
internal static List<PBXSourceTree> AllAbsoluteSourceTrees()
|
||||
{
|
||||
return new List<PBXSourceTree>{PBXSourceTree.Absolute, PBXSourceTree.Build,
|
||||
PBXSourceTree.Developer, PBXSourceTree.Sdk, PBXSourceTree.Source};
|
||||
}
|
||||
}
|
||||
|
||||
} // UnityEditor.iOS.Xcode
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8eafbccf2ded14760af588ffcb1ca0f5
|
||||
timeCreated: 1496741691
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user