void InitializeBlocks()
        {
            uint         fileOffset = 0;
            bool         hasEnded   = false;
            List <Block> result     = new List <Block> ();
            ulong        counter    = 0;

            byte [] header = new byte [BlockData.BLOCK_HEADER_SIZE];
            ProfilerEventHandler eventProcessor = new ProfilerEventHandler();

            while (!hasEnded)
            {
                int bytesRead = stream.Read(header, 0, BlockData.BLOCK_HEADER_SIZE);
                if (bytesRead != BlockData.BLOCK_HEADER_SIZE)
                {
                    if (bytesRead == 0)
                    {
                        Console.WriteLine("WARNING: File truncated at offset {0} without end block", fileOffset);
                        break;
                    }
                    else
                    {
                        throw new Exception(String.Format("At file offset {0} block header is not complete", fileOffset));
                    }
                }
                fileOffset += (uint)BlockData.BLOCK_HEADER_SIZE;
                counter    += BlockData.DecodeHeaderBlockCounterDelta(header);

                Block block = new Block(fileOffset, BlockData.DecodeHeaderBlockCode(header), (uint)BlockData.DecodeHeaderBlockLength(header), counter);
                result.Add(block);

                fileOffset += block.Length;
                stream.Seek(fileOffset, SeekOrigin.Begin);
                if (block.Code == BlockCode.INTRO)
                {
                    ReadBlock(block).Decode(eventProcessor);
                    startCounter = eventProcessor.StartCounter;
                    startTime    = eventProcessor.StartTime;
                }
                if (block.Code == BlockCode.END)
                {
                    hasEnded = true;
                    ReadBlock(block).Decode(eventProcessor);
                    endCounter = eventProcessor.EndCounter;
                    endTime    = eventProcessor.EndTime;
                }
            }

            blocks = result.ToArray();

            foreach (Block block in blocks)
            {
                block.TimeFromStart = eventProcessor.ClicksToTimeSpan(block.Counter);
            }
        }
        public BlockData ReadBlock()
        {
            if (!hasEnded)
            {
                byte []   header;
                byte []   block;
                BlockCode code;
                int       length;
                int       bytesRead;
                BlockData result = null;

                header    = new byte [BlockData.BLOCK_HEADER_SIZE];
                bytesRead = stream.Read(header, 0, BlockData.BLOCK_HEADER_SIZE);
                if (bytesRead == 0)
                {
                    return(null);
                }
                else if (bytesRead < BlockData.BLOCK_HEADER_SIZE)
                {
                    throw new DecodingException(result, 0, String.Format("Invalid header: length is {0} instead of {1}", bytesRead, BlockData.BLOCK_HEADER_SIZE));
                }
                fileOffset += (uint)BlockData.BLOCK_HEADER_SIZE;

                code   = BlockData.DecodeHeaderBlockCode(header);
                length = BlockData.DecodeHeaderBlockLength(header);
                if (code == BlockCode.END)
                {
                    hasEnded = true;
                }
                counter += BlockData.DecodeHeaderBlockCounterDelta(header);

                block = NewData(length);
                stream.Read(block, 0, length);
                result      = new BlockData(fileOffset, code, length, counter, block);
                fileOffset += (uint)length;

                return(result);
            }
            else
            {
                return(null);
            }
        }