Пример #1
0
        /// <summary>
        /// Reads the preamble, the ranges, and the names of the rest of the buffers.
        /// </summary>
        public static BFastHeader ReadBFastHeader(this Stream stream)
        {
            var r = new BFastHeader();

            var br = new BinaryReader(stream);

            r.Preamble = new BFastPreamble
            {
                Magic     = br.ReadInt64(),
                DataStart = br.ReadInt64(),
                DataEnd   = br.ReadInt64(),
                NumArrays = br.ReadInt64(),
            }
            .Validate();

            r.Ranges = stream.ReadArray <BFastRange>((int)r.Preamble.NumArrays);

            var padding = ComputePadding(r.Ranges);

            br.ReadBytes((int)padding);

            CheckAlignment(br.BaseStream);
            var nameBytes = br.ReadBytes((int)r.Ranges[0].Count);

            r.Names = UnpackStrings(nameBytes);
            padding = ComputePadding(r.Ranges[0].End);
            br.ReadBytes((int)padding);
            CheckAlignment(br.BaseStream);

            return(r.Validate());
        }
Пример #2
0
        /// <summary>
        /// Checks that the header values are sensible, and throws an exception otherwise.
        /// </summary>
        public static BFastHeader Validate(this BFastHeader header)
        {
            var preamble = header.Preamble.Validate();
            var ranges   = header.Ranges;
            var names    = header.Names;

            if (preamble.RangesEnd > preamble.DataStart)
            {
                throw new Exception($"Computed arrays ranges end must be less than the start of data {preamble.DataStart}");
            }

            if (ranges == null)
            {
                throw new Exception("Ranges must not be null");
            }

            var min = preamble.DataStart;
            var max = preamble.DataEnd;

            for (var i = 0; i < ranges.Length; ++i)
            {
                var begin = ranges[i].Begin;
                if (!IsAligned(begin))
                {
                    throw new Exception($"The beginning of the range is not well aligned {begin}");
                }
                var end = ranges[i].End;
                if (begin < min || begin > max)
                {
                    throw new Exception($"Array offset begin {begin} is not in valid span of {min} to {max}");
                }
                if (i > 0)
                {
                    if (begin < ranges[i - 1].End)
                    {
                        throw new Exception($"Array offset begin {begin} is overlapping with previous array {ranges[i - 1].End}");
                    }
                }

                if (end < begin || end > max)
                {
                    throw new Exception($"Array offset end {end} is not in valid span of {begin} to {max}");
                }
            }

            if (names.Length < ranges.Length - 1)
            {
                throw new Exception($"Number of buffer names {names.Length} is not one less than the number of ranges {ranges.Length}");
            }

            return(header);
        }
Пример #3
0
        /// <summary>
        /// Creates a BFAST structure, without any actual data buffers, from a list of sizes of buffers (not counting the name buffer).
        /// Used as an intermediate step to create a BFAST.
        /// </summary>
        public static BFastHeader CreateBFastHeader(this long[] bufferSizes, string[] bufferNames)
        {
            if (bufferNames.Length != bufferSizes.Length)
            {
                throw new Exception($"The number of buffer sizes {bufferSizes.Length} is not equal to the number of buffer names {bufferNames.Length}");
            }

            var header = new BFastHeader
            {
                Names = bufferNames
            };

            header.Preamble.Magic     = Constants.Magic;
            header.Preamble.NumArrays = bufferSizes.Length + 1;

            // Allocate the data for the ranges
            header.Ranges             = new BFastRange[header.Preamble.NumArrays];
            header.Preamble.DataStart = ComputeNextAlignment(header.Preamble.RangesEnd);

            var nameBufferLength = PackStrings(bufferNames).LongLength;
            var sizes            = (new[] { nameBufferLength }).Concat(bufferSizes).ToArray();

            // Compute the offsets for the data buffers
            var curIndex = header.Preamble.DataStart;
            var i        = 0;

            foreach (var size in sizes)
            {
                curIndex = ComputeNextAlignment(curIndex);
                Debug.Assert(IsAligned(curIndex));

                header.Ranges[i].Begin = curIndex;
                curIndex += size;

                header.Ranges[i].End = curIndex;
                i++;
            }

            // Finish with the header
            // Each buffer we contain is padded to ensure the next one
            // starts on alignment, so we pad our DataEnd to reflect this reality
            header.Preamble.DataEnd = ComputeNextAlignment(curIndex);

            // Check that everything adds up
            return(header.Validate());
        }
Пример #4
0
 public bool Equals(BFastHeader other)
 => Preamble.Equals(other.Preamble) &&
 Ranges.Length == other.Ranges.Length &&
 Ranges.Zip(other.Ranges, (x, y) => x.Equals(y)).All(x => x) &&
 Names.Zip(other.Names, (x, y) => x.Equals(y)).All(x => x);