ProjectArcade

Форк
0
515 строк · 16.1 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.IO;
6
using System.Xml.Linq;
7
using System.Dynamic;
8

9
namespace EmulatorLauncher.Common.FileFormats
10
{
11
    public class ConfigFile : DynamicObject, IEnumerable<ConfigItem>
12
    {
13
        public ConfigFileOptions Options { get; set; }
14

15
        public static ConfigFile FromArguments(string[] args)
16
        {
17
            ConfigFile arguments = new ConfigFile();
18

19
            string current = null;
20
            foreach (string arg in args)
21
            {
22
                if (arg.StartsWith("-"))
23
                    current = arg.Substring(1);
24
                else if (!string.IsNullOrEmpty(current))
25
                {
26
                    arguments[current] = arg;
27
                    current = null;
28
                }
29
                else
30
                    arguments["rom"] = arg;
31
            }
32

33
            return arguments;
34
        }
35

36
        public static ConfigFile LoadEmulationStationSettings(string file)
37
        {
38
            var ret = new ConfigFile();
39
            if (!File.Exists(file))
40
                return ret;
41

42
            try
43
            {
44
                XDocument doc = XDocument.Load(file);
45

46
                foreach (XElement element in doc.Root.Descendants())
47
                {
48
                    if (element.Attribute("name") != null && element.Attribute("value") != null)
49
                    {
50
                        string name = element.Attribute("name").Value;
51
                        string val = element.Attribute("value").Value;
52
                        ret[name] = val;
53
                    }
54
                }
55
            }
56
            catch { }
57

58
            return ret;
59
        }
60

61
        private static string EmptyLine = "------------EmptyLine----------------";
62

63
        public static ConfigFile FromFile(string file, ConfigFileOptions options = null)
64
        {
65
            var ret = new ConfigFile();
66
            ret.Options = options;
67
            if (!File.Exists(file))
68
                return ret;
69

70
            bool keepComments = options != null && options.KeepComments;
71

72
            foreach (var line in File.ReadAllLines(file))
73
            {
74
                bool skip = false;
75

76
                foreach (var chr in line)
77
                {
78
                    if (chr == '#' || chr == ';')
79
                    {
80
                        skip = true;
81
                        break;
82
                    }
83

84
                    if (chr != ' ' && chr != '\t')
85
                        break;
86
                }
87

88
                if (skip && !keepComments)
89
                    continue;
90

91
                bool doubleEquals = options != null && options.UseDoubleEqual;
92

93
                int idx = doubleEquals ? line.IndexOf("==", StringComparison.Ordinal) : line.IndexOf("=", StringComparison.Ordinal);
94
                if (idx >= 0)
95
                {
96
                    string value = line.Substring(idx + (doubleEquals ? 2 : 1)).Trim();
97
                    if (value.StartsWith("\""))
98
                        value = value.Substring(1);
99

100
                    if (value.EndsWith("\""))
101
                        value = value.Substring(0, value.Length-1);
102

103
                    ret[line.Substring(0, idx).Trim()] = value;
104
                }
105
                else
106
                    ret[line] = EmptyLine;
107
            }
108

109
            return ret;
110
        }
111

112
        public void ImportOverrides(ConfigFile cfg)
113
        {
114
            if (cfg == null)
115
                return;
116

117
            foreach (var item in cfg._data.Values)
118
                this[item.Name] = item.Value;
119
        }
120

121
        public string GetFullPath(string key)
122
        {
123
            string data = this[key];
124
            if (string.IsNullOrEmpty(data))
125
            {
126
                if (key == "home" && Directory.Exists(Path.Combine(LocalPath, ".emulationstation")))                        
127
                    return Path.Combine(LocalPath, ".emulationstation");
128

129
                if (key == "bios" || key == "saves" || key == "thumbnails" || key == "shaders" || key == "decorations" || key == "screenshots" || key == "roms" || key == "records" || key == "cheats")
130
                {
131
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", key))))
132
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", key)));
133
                }
134
                else if (key == "projectarcade")
135
                {
136
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath))))
137
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..")));
138
                }
139
                else
140
                {
141
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, key))))
142
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, key)));
143

144
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "emulators", key))))
145
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "emulators", key)));
146

147
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", "emulators", key))))
148
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", "emulators", key)));
149

150
                    if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", key))))
151
                        return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", key)));
152
                }
153
                
154
                return string.Empty;
155
            }
156

157
            if (data.Contains(":")) // drive letter -> Full path
158
                return data;
159

160
            if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, data))))
161
                return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, data)));
162

163
            if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "emulators", data))))
164
                return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "emulators", data)));
165

166
            if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", "emulators", data))))
167
                return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", "emulators", data)));
168

169
            if (Directory.Exists(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", data))))
170
                return Path.Combine(Path.GetFullPath(Path.Combine(LocalPath, "..", "system", data)));
171

172
            return data;
173
        }
174

175
        private OrderedDictionary<string, ConfigItem> _data = new OrderedDictionary<string, ConfigItem>();
176

177
        public ConfigFile() { }
178

179
        private string FormatKey(string key)
180
        {
181
            if (string.IsNullOrEmpty(key))
182
                return key;
183

184
            if (Options != null && Options.CaseSensitive)
185
                return key.Trim();
186

187
            return key.ToLowerInvariant().Trim();
188
        }
189

190
        public string this[string key]
191
        {
192
            get
193
            {
194
                if (!string.IsNullOrEmpty(key))
195
                {
196
                    ConfigItem item;
197
                    if (_data.TryGetValue(FormatKey(key), out item) && item != null)
198
                        if (item.Value != EmptyLine)
199
                            return item.Value;
200
                }
201

202
                return string.Empty;
203
            }
204
            set
205
            {
206
                var indexKey = key;
207

208
                if (string.IsNullOrEmpty(indexKey) && value == EmptyLine)
209
                {
210
                    if (this.Options == null || !Options.KeepEmptyLines)
211
                        return;
212

213
                    indexKey = EmptyLine + Guid.NewGuid();
214
                }
215
                else
216
                    indexKey = FormatKey(key);
217

218
                ConfigItem item;
219
                if (!_data.TryGetValue(indexKey, out item) || item == null)
220
                {
221
                    if ((this.Options == null || !Options.KeepEmptyValues) && string.IsNullOrEmpty(value))
222
                        return;
223

224
                    item = new ConfigItem() { Name = key, Value = value };
225
                    _data.Add(indexKey, item);
226
                    return;
227
                }
228

229
                if ((this.Options == null || !Options.KeepEmptyValues) && string.IsNullOrEmpty(value))
230
                    _data.Remove(indexKey);
231
                else if (item.Value != value)
232
                {
233
                    item.Value = value;
234
                    IsDirty = true;
235
                }
236
            }
237
        }
238

239
        public string GetValueOrDefault(string key, string defaultValue)
240
        {
241
            ConfigItem item;
242
            if (_data.TryGetValue(FormatKey(key), out item) && item != null)
243
                if (!string.IsNullOrEmpty(item.Value))
244
                    return item.Value;
245

246
            return defaultValue;
247
        }
248

249
        public virtual bool IsDirty { get; protected set; }
250

251
        public override string ToString()
252
        {
253
            StringBuilder sb = new StringBuilder();
254

255
            string equalSign = this.Options != null && this.Options.UseDoubleEqual ? "==" : "=";
256
            bool useSpaces = this.Options != null && this.Options.UseSpaces;
257
            bool useQuotes = this.Options != null && this.Options.UseQuotes;
258

259
            foreach (var item in _data.Values)
260
            {
261
                sb.Append(item.Name);
262

263
                if (item.Value == EmptyLine)
264
                {
265
                    sb.AppendLine();
266
                    continue;
267
                }
268

269
                if (useSpaces)
270
                {
271
                    sb.Append(" ");
272
                    sb.Append(equalSign);
273
                    sb.Append(" ");
274
                }
275
                else
276
                    sb.Append(equalSign);
277

278
                if (useQuotes)
279
                    sb.Append("\"");
280
                    
281
                sb.Append(item.Value);
282

283
                if (useQuotes)
284
                    sb.Append("\"");
285

286
                sb.AppendLine();
287
            }
288

289
            return sb.ToString();
290
        }
291

292
        public void Save(string fileName, bool retroarchformat = false)
293
        {
294
            if (retroarchformat)
295
            {
296
                if (this.Options == null)
297
                    this.Options = new ConfigFileOptions();
298

299
                this.Options.UseDoubleEqual = false;
300
                this.Options.UseQuotes = true;
301
                this.Options.UseSpaces = true;
302

303
            }
304

305
            string text = ToString();
306
            File.WriteAllText(fileName, text);
307
        }
308

309
        public ConfigFile LoadAll(string key)
310
        {
311
            ConfigFile ret = new ConfigFile();
312

313
            if (string.IsNullOrEmpty(key))
314
                return ret;
315

316
            key = FormatKey(key) + ".";
317

318
            foreach (var item in _data.Values)
319
                if (item.Name.StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
320
                    ret[item.Name.Substring(key.Length)] = item.Value;
321

322
            return ret;
323
        }
324

325
        public bool isOptSet(string key)
326
        {
327
            if (string.IsNullOrEmpty(key))
328
                return false;
329

330
            return _data.ContainsKey(FormatKey(key));
331
        }
332

333
        public bool getOptBoolean(string key)
334
        {
335
            if (string.IsNullOrEmpty(key))
336
                return false;
337

338
            ConfigItem item;
339
            if (_data.TryGetValue(FormatKey(key), out item) && item != null)
340
                return item.Value != null && (item.Value.ToLower() == "true" || item.Value == "1" || item.Value.ToLower() == "enabled");
341

342
            return false;
343
        }
344

345
        public int getInteger(string key)
346
        {
347
            if (string.IsNullOrEmpty(key))
348
                return 0;
349

350
            ConfigItem item;
351
            if (_data.TryGetValue(FormatKey(key), out item) && item != null)
352
            {
353
                int ret;
354
                if (int.TryParse(item.Value, out ret))
355
                    return ret;
356
            }
357
            
358
            return 0;
359
        }
360

361
        public IEnumerator<ConfigItem> GetEnumerator()
362
        {
363
            return _data.Values.GetEnumerator();
364
        }
365

366
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
367
        {
368
            return _data.Values.GetEnumerator();
369
        }
370

371
        public void DisableAll(string key)
372
        {
373
            if (string.IsNullOrEmpty(key))
374
                return;
375

376
            List<string> toRemove = new List<string>();
377

378
            key = FormatKey(key);
379

380
            foreach (var item in _data)
381
                if (item.Value.Name != EmptyLine && item.Key.Contains(key))
382
                    toRemove.Add(item.Key);
383

384
            foreach (var item in toRemove)
385
                _data.Remove(item);            
386
        }
387

388
        public static string LocalPath
389
        {
390
            get
391
            {
392
                if (_localPath == null)
393
                    _localPath = Path.GetDirectoryName(typeof(ConfigFile).Assembly.Location);
394

395
                return _localPath;
396
            }
397
        }
398

399
        public void AppendLine(string line)
400
        {
401
            _data.Add(EmptyLine + Guid.NewGuid().ToString(), new ConfigItem()
402
            {
403
                Name = line,
404
                Value = EmptyLine
405
            });
406
        }
407

408
        private static string _localPath;
409

410
        #region DynamicObject
411
        public override IEnumerable<string> GetDynamicMemberNames()
412
        {
413
            PartialConfigFile me = this as PartialConfigFile;
414
            if (me != null)
415
            {
416
                return _data
417
                    .Where(d => !string.IsNullOrEmpty(d.Value.Name) && d.Value != null && d.Value.Name.StartsWith(me.Root))
418
                    .Select(d => d.Value.Name);
419
            }             
420

421
            return _data.Where(d => !string.IsNullOrEmpty(d.Value.Name) && d.Value != null).Select(d => d.Value.Name);
422
        }
423

424
        class PartialConfigFile : ConfigFile
425
        {           
426
            public PartialConfigFile(ConfigFile parent, string root)
427
            {
428
                _parent = parent;
429
                Root = root;
430
            }
431

432
            private ConfigFile _parent;
433
            public string Root { get; set; }
434

435
            public override bool IsDirty
436
            {
437
                get { return _parent.IsDirty; }
438
                protected set { _parent.IsDirty = value; }
439
            }
440
        }
441

442
        public override bool TryGetMember(GetMemberBinder binder, out object result)
443
        {
444
            string propertyPath = binder.Name;
445

446
            PartialConfigFile me = this as PartialConfigFile;
447
            if (me != null)
448
                propertyPath = me.Root + propertyPath;
449

450
            ConfigItem item;
451
            if (_data.TryGetValue(FormatKey(propertyPath), out item))
452
            {
453
                result = item.Value;
454
                return true;
455
            }
456

457
            var root = propertyPath + ".";
458

459
            if (_data.Values.Any(v => v.Name != null && v.Name.StartsWith(root)))
460
            {
461
                result = new PartialConfigFile(this, root) { _data = this._data };
462
                return true;
463
            }
464

465
            result = null;
466
            return true;
467
        }
468

469
        public override bool TrySetMember(SetMemberBinder binder, object value)
470
        {
471
            string propertyPath = binder.Name;
472

473
            PartialConfigFile me = this as PartialConfigFile;
474
            if (me != null)
475
                propertyPath = me.Root + propertyPath;
476

477
            if (value == null)
478
                this.DisableAll(propertyPath);
479
            else
480
                this[propertyPath] = value.ToString();
481

482
            return true;
483
        }
484
        #endregion
485

486
    }
487

488
    public class ConfigItem
489
    {
490
        public override string ToString()
491
        {
492
            return Name + " = " + Value;
493
        }
494

495
        public string Name { get; set; }
496
        public string Value { get; set; }
497
    }
498

499
    public class ConfigFileOptions
500
    {
501
        public ConfigFileOptions()
502
        {
503
            KeepEmptyValues = true;
504
        }
505

506
        public bool KeepEmptyLines { get; set; }
507
        public bool KeepEmptyValues { get; set; }
508
        public bool KeepComments { get; set; }
509
        public bool CaseSensitive { get; set; }
510
        public bool UseDoubleEqual { get; set; }
511
        public bool UseSpaces { get; set; }
512
        public bool UseQuotes { get; set; }
513

514
    }
515
}
516

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.