ProjectArcade

Форк
0
520 строк · 15.0 Кб
1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using System.IO;
5
using System.Runtime.InteropServices;
6
using System.Text;
7
using System.Linq;
8

9
namespace EmulatorLauncher.Common.FileFormats
10
{
11
    [Flags]
12
    public enum IniOptions
13
    {
14
        UseSpaces = 1,
15
        KeepEmptyValues = 2,
16
        AllowDuplicateValues = 4,
17
        KeepEmptyLines = 8,
18
        UseDoubleEqual = 16,  // nosgba inifile uses double equals as separator !
19
    }
20

21
    public class IniFile : IDisposable
22
    {
23
        public static IniFile FromFile(string path, IniOptions options = (IniOptions) 0)
24
        {
25
            return new IniFile(path, options);
26
        }
27

28
        public IniFile(string path, IniOptions options = (IniOptions) 0)
29
        {
30
            _options = options;
31
            _path = path;
32
            _dirty = false;
33

34
            if (!File.Exists(_path))
35
                return;
36

37
            try
38
            {
39
                using (TextReader iniFile = new StreamReader(_path))
40
                {
41
                    Section currentSection = null;
42

43
                    var namesInSection = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
44

45
                    string strLine = iniFile.ReadLine();
46
                    while (strLine != null)
47
                    {
48
                        strLine = strLine.Trim();
49

50
                        if (strLine != "" || _options.HasFlag(IniOptions.KeepEmptyLines))
51
                        {
52
                            if (strLine.StartsWith("["))
53
                            {
54
                                int end = strLine.IndexOf("]");
55
                                if (end > 0)
56
                                {
57
                                    namesInSection.Clear();
58
                                    currentSection = _sections.GetOrAddSection(strLine.Substring(1, end - 1));
59
                                }
60
                            }
61
                            else
62
                            {
63
                                string[] keyPair = _options.HasFlag(IniOptions.UseDoubleEqual) ? strLine.Split(new string[] { "==" }, 2, StringSplitOptions.None) : strLine.Split(new char[] { '=' }, 2);
64

65
                                if (currentSection == null)
66
                                {
67
                                    namesInSection.Clear();
68
                                    currentSection = _sections.GetOrAddSection(null);
69
                                }
70

71
                                var key = new Key();
72
                                key.Name = keyPair[0].Trim();
73

74
                                if (!key.IsComment && !_options.HasFlag(IniOptions.AllowDuplicateValues) && namesInSection.Contains(key.Name))
75
                                {
76
                                    strLine = iniFile.ReadLine();
77
                                    continue;
78
                                }
79

80
                                if (key.IsComment)
81
                                {
82
                                    key.Name = strLine;
83
                                    key.Value = null;
84
                                }
85
                                else if (keyPair.Length > 1)
86
                                {
87
                                    namesInSection.Add(key.Name);
88

89
                                    var commentIdx = keyPair[1].IndexOf(";");
90
                                    if (commentIdx > 0)
91
                                    {
92
                                        key.Comment = keyPair[1].Substring(commentIdx);
93
                                        keyPair[1] = keyPair[1].Substring(0, commentIdx);
94
                                    }
95

96
                                    key.Value = keyPair[1].Trim();
97
                                }
98
                           
99
                                currentSection.Add(key);
100
                            }
101
                        }
102

103
                        strLine = iniFile.ReadLine();
104
                    }
105

106
                    iniFile.Close();
107
                }
108
            }
109
            catch (Exception ex)
110
            {
111
                throw ex;
112
            }
113
        }
114

115
        public IniSection GetOrCreateSection(string key)
116
        {
117
            return new PrivateIniSection(key, this);
118
        }
119

120
        class PrivateIniSection : IniSection { public PrivateIniSection(string name, IniFile ini) : base(name, ini) { } }
121

122
        public string[] EnumerateSections()
123
        {
124
            return _sections.Select(s => s.Name).Distinct().ToArray();
125
        }
126

127
        public string[] EnumerateKeys(string sectionName)
128
        {
129
            var section = _sections.Get(sectionName);
130
            if (section != null)
131
                return section.Select(k => k.Name).ToArray();
132

133
            return new string[] { };
134
        }
135

136
        public KeyValuePair<string, string>[] EnumerateValues(string sectionName)
137
        {
138
            var ret = new List<KeyValuePair<string, string>>();
139

140
            var section = _sections.Get(sectionName);
141
            if (section != null)
142
            {
143
                foreach (var item in section)
144
                {
145
                    if (item.IsComment || string.IsNullOrEmpty(item.Name))
146
                        continue;
147

148
                    ret.Add(new KeyValuePair<string, string>(item.Name, item.Value));
149
                }
150
            }
151

152
            return ret.ToArray();
153
        }
154

155
        public void ClearSection(string sectionName)
156
        {
157
            var section = _sections.Get(sectionName);
158
            if (section != null && section.Any())
159
            {
160
                _dirty = true;
161
                section.Clear();
162
            }
163
        }
164

165
        public string GetValue(string sectionName, string key)
166
        {
167
            var section = _sections.Get(sectionName);
168
            if (section != null)
169
                return section.GetValue(key);
170

171
            return null;
172
        }
173

174
        public void WriteValue(string sectionName, string keyName, string value)
175
        {
176
            var section = _sections.GetOrAddSection(sectionName);
177

178
            var key = section.Get(keyName);
179
            if (key != null && key.Value == value)
180
                return;
181

182
            if (key == null)
183
                key = section.Add(keyName);
184

185
            key.Value = value;
186

187
            _dirty = true;
188
        }
189

190
        public void AppendValue(string sectionName, string keyName, string value)
191
        {
192
            if (!_options.HasFlag(IniOptions.AllowDuplicateValues))
193
            {
194
                WriteValue(sectionName, keyName, value);
195
                return;
196
            }
197

198
            var section = _sections.GetOrAddSection(sectionName);
199
            section.Add(keyName, value);
200

201
            _dirty = true;
202
        }
203

204
        public void Remove(string sectionName, string keyName)
205
        {
206
            var section = _sections.Get(sectionName);
207
            if (section != null)
208
            {
209
                foreach (var key in section.Where(k => k.Name.Equals(keyName, StringComparison.InvariantCultureIgnoreCase)).ToArray())
210
                {
211
                    _dirty = true;
212
                    section.Remove(key);
213
                }
214
            }
215
        }
216

217
        public bool IsDirty { get { return _dirty; } }
218

219
        public override string ToString()
220
        {
221
            ArrayList sections = new ArrayList();
222

223
            StringBuilder sb = new StringBuilder();
224

225
            foreach (var section in _sections)
226
            {
227
                if (!string.IsNullOrEmpty(section.Name) && section.Name != "ROOT" && section.Any())
228
                    sb.AppendLine("[" + section.Name + "]");
229

230
                foreach (Key entry in section)
231
                {
232
                    if (string.IsNullOrEmpty(entry.Name))
233
                    {
234
                        if (!string.IsNullOrEmpty(entry.Comment))
235
                            sb.AppendLine(entry.Comment);
236
                        else if (_options.HasFlag(IniOptions.KeepEmptyLines))
237
                            sb.AppendLine();
238

239
                        continue;
240
                    }
241

242
                    if (entry.IsComment)
243
                    {
244
                        sb.AppendLine(entry.Name);
245
                        continue;
246
                    }
247

248
                    if (string.IsNullOrEmpty(entry.Value) && !_options.HasFlag(IniOptions.KeepEmptyValues))
249
                        continue;
250

251
                    if (string.IsNullOrEmpty(entry.Name))
252
                        continue;
253

254
                    sb.Append(entry.Name);
255

256
                    if (_options.HasFlag(IniOptions.UseSpaces))
257
                        sb.Append(" ");
258

259
                    if (_options.HasFlag(IniOptions.UseDoubleEqual))
260
                        sb.Append("==");
261
                    else
262
                        sb.Append("=");
263

264
                    if (_options.HasFlag(IniOptions.UseSpaces))
265
                        sb.Append(" ");
266

267
                    sb.Append(entry.Value);
268

269
                    if (!string.IsNullOrEmpty(entry.Comment))
270
                    {
271
                        sb.Append("\t\t\t");
272
                        sb.Append(entry.Comment);
273
                    }
274

275
                    sb.AppendLine();
276
                }
277

278
                if (!_options.HasFlag(IniOptions.KeepEmptyLines))
279
                    sb.AppendLine();
280
            }
281

282
            return sb.ToString();
283
        }
284

285
        public void Save()
286
        {
287
            if (!_dirty)
288
                return;
289
                        
290
            try
291
            {
292
                string dir = Path.GetDirectoryName(_path);
293
                if (!Directory.Exists(dir))
294
                    Directory.CreateDirectory(dir);
295

296
                using (TextWriter tw = new StreamWriter(_path))
297
                {
298
                    tw.Write(ToString());
299
                    tw.Close();
300
                }
301

302
                _dirty = false;
303
            }
304
            catch (Exception ex)
305
            {
306
                SimpleLogger.Instance.Error("[IniFile] Save failed " + ex.Message, ex);
307
            }
308
        }
309

310
        public void Dispose()
311
        {
312
            Save();
313
        }
314

315
        private IniOptions _options;
316
        private bool _dirty;
317
        private string _path;
318

319
        #region Private classes
320
        class Key
321
        {
322
            public string Name { get; set; }
323
            public string Value { get; set; }
324
            public string Comment { get; set; }
325

326
            public bool IsComment
327
            {
328
                get
329
                {
330
                    return Name == null || Name.StartsWith(";") || Name.StartsWith("#");
331
                }
332
            }
333

334
            public override string ToString()
335
            {
336
                if (string.IsNullOrEmpty(Name))
337
                    return "";
338

339
                if (string.IsNullOrEmpty(Value))
340
                    return Name + "=";
341

342
                return Name + "=" + Value;
343
            }
344
        }
345

346
        class KeyList : List<Key>
347
        {
348

349
        }
350

351
        class Section : IEnumerable<Key>
352
        {
353
            public Section()
354
            {
355
                _keys = new KeyList();
356
            }
357

358
            public string Name { get; set; }
359

360

361
            public override string ToString()
362
            {
363
                if (string.IsNullOrEmpty(Name))
364
                    return "";
365

366
                return "[" + Name + "]";
367
            }
368

369
            public bool Exists(string keyName)
370
            {
371
                foreach (var key in _keys)
372
                    if (key.Name.Equals(keyName, StringComparison.InvariantCultureIgnoreCase))
373
                        return true;
374

375
                return false;
376
            }
377

378
            public Key Get(string keyName)
379
            {
380
                foreach (var key in _keys)
381
                    if (key.Name.Equals(keyName, StringComparison.InvariantCultureIgnoreCase))
382
                        return key;
383

384
                return null;
385
            }
386

387
            public string GetValue(string keyName)
388
            {
389
                foreach (var key in _keys)
390
                    if (key.Name.Equals(keyName, StringComparison.InvariantCultureIgnoreCase))
391
                        return key.Value;
392

393
                return null;
394
            }
395

396
            private KeyList _keys;
397

398
            public IEnumerator<Key> GetEnumerator()
399
            {
400
                return _keys.GetEnumerator();
401
            }
402

403
            IEnumerator IEnumerable.GetEnumerator()
404
            {
405
                return _keys.GetEnumerator();
406
            }
407

408
            public Key Add(string keyName, string value = null)
409
            {
410
                var key = new Key() { Name = keyName, Value = value };
411
                _keys.Add(key);
412
                return key;
413
            }
414

415
            public Key Add(Key key)
416
            {
417
                _keys.Add(key);
418
                return key;
419
            }
420

421
            internal void Clear()
422
            {
423
                _keys.Clear();
424
            }
425

426
            internal void Remove(Key key)
427
            {
428
                _keys.Remove(key);
429
            }
430
        }
431

432
        class Sections : IEnumerable<Section>
433
        {
434
            public Sections()
435
            {
436
                _sections = new List<Section>();
437
            }
438

439
            public Section Get(string sectionName)
440
            {
441
                if (sectionName == null)
442
                    sectionName = string.Empty;
443

444
                return _sections.FirstOrDefault(s => s.Name.Equals(sectionName, StringComparison.InvariantCultureIgnoreCase));
445
            }
446

447
            public Section GetOrAddSection(string sectionName)
448
            {
449
                if (sectionName == null)
450
                    sectionName = string.Empty;
451

452
                var section = Get(sectionName);
453
                if (section == null)
454
                {
455
                    section = new Section() { Name = sectionName };
456

457
                    if ((string.IsNullOrEmpty(sectionName) || sectionName == "ROOT") && _sections.Count > 0)
458
                        _sections.Insert(0, section);
459
                    else
460
                        _sections.Add(section);
461
                }
462

463
                return section;
464
            }
465

466
            private List<Section> _sections;
467

468
            public IEnumerator<Section> GetEnumerator()
469
            {
470
                return _sections.GetEnumerator();
471
            }
472

473
            IEnumerator IEnumerable.GetEnumerator()
474
            {
475
                return _sections.GetEnumerator();
476
            }
477
        }
478

479
        private Sections _sections = new Sections();
480
        #endregion
481
    }
482

483

484
    public class IniSection
485
    {
486
        private IniFile _ini;
487
        private string _sectionName;
488

489
        protected IniSection(string name, IniFile ini)
490
        {
491
            _ini = ini;
492
            _sectionName = name;
493
        }
494

495
        public string this[string key]
496
        {
497
            get
498
            {
499
                return _ini.GetValue(_sectionName, key);
500
            }
501
            set
502
            {
503
                _ini.WriteValue(_sectionName, key, value);
504
            }
505
        }
506

507
        public void Clear()
508
        {
509
            _ini.ClearSection(_sectionName);            
510
        }
511

512
        public string[] Keys
513
        {
514
            get
515
            {                
516
                return _ini.EnumerateKeys(_sectionName);
517
            }
518
        }
519
    }
520
}

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

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

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

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