少年修仙传客户端基础资源
dabaoji
2025-06-04 34d28a982a741d63f183884881b0bea73f8c8b47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
 
#if UNITY_XCODE_API_BUILD
namespace UnityEditor.iOS.Xcode.PBX
#else
namespace UnityEditor.iOS.Xcode.Custom.PBX
#endif
{
    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