예제 #1
0
        private void CommitToNew()
        {
            // don't unload this instance since it needs to read from it first

            // NOTE: this method does not preserve custom ResourceHeader fields like Characteristics and MemoryFlags

            var tempFileName = Path.GetTempFileName();

            using (var o = new FileStream(tempFileName, FileMode.Open, FileAccess.Write))
            {
                var wtr = new BinaryWriter(o, Encoding.Unicode);

                foreach (var lang in AllLangs)
                {
                    if (lang.Action == ResourceDataAction.Delete)
                    {
                        continue; // skip langs to delete, which means they'll get deleted
                    }
                    // the actual data will be lazy-loaded on each write
                    ResResourceHeader.WriteResource(lang, wtr);
                }
            }

            // close the current input stream
            Unload();

            // and overwrite the file
            FileInfo.Delete();
            File.Move(tempFileName, FileInfo.FullName);

            Reload();
        }
예제 #2
0
        private void CommitAddChanges()
        {
            Unload();

            _stream = new FileStream(FileInfo.FullName, FileMode.Open, FileAccess.Write);

            _stream.Seek(0, SeekOrigin.End); // seek to end

            var wtr = new BinaryWriter(_stream, Encoding.Unicode);

            wtr.Align4();

            foreach (var lang in AllActiveLangs)
            {
                ResResourceHeader.WriteResource(lang, wtr);
            }

            _stream.Close();

            Reload();
        }
예제 #3
0
        public override void Reload()
        {
            UnderlyingClear();

            _stream?.Close(); // consequtive calls to .Close() is safe
            _stream = new FileStream(FileInfo.FullName, FileMode.Open);
            if (!_stream.CanSeek)
            {
                throw new AnolisException("RES FileStream must support seeking");
            }

            _resources.Clear();

            // the RES format is quite simple, it's just a concatenated list of Resource Data instances, all with their header info

            _stream.Seek(0, SeekOrigin.Begin);

            var rdr = new BinaryReader(_stream, Encoding.Unicode);

            while (rdr.BaseStream.Position < rdr.BaseStream.Length)
            {
                ///////////////////////////////
                // Read the RESOURCEHEADER

                var start = rdr.BaseStream.Position;

                var header = new ResResourceHeader(rdr);
                if (header.DataSize == 0 && rdr.BaseStream.Position == rdr.BaseStream.Length)
                {
                    break;
                }

                var stop       = rdr.BaseStream.Position;
                var headerSize = (int)(stop - start);

                var res = new ResResource
                {
                    DataOffset = rdr.BaseStream.Position,
                    // HACK: this might cause problems for resources larger than 2GB
                    DataLength   = (int)header.DataSize,
                    HeaderOffset = start,
                    HeaderLength = header.HeaderSize
                };


                // Read past the Resource data
                _stream.Seek(header.DataSize, SeekOrigin.Current);

                // don't do anything if it's empty
                if (!(header.Type is string))
                {
                    var headerType = Convert.ToInt32(header.Type, CultureInfo.InvariantCulture);
                    if (headerType == 0)
                    {
                        rdr.Align4();
                        continue;
                    }
                }

                ///////////////////////////////
                // Create ResourceType, Name, and Lang instance

                var typeId = header.Type is string s
                    ? new ResourceTypeIdentifier(s)
                    : new ResourceTypeIdentifier(Convert.ToInt32(header.Type, CultureInfo.InvariantCulture));

                var type = UnderlyingFind(t => t.Identifier.Equals(typeId));
                if (type == null)
                {
                    type = new ResourceType(typeId, this);

                    UnderlyingAdd(type);
                }

                ///////////////////////////////////////////////////////////

                var nameId = header.Name is string headerName
                    ? new ResourceIdentifier(headerName)
                    : new ResourceIdentifier(Convert.ToInt32(header.Name, CultureInfo.InvariantCulture));
                var name = UnderlyingFind(type, n => n.Identifier.Equals(nameId));
                if (name == null)
                {
                    name = new ResourceName(nameId, type);

                    UnderlyingAdd(type, name);
                }

                ///////////////////////////////////////////////////////////

                // TODO: Maybe do some validation to ensure the same lang hasn't been added twice?

                var lang = new ResourceLang(header.LanguageId, name);

                UnderlyingAdd(name, lang);

                ///////////////////////////////////////////////////////////

                res.Lang = lang;

                _resources.Add(res);

                rdr.Align4();
            }
        }