~ruther/NosSmooth

ref: fcd0751c2f76ffee45134260ce9d7c0bddf837d2 NosSmooth/Data/NosSmooth.Data.NOSFiles/Parsers/Dat/DatReader.cs -rw-r--r-- 2.7 KiB
fcd0751c — František Boháček Merge pull request #22 from Rutherther/data 3 years ago
                                                                                
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
//
//  DatReader.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics.CodeAnalysis;
using System.Text;
using NosSmooth.Data.NOSFiles.Files;
using Remora.Results;

namespace NosSmooth.Data.NOSFiles.Parsers.Dat;

/// <summary>
/// Reader of .dat files.
/// </summary>
public class DatReader
{
    private readonly RawFile _file;
    private IReadOnlyList<string> _lines;
    private int _currentLine;
    private string _separator;

    /// <summary>
    /// Initializes a new instance of the <see cref="DatReader"/> class.
    /// </summary>
    /// <param name="file">The file to read.</param>
    public DatReader(RawFile file)
    {
        _lines = Encoding.ASCII.GetString(file.Content).Split('\r', '\n').ToArray();
        _currentLine = 0;
        _file = file;
        _separator = "VNUM";
    }

    /// <summary>
    /// Gets whether the reader has reached the end.
    /// </summary>
    public bool ReachedEnd => _currentLine >= _lines.Count;

    /// <summary>
    /// Sets the separator of a new item.
    /// </summary>
    /// <param name="separator">The separator of new item.</param>
    public void SetSeparatorField(string separator)
    {
        _separator = separator;
    }

    /// <summary>
    /// Read next item.
    /// </summary>
    /// <param name="item">The read item.</param>
    /// <returns>Whether an item was read.</returns>
    public bool ReadItem([NotNullWhen(true)] out DatItem? item)
    {
        return ReadItem(out item, _currentLine > 0);
    }

    private bool ReadItem([NotNullWhen(true)] out DatItem? item, bool readFirstItem)
    {
        if (ReachedEnd)
        {
            item = null;
            return false;
        }

        int startLine = _currentLine;
        if (readFirstItem && _lines[_currentLine].Trim().StartsWith(_separator))
        {
            _currentLine++;
        }

        while (!ReachedEnd && !_lines[_currentLine].Trim().StartsWith(_separator))
        {
            _currentLine++;
        }

        if (!readFirstItem)
        {
            return ReadItem(out item, true);
        }

        var dictionary = new Dictionary<string, IReadOnlyList<DatEntry>>();
        for (int i = startLine; i < _currentLine; i++)
        {
            var line = _lines[i];
            var splitted = line.Trim().Split('\t');
            var key = splitted[0];
            var entry = new DatEntry(key, splitted);
            if (!dictionary.ContainsKey(key))
            {
                dictionary.Add(key, new List<DatEntry>());
            }

            ((List<DatEntry>)dictionary[key]).Add(entry);
        }

        item = new DatItem(dictionary);
        return true;
    }
}
Do not follow this link