XFileの読み込みライブラリ(作りかけ)を移動
@@ -1,331 +0,0 @@ | ||
1 | -using System; | |
2 | -using System.Collections.Generic; | |
3 | -using System.Linq; | |
4 | -using System.Text; | |
5 | -using System.Text.RegularExpressions; | |
6 | -using System.IO; | |
7 | - | |
8 | -namespace CGL.Graphics.XFileLib.Text | |
9 | -{ | |
10 | - static class XFileTextReader | |
11 | - { | |
12 | - public static XFile FromTxtFile(string xfile, FloatMode floatMode) | |
13 | - { | |
14 | - //改行排除 | |
15 | - xfile = xfile.Replace("\r", ""); | |
16 | - xfile = xfile.Replace("\n", ""); | |
17 | - //ヘッダ排除 | |
18 | - xfile = xfile.Substring(16); | |
19 | - //{}のツリーを作成 | |
20 | - dynamic xtree = BuildTree(ref xfile); | |
21 | - | |
22 | - //テンプレート読み込み | |
23 | - Dictionary<string, XTemplateInfo> templateInfo; | |
24 | - Dictionary<string, string> UUIDTotmpName; | |
25 | - xtree = ReadTemplates(xtree, out templateInfo, out UUIDTotmpName); | |
26 | - //データの読み込み | |
27 | - XFile result = new XFile(); | |
28 | - Regex data_regex = new Regex(@"(?<type>[a-zA-Z_0-9]+)(?<id>(\s+?[a-zA-Z_0-9]+?)?)\s*?", RegexOptions.IgnoreCase); | |
29 | - for (int i = 0; i < xtree.Count; ) | |
30 | - { | |
31 | - MatchCollection mc = data_regex.Matches(xtree[i]); | |
32 | - if (mc.Count == 0) | |
33 | - { | |
34 | - ++i; continue;//ここに来るはず無いんだけどね…… | |
35 | - } | |
36 | - xtree.RemoveAt(i); | |
37 | - Match match = mc[0]; | |
38 | - string typename = match.Groups["type"].Value; | |
39 | - string id = match.Groups["id"].Value; | |
40 | - if (string.IsNullOrEmpty(id)) | |
41 | - id = typename; | |
42 | - dynamic data = xtree[i]; | |
43 | - xtree.RemoveAt(i); | |
44 | - result.FileData.Add(id, BuildData(typename, floatMode, ref data, templateInfo, UUIDTotmpName)); | |
45 | - | |
46 | - } | |
47 | - return result; | |
48 | - } | |
49 | - static dynamic BuildTree(ref string source) | |
50 | - { | |
51 | - List<dynamic> result = new List<dynamic>(); | |
52 | - while (true) | |
53 | - { | |
54 | - int pos1 = source.IndexOf('{'); | |
55 | - int pos2 = source.IndexOf('}'); | |
56 | - | |
57 | - if (pos1 != -1 && pos1<pos2) | |
58 | - { | |
59 | - string data = source.Substring(0, pos1); | |
60 | - if (!string.IsNullOrWhiteSpace(data)) | |
61 | - result.Add(data); | |
62 | - source = source.Substring(pos1 + 1).Trim(); | |
63 | - result.Add(BuildTree(ref source)); | |
64 | - } | |
65 | - else | |
66 | - { | |
67 | - if (pos2 != -1) | |
68 | - { | |
69 | - string data = source.Substring(0, pos2); | |
70 | - if (!string.IsNullOrWhiteSpace(data)) | |
71 | - result.Add(data); | |
72 | - source = source.Substring(pos2 + 1); | |
73 | - return result; | |
74 | - } | |
75 | - else | |
76 | - { | |
77 | - result.Add(source); | |
78 | - source = ""; | |
79 | - return result; | |
80 | - } | |
81 | - } | |
82 | - } | |
83 | - } | |
84 | - static dynamic ReadTemplates(dynamic xtree, out Dictionary<string, XTemplateInfo> templateInfo, out Dictionary<string, string> UUIDTotmpName) | |
85 | - { | |
86 | - //テンプレートを抜き出し | |
87 | - MatchCollection mc; | |
88 | - Regex template_regex = new Regex(@"template\s+?(?<template_name>[a-zA-Z_0-9]+)\s*?", RegexOptions.IgnoreCase | RegexOptions.Compiled); | |
89 | - Regex uuid_regex = new Regex(@"\<(?<uuid>.+?)\>", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
90 | - Regex field_regex = new Regex(@"(?<array>(array\s+?)?)(?<type>[a-zA-Z_0-9]+?)\s+?(?<field>[a-zA-Z_0-9]+?)(?<dimsize>(\[[a-zA-Z_0-9\[\]]+?\])?)\;", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
91 | - | |
92 | - //テンプレートの解析 | |
93 | - templateInfo = new Dictionary<string, XTemplateInfo>(); | |
94 | - UUIDTotmpName = new Dictionary<string, string>(); | |
95 | - for (int i = 0; i < xtree.Count; ++i) | |
96 | - { | |
97 | - if (xtree[i] is string) | |
98 | - { | |
99 | - mc = template_regex.Matches(xtree[i]); | |
100 | - if (mc.Count > 0) | |
101 | - { | |
102 | - Match match = mc[0]; | |
103 | - string temp_data = xtree[i + 1][0]; | |
104 | - xtree.RemoveAt(i); | |
105 | - xtree.RemoveAt(i); | |
106 | - --i; | |
107 | - //テンプレート名の抜き出し | |
108 | - string tmpName = match.Groups["template_name"].Value; | |
109 | - //テンプレートの中身解析 | |
110 | - //uuid抜き出し | |
111 | - string uuid = ""; | |
112 | - Match m; | |
113 | - if ((m = uuid_regex.Match(temp_data)) != null) | |
114 | - uuid = m.Groups["uuid"].Value; | |
115 | - temp_data = uuid_regex.Replace(temp_data, ""); | |
116 | - //テンプレートオブジェクト生成 | |
117 | - XTemplateInfo template = new XTemplateInfo(uuid); | |
118 | - //フィールド抜き出し | |
119 | - MatchCollection fmc = field_regex.Matches(temp_data); | |
120 | - temp_data = field_regex.Replace(temp_data, ""); | |
121 | - foreach (Match fmatch in fmc) | |
122 | - { | |
123 | - XTypeInfo typeinfo = new XTypeInfo(); | |
124 | - string array = fmatch.Groups["array"].Value; | |
125 | - typeinfo.TypeName = fmatch.Groups["type"].Value; | |
126 | - typeinfo.FieldName = fmatch.Groups["field"].Value; | |
127 | - string dimensions = fmatch.Groups["dimsize"].Value; | |
128 | - | |
129 | - if (!string.IsNullOrEmpty(array)) | |
130 | - { | |
131 | - dimensions = dimensions.Trim(); | |
132 | - dimensions = dimensions.Substring(1, dimensions.Length - 2); | |
133 | - typeinfo.Dimensions = new List<string>(dimensions.Split(new string[1] { "][" }, StringSplitOptions.RemoveEmptyEntries)); | |
134 | - } | |
135 | - else | |
136 | - typeinfo.Dimensions = null; | |
137 | - template.Fields.Add(typeinfo.FieldName, typeinfo); | |
138 | - } | |
139 | - templateInfo.Add(tmpName, template); | |
140 | - UUIDTotmpName.Add(template.UUID, tmpName); | |
141 | - } | |
142 | - } | |
143 | - } | |
144 | - | |
145 | - return xtree; | |
146 | - } | |
147 | - static Dictionary<string, dynamic> BuildData(string typename,FloatMode floatMode, ref dynamic data, Dictionary<string, XTemplateInfo> templates, Dictionary<string, string> UUIDInfo) | |
148 | - { | |
149 | - Dictionary<string, dynamic> result = new Dictionary<string, dynamic>(); | |
150 | - //型情報取得 | |
151 | - XTemplateInfo temp = templates[typename]; | |
152 | - //データの処理 | |
153 | - for (int i = 0; i < data.Count; ) | |
154 | - { | |
155 | - string strData = (string)data[i]; | |
156 | - data.RemoveAt(i); | |
157 | - //フィールド情報ごとに処理 | |
158 | - foreach (var field in temp.Fields) | |
159 | - { | |
160 | - dynamic value = ReadData(field.Value, floatMode, ref strData, templates, UUIDInfo, result); | |
161 | - result.Add(field.Value.FieldName, value); | |
162 | - } | |
163 | - strData = strData.Trim(); | |
164 | - //開いたテンプレートの分を読み込み | |
165 | - Regex openRegex = new Regex(@"^\s*?(?<typename>[a-zA-Z_]+)\s*?", RegexOptions.IgnoreCase); | |
166 | - while (true) | |
167 | - { | |
168 | - MatchCollection mc = openRegex.Matches(strData); | |
169 | - if (mc.Count > 0) | |
170 | - { | |
171 | - if (data.Count == 0) | |
172 | - { | |
173 | - data.Add(strData); | |
174 | - return result; | |
175 | - } | |
176 | - else | |
177 | - { | |
178 | - Match match = mc[0]; | |
179 | - string innertype = match.Groups["typename"].Value.Trim(); | |
180 | - dynamic data2 = data[i]; | |
181 | - data.RemoveAt(i); | |
182 | - result.Add(innertype, BuildData(innertype, floatMode, ref data2, templates, UUIDInfo)); | |
183 | - if (data.Count > 0) | |
184 | - { | |
185 | - strData = data[i]; | |
186 | - data.RemoveAt(i); | |
187 | - continue; | |
188 | - } | |
189 | - | |
190 | - } | |
191 | - } | |
192 | - else if (strData.Length > 0) | |
193 | - { | |
194 | - data.Add(strData); | |
195 | - return result; | |
196 | - } | |
197 | - break; | |
198 | - } | |
199 | - } | |
200 | - return result; | |
201 | - } | |
202 | - static bool IsPrimitive(string typename) | |
203 | - { | |
204 | - switch (typename.ToUpper()) | |
205 | - { | |
206 | - case "WORD": | |
207 | - case "DWORD": | |
208 | - case "FLOAT": | |
209 | - case "DOUBLE": | |
210 | - case "CHAR": | |
211 | - case "UCHAR": | |
212 | - case "BYTE": | |
213 | - case "STRING": | |
214 | - return true; | |
215 | - case "CSTRING": | |
216 | - case "UNICODE": | |
217 | - throw new FileLoadException(typename + "型をXファイル形式で使うことは出来ません"); | |
218 | - default: | |
219 | - return false; | |
220 | - } | |
221 | - } | |
222 | - static dynamic ReadData(XTypeInfo field, FloatMode floatMode, ref string data, Dictionary<string, XTemplateInfo> templates, Dictionary<string, string> UUIDInfo,Dictionary<string,dynamic> othreFields) | |
223 | - { | |
224 | - dynamic returnvalue; | |
225 | - if (field.Dimensions != null && field.Dimensions.Count > 0) | |
226 | - {//配列 | |
227 | - XTypeInfo newfield = (XTypeInfo)field.Clone(); | |
228 | - int dimension; | |
229 | - if (!int.TryParse(newfield.Dimensions[0], out dimension)) | |
230 | - { | |
231 | - //他のフィールド値が知っている? | |
232 | - dimension = (int)othreFields[newfield.Dimensions[0]]; | |
233 | - } | |
234 | - newfield.Dimensions.RemoveAt(0); | |
235 | - //配列データ読み込み | |
236 | - List<dynamic> array = new List<dynamic>(); | |
237 | - for (int i = 0; i < dimension; ++i) | |
238 | - { | |
239 | - if (i != 0) | |
240 | - {//配列の各値にある,をチェックして除く | |
241 | - if (data.Length>0 && data[0] == ',') | |
242 | - data = data.Substring(1); | |
243 | - } | |
244 | - array.Add(ReadData(newfield,floatMode, ref data, templates, UUIDInfo, othreFields)); | |
245 | - } | |
246 | - //配列の最後にある;をチェックして除く | |
247 | - if (data.Length > 0 && data[0] == ';') | |
248 | - data = data.Substring(1); | |
249 | - returnvalue = array.ToArray(); | |
250 | - } | |
251 | - else | |
252 | - { | |
253 | - if (IsPrimitive(field.TypeName)) | |
254 | - { | |
255 | - returnvalue = ReadPrimitiveData(field.TypeName, ref data, floatMode); | |
256 | - } | |
257 | - else | |
258 | - { | |
259 | - dynamic temp = new List<string>(); | |
260 | - temp.Add(data); | |
261 | - returnvalue = BuildData(field.TypeName, floatMode, ref temp, templates, UUIDInfo); | |
262 | - if (temp.Count > 0) | |
263 | - { | |
264 | - data = temp[0]; | |
265 | - //フィールドの最後にある;をチェックして除く | |
266 | - if (data.Length > 0 && data[0] == ';') | |
267 | - data = data.Substring(1); | |
268 | - } | |
269 | - | |
270 | - } | |
271 | - } | |
272 | - return returnvalue; | |
273 | - } | |
274 | - static dynamic ReadPrimitiveData(string typename, ref string data, FloatMode floatMode) | |
275 | - { | |
276 | - /*int pos1 = data.IndexOf(';'); | |
277 | - int pos2 = data.IndexOf(','); | |
278 | - int pos; | |
279 | - if (pos1 == -1 && pos2 == -1) | |
280 | - pos = -1; | |
281 | - else if(pos1==-1) | |
282 | - string strValue = ""; | |
283 | - if (pos == -1) | |
284 | - { | |
285 | - strValue = data; | |
286 | - data = ""; | |
287 | - } | |
288 | - else | |
289 | - { | |
290 | - strValue = data.Substring(0, pos); | |
291 | - data = data.Substring(pos + 1); | |
292 | - }*/ | |
293 | - Regex reg_num = new Regex(@"^\s*?(?<number>[0-9\.\-]+)(\;)?", RegexOptions.IgnoreCase); | |
294 | - Regex reg_str = new Regex(@"^\s*?(?<string>.*?)(\;|,)", RegexOptions.IgnoreCase); | |
295 | - string strValue; | |
296 | - if (typename.ToUpper() == "STRING") | |
297 | - { | |
298 | - strValue = reg_str.Match(data).Groups["string"].Value; | |
299 | - data = reg_str.Replace(data, ""); | |
300 | - return strValue; | |
301 | - } | |
302 | - else | |
303 | - { | |
304 | - strValue = reg_num.Match(data).Groups["number"].Value; | |
305 | - data = reg_num.Replace(data, ""); | |
306 | - } | |
307 | - switch (typename.ToUpper()) | |
308 | - { | |
309 | - case "WORD": | |
310 | - | |
311 | - return Convert.ToInt16(strValue); | |
312 | - case "DWORD": | |
313 | - return Convert.ToInt32(strValue); | |
314 | - case "FLOAT": | |
315 | - if (floatMode == FloatMode.Single) | |
316 | - return Convert.ToSingle(strValue); | |
317 | - else | |
318 | - return Convert.ToDouble(strValue); | |
319 | - case "DOUBLE": | |
320 | - return Convert.ToDouble(strValue); | |
321 | - case "CHAR": | |
322 | - case "UCHAR": | |
323 | - case "BYTE": | |
324 | - return Convert.ToByte(strValue); | |
325 | - default: | |
326 | - throw new Exception("……ここに来るはず無いんだけど"); | |
327 | - } | |
328 | - } | |
329 | - | |
330 | - } | |
331 | -} |
@@ -1,58 +0,0 @@ | ||
1 | -using System; | |
2 | -using System.Collections.Generic; | |
3 | -using System.Linq; | |
4 | -using System.Text; | |
5 | - | |
6 | -namespace CGL.Graphics.XFileLib.Text | |
7 | -{ | |
8 | - | |
9 | - /// <summary> | |
10 | - /// テンプレート情報 | |
11 | - /// </summary> | |
12 | - class XTemplateInfo | |
13 | - { | |
14 | - Dictionary<string, XTypeInfo> fields = new Dictionary<string, XTypeInfo>(); | |
15 | - | |
16 | - string uuid = ""; | |
17 | - /// <summary> | |
18 | - /// UUID | |
19 | - /// </summary> | |
20 | - public string UUID { get { return uuid; } } | |
21 | - /// <summary> | |
22 | - /// フィールド情報 | |
23 | - /// </summary> | |
24 | - public Dictionary<string, XTypeInfo> Fields { get { return fields; } } | |
25 | - | |
26 | - public XTemplateInfo(string uuid) | |
27 | - { | |
28 | - this.uuid = uuid; | |
29 | - } | |
30 | - } | |
31 | - /// <summary> | |
32 | - /// 型情報 | |
33 | - /// </summary> | |
34 | - class XTypeInfo : ICloneable | |
35 | - { | |
36 | - /// <summary> | |
37 | - /// フィールド名 | |
38 | - /// </summary> | |
39 | - public string FieldName; | |
40 | - /// <summary> | |
41 | - /// 型名 | |
42 | - /// </summary> | |
43 | - public string TypeName; | |
44 | - /// <summary> | |
45 | - /// 配列のサイズ | |
46 | - /// </summary> | |
47 | - public List<string> Dimensions; | |
48 | - | |
49 | - #region ICloneable メンバー | |
50 | - | |
51 | - public object Clone() | |
52 | - { | |
53 | - return new XTypeInfo { FieldName = FieldName, TypeName = TypeName, Dimensions = new List<string>(Dimensions) }; | |
54 | - } | |
55 | - | |
56 | - #endregion | |
57 | - } | |
58 | -} |
@@ -1,73 +0,0 @@ | ||
1 | -using System; | |
2 | -using System.Collections.Generic; | |
3 | -using System.Linq; | |
4 | -using System.Text; | |
5 | -using System.IO; | |
6 | -using System.Text.RegularExpressions; | |
7 | -using CGL.Graphics.XFileLib.Text; | |
8 | - | |
9 | -namespace CGL.Graphics.XFileLib | |
10 | -{ | |
11 | - enum FloatMode | |
12 | - { | |
13 | - Single, | |
14 | - Double, | |
15 | - } | |
16 | - | |
17 | - public class XFile | |
18 | - { | |
19 | - Dictionary<string, Dictionary<string, dynamic>> data = new Dictionary<string, Dictionary<string, dynamic>>(); | |
20 | - /// <summary> | |
21 | - /// XFile中のデータ | |
22 | - /// </summary> | |
23 | - public Dictionary<string, Dictionary<string, dynamic>> FileData { get { return data; } } | |
24 | - | |
25 | - public static XFile FromFile(string filename) | |
26 | - { | |
27 | - filename = Path.GetFullPath(filename); | |
28 | - | |
29 | - if (!File.Exists(filename)) | |
30 | - throw new FileNotFoundException("ファイルがみつかりません", filename); | |
31 | - string fileMode = ""; | |
32 | - FloatMode floatMode; | |
33 | - using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open))) | |
34 | - { | |
35 | - string magic = (new string(br.ReadChars(4))).Trim(); | |
36 | - if (magic != "xof") | |
37 | - throw new FileLoadException("XFileではありません", filename); | |
38 | - br.ReadBytes(4);//バージョン読み飛ばし | |
39 | - fileMode = (new string(br.ReadChars(4))).Trim(); | |
40 | - string f = (new string(br.ReadChars(4))).Trim(); | |
41 | - switch (f) | |
42 | - { | |
43 | - case "0032": | |
44 | - floatMode = FloatMode.Single; | |
45 | - break; | |
46 | - case "0064": | |
47 | - floatMode = FloatMode.Double; | |
48 | - break; | |
49 | - default: | |
50 | - throw new FileLoadException("不明な浮動小数点型です:" + f, filename); | |
51 | - } | |
52 | - br.Close(); | |
53 | - } | |
54 | - switch (fileMode) | |
55 | - { | |
56 | - case "txt": | |
57 | - { | |
58 | - string data = File.ReadAllText(filename, Encoding.GetEncoding("Shift_JIS")); | |
59 | - return XFileTextReader.FromTxtFile(data, floatMode); | |
60 | - } | |
61 | - case "bin": | |
62 | - throw new NotImplementedException("バイナリ形式のXFileは読み込めません"); | |
63 | - case "tzip": | |
64 | - throw new NotImplementedException("zip圧縮形式のXFileは読み込めません"); | |
65 | - case "bzip": | |
66 | - throw new NotImplementedException("zip圧縮形式のXFileは読み込めません"); | |
67 | - default: | |
68 | - throw new FileLoadException("不明なXFileデータ型です"); | |
69 | - } | |
70 | - } | |
71 | - | |
72 | - } | |
73 | -} |
@@ -1,36 +0,0 @@ | ||
1 | -using System.Reflection; | |
2 | -using System.Runtime.CompilerServices; | |
3 | -using System.Runtime.InteropServices; | |
4 | - | |
5 | -// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 | |
6 | -// アセンブリに関連付けられている情報を変更するには、 | |
7 | -// これらの属性値を変更してください。 | |
8 | -[assembly: AssemblyTitle("XFileLib")] | |
9 | -[assembly: AssemblyDescription("")] | |
10 | -[assembly: AssemblyConfiguration("")] | |
11 | -[assembly: AssemblyCompany("")] | |
12 | -[assembly: AssemblyProduct("XFileLib")] | |
13 | -[assembly: AssemblyCopyright("Copyright © 2011")] | |
14 | -[assembly: AssemblyTrademark("")] | |
15 | -[assembly: AssemblyCulture("")] | |
16 | - | |
17 | -// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから | |
18 | -// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 | |
19 | -// その型の ComVisible 属性を true に設定してください。 | |
20 | -[assembly: ComVisible(false)] | |
21 | - | |
22 | -// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です | |
23 | -[assembly: Guid("bfcd47ab-5de9-4767-92cf-2ff47374742a")] | |
24 | - | |
25 | -// アセンブリのバージョン情報は、以下の 4 つの値で構成されています: | |
26 | -// | |
27 | -// Major Version | |
28 | -// Minor Version | |
29 | -// Build Number | |
30 | -// Revision | |
31 | -// | |
32 | -// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を | |
33 | -// 既定値にすることができます: | |
34 | -// [assembly: AssemblyVersion("1.0.*")] | |
35 | -[assembly: AssemblyVersion("1.0.0.0")] | |
36 | -[assembly: AssemblyFileVersion("1.0.0.0")] |
@@ -0,0 +1,331 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | +using System.Text.RegularExpressions; | |
6 | +using System.IO; | |
7 | + | |
8 | +namespace CGL.Graphics.XFileLib.Text | |
9 | +{ | |
10 | + static class XFileTextReader | |
11 | + { | |
12 | + public static XFile FromTxtFile(string xfile, FloatMode floatMode) | |
13 | + { | |
14 | + //改行排除 | |
15 | + xfile = xfile.Replace("\r", ""); | |
16 | + xfile = xfile.Replace("\n", ""); | |
17 | + //ヘッダ排除 | |
18 | + xfile = xfile.Substring(16); | |
19 | + //{}のツリーを作成 | |
20 | + dynamic xtree = BuildTree(ref xfile); | |
21 | + | |
22 | + //テンプレート読み込み | |
23 | + Dictionary<string, XTemplateInfo> templateInfo; | |
24 | + Dictionary<string, string> UUIDTotmpName; | |
25 | + xtree = ReadTemplates(xtree, out templateInfo, out UUIDTotmpName); | |
26 | + //データの読み込み | |
27 | + XFile result = new XFile(); | |
28 | + Regex data_regex = new Regex(@"(?<type>[a-zA-Z_0-9]+)(?<id>(\s+?[a-zA-Z_0-9]+?)?)\s*?", RegexOptions.IgnoreCase); | |
29 | + for (int i = 0; i < xtree.Count; ) | |
30 | + { | |
31 | + MatchCollection mc = data_regex.Matches(xtree[i]); | |
32 | + if (mc.Count == 0) | |
33 | + { | |
34 | + ++i; continue;//ここに来るはず無いんだけどね…… | |
35 | + } | |
36 | + xtree.RemoveAt(i); | |
37 | + Match match = mc[0]; | |
38 | + string typename = match.Groups["type"].Value; | |
39 | + string id = match.Groups["id"].Value; | |
40 | + if (string.IsNullOrEmpty(id)) | |
41 | + id = typename; | |
42 | + dynamic data = xtree[i]; | |
43 | + xtree.RemoveAt(i); | |
44 | + result.FileData.Add(id, BuildData(typename, floatMode, ref data, templateInfo, UUIDTotmpName)); | |
45 | + | |
46 | + } | |
47 | + return result; | |
48 | + } | |
49 | + static dynamic BuildTree(ref string source) | |
50 | + { | |
51 | + List<dynamic> result = new List<dynamic>(); | |
52 | + while (true) | |
53 | + { | |
54 | + int pos1 = source.IndexOf('{'); | |
55 | + int pos2 = source.IndexOf('}'); | |
56 | + | |
57 | + if (pos1 != -1 && pos1<pos2) | |
58 | + { | |
59 | + string data = source.Substring(0, pos1); | |
60 | + if (!string.IsNullOrWhiteSpace(data)) | |
61 | + result.Add(data); | |
62 | + source = source.Substring(pos1 + 1).Trim(); | |
63 | + result.Add(BuildTree(ref source)); | |
64 | + } | |
65 | + else | |
66 | + { | |
67 | + if (pos2 != -1) | |
68 | + { | |
69 | + string data = source.Substring(0, pos2); | |
70 | + if (!string.IsNullOrWhiteSpace(data)) | |
71 | + result.Add(data); | |
72 | + source = source.Substring(pos2 + 1); | |
73 | + return result; | |
74 | + } | |
75 | + else | |
76 | + { | |
77 | + result.Add(source); | |
78 | + source = ""; | |
79 | + return result; | |
80 | + } | |
81 | + } | |
82 | + } | |
83 | + } | |
84 | + static dynamic ReadTemplates(dynamic xtree, out Dictionary<string, XTemplateInfo> templateInfo, out Dictionary<string, string> UUIDTotmpName) | |
85 | + { | |
86 | + //テンプレートを抜き出し | |
87 | + MatchCollection mc; | |
88 | + Regex template_regex = new Regex(@"template\s+?(?<template_name>[a-zA-Z_0-9]+)\s*?", RegexOptions.IgnoreCase | RegexOptions.Compiled); | |
89 | + Regex uuid_regex = new Regex(@"\<(?<uuid>.+?)\>", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
90 | + Regex field_regex = new Regex(@"(?<array>(array\s+?)?)(?<type>[a-zA-Z_0-9]+?)\s+?(?<field>[a-zA-Z_0-9]+?)(?<dimsize>(\[[a-zA-Z_0-9\[\]]+?\])?)\;", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
91 | + | |
92 | + //テンプレートの解析 | |
93 | + templateInfo = new Dictionary<string, XTemplateInfo>(); | |
94 | + UUIDTotmpName = new Dictionary<string, string>(); | |
95 | + for (int i = 0; i < xtree.Count; ++i) | |
96 | + { | |
97 | + if (xtree[i] is string) | |
98 | + { | |
99 | + mc = template_regex.Matches(xtree[i]); | |
100 | + if (mc.Count > 0) | |
101 | + { | |
102 | + Match match = mc[0]; | |
103 | + string temp_data = xtree[i + 1][0]; | |
104 | + xtree.RemoveAt(i); | |
105 | + xtree.RemoveAt(i); | |
106 | + --i; | |
107 | + //テンプレート名の抜き出し | |
108 | + string tmpName = match.Groups["template_name"].Value; | |
109 | + //テンプレートの中身解析 | |
110 | + //uuid抜き出し | |
111 | + string uuid = ""; | |
112 | + Match m; | |
113 | + if ((m = uuid_regex.Match(temp_data)) != null) | |
114 | + uuid = m.Groups["uuid"].Value; | |
115 | + temp_data = uuid_regex.Replace(temp_data, ""); | |
116 | + //テンプレートオブジェクト生成 | |
117 | + XTemplateInfo template = new XTemplateInfo(uuid); | |
118 | + //フィールド抜き出し | |
119 | + MatchCollection fmc = field_regex.Matches(temp_data); | |
120 | + temp_data = field_regex.Replace(temp_data, ""); | |
121 | + foreach (Match fmatch in fmc) | |
122 | + { | |
123 | + XTypeInfo typeinfo = new XTypeInfo(); | |
124 | + string array = fmatch.Groups["array"].Value; | |
125 | + typeinfo.TypeName = fmatch.Groups["type"].Value; | |
126 | + typeinfo.FieldName = fmatch.Groups["field"].Value; | |
127 | + string dimensions = fmatch.Groups["dimsize"].Value; | |
128 | + | |
129 | + if (!string.IsNullOrEmpty(array)) | |
130 | + { | |
131 | + dimensions = dimensions.Trim(); | |
132 | + dimensions = dimensions.Substring(1, dimensions.Length - 2); | |
133 | + typeinfo.Dimensions = new List<string>(dimensions.Split(new string[1] { "][" }, StringSplitOptions.RemoveEmptyEntries)); | |
134 | + } | |
135 | + else | |
136 | + typeinfo.Dimensions = null; | |
137 | + template.Fields.Add(typeinfo.FieldName, typeinfo); | |
138 | + } | |
139 | + templateInfo.Add(tmpName, template); | |
140 | + UUIDTotmpName.Add(template.UUID, tmpName); | |
141 | + } | |
142 | + } | |
143 | + } | |
144 | + | |
145 | + return xtree; | |
146 | + } | |
147 | + static Dictionary<string, dynamic> BuildData(string typename,FloatMode floatMode, ref dynamic data, Dictionary<string, XTemplateInfo> templates, Dictionary<string, string> UUIDInfo) | |
148 | + { | |
149 | + Dictionary<string, dynamic> result = new Dictionary<string, dynamic>(); | |
150 | + //型情報取得 | |
151 | + XTemplateInfo temp = templates[typename]; | |
152 | + //データの処理 | |
153 | + for (int i = 0; i < data.Count; ) | |
154 | + { | |
155 | + string strData = (string)data[i]; | |
156 | + data.RemoveAt(i); | |
157 | + //フィールド情報ごとに処理 | |
158 | + foreach (var field in temp.Fields) | |
159 | + { | |
160 | + dynamic value = ReadData(field.Value, floatMode, ref strData, templates, UUIDInfo, result); | |
161 | + result.Add(field.Value.FieldName, value); | |
162 | + } | |
163 | + strData = strData.Trim(); | |
164 | + //開いたテンプレートの分を読み込み | |
165 | + Regex openRegex = new Regex(@"^\s*?(?<typename>[a-zA-Z_]+)\s*?", RegexOptions.IgnoreCase); | |
166 | + while (true) | |
167 | + { | |
168 | + MatchCollection mc = openRegex.Matches(strData); | |
169 | + if (mc.Count > 0) | |
170 | + { | |
171 | + if (data.Count == 0) | |
172 | + { | |
173 | + data.Add(strData); | |
174 | + return result; | |
175 | + } | |
176 | + else | |
177 | + { | |
178 | + Match match = mc[0]; | |
179 | + string innertype = match.Groups["typename"].Value.Trim(); | |
180 | + dynamic data2 = data[i]; | |
181 | + data.RemoveAt(i); | |
182 | + result.Add(innertype, BuildData(innertype, floatMode, ref data2, templates, UUIDInfo)); | |
183 | + if (data.Count > 0) | |
184 | + { | |
185 | + strData = data[i]; | |
186 | + data.RemoveAt(i); | |
187 | + continue; | |
188 | + } | |
189 | + | |
190 | + } | |
191 | + } | |
192 | + else if (strData.Length > 0) | |
193 | + { | |
194 | + data.Add(strData); | |
195 | + return result; | |
196 | + } | |
197 | + break; | |
198 | + } | |
199 | + } | |
200 | + return result; | |
201 | + } | |
202 | + static bool IsPrimitive(string typename) | |
203 | + { | |
204 | + switch (typename.ToUpper()) | |
205 | + { | |
206 | + case "WORD": | |
207 | + case "DWORD": | |
208 | + case "FLOAT": | |
209 | + case "DOUBLE": | |
210 | + case "CHAR": | |
211 | + case "UCHAR": | |
212 | + case "BYTE": | |
213 | + case "STRING": | |
214 | + return true; | |
215 | + case "CSTRING": | |
216 | + case "UNICODE": | |
217 | + throw new FileLoadException(typename + "型をXファイル形式で使うことは出来ません"); | |
218 | + default: | |
219 | + return false; | |
220 | + } | |
221 | + } | |
222 | + static dynamic ReadData(XTypeInfo field, FloatMode floatMode, ref string data, Dictionary<string, XTemplateInfo> templates, Dictionary<string, string> UUIDInfo,Dictionary<string,dynamic> othreFields) | |
223 | + { | |
224 | + dynamic returnvalue; | |
225 | + if (field.Dimensions != null && field.Dimensions.Count > 0) | |
226 | + {//配列 | |
227 | + XTypeInfo newfield = (XTypeInfo)field.Clone(); | |
228 | + int dimension; | |
229 | + if (!int.TryParse(newfield.Dimensions[0], out dimension)) | |
230 | + { | |
231 | + //他のフィールド値が知っている? | |
232 | + dimension = (int)othreFields[newfield.Dimensions[0]]; | |
233 | + } | |
234 | + newfield.Dimensions.RemoveAt(0); | |
235 | + //配列データ読み込み | |
236 | + List<dynamic> array = new List<dynamic>(); | |
237 | + for (int i = 0; i < dimension; ++i) | |
238 | + { | |
239 | + if (i != 0) | |
240 | + {//配列の各値にある,をチェックして除く | |
241 | + if (data.Length>0 && data[0] == ',') | |
242 | + data = data.Substring(1); | |
243 | + } | |
244 | + array.Add(ReadData(newfield,floatMode, ref data, templates, UUIDInfo, othreFields)); | |
245 | + } | |
246 | + //配列の最後にある;をチェックして除く | |
247 | + if (data.Length > 0 && data[0] == ';') | |
248 | + data = data.Substring(1); | |
249 | + returnvalue = array.ToArray(); | |
250 | + } | |
251 | + else | |
252 | + { | |
253 | + if (IsPrimitive(field.TypeName)) | |
254 | + { | |
255 | + returnvalue = ReadPrimitiveData(field.TypeName, ref data, floatMode); | |
256 | + } | |
257 | + else | |
258 | + { | |
259 | + dynamic temp = new List<string>(); | |
260 | + temp.Add(data); | |
261 | + returnvalue = BuildData(field.TypeName, floatMode, ref temp, templates, UUIDInfo); | |
262 | + if (temp.Count > 0) | |
263 | + { | |
264 | + data = temp[0]; | |
265 | + //フィールドの最後にある;をチェックして除く | |
266 | + if (data.Length > 0 && data[0] == ';') | |
267 | + data = data.Substring(1); | |
268 | + } | |
269 | + | |
270 | + } | |
271 | + } | |
272 | + return returnvalue; | |
273 | + } | |
274 | + static dynamic ReadPrimitiveData(string typename, ref string data, FloatMode floatMode) | |
275 | + { | |
276 | + /*int pos1 = data.IndexOf(';'); | |
277 | + int pos2 = data.IndexOf(','); | |
278 | + int pos; | |
279 | + if (pos1 == -1 && pos2 == -1) | |
280 | + pos = -1; | |
281 | + else if(pos1==-1) | |
282 | + string strValue = ""; | |
283 | + if (pos == -1) | |
284 | + { | |
285 | + strValue = data; | |
286 | + data = ""; | |
287 | + } | |
288 | + else | |
289 | + { | |
290 | + strValue = data.Substring(0, pos); | |
291 | + data = data.Substring(pos + 1); | |
292 | + }*/ | |
293 | + Regex reg_num = new Regex(@"^\s*?(?<number>[0-9\.\-]+)(\;)?", RegexOptions.IgnoreCase); | |
294 | + Regex reg_str = new Regex(@"^\s*?(?<string>.*?)(\;|,)", RegexOptions.IgnoreCase); | |
295 | + string strValue; | |
296 | + if (typename.ToUpper() == "STRING") | |
297 | + { | |
298 | + strValue = reg_str.Match(data).Groups["string"].Value; | |
299 | + data = reg_str.Replace(data, ""); | |
300 | + return strValue; | |
301 | + } | |
302 | + else | |
303 | + { | |
304 | + strValue = reg_num.Match(data).Groups["number"].Value; | |
305 | + data = reg_num.Replace(data, ""); | |
306 | + } | |
307 | + switch (typename.ToUpper()) | |
308 | + { | |
309 | + case "WORD": | |
310 | + | |
311 | + return Convert.ToInt16(strValue); | |
312 | + case "DWORD": | |
313 | + return Convert.ToInt32(strValue); | |
314 | + case "FLOAT": | |
315 | + if (floatMode == FloatMode.Single) | |
316 | + return Convert.ToSingle(strValue); | |
317 | + else | |
318 | + return Convert.ToDouble(strValue); | |
319 | + case "DOUBLE": | |
320 | + return Convert.ToDouble(strValue); | |
321 | + case "CHAR": | |
322 | + case "UCHAR": | |
323 | + case "BYTE": | |
324 | + return Convert.ToByte(strValue); | |
325 | + default: | |
326 | + throw new Exception("……ここに来るはず無いんだけど"); | |
327 | + } | |
328 | + } | |
329 | + | |
330 | + } | |
331 | +} |
@@ -0,0 +1,58 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace CGL.Graphics.XFileLib.Text | |
7 | +{ | |
8 | + | |
9 | + /// <summary> | |
10 | + /// テンプレート情報 | |
11 | + /// </summary> | |
12 | + class XTemplateInfo | |
13 | + { | |
14 | + Dictionary<string, XTypeInfo> fields = new Dictionary<string, XTypeInfo>(); | |
15 | + | |
16 | + string uuid = ""; | |
17 | + /// <summary> | |
18 | + /// UUID | |
19 | + /// </summary> | |
20 | + public string UUID { get { return uuid; } } | |
21 | + /// <summary> | |
22 | + /// フィールド情報 | |
23 | + /// </summary> | |
24 | + public Dictionary<string, XTypeInfo> Fields { get { return fields; } } | |
25 | + | |
26 | + public XTemplateInfo(string uuid) | |
27 | + { | |
28 | + this.uuid = uuid; | |
29 | + } | |
30 | + } | |
31 | + /// <summary> | |
32 | + /// 型情報 | |
33 | + /// </summary> | |
34 | + class XTypeInfo : ICloneable | |
35 | + { | |
36 | + /// <summary> | |
37 | + /// フィールド名 | |
38 | + /// </summary> | |
39 | + public string FieldName; | |
40 | + /// <summary> | |
41 | + /// 型名 | |
42 | + /// </summary> | |
43 | + public string TypeName; | |
44 | + /// <summary> | |
45 | + /// 配列のサイズ | |
46 | + /// </summary> | |
47 | + public List<string> Dimensions; | |
48 | + | |
49 | + #region ICloneable メンバー | |
50 | + | |
51 | + public object Clone() | |
52 | + { | |
53 | + return new XTypeInfo { FieldName = FieldName, TypeName = TypeName, Dimensions = new List<string>(Dimensions) }; | |
54 | + } | |
55 | + | |
56 | + #endregion | |
57 | + } | |
58 | +} |
@@ -0,0 +1,73 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | +using System.IO; | |
6 | +using System.Text.RegularExpressions; | |
7 | +using CGL.Graphics.XFileLib.Text; | |
8 | + | |
9 | +namespace CGL.Graphics.XFileLib | |
10 | +{ | |
11 | + enum FloatMode | |
12 | + { | |
13 | + Single, | |
14 | + Double, | |
15 | + } | |
16 | + | |
17 | + public class XFile | |
18 | + { | |
19 | + Dictionary<string, Dictionary<string, dynamic>> data = new Dictionary<string, Dictionary<string, dynamic>>(); | |
20 | + /// <summary> | |
21 | + /// XFile中のデータ | |
22 | + /// </summary> | |
23 | + public Dictionary<string, Dictionary<string, dynamic>> FileData { get { return data; } } | |
24 | + | |
25 | + public static XFile FromFile(string filename) | |
26 | + { | |
27 | + filename = Path.GetFullPath(filename); | |
28 | + | |
29 | + if (!File.Exists(filename)) | |
30 | + throw new FileNotFoundException("ファイルがみつかりません", filename); | |
31 | + string fileMode = ""; | |
32 | + FloatMode floatMode; | |
33 | + using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open))) | |
34 | + { | |
35 | + string magic = (new string(br.ReadChars(4))).Trim(); | |
36 | + if (magic != "xof") | |
37 | + throw new FileLoadException("XFileではありません", filename); | |
38 | + br.ReadBytes(4);//バージョン読み飛ばし | |
39 | + fileMode = (new string(br.ReadChars(4))).Trim(); | |
40 | + string f = (new string(br.ReadChars(4))).Trim(); | |
41 | + switch (f) | |
42 | + { | |
43 | + case "0032": | |
44 | + floatMode = FloatMode.Single; | |
45 | + break; | |
46 | + case "0064": | |
47 | + floatMode = FloatMode.Double; | |
48 | + break; | |
49 | + default: | |
50 | + throw new FileLoadException("不明な浮動小数点型です:" + f, filename); | |
51 | + } | |
52 | + br.Close(); | |
53 | + } | |
54 | + switch (fileMode) | |
55 | + { | |
56 | + case "txt": | |
57 | + { | |
58 | + string data = File.ReadAllText(filename, Encoding.GetEncoding("Shift_JIS")); | |
59 | + return XFileTextReader.FromTxtFile(data, floatMode); | |
60 | + } | |
61 | + case "bin": | |
62 | + throw new NotImplementedException("バイナリ形式のXFileは読み込めません"); | |
63 | + case "tzip": | |
64 | + throw new NotImplementedException("zip圧縮形式のXFileは読み込めません"); | |
65 | + case "bzip": | |
66 | + throw new NotImplementedException("zip圧縮形式のXFileは読み込めません"); | |
67 | + default: | |
68 | + throw new FileLoadException("不明なXFileデータ型です"); | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + } | |
73 | +} |
@@ -0,0 +1,36 @@ | ||
1 | +using System.Reflection; | |
2 | +using System.Runtime.CompilerServices; | |
3 | +using System.Runtime.InteropServices; | |
4 | + | |
5 | +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 | |
6 | +// アセンブリに関連付けられている情報を変更するには、 | |
7 | +// これらの属性値を変更してください。 | |
8 | +[assembly: AssemblyTitle("XFileLib")] | |
9 | +[assembly: AssemblyDescription("")] | |
10 | +[assembly: AssemblyConfiguration("")] | |
11 | +[assembly: AssemblyCompany("")] | |
12 | +[assembly: AssemblyProduct("XFileLib")] | |
13 | +[assembly: AssemblyCopyright("Copyright © 2011")] | |
14 | +[assembly: AssemblyTrademark("")] | |
15 | +[assembly: AssemblyCulture("")] | |
16 | + | |
17 | +// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから | |
18 | +// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 | |
19 | +// その型の ComVisible 属性を true に設定してください。 | |
20 | +[assembly: ComVisible(false)] | |
21 | + | |
22 | +// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です | |
23 | +[assembly: Guid("bfcd47ab-5de9-4767-92cf-2ff47374742a")] | |
24 | + | |
25 | +// アセンブリのバージョン情報は、以下の 4 つの値で構成されています: | |
26 | +// | |
27 | +// Major Version | |
28 | +// Minor Version | |
29 | +// Build Number | |
30 | +// Revision | |
31 | +// | |
32 | +// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を | |
33 | +// 既定値にすることができます: | |
34 | +// [assembly: AssemblyVersion("1.0.*")] | |
35 | +[assembly: AssemblyVersion("1.0.0.0")] | |
36 | +[assembly: AssemblyFileVersion("1.0.0.0")] |