Beispiel #1
0
        private static void AlignMajorRecordsByRules(
            IMutagenReadStream inputStream,
            MutagenWriter writer,
            AlignmentRules alignmentRules,
            RecordLocator.FileLocations fileLocs)
        {
            while (!inputStream.Complete)
            {
                // Import until next listed major record
                long noRecordLength;
                if (fileLocs.ListedRecords.TryGetInDirection(
                        inputStream.Position,
                        higher: true,
                        result: out var nextRec))
                {
                    var recordLocation = fileLocs.ListedRecords.Keys[nextRec.Key];
                    noRecordLength = recordLocation - inputStream.Position;
                }
                else
                {
                    noRecordLength = inputStream.Remaining;
                }
                inputStream.WriteTo(writer.BaseStream, (int)noRecordLength);

                // If complete overall, return
                if (inputStream.Complete)
                {
                    break;
                }

                var recType = HeaderTranslation.ReadNextRecordType(
                    inputStream,
                    out var len);
                IEnumerable <RecordType>?stopMarkers;
                if (!alignmentRules.StopMarkers.TryGetValue(recType, out stopMarkers))
                {
                    stopMarkers = null;
                }
                if (!alignmentRules.Alignments.TryGetValue(recType, out var alignments))
                {
                    throw new ArgumentException($"Encountered an unknown record: {recType}");
                }
                writer.Write(recType.TypeInt);
                writer.Write(len);
                inputStream.WriteTo(writer.BaseStream, 12);
                var endPos = inputStream.Position + len;
                Dictionary <RecordType, byte[]> dataDict = new Dictionary <RecordType, byte[]>();
                ReadOnlyMemorySlice <byte>?     rest     = null;
                while (inputStream.Position < endPos)
                {
                    var subType = HeaderTranslation.GetNextSubrecordType(
                        inputStream,
                        out var subLen);
                    if (stopMarkers?.Contains(subType) ?? false)
                    {
                        rest = inputStream.ReadMemory((int)(endPos - inputStream.Position), readSafe: true);
                        break;
                    }
                    if (!alignments.TryGetValue(subType, out var rule))
                    {
                        throw new ArgumentException($"Encountered an unknown record: {subType}");
                    }
                    dataDict[subType] = rule.GetBytes(inputStream);
                }
                foreach (var alignment in alignmentRules.Alignments[recType])
                {
                    if (dataDict.TryGetValue(
                            alignment.Key,
                            out var data))
                    {
                        writer.Write(data);
                        dataDict.Remove(alignment.Key);
                    }
                }
                if (dataDict.Count > 0)
                {
                    throw new ArgumentException($"Encountered an unknown record: {dataDict.First().Key}");
                }
                if (rest != null)
                {
                    writer.Write(rest.Value);
                }
            }
        }
Beispiel #2
0
        private static void AlignGroupsByRules(
            MutagenBinaryReadStream inputStream,
            MutagenWriter writer,
            AlignmentRules alignmentRules,
            RecordLocator.FileLocations fileLocs)
        {
            while (!inputStream.Complete)
            {
                // Import until next listed major record
                long noRecordLength;
                if (fileLocs.GrupLocations.TryGetInDirection(
                        inputStream.Position,
                        higher: true,
                        result: out var nextRec))
                {
                    noRecordLength = nextRec.Value - inputStream.Position;
                }
                else
                {
                    noRecordLength = inputStream.Remaining;
                }
                inputStream.WriteTo(writer.BaseStream, (int)noRecordLength);

                // If complete overall, return
                if (inputStream.Complete)
                {
                    break;
                }
                var groupMeta = inputStream.GetGroup();
                if (!groupMeta.IsGroup)
                {
                    throw new ArgumentException();
                }
                inputStream.WriteTo(writer.BaseStream, checked ((int)groupMeta.HeaderLength));

                if (!alignmentRules.GroupTypeAlignment.TryGetValue(groupMeta.GroupType, out var groupRules))
                {
                    continue;
                }

                var storage = new Dictionary <RecordType, List <ReadOnlyMemorySlice <byte> > >();
                var rest    = new List <ReadOnlyMemorySlice <byte> >();
                using (var frame = MutagenFrame.ByLength(inputStream, groupMeta.ContentLength))
                {
                    while (!frame.Complete)
                    {
                        var majorMeta = inputStream.GetMajorRecord();
                        var bytes     = inputStream.ReadMemory(checked ((int)majorMeta.TotalLength), readSafe: true);
                        var type      = majorMeta.RecordType;
                        if (groupRules.Contains(type))
                        {
                            storage.GetOrAdd(type).Add(bytes);
                        }
                        else
                        {
                            rest.Add(bytes);
                        }
                    }
                }
                foreach (var rule in groupRules)
                {
                    if (storage.TryGetValue(rule, out var storageBytes))
                    {
                        foreach (var item in storageBytes)
                        {
                            writer.Write(item);
                        }
                    }
                }
                foreach (var item in rest)
                {
                    writer.Write(item);
                }
            }
        }
Beispiel #3
0
        public async Task Process(
            TempFolder tmpFolder,
            Subject <string> logging,
            ModPath sourcePath,
            string preprocessedPath,
            string outputPath)
        {
            this.Logging          = logging;
            this.TempFolder       = tmpFolder;
            this.SourcePath       = sourcePath;
            this.Masters          = MasterReferenceReader.FromPath(SourcePath, GameRelease);
            this.Bundle           = new ParsingBundle(GameRelease, Masters);
            this._NumMasters      = GetNumMasters();
            this._AlignedFileLocs = RecordLocator.GetFileLocations(new ModPath(ModKey, preprocessedPath), this.GameRelease);

            var preprocessedBytes = File.ReadAllBytes(preprocessedPath);

            IMutagenReadStream streamGetter() => new MutagenMemoryReadStream(preprocessedBytes, Bundle);

            using (var stream = streamGetter())
            {
                lock (_lengthTracker)
                {
                    foreach (var grup in this._AlignedFileLocs.GrupLocations.And(this._AlignedFileLocs.ListedRecords.Keys))
                    {
                        stream.Position           = grup + 4;
                        this._lengthTracker[grup] = stream.ReadUInt32();
                    }
                }

                await this.PreProcessorJobs(streamGetter);

                await Task.WhenAll(ExtraJobs(streamGetter));

                this.AddDynamicProcessorInstructions();
                Parallel.ForEach(this.DynamicProcessors.Keys
                                 .And(this.DynamicStreamProcessors.Keys)
                                 .And(RecordType.Null)
                                 .Distinct(),
                                 ParallelOptions,
                                 type => ProcessDynamicType(type, streamGetter));

                lock (_lengthTracker)
                {
                    foreach (var grup in this._lengthTracker)
                    {
                        stream.Position = grup.Key + 4;
                        if (grup.Value == stream.ReadUInt32())
                        {
                            continue;
                        }
                        this._Instructions.SetSubstitution(
                            loc: grup.Key + 4,
                            sub: BitConverter.GetBytes(grup.Value));
                    }
                }
            }

            var config = this._Instructions.GetConfig();

            using (var processor = new BinaryFileProcessor(
                       new FileStream(preprocessedPath, FileMode.Open, FileAccess.Read),
                       config))
            {
                try
                {
                    using var outStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
                    processor.CopyTo(outStream);
                }
                catch (Exception)
                {
                    if (File.Exists(outputPath))
                    {
                        File.Delete(outputPath);
                    }
                    throw;
                }
            }
        }