-
Notifications
You must be signed in to change notification settings - Fork 1
/
GOB.cs
159 lines (130 loc) · 4.2 KB
/
GOB.cs
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
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Smith
{
public unsafe class GOB : IDisposable, IEnumerable<string>
{
private class FileEntry
{
public readonly int offset;
public readonly int length;
public FileEntry(int _offset, int _length)
{
offset = _offset;
length = _length;
}
}
public override string ToString()
{
return Path.GetFileName(path);
}
private Stream Stream;
public readonly string path;
private Dictionary<string, FileEntry> FileEntries = new Dictionary<string, FileEntry>(StringComparer.InvariantCultureIgnoreCase);
public GOB(string gobfile, Stream s)
{
if (s.Length == 0)
throw new Exception("crappy gob");
path = gobfile;
Stream = s;
BinaryReader br = new BinaryReader(Stream);
br.ReadBytes(3); // verification GOB
br.ReadByte(); // version?
br.ReadInt32(); // offset to first file length
br.ReadInt32(); // offset to number of files
int numFiles = br.ReadInt32();
for (int x = 0; x < numFiles; x++)
{
int offset = br.ReadInt32();
int length = br.ReadInt32();
byte[] sz = br.ReadBytes(128);
string filename;
fixed (byte* psz = sz)
filename = new string((sbyte*)psz);
if (string.IsNullOrEmpty(filename))
{
//Log.Warning("GOB " + Path.GetFileName(path) + " has empty file name");
continue;
}
/*if(Tokenizer.IsGarbage(filename))
{
Log.Error("CORRUPT GOB " + Path.GetFileName(path) + " has invalid file string (" + filename[0] + "), stopping load of gob");
return;
}*/
if (FileEntries.ContainsKey(filename))
{
//Log.Warning("GOB specifies duplicate file entry " + filename + "; ignoring");
}
else
FileEntries.Add(filename, new FileEntry(offset, length));
}
}
public IEnumerator<string> GetEnumerator()
{
return FileEntries.Keys.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int Count
{
get
{
return FileEntries.Count;
}
}
public MemoryStream this[string filename]
{
get
{
if (!FileEntries.ContainsKey(filename))
return null;
FileEntry fe = FileEntries[filename];
Stream.Position = fe.offset;
byte[] buf = new byte[fe.length];
Stream.Read(buf, 0, fe.length);
return new MemoryStream(buf);
}
}
public string[] GetFilesWithExtension(string ext)
{
if (string.IsNullOrEmpty(ext))
return new string[0];
if (!ext.StartsWith("."))
ext = "." + ext;
List<string> files = new List<string>();
foreach (string file in this)
if (ext.Equals(System.IO.Path.GetExtension(file)))
files.Add(file);
return files.ToArray();
}
~GOB()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
if (Stream != null)
{
Stream.Dispose();
Stream = null;
}
}
disposed = true;
}
}
}