예제 #1
0
        protected override void ReadATime(MetadataDateReader data)
        {
            System.Diagnostics.Debug.Assert(mADates == null);
            System.Diagnostics.Debug.Assert(data.Count == mItemCount);

            mADates = new List <DateTime?>(data.Count);
            for (int i = 0; i < data.Count; i++)
            {
                mADates.Add(data.ReadDate());
            }
        }
        private ArchiveMetadata ReadArchive()
        {
            var token = ReadToken();

            if (token == ArchiveMetadataToken.ArchiveProperties)
            {
                ReadArchiveProperties();
                token = ReadToken();
            }

            var streams = ImmutableArray<Stream>.Empty;
            if (token == ArchiveMetadataToken.AdditionalStreams)
            {
                streams = ReadPackedStreams();
                token = ReadToken();
            }

            List<long> unpackSizes;
            List<Checksum?> checksums;

            ArchiveMetadata metadata;
            if (token == ArchiveMetadataToken.MainStreams)
            {
                metadata = ReadMetadata(streams, true);
                token = ReadToken();
            }
            else
            {
                throw new NotImplementedException();
            }

            int? emptyStreamCount = null;

            if (token != ArchiveMetadataToken.End)
            {
                if (token != ArchiveMetadataToken.Files)
                    throw new InvalidDataException();

                var fileCount = ReadNumberAsInt32();
                Initialize(fileCount);

                for (;;)
                {
                    token = ReadToken();
                    if (token == ArchiveMetadataToken.End)
                        break;

                    var recordSize = (long)ReadNumber();
                    if (recordSize < 0)
                        throw new InvalidDataException();

                    var oldOffset = GetCurrentOffset();

                    #region File Metadata

                    switch (token)
                    {
                        case ArchiveMetadataToken.Name:
                            using (SelectStream(streams))
                            {
                                var reader = new MetadataStringReader(this, fileCount);
                                ReadNames(reader);
                                reader.Complete();
                            }
                            break;

                        case ArchiveMetadataToken.WinAttributes:
                            {
                                var vector = ReadOptionalBitVector(fileCount);
                                using (SelectStream(streams))
                                {
                                    var reader = new MetadataAttributeReader(this, fileCount, vector);
                                    ReadAttributes(reader);
                                    reader.Complete();
                                }

                                break;
                            }

                        case ArchiveMetadataToken.EmptyStream:
                            {
                                var emptyStreams = ReadRequiredBitVector(fileCount);
                                emptyStreamCount = emptyStreams.CountSetBits();

                                var reader = new MetadataBitReader(this, emptyStreams);
                                ReadEmptyStreamMarkers(reader);
                                reader.Complete();
                                break;
                            }

                        case ArchiveMetadataToken.EmptyFile:
                            {
                                if (emptyStreamCount == null)
                                    throw new InvalidDataException();

                                var reader = new MetadataBitReader(this, ReadRequiredBitVector(emptyStreamCount.Value));
                                ReadEmptyFileMarkers(reader);
                                reader.Complete();
                                break;
                            }

                        case ArchiveMetadataToken.Anti:
                            {
                                if (emptyStreamCount == null)
                                    throw new InvalidDataException();

                                var reader = new MetadataBitReader(this, ReadRequiredBitVector(emptyStreamCount.Value));
                                ReadRemovedFileMarkers(reader);
                                reader.Complete();
                                break;
                            }

                        case ArchiveMetadataToken.StartPos:
                            {
                                var vector = ReadOptionalBitVector(fileCount);
                                using (SelectStream(streams))
                                {
                                    var reader = new MetadataNumberReader(this, fileCount, vector);
                                    ReadOffsets(reader);
                                    reader.Complete();
                                }

                                break;
                            }

                        case ArchiveMetadataToken.CTime:
                            {
                                var vector = ReadOptionalBitVector(fileCount);
                                using (SelectStream(streams))
                                {
                                    var reader = new MetadataDateReader(this, fileCount, vector);
                                    ReadCTime(reader);
                                    reader.Complete();
                                }

                                break;
                            }

                        case ArchiveMetadataToken.ATime:
                            {
                                var vector = ReadOptionalBitVector(fileCount);
                                using (SelectStream(streams))
                                {
                                    var reader = new MetadataDateReader(this, fileCount, vector);
                                    ReadATime(reader);
                                    reader.Complete();
                                }

                                break;
                            }

                        case ArchiveMetadataToken.MTime:
                            {
                                var vector = ReadOptionalBitVector(fileCount);
                                using (SelectStream(streams))
                                {
                                    var reader = new MetadataDateReader(this, fileCount, vector);
                                    ReadMTime(reader);
                                    reader.Complete();
                                }

                                break;
                            }

                        case ArchiveMetadataToken.Padding:
                            // TODO: what does the reference implementation do here? just skip it? then we shouldn't throw an exception!
                            for (int i = 0; i < recordSize; i++)
                                if (ReadByte() != 0)
                                    throw new InvalidDataException();

                            break;

                        default:
                            // TODO: skip data
                            break;
                    }

                    #endregion

                    // Up until version 0.3 there was a bug which could emit invalid record sizes, but it didn't really matter.
                    // Starting from version 0.3 there have been extensions to the file format which require correct record sizes.
                    if (!(mMajorVersion == 0 && mMinorVersion < 3))
                    {
                        var newOffset = GetCurrentOffset();
                        if (newOffset - oldOffset != recordSize)
                            throw new InvalidDataException();
                    }
                }
            }

            return metadata;
        }
 protected virtual void ReadMTime(MetadataDateReader data) { }