2002-01-24 Nick Drochak <ndrochak@gol.com>
[mono.git] / mcs / class / corlib / System.Resources / ResourceReader.cs
1 //
2 // System.Resources.ResourceReader.cs
3 //
4 // Authors: 
5 //      Duncan Mak <duncan@ximian.com>
6 //      Nick Drochak <ndrochak@gol.com>
7 //
8 // 2001 (C) Ximian Inc, http://www.ximian.com
9 //
10 // TODO: Finish this
11
12 using System.Collections;
13 using System.Resources;
14 using System.IO;
15
16 namespace System.Resources
17 {
18         class MonoTODO : Attribute {}\r
19         public sealed class ResourceReader : IResourceReader, IDisposable
20         {
21                 Stream stream;
22                 ArrayList resourceNames = null;
23                 ArrayList resourceValues = null;
24                 BinaryReader binaryReader;
25                 int resourceCount = 0;
26                 int typeCount = 0;
27                 ArrayList typeArray = new ArrayList();
28                 ArrayList hashes = new ArrayList();
29                 ArrayList positions = new ArrayList();
30                 int dataSectionOffset;
31
32                 // Constructors
33                 public ResourceReader (Stream stream)
34                 {
35                         if (stream == null)
36                                 throw new ArgumentNullException ("Value cannot be null.");
37                         
38                         if (!stream.CanRead)
39                                 throw new ArgumentException ("Stream was not readable.");
40
41                         this.stream = stream;
42                         
43                         if (!IsStreamValid()){
44                                 throw new ArgumentException("Stream is not a valid .resources file!  It was possibly truncated.");
45                         }
46                 }
47                 
48                 public ResourceReader (string fileName)
49                 {
50                         if (fileName == null)
51                                 throw new ArgumentException ("Path cannot be null.");
52                         
53                         if (String.Empty == fileName)
54                                 throw new ArgumentException("Empty path name is not legal.");
55
56                         if (!System.IO.File.Exists (fileName)) 
57                                 throw new FileNotFoundException ("Could not find file " + Path.GetFullPath(fileName));
58
59                         stream = new FileStream (fileName, FileMode.Open);
60
61                         if (!IsStreamValid()){
62                                 throw new ArgumentException("Stream is not a valid .resources file!  It was possibly truncated.");
63                         }
64                 }
65                 
66                 [MonoTODO]
67                 private bool IsStreamValid() {
68                         // not sure how much to check to determine if it's valid, 
69                         // but look at magic number, version numbers and class names
70                         string readerClass;
71                         string resourceSetClass;
72                         try {
73                                 binaryReader = new BinaryReader(stream);
74                                 int magicNumber = binaryReader.ReadInt32();
75                                 if (-1091581234 != magicNumber) {
76                                         return false;
77                                 }
78                                 int versionNumber = binaryReader.ReadInt32();
79                                 if (1 != versionNumber){
80                                         return false;
81                                 }
82                                 // Ignore next 32bits. they contain the length of the class name strings
83                                 binaryReader.ReadInt32();
84
85                                 readerClass = binaryReader.ReadString();
86                                 if (!readerClass.StartsWith("System.Resources.ResourceReader")){
87                                         return false;
88                                 }
89                                 resourceSetClass = binaryReader.ReadString();
90                                 if (!resourceSetClass.StartsWith("System.Resources.RuntimeResourceSet")){
91                                         return false;
92                                 }
93                                 int versionNumber2 = binaryReader.ReadInt32();
94                                 if (1 != versionNumber2){
95                                         return false;
96                                 }
97
98                                 resourceCount = binaryReader.ReadInt32();
99                                 typeCount = binaryReader.ReadInt32();
100
101                                 for (int i = 0; i < typeCount; i++) {
102                                         typeArray.Add(binaryReader.ReadString());
103                                 }
104                                 for (int i = 0; i < resourceCount; i++) {
105                                         hashes.Add(binaryReader.ReadInt32());
106                                 }
107                                 for (int i = 0; i < resourceCount; i++) {
108                                         positions.Add(binaryReader.ReadInt32());
109                                 }
110
111                                 dataSectionOffset = binaryReader.ReadInt32();
112                         }
113                         catch{
114                                 return false;
115                         }
116                         return true;
117                 }
118
119                 private string ReadString(BinaryReader br) {
120                         return br.ReadString();
121                 }
122
123                 public void Close ()
124                 {
125                         stream.Close ();
126                         stream = null;
127                 }
128                 
129                 public IDictionaryEnumerator GetEnumerator () {
130                         if (null == stream){
131                                 throw new InvalidOperationException("ResourceReader is closed.");
132                         }
133                         else {
134                                 // STRATEGY: if this is the first enumerator requested, fill the hash.
135                                 // delaying in this way seems ok since there's not much you can do with just
136                                 // a reader except close it.  And if you close it, you cannot get the enumerator.
137                                 // So, create the hash for the first enumerator, and re-use it for all others.
138                                 if (null == resourceNames) {
139                                         FillResources();
140                                 }
141                                 return new ResourceEnumerator (this);
142                         }
143                 }
144                 
145                 [MonoTODO]
146                 private void FillResources(){
147                         resourceNames = new ArrayList();
148                         BinaryReader unicodeReader = 
149                                 new BinaryReader(binaryReader.BaseStream, System.Text.Encoding.Unicode);
150                         // TODO: need to put these in an array and work out when to get the values.
151                         // also need to figure out the hash and how/if to use it.
152                         string test = unicodeReader.ReadString();
153                         int offset = binaryReader.ReadInt32();
154                 }
155
156                 IEnumerator IEnumerable.GetEnumerator ()
157                 {
158                         return ((IResourceReader) this).GetEnumerator();
159                 }
160                 
161                 [MonoTODO]
162                 void IDisposable.Dispose ()
163                 {
164                         // FIXME: is this all we need to do?
165                         Close();
166                 }
167                 
168         }
169         
170         internal class ResourceEnumerator : IDictionaryEnumerator
171         {
172                 protected DictionaryEntry entry;
173                 protected object key;
174                 protected object value;
175                 protected ResourceReader reader;
176                 
177                 public ResourceEnumerator(ResourceReader readerToEnumerate){
178                         reader = readerToEnumerate;
179                 }
180
181                 public DictionaryEntry Entry
182                 {
183                         get { return entry; }
184                 }
185                 
186                 public object Key
187              {
188                         get { return key; }
189                 }
190                 
191                 public object Value
192                 {
193                         get { return value; }
194                 }
195                 
196                 [MonoTODO]
197                 public object Current
198                 {
199                         get { return null; }
200                 }
201                 
202                 [MonoTODO]
203                 public bool MoveNext ()
204                 {
205                         return false;
206                 }
207                 
208                 [MonoTODO]
209                 public void Reset () { }
210         }
211 }