|
|
@@ -1,669 +0,0 @@
|
|
|
-//
|
|
|
-// System.Resources.ResourceReader.cs
|
|
|
-//
|
|
|
-// Authors:
|
|
|
-// Duncan Mak <[email protected]>
|
|
|
-// Nick Drochak <[email protected]>
|
|
|
-// Dick Porter <[email protected]>
|
|
|
-// Marek Safar <[email protected]>
|
|
|
-// Atsushi Enomoto <[email protected]>
|
|
|
-// Larry Ewing <[email protected]>
|
|
|
-//
|
|
|
-// (C) 2001, 2002 Ximian Inc, http://www.ximian.com
|
|
|
-// Copyright (C) 2004-2005,2007-2008 Novell, Inc (http://www.novell.com)
|
|
|
-//
|
|
|
-// Permission is hereby granted, free of charge, to any person obtaining
|
|
|
-// a copy of this software and associated documentation files (the
|
|
|
-// "Software"), to deal in the Software without restriction, including
|
|
|
-// without limitation the rights to use, copy, modify, merge, publish,
|
|
|
-// distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
-// permit persons to whom the Software is furnished to do so, subject to
|
|
|
-// the following conditions:
|
|
|
-//
|
|
|
-// The above copyright notice and this permission notice shall be
|
|
|
-// included in all copies or substantial portions of the Software.
|
|
|
-//
|
|
|
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
|
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
-//
|
|
|
-
|
|
|
-using System.Collections;
|
|
|
-using System.Resources;
|
|
|
-using System.IO;
|
|
|
-using System.Text;
|
|
|
-using System.Runtime.InteropServices;
|
|
|
-using System.Runtime.Serialization;
|
|
|
-using System.Runtime.Serialization.Formatters.Binary;
|
|
|
-using System.Security.Permissions;
|
|
|
-using System.Collections.Generic;
|
|
|
-
|
|
|
-namespace System.Resources
|
|
|
-{
|
|
|
- internal enum PredefinedResourceType
|
|
|
- {
|
|
|
- Null = 0,
|
|
|
- String = 1,
|
|
|
- Bool = 2,
|
|
|
- Char = 3,
|
|
|
- Byte = 4,
|
|
|
- SByte = 5,
|
|
|
- Int16 = 6,
|
|
|
- UInt16 = 7,
|
|
|
- Int32 = 8,
|
|
|
- UInt32 = 9,
|
|
|
- Int64 = 10,
|
|
|
- UInt64 = 11,
|
|
|
- Single = 12,
|
|
|
- Double = 13,
|
|
|
- Decimal = 14,
|
|
|
- DateTime = 15,
|
|
|
- TimeSpan = 16,
|
|
|
- ByteArray = 32,
|
|
|
- Stream = 33,
|
|
|
- FistCustom = 64
|
|
|
- }
|
|
|
-
|
|
|
- [System.Runtime.InteropServices.ComVisible (true)]
|
|
|
- public sealed class ResourceReader : IResourceReader, IEnumerable, IDisposable
|
|
|
- {
|
|
|
- struct ResourceInfo
|
|
|
- {
|
|
|
- public readonly long ValuePosition;
|
|
|
- public readonly string ResourceName;
|
|
|
- public readonly int TypeIndex;
|
|
|
-
|
|
|
- public ResourceInfo (string resourceName, long valuePosition, int type_index)
|
|
|
- {
|
|
|
- ValuePosition = valuePosition;
|
|
|
- ResourceName = resourceName;
|
|
|
- TypeIndex = type_index;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- struct ResourceCacheItem
|
|
|
- {
|
|
|
- public readonly string ResourceName;
|
|
|
- public readonly object ResourceValue;
|
|
|
-
|
|
|
- public ResourceCacheItem (string name, object value)
|
|
|
- {
|
|
|
- ResourceName = name;
|
|
|
- ResourceValue = value;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- BinaryReader reader;
|
|
|
- object readerLock = new object ();
|
|
|
- IFormatter formatter;
|
|
|
- internal int resourceCount = 0;
|
|
|
- int typeCount = 0;
|
|
|
- string[] typeNames;
|
|
|
- int[] hashes;
|
|
|
- ResourceInfo[] infos;
|
|
|
- int dataSectionOffset;
|
|
|
- long nameSectionOffset;
|
|
|
- int resource_ver;
|
|
|
- ResourceCacheItem[] cache;
|
|
|
- object cache_lock = new object ();
|
|
|
-
|
|
|
- // Constructors
|
|
|
- [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
|
|
|
- public ResourceReader (Stream stream)
|
|
|
- {
|
|
|
- if (stream == null)
|
|
|
- throw new ArgumentNullException ("stream");
|
|
|
-
|
|
|
- if (!stream.CanRead)
|
|
|
- throw new ArgumentException ("Stream was not readable.");
|
|
|
-
|
|
|
- reader = new BinaryReader(stream, Encoding.UTF8);
|
|
|
- formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File|StreamingContextStates.Persistence));
|
|
|
-
|
|
|
- ReadHeaders();
|
|
|
- }
|
|
|
-
|
|
|
- public ResourceReader (string fileName)
|
|
|
- {
|
|
|
- reader = new BinaryReader (new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read));
|
|
|
- formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File|StreamingContextStates.Persistence));
|
|
|
-
|
|
|
- ReadHeaders();
|
|
|
- }
|
|
|
-
|
|
|
- /* Read the ResourceManager header and the
|
|
|
- * ResourceReader header.
|
|
|
- */
|
|
|
- private void ReadHeaders()
|
|
|
- {
|
|
|
- try {
|
|
|
- int manager_magic = reader.ReadInt32();
|
|
|
-
|
|
|
- if(manager_magic != ResourceManager.MagicNumber)
|
|
|
- throw new ArgumentException(String.Format ("Stream is not a valid .resources file, magic=0x{0:x}", manager_magic));
|
|
|
-
|
|
|
- int manager_ver = reader.ReadInt32();
|
|
|
- int manager_len = reader.ReadInt32();
|
|
|
-
|
|
|
- /* We know how long the header is, even if
|
|
|
- * the version number is too new
|
|
|
- */
|
|
|
- if(manager_ver > ResourceManager.HeaderVersionNumber) {
|
|
|
- reader.BaseStream.Seek(manager_len, SeekOrigin.Current);
|
|
|
- } else {
|
|
|
- string reader_class=reader.ReadString();
|
|
|
- if(!reader_class.StartsWith("System.Resources.ResourceReader")) {
|
|
|
- throw new NotSupportedException("This .resources file requires reader class " + reader_class);
|
|
|
- }
|
|
|
-
|
|
|
- string set_class=reader.ReadString();
|
|
|
- if(!set_class.StartsWith(typeof(ResourceSet).FullName) && !set_class.StartsWith("System.Resources.RuntimeResourceSet")) {
|
|
|
- throw new NotSupportedException("This .resources file requires set class " + set_class);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Now read the ResourceReader header */
|
|
|
- resource_ver = reader.ReadInt32();
|
|
|
-
|
|
|
- if(resource_ver != 1 && resource_ver != 2) {
|
|
|
- throw new NotSupportedException("This .resources file requires unsupported set class version: " + resource_ver.ToString());
|
|
|
- }
|
|
|
-
|
|
|
- resourceCount = reader.ReadInt32();
|
|
|
- typeCount = reader.ReadInt32();
|
|
|
-
|
|
|
- typeNames=new string[typeCount];
|
|
|
-
|
|
|
- for(int i=0; i<typeCount; i++) {
|
|
|
- typeNames[i]=reader.ReadString();
|
|
|
- }
|
|
|
-
|
|
|
- /* There are between 0 and 7 bytes of
|
|
|
- * padding here, consisting of the
|
|
|
- * letters PAD. The next item (Hash
|
|
|
- * values for each resource name) need
|
|
|
- * to be aligned on an 8-byte
|
|
|
- * boundary.
|
|
|
- */
|
|
|
-
|
|
|
- int pad_align=(int)(reader.BaseStream.Position & 7);
|
|
|
- int pad_chars=0;
|
|
|
-
|
|
|
- if(pad_align!=0) {
|
|
|
- pad_chars=8-pad_align;
|
|
|
- }
|
|
|
-
|
|
|
- for(int i=0; i<pad_chars; i++) {
|
|
|
- byte pad_byte=reader.ReadByte();
|
|
|
- if(pad_byte!="PAD"[i%3]) {
|
|
|
- throw new ArgumentException("Malformed .resources file (padding values incorrect)");
|
|
|
- }
|
|
|
- }
|
|
|
- /* Read in the hash values for each
|
|
|
- * resource name. These can be used
|
|
|
- * by ResourceSet (calling internal
|
|
|
- * methods) to do a fast compare on
|
|
|
- * resource names without doing
|
|
|
- * expensive string compares (but we
|
|
|
- * dont do that yet, so far we only
|
|
|
- * implement the Enumerator interface)
|
|
|
- */
|
|
|
- hashes=new int[resourceCount];
|
|
|
- for(int i=0; i<resourceCount; i++) {
|
|
|
- hashes[i]=reader.ReadInt32();
|
|
|
- }
|
|
|
-
|
|
|
- /* Read in the virtual offsets for
|
|
|
- * each resource name
|
|
|
- */
|
|
|
- long[] positions = new long [resourceCount];
|
|
|
- for(int i = 0; i < resourceCount; i++)
|
|
|
- positions [i] = reader.ReadInt32();
|
|
|
-
|
|
|
- dataSectionOffset = reader.ReadInt32();
|
|
|
- nameSectionOffset = reader.BaseStream.Position;
|
|
|
-
|
|
|
- long origPosition = reader.BaseStream.Position;
|
|
|
- infos = new ResourceInfo [resourceCount];
|
|
|
- for (int i = 0; i < resourceCount; i++)
|
|
|
- CreateResourceInfo (positions [i], ref infos [i]);
|
|
|
- reader.BaseStream.Seek (origPosition, SeekOrigin.Begin);
|
|
|
-
|
|
|
- positions = null;
|
|
|
- } catch(EndOfStreamException e) {
|
|
|
- throw new ArgumentException("Stream is not a valid .resources file! It was possibly truncated.", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void CreateResourceInfo (long position, ref ResourceInfo info)
|
|
|
- {
|
|
|
- long pos = position + nameSectionOffset;
|
|
|
-
|
|
|
- reader.BaseStream.Seek (pos, SeekOrigin.Begin);
|
|
|
-
|
|
|
- // Resource name
|
|
|
- int len = Read7BitEncodedInt ();
|
|
|
- byte[] str = new byte [len];
|
|
|
-
|
|
|
- reader.Read (str, 0, len);
|
|
|
- string resourceName = Encoding.Unicode.GetString (str);
|
|
|
-
|
|
|
- long data_offset = reader.ReadInt32 () + dataSectionOffset;
|
|
|
- reader.BaseStream.Seek (data_offset, SeekOrigin.Begin);
|
|
|
- int type_index = Read7BitEncodedInt ();
|
|
|
-
|
|
|
- info = new ResourceInfo (resourceName, reader.BaseStream.Position, type_index);
|
|
|
- }
|
|
|
-
|
|
|
- /* Cut and pasted from BinaryReader, because it's
|
|
|
- * 'protected' there
|
|
|
- */
|
|
|
- private int Read7BitEncodedInt() {
|
|
|
- int ret = 0;
|
|
|
- int shift = 0;
|
|
|
- byte b;
|
|
|
-
|
|
|
- do {
|
|
|
- b = reader.ReadByte();
|
|
|
-
|
|
|
- ret = ret | ((b & 0x7f) << shift);
|
|
|
- shift += 7;
|
|
|
- } while ((b & 0x80) == 0x80);
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- object ReadValueVer2 (int type_index)
|
|
|
- {
|
|
|
- switch ((PredefinedResourceType)type_index)
|
|
|
- {
|
|
|
- case PredefinedResourceType.Null:
|
|
|
- return null;
|
|
|
-
|
|
|
- case PredefinedResourceType.String:
|
|
|
- return reader.ReadString();
|
|
|
-
|
|
|
- case PredefinedResourceType.Bool:
|
|
|
- return reader.ReadBoolean ();
|
|
|
-
|
|
|
- case PredefinedResourceType.Char:
|
|
|
- return (char)reader.ReadUInt16();
|
|
|
-
|
|
|
- case PredefinedResourceType.Byte:
|
|
|
- return reader.ReadByte();
|
|
|
-
|
|
|
- case PredefinedResourceType.SByte:
|
|
|
- return reader.ReadSByte();
|
|
|
-
|
|
|
- case PredefinedResourceType.Int16:
|
|
|
- return reader.ReadInt16();
|
|
|
-
|
|
|
- case PredefinedResourceType.UInt16:
|
|
|
- return reader.ReadUInt16();
|
|
|
-
|
|
|
- case PredefinedResourceType.Int32:
|
|
|
- return reader.ReadInt32();
|
|
|
-
|
|
|
- case PredefinedResourceType.UInt32:
|
|
|
- return reader.ReadUInt32();
|
|
|
-
|
|
|
- case PredefinedResourceType.Int64:
|
|
|
- return reader.ReadInt64();
|
|
|
-
|
|
|
- case PredefinedResourceType.UInt64:
|
|
|
- return reader.ReadUInt64();
|
|
|
-
|
|
|
- case PredefinedResourceType.Single:
|
|
|
- return reader.ReadSingle();
|
|
|
-
|
|
|
- case PredefinedResourceType.Double:
|
|
|
- return reader.ReadDouble();
|
|
|
-
|
|
|
- case PredefinedResourceType.Decimal:
|
|
|
- return reader.ReadDecimal();
|
|
|
-
|
|
|
- case PredefinedResourceType.DateTime:
|
|
|
- return new DateTime(reader.ReadInt64());
|
|
|
-
|
|
|
- case PredefinedResourceType.TimeSpan:
|
|
|
- return new TimeSpan(reader.ReadInt64());
|
|
|
-
|
|
|
- case PredefinedResourceType.ByteArray:
|
|
|
- return reader.ReadBytes (reader.ReadInt32 ());
|
|
|
-
|
|
|
- case PredefinedResourceType.Stream:
|
|
|
- // FIXME: create pinned UnmanagedMemoryStream for efficiency.
|
|
|
- byte [] bytes = new byte [reader.ReadUInt32 ()];
|
|
|
- reader.Read (bytes, 0, bytes.Length);
|
|
|
- return new MemoryStream (bytes);
|
|
|
- }
|
|
|
-
|
|
|
- type_index -= (int)PredefinedResourceType.FistCustom;
|
|
|
- return ReadNonPredefinedValue (Type.GetType (typeNames[type_index], true));
|
|
|
- }
|
|
|
-
|
|
|
- object ReadValueVer1 (Type type)
|
|
|
- {
|
|
|
- // The most common first
|
|
|
- if (type==typeof(String))
|
|
|
- return reader.ReadString();
|
|
|
- if (type==typeof(Int32))
|
|
|
- return reader.ReadInt32();
|
|
|
- if (type==typeof(Byte))
|
|
|
- return(reader.ReadByte());
|
|
|
- if (type==typeof(Double))
|
|
|
- return(reader.ReadDouble());
|
|
|
- if (type==typeof(Int16))
|
|
|
- return(reader.ReadInt16());
|
|
|
- if (type==typeof(Int64))
|
|
|
- return(reader.ReadInt64());
|
|
|
- if (type==typeof(SByte))
|
|
|
- return(reader.ReadSByte());
|
|
|
- if (type==typeof(Single))
|
|
|
- return(reader.ReadSingle());
|
|
|
- if (type==typeof(TimeSpan))
|
|
|
- return(new TimeSpan(reader.ReadInt64()));
|
|
|
- if (type==typeof(UInt16))
|
|
|
- return(reader.ReadUInt16());
|
|
|
- if (type==typeof(UInt32))
|
|
|
- return(reader.ReadUInt32());
|
|
|
- if (type==typeof(UInt64))
|
|
|
- return(reader.ReadUInt64());
|
|
|
- if (type==typeof(Decimal))
|
|
|
- return(reader.ReadDecimal());
|
|
|
- if (type==typeof(DateTime))
|
|
|
- return(new DateTime(reader.ReadInt64()));
|
|
|
-
|
|
|
- return ReadNonPredefinedValue(type);
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Add security checks
|
|
|
- object ReadNonPredefinedValue (Type exp_type)
|
|
|
- {
|
|
|
- object obj=formatter.Deserialize(reader.BaseStream);
|
|
|
- if(obj.GetType() != exp_type) {
|
|
|
- /* We got a bogus
|
|
|
- * object. This
|
|
|
- * exception is the
|
|
|
- * best match I could
|
|
|
- * find. (.net seems
|
|
|
- * to throw
|
|
|
- * BadImageFormatException,
|
|
|
- * which the docs
|
|
|
- * state is used when
|
|
|
- * file or dll images
|
|
|
- * cant be loaded by
|
|
|
- * the runtime.)
|
|
|
- */
|
|
|
- throw new InvalidOperationException("Deserialized object is wrong type");
|
|
|
- }
|
|
|
- return obj;
|
|
|
- }
|
|
|
-
|
|
|
- void LoadResourceValues (ResourceCacheItem[] store)
|
|
|
- {
|
|
|
- ResourceInfo ri;
|
|
|
- object value;
|
|
|
-
|
|
|
- lock (readerLock) {
|
|
|
- for (int i = 0; i < resourceCount; i++) {
|
|
|
- ri = infos [i];
|
|
|
- if (ri.TypeIndex == -1) {
|
|
|
- store [i] = new ResourceCacheItem (ri.ResourceName, null);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- reader.BaseStream.Seek (ri.ValuePosition, SeekOrigin.Begin);
|
|
|
- if (resource_ver == 2)
|
|
|
- value = ReadValueVer2 (ri.TypeIndex);
|
|
|
- else
|
|
|
- value = ReadValueVer1 (Type.GetType (typeNames [ri.TypeIndex], true));
|
|
|
-
|
|
|
- store [i] = new ResourceCacheItem (ri.ResourceName, value);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- internal UnmanagedMemoryStream ResourceValueAsStream (string name, int index)
|
|
|
- {
|
|
|
- ResourceInfo ri = infos [index];
|
|
|
- if ((PredefinedResourceType)ri.TypeIndex != PredefinedResourceType.Stream)
|
|
|
- throw new InvalidOperationException (String.Format ("Resource '{0}' was not a Stream. Use GetObject() instead.", name));
|
|
|
-
|
|
|
- lock (readerLock) {
|
|
|
- reader.BaseStream.Seek (ri.ValuePosition, SeekOrigin.Begin);
|
|
|
-
|
|
|
- // here we return a Stream from exactly
|
|
|
- // current position so that the returned
|
|
|
- // Stream represents a single object stream.
|
|
|
- long slen = reader.ReadInt32();
|
|
|
- UnmanagedMemoryStream basePtrStream = reader.BaseStream as UnmanagedMemoryStream;
|
|
|
- unsafe {
|
|
|
- if (basePtrStream != null) {
|
|
|
- return new UnmanagedMemoryStream (basePtrStream.PositionPointer, slen);
|
|
|
- } else {
|
|
|
- IntPtr ptr = Marshal.AllocHGlobal ((int) slen);
|
|
|
- byte* addr = (byte*) ptr.ToPointer ();
|
|
|
- UnmanagedMemoryStream ms = new HGlobalUnmanagedMemoryStream (addr, slen, ptr);
|
|
|
-
|
|
|
- byte [] bytes = new byte [slen < 1024 ? slen : 1024];
|
|
|
- while (slen > 0 ) {
|
|
|
- int x = reader.Read (bytes, 0, (int)Math.Min (bytes.Length, slen));
|
|
|
-
|
|
|
- if (x == 0)
|
|
|
- throw new FormatException ("The resource data is corrupt. Resource stream ended");
|
|
|
-
|
|
|
- ms.Write (bytes, 0, x);
|
|
|
- slen -= x;
|
|
|
- }
|
|
|
- ms.Seek (0, SeekOrigin.Begin);
|
|
|
- return ms;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void Close ()
|
|
|
- {
|
|
|
- Dispose(true);
|
|
|
- }
|
|
|
-
|
|
|
- public void Dispose ()
|
|
|
- {
|
|
|
- Dispose(true);
|
|
|
- }
|
|
|
-
|
|
|
- public IDictionaryEnumerator GetEnumerator () {
|
|
|
- if (reader == null){
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- }
|
|
|
- else {
|
|
|
- return new ResourceEnumerator (this);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- IEnumerator IEnumerable.GetEnumerator ()
|
|
|
- {
|
|
|
- return ((IResourceReader) this).GetEnumerator();
|
|
|
- }
|
|
|
-
|
|
|
- public void GetResourceData (string resourceName, out string resourceType, out byte [] resourceData)
|
|
|
- {
|
|
|
- if (resourceName == null)
|
|
|
- throw new ArgumentNullException ("resourceName");
|
|
|
- ResourceEnumerator en = new ResourceEnumerator (this);
|
|
|
- while (en.MoveNext ())
|
|
|
- if ((string) en.Key == resourceName) {
|
|
|
- GetResourceDataAt (en.Index, out resourceType, out resourceData);
|
|
|
- return;
|
|
|
- }
|
|
|
- throw new ArgumentException (String.Format ("Specified resource not found: {0}", resourceName));
|
|
|
- }
|
|
|
-
|
|
|
- private void GetResourceDataAt (int index, out string resourceType, out byte [] data)
|
|
|
- {
|
|
|
- ResourceInfo ri = infos [index];
|
|
|
- int type_index = ri.TypeIndex;
|
|
|
- if (type_index == -1)
|
|
|
- throw new FormatException ("The resource data is corrupt");
|
|
|
-
|
|
|
- lock (readerLock) {
|
|
|
- reader.BaseStream.Seek (ri.ValuePosition, SeekOrigin.Begin);
|
|
|
- long pos2 = reader.BaseStream.Position;
|
|
|
-
|
|
|
- // Simply read data, and seek back to the original position
|
|
|
- if (resource_ver == 2) {
|
|
|
- if (type_index >= (int) PredefinedResourceType.FistCustom) {
|
|
|
- int typenameidx = type_index - (int)PredefinedResourceType.FistCustom;
|
|
|
- if (typenameidx >= typeNames.Length)
|
|
|
- throw new FormatException ("The resource data is corrupt. Invalid index to types");
|
|
|
- resourceType = typeNames[typenameidx];
|
|
|
- }
|
|
|
- else
|
|
|
- resourceType = "ResourceTypeCode." + (PredefinedResourceType) type_index;
|
|
|
- ReadValueVer2 (type_index);
|
|
|
- } else {
|
|
|
- // resource ver 1 == untyped
|
|
|
- resourceType = "ResourceTypeCode.Null";
|
|
|
- ReadValueVer1 (Type.GetType (typeNames [type_index], true));
|
|
|
- }
|
|
|
-
|
|
|
- // FIXME: the data size is wrong.
|
|
|
- int datalen = (int) (reader.BaseStream.Position - pos2);
|
|
|
- reader.BaseStream.Seek (-datalen, SeekOrigin.Current);
|
|
|
- data = new byte [datalen];
|
|
|
- reader.BaseStream.Read (data, 0, datalen);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void Dispose (bool disposing)
|
|
|
- {
|
|
|
- if(disposing) {
|
|
|
- if(reader!=null) {
|
|
|
- reader.Close();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- reader=null;
|
|
|
- hashes=null;
|
|
|
- infos=null;
|
|
|
- typeNames=null;
|
|
|
- cache = null;
|
|
|
- }
|
|
|
-
|
|
|
- internal sealed class ResourceEnumerator : IDictionaryEnumerator
|
|
|
- {
|
|
|
- private ResourceReader reader;
|
|
|
- private int index = -1;
|
|
|
- private bool finished;
|
|
|
-
|
|
|
- internal ResourceEnumerator(ResourceReader readerToEnumerate)
|
|
|
- {
|
|
|
- reader = readerToEnumerate;
|
|
|
- FillCache ();
|
|
|
- }
|
|
|
-
|
|
|
- public int Index
|
|
|
- {
|
|
|
- get { return index; }
|
|
|
- }
|
|
|
-
|
|
|
- public DictionaryEntry Entry {
|
|
|
- get {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- if (index < 0)
|
|
|
- throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
|
|
|
-
|
|
|
- return new DictionaryEntry(Key, Value);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public object Key
|
|
|
- {
|
|
|
- get {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- if (index < 0)
|
|
|
- throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
|
|
|
-
|
|
|
- return reader.cache [index].ResourceName;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public object Value
|
|
|
- {
|
|
|
- get {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- if (index < 0)
|
|
|
- throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
|
|
|
- return reader.cache [index].ResourceValue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public UnmanagedMemoryStream ValueAsStream
|
|
|
- {
|
|
|
- get {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- if (index < 0)
|
|
|
- throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
|
|
|
- return(reader.ResourceValueAsStream((string) Key, index));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public object Current
|
|
|
- {
|
|
|
- get {
|
|
|
- /* Entry does the checking, no
|
|
|
- * need to repeat it here
|
|
|
- */
|
|
|
- return Entry;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public bool MoveNext ()
|
|
|
- {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- if (finished) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (++index < reader.resourceCount){
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- finished=true;
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- public void Reset () {
|
|
|
- if (reader.reader == null)
|
|
|
- throw new InvalidOperationException("ResourceReader is closed.");
|
|
|
- index = -1;
|
|
|
- finished = false;
|
|
|
- }
|
|
|
-
|
|
|
- void FillCache ()
|
|
|
- {
|
|
|
- if (reader.cache != null)
|
|
|
- return;
|
|
|
-
|
|
|
- lock (reader.cache_lock) {
|
|
|
- if (reader.cache != null)
|
|
|
- return;
|
|
|
-
|
|
|
- ResourceCacheItem[] resources = new ResourceCacheItem [reader.resourceCount];
|
|
|
- reader.LoadResourceValues (resources);
|
|
|
- reader.cache = resources;
|
|
|
- }
|
|
|
- }
|
|
|
- } // internal class ResourceEnumerator
|
|
|
- } // public sealed class ResourceReader
|
|
|
-} // namespace System.Resources
|