Example #1
0
        public ResourceReader(Stream stream)
        {
            if (stream==null)
                throw new ArgumentNullException("stream");
            if (!stream.CanRead)
                throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));

            _table = new Hashtable(FastResourceComparer.Default, FastResourceComparer.Default);
            _store = new BinaryReader(stream, Encoding.UTF8);
            // We have a faster code path for reading resource files from an assembly.
            _ums = stream as __UnmanagedMemoryStream;
            BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream).  UnmanagedMemoryStream: "+(_ums!=null));
            ReadResources();
        }
Example #2
0
 private void Dispose(bool disposing)
 {
     if (_store != null) {
         if (disposing) {
             // Close the stream in a thread-safe way.  This fix means 
             // that we may call Close n times, but that's safe.
             BinaryReader copyOfStore = _store;
             if (copyOfStore != null)
                 copyOfStore.Close();
         }
         _store = null;
         _table = null;
         _namePositions = null;
         _nameHashes = null;
         _ums = null;
         _namePositionsPtr = null;
         _nameHashesPtr = null;
     }
 }
Example #3
0
        // Reads in the header information for a .resources file.  Verifies some
        // of the assumptions about this resource set, and builds the class table
        // for the default resource file format.
        private void ReadResources()
        {
            BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence));
            // Do partial binds so we can be tolerant of version number changes.
            bf.AssemblyFormat = FormatterAssemblyStyle.Simple;
            _objFormatter = bf;

            try {
                // Read ResourceManager header
                // Check for magic number
                int magicNum = _store.ReadInt32();
                if (magicNum != ResourceManager.MagicNumber)
                    throw new ArgumentException("Stream is not a valid resource file!");
                // Assuming this is ResourceManager header V1 or greater, hopefully
                // after the version number there is a number of bytes to skip
                // to bypass the rest of the ResMgr header.
                int resMgrHeaderVersion = _store.ReadInt32();
                if (resMgrHeaderVersion > 1) {
                    int numBytesToSkip = _store.ReadInt32();
                    BCLDebug.Log("RESMGRFILEFORMAT", LogLevel.Status, "ReadResources: Unexpected ResMgr header version: {0}  Skipping ahead {1} bytes.", resMgrHeaderVersion, numBytesToSkip);
                    BCLDebug.Assert(numBytesToSkip >= 0, "numBytesToSkip in ResMgr header should be positive!");
                    _store.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current);
                }
                else {
                    BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Parsing ResMgr header v1.");
                    _store.ReadInt32();  // We don't care about numBytesToSkip.

                    // Read in type name for a suitable ResourceReader
                    // Note ResourceWriter & InternalResGen use different Strings.
                    String readerType = _store.ReadString();
                    if (!readerType.Equals(ResourceManager.ResReaderTypeName) && 
                        !readerType.Equals(typeof(ResourceReader).FullName) &&
                        !readerType.Equals(ResourceManager.ResReaderTypeNameInternal)) {
                        throw new NotSupportedException("This .resources file shouldn't be used with this reader.  Your resource reader type: "+readerType);
                    }

                    // Skip over type name for a suitable ResourceSet
                    _store.ReadString();
                }

                // Read RuntimeResourceSet header
                // Do file version check
                int version = _store.ReadInt32();
                if (version != RuntimeResourceSet.Version)
                    throw new ArgumentException(String.Format("Version conflict with ResourceManager .resources files!  Expected version: {0} but got: {1}", RuntimeResourceSet.Version, version));
            
                _numResources = _store.ReadInt32();
                BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Expecting "+ _numResources+ " resources.");
#if _DEBUG      
                if (ResourceManager.DEBUG >= 4)
                    Console.WriteLine("ResourceReader::ReadResources - Reading in "+_numResources+" resources");
#endif

                // Read type names into type array.
                int numTypes = _store.ReadInt32();
                _typeTable = new Type[numTypes];
                for(int i=0; i<numTypes; i++) {
                    String typeName = _store.ReadString();
                    // Do partial binds to be tolerant of version number changes.
                    _typeTable[i] = Assembly.LoadTypeWithPartialName(typeName, false);
                    if (_typeTable[i] == null)
                        throw new TypeLoadException(Environment.GetResourceString("TypeLoad_PartialBindFailed", typeName));
                }


#if _DEBUG
                if (ResourceManager.DEBUG >= 5)
                    Console.WriteLine("ResourceReader::ReadResources - Reading in "+numTypes+" type table entries");
#endif

                // Prepare to read in the array of name hashes
                //  Note that the name hashes array is aligned to 8 bytes so 
                //  we can use pointers into it on 64 bit machines. (4 bytes 
                //  may be sufficient, but let's plan for the future)
                //  Skip over alignment stuff, if it's present.
                long pos = _store.BaseStream.Position;
                int alignBytes = ((int)pos) & 7;
                bool fileIsAligned = true;
                if (alignBytes != 0) {
                    // For backwards compatibility, don't require the "PAD" stuff
                    // in here, but we should definitely skip it if present.
                    for(int i=0; i<8 - alignBytes; i++) {
                        byte b = _store.ReadByte();
                        if (b != "PAD"[i % 3]) {
                            fileIsAligned = false;
                            break;
                        }
                    }
                    // If we weren't aligned, we shouldn't have skipped this data!
                    if (!fileIsAligned)
                        _store.BaseStream.Position = pos;
                    else {
                        BCLDebug.Assert((_store.BaseStream.Position & 7) == 0, "ResourceReader: Stream should be aligned on an 8 byte boundary now!");
                    }
                }
#if RESOURCE_FILE_FORMAT_DEBUG
                Console.WriteLine("ResourceReader: File alignment: "+fileIsAligned);
#endif
#if !WIN32
                if (!fileIsAligned)
                    _ums = null;
#endif

                // Read in the array of name hashes
#if RESOURCE_FILE_FORMAT_DEBUG
                //  Skip over "HASHES->"
                _store.BaseStream.Position += 8;
#endif

                if (_ums == null) {
                    _nameHashes = new int[_numResources];
                    for(int i=0; i<_numResources; i++)
                        _nameHashes[i] = _store.ReadInt32();
                }
                else {
                    _nameHashesPtr = (int*) _ums.GetBytePtr();
                    // Skip over the array of nameHashes.
                    _ums.Seek(4 * _numResources, SeekOrigin.Current);
                }

                // Read in the array of relative positions for all the names.
#if RESOURCE_FILE_FORMAT_DEBUG
                // Skip over "POS---->"
                _store.BaseStream.Position += 8;
#endif
                if (_ums == null) {
                    _namePositions = new int[_numResources];
                    for(int i=0; i<_numResources; i++)
                        _namePositions[i] = _store.ReadInt32();
                }
                else {
                    _namePositionsPtr = (int*) _ums.GetBytePtr();
                    // Skip over the array of namePositions.
                    _ums.Seek(4 * _numResources, SeekOrigin.Current);
                }

                // Read location of data section.
                _dataSectionOffset = _store.ReadInt32();

                // Store current location as start of name section
                _nameSectionOffset = _store.BaseStream.Position;
                BCLDebug.Log("RESMGRFILEFORMAT", String.Format("ReadResources: _nameOffset = 0x{0:x}  _dataOffset = 0x{1:x}", _nameSectionOffset, _dataSectionOffset));
            }
            catch (EndOfStreamException eof) {
                throw new ArgumentException("Stream is not a valid .resources file!  It was possibly truncated.", eof);
            }
        }
Example #4
0
        // This is the constructor the RuntimeResourceSet calls,
        // passing in the stream to read from and the RuntimeResourceSet's 
        // internal hash table (hash table of names with file offsets
        // and values, coupled to this ResourceReader).
        internal ResourceReader(Stream stream, Hashtable table)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            if (table == null)
                throw new ArgumentNullException("table");
            if (!stream.CanRead)
                throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));

            _table = table;
            _store = new BinaryReader(stream, Encoding.UTF8);
            _ums = stream as __UnmanagedMemoryStream;

            BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream, Hashtable).  UnmanagedMemoryStream: "+(_ums!=null));
            ReadResources();
        }