Example #1
0
        /// <summary>
        /// Set the record to a FreeRecord
        /// </summary>
        public virtual void MarkAsFreeRecord()
        {
            var bw = ggpkContainer.Writer;

            bw.BaseStream.Seek(Offset, SeekOrigin.Begin);
            var free = new FreeRecord(Length, ggpkContainer, 0, Offset);

            free.Write();
            var lastFree = ggpkContainer.LinkedFreeRecords.Last?.Value;

            if (lastFree == null) // No FreeRecord
            {
                ggpkContainer.ggpkRecord.FirstFreeRecordOffset = Offset;
                ggpkContainer.fileStream.Seek(ggpkContainer.ggpkRecord.Offset + 20, SeekOrigin.Begin);
                ggpkContainer.Writer.Write(Offset);
            }
            else
            {
                lastFree.NextFreeOffset = Offset;
                ggpkContainer.fileStream.Seek(lastFree.Offset + 8, SeekOrigin.Begin);
                ggpkContainer.Writer.Write(Offset);
            }
            ggpkContainer.LinkedFreeRecords.AddLast(free);
        }
Example #2
0
        /// <summary>
        /// Replace the file content with a new content,
        /// and move the record to the FreeRecord with most suitable size.
        /// </summary>
        public virtual void ReplaceContent(byte[] NewContent)
        {
            var bw = ggpkContainer.Writer;

            Hash = Hash256.ComputeHash(NewContent); // New Hash

            if (NewContent.Length == DataLength)    // Replace in situ
            {
                bw.BaseStream.Seek(DataBegin, SeekOrigin.Begin);
                bw.Write(NewContent);
            }
            else // Replace a FreeRecord
            {
                var oldOffset = Offset;
                MarkAsFreeRecord();
                DataLength = NewContent.Length;
                Length     = 44 + (Name.Length + 1) * 2 + DataLength; // (8 + (Name + "\0").Length * 2 + 32 + 4) + DataLength

                LinkedListNode <FreeRecord> bestNode = null;          // Find the FreeRecord with most suitable size
                var currentNode = ggpkContainer.LinkedFreeRecords.First;
                var space       = int.MaxValue;
                do
                {
                    if (currentNode.Value.Length == Length)
                    {
                        bestNode = currentNode;
                        space    = 0;
                        break;
                    }
                    var tmpSpace = currentNode.Value.Length - Length;
                    if (tmpSpace < space && tmpSpace >= 16)
                    {
                        bestNode = currentNode;
                        space    = tmpSpace;
                    }
                } while ((currentNode = currentNode.Next) != null);

                if (bestNode == null)
                {
                    bw.BaseStream.Seek(0, SeekOrigin.End); // Write to the end of GGPK
                    Write();
                    bw.Write(NewContent);
                }
                else
                {
                    FreeRecord free = bestNode.Value;
                    bw.BaseStream.Seek(free.Offset + free.Length - Length, SeekOrigin.Begin); // Write to the FreeRecord
                    Write();
                    bw.Write(NewContent);
                    free.Length = space;
                    if (space >= 16) // Update offset of FreeRecord
                    {
                        bw.BaseStream.Seek(free.Offset, SeekOrigin.Begin);
                        bw.Write(free.Length);
                    }
                    else // Remove the FreeRecord
                    {
                        free.Remove(bestNode);
                    }
                }

                UpdateOffset(oldOffset); // Update the offset of FileRecord in Parent.Entries/>
            }
            bw.Flush();
        }