Beispiel #1
0
        /// <summary>
        /// Completes an asynchronous operation initiated by <see cref="BeginRequest(Message,AsyncCallback,object)" />
        /// or <see cref="BeginRequest(Message,TimeSpan,AsyncCallback,object)" />.
        /// </summary>
        /// <param name="result">The <see cref="IAsyncResult" /> instance returned by <b>BeginRequest()</b>.</param>
        /// <returns>The correlated response message.</returns>
        public Message EndRequest(IAsyncResult result)
        {
            try
            {
                WcfEnvelopeMsg replyMsg;

                replyMsg = (WcfEnvelopeMsg)ChannelHost.Router.EndQuery(result);

                if (!base.CanAcceptMessages)
                {
                    // This is a bit of a hack to simulate aborting pending
                    // requests when the channel is closed.

                    throw ServiceModelHelper.CreateObjectDisposedException(this);
                }

                // Decode the reply

                using (BlockStream bs = new BlockStream((Block)replyMsg.Payload))
                    return(encoder.ReadMessage(bs, ServiceModelHelper.MaxXmlHeaderSize));
            }
            catch (Exception e)
            {
                throw ServiceModelHelper.GetCommunicationException(e);
            }
        }
Beispiel #2
0
        /// <summary>
        /// constructor (stream)
        /// </summary>
        public GlobalCacheReader(Stream stream)
        {
            var blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Decompress);

            _reader    = new ExtendedBinaryReader(blockStream, Encoding.UTF8);
            FileHeader = GetHeader(blockStream);
        }
Beispiel #3
0
        public TranscriptCacheReader(Stream stream)
        {
            Header = CacheHeader.Read(stream);
            var blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Decompress);

            _reader = new BufferedBinaryReader(blockStream);
        }
Beispiel #4
0
        public static NgaReader Read(Stream stream)
        {
            (IDataSourceVersion version, string jsonKey, bool isArray) = ReadHeader(stream);

            Dictionary <string, List <string> > geneSymbolToJsonStrings;

            using (var blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Decompress))
                using (var reader = new ExtendedBinaryReader(blockStream))
                {
                    int geneCount = reader.ReadOptInt32();
                    geneSymbolToJsonStrings = new Dictionary <string, List <string> >(geneCount);

                    for (var i = 0; i < geneCount; i++)
                    {
                        string geneSymbol = reader.ReadAsciiString();
                        int    numEntries = reader.ReadOptInt32();
                        var    entries    = new List <string>(numEntries);

                        for (var j = 0; j < numEntries; j++)
                        {
                            entries.Add(reader.ReadString());
                        }

                        geneSymbolToJsonStrings[geneSymbol] = entries;
                    }
                }

            return(new NgaReader(version, jsonKey, isArray, geneSymbolToJsonStrings));
        }
    public void T01_SimpleWriteRead()
    {
        BlockStream blocks = new BlockStream();

        blocks.CreateMemoryStream();

        Guid id = Guid.NewGuid();

        Hashtable tags0 = new Hashtable();

        tags0["Name"]        = "Test Write";
        tags0["Description"] = "Simple Write/Read Test.";

        byte[] bytes0 = new byte[256];
        for (int ndx = 0; ndx < 256; ndx++)
        {
            bytes0[ndx] = (byte)ndx;
        }

        blocks.WriteBlock(id, tags0, bytes0);

        Hashtable tags1 = null;

        byte[] bytes1 = null;
        blocks.ReadBlock(id, ref tags1, ref bytes1);

        //Assert.IsTrue( DataManagement.AreEqual( tags0, tags1 ) );
        Assert.IsTrue(DataManagement.AreEqual(bytes0, bytes1));

        return;
    }
        unsafe void SolveSingleJoint(JointData *jointData, int numIterations, float timestep,
                                     ref MotionVelocity velocityA, ref MotionVelocity velocityB, ref MotionData motionA, ref MotionData motionB, out BlockStream jacobiansOut)
        {
            Solver.StepInput stepInput = new Solver.StepInput
            {
                IsLastIteration        = false,
                InvNumSolverIterations = 1.0f / numIterations,
                Timestep    = timestep,
                InvTimestep = timestep > 0.0f ? 1.0f / timestep : 0.0f
            };

            // Build jacobians
            jacobiansOut = new BlockStream(1, 0);
            {
                BlockStream.Writer jacobianWriter = jacobiansOut;
                jacobianWriter.BeginForEachIndex(0);
                Solver.BuildJointJacobian(jointData, new BodyIndexPair(), velocityA, velocityB, motionA, motionB, timestep, numIterations, ref jacobianWriter);
                jacobianWriter.EndForEachIndex();
            }

            BlockStream.Writer eventWriter = new BlockStream.Writer(); // no events expected

            // Solve the joint
            for (int iIteration = 0; iIteration < numIterations; iIteration++)
            {
                stepInput.IsLastIteration = (iIteration == numIterations - 1);
                BlockStream.Reader jacobianReader = jacobiansOut;
                JacobianIterator   jacIterator    = new JacobianIterator(jacobianReader, 0);
                while (jacIterator.HasJacobiansLeft())
                {
                    ref JacobianHeader header = ref jacIterator.ReadJacobianHeader();
                    header.Solve(ref velocityA, ref velocityB, stepInput, ref eventWriter, ref eventWriter);
                }
            }
        public TranscriptCacheReader(Stream stream)
        {
            var blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Decompress);

            _reader = new ExtendedBinaryReader(blockStream, Encoding.UTF8);
            Header  = blockStream.ReadHeader(CacheHeader.Read, TranscriptCacheCustomHeader.Read) as CacheHeader;
        }
Beispiel #8
0
        public unsafe void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service)
        {
            Debug.Assert(stage == 0);

            // 1) We first write object to stream.
            BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)objectData.LongLength);

            stream.Write(objectData);

            // 2) We may need to delete object from B+ stream.
            Block block = service.Read(BlockType.TypedStreamHeader, typedStreamHeader);

            fixed(byte *p = block.Data)
            {
                TypedStreamHeader *header = (TypedStreamHeader *)p;

                // We may need to delete link.
                if (header->ObjectsAddress != 0)
                {
                    BlockStream objToDelete = BlockStream.FromBase(header->ObjectsAddress, service);
                    objToDelete.Deallocate();
                }

                // 3) We must relink it to out block.
                header->ObjectsAddress = stream.BaseAddress;
                header->ObjectSize     = (ulong)objectData.LongLength;
            }

            service.Write(BlockType.TypedStreamHeader, typedStreamHeader, block);
        }
Beispiel #9
0
        /// <summary>
        /// Internal prepare
        /// </summary>
        /// <param name="readService"></param>
        /// <param name="data"></param>
        /// <param name="subOps"></param>
        unsafe void PrepareInternal(IReadService readService, List <DeleteChild> subOps)
        {
            // We inspect children.
            ulong childrenTS;
            Block block = readService.Read(BlockType.NodeHeaderBlock, commonAddress);

            fixed(byte *p = block.Data)
            {
                NodeCommonHeader *header = (NodeCommonHeader *)p;

                childrenTS = header->ChildrenBTree;
            }

            // We check children count.
            BPlusTree         tree    = new BPlusTree(childrenTS);
            List <ObjectInfo> objects = tree.ListAll(readService);

            // We update stage index/count.
            for (int j = 0; j < objects.Count; j++)
            {
                BlockStream childTagStream = BlockStream.FromBase(objects[j].Address, readService);
                ChildTag    childTag       = Common.DeserializeFromArray(childTagStream.Read(objects[j].Size)) as ChildTag;

                foreach (KeyValuePair <string, ulong> child in childTag.Children)
                {
                    DeleteChild subOp = new DeleteChild(child.Value, childrenTS, child.Key);
                    subOps.Add(subOp);
                }
            }

            subOps.Add(this);
        }
Beispiel #10
0
        static void ReadBlocks()
        {
            var zmq = new SubscriberSocket(Config.BitcoinRawBlocks);

            zmq.Subscribe("rawblock");
            //zmq.Subscribe("rawtx");
            //zmq.SubscribeToAnyTopic();

            Console.WriteLine("Waiting for blocks..");
            while (IsRunning)
            {
                var msg      = zmq.ReceiveMultipartMessage();
                var tag      = msg[0].ConvertToString();
                var msg_data = msg[1].Buffer;

                if (tag == "rawtx")
                {
                    var tx = Transaction.Load(msg_data, Network.Main);
                    Console.WriteLine($"Got new tx! {tx}");
                }
                else if (tag == "rawblock")
                {
                    var bp = Block.Load(msg_data, Consensus.Main);
                    BlockStream.Post(bp);
                }
            }
        }
Beispiel #11
0
        public void BlockStream_ToByteArray()
        {
            BlockStream s = new BlockStream();

            s.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 10);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s.ToArray());
        }
Beispiel #12
0
        private static CacheHeader GetHeader(BlockStream blockStream, out DemoCustomHeader customHeader)
        {
            var header = (CacheHeader)blockStream.ReadHeader(CacheHeader.Read, DemoCustomHeader.Read);

            customHeader = header.CustomHeader as DemoCustomHeader;
            return(header);
        }
Beispiel #13
0
 public PredictionCacheWriter(BlockStream blockStream, CacheHeader header, bool leaveOpen = false)
 {
     _blockStream = blockStream;
     _writer      = new BinaryWriter(blockStream);
     _header      = header;
     _leaveOpen   = leaveOpen;
 }
Beispiel #14
0
        /// <summary>
        /// Serializes the request/response line and headers into a binary
        /// form suitiable for network transmission.
        /// </summary>
        /// <param name="blockSize">Size of the underlying blocks.</param>
        /// <returns>The request as a block array.</returns>
        internal BlockArray Serialize(int blockSize)
        {
            var bs     = new BlockStream(0, blockSize);
            var writer = new StreamWriter(bs);

            if (isRequest)
            {
                writer.Write("{0} {1} HTTP/{2}.{3}\r\n", method, rawUri, version.Major, version.Major);
            }
            else
            {
                writer.Write("HTTP/{0}.{1} {2} {3}\r\n", version.Major, version.Major, (int)status, reason);
            }

            foreach (HttpHeader header in headers.Values)
            {
                writer.Write("{0}: {1}\r\n", header.Name, header.Value);
            }

            writer.Write("\r\n");

            writer.Flush();

            return(bs.ToBlocks(true));
        }
Beispiel #15
0
            public static FileDescriptor Create(EndianReader reader, BlockStream block)
            {
                FileDescriptor file = new FileDescriptor();

                file.Name = reader.ReadString(0x28);
                byte namelen = reader.ReadByte();

                file.Flags     = (byte)(namelen & 0xC0);
                file.BlockSize = ReadUInt24LE(reader);
                if (ReadUInt24LE(reader) != file.BlockSize)
                {
                    throw new FormatException();
                }
                file.Block      = ReadUInt24LE(reader);
                file.Parent     = reader.ReadUInt16();
                file.Size       = reader.ReadUInt32();
                file.UpdateTime = reader.ReadUInt32();
                file.AccessTime = reader.ReadUInt32();

                if ((file.Flags & 0x80) == 0)
                {
                    file.Data = new Substream(block, block.GetBlockOffset(file.Block), file.Size);
                }

                return(file);
            }
Beispiel #16
0
        public void EndOfFile()
        {
            using (var ms = new MemoryStream())
            {
                var writeBuffer = GetRandomBytes(100);
                var readBuffer  = new byte[60];

                using (var blockStream = new BlockStream(Zstd, ms, CompressionMode.Compress, true))
                {
                    blockStream.Write(writeBuffer, 0, writeBuffer.Length);
                }

                ms.Position = 0;

                using (var blockStream = new BlockStream(Zstd, ms, CompressionMode.Decompress))
                {
                    int numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length);
                    Assert.Equal(readBuffer.Length, numBytesRead);

                    numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length);
                    Assert.Equal(writeBuffer.Length - readBuffer.Length, numBytesRead);

                    numBytesRead = blockStream.Read(readBuffer, 0, readBuffer.Length);
                    Assert.Equal(0, numBytesRead);
                }
            }
        }
Beispiel #17
0
        public void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service)
        {
            Debug.Assert(stage == 0);

            // 1) We first write to allocated block stream.
            BlockStream stream = service.AllocationContext.CreateBlockStream((ulong)objectData.LongLength);

            stream.Write(objectData);

            // 2) We may need to delete object at index.
            ObjectInfo data = tree.Find(service, index);

            if (data != null)
            {
                // Deallocate link.
                BlockStream stream2 = BlockStream.FromBase(data.Address, service);
                stream2.Deallocate();

                // We replace the entry (cheaper than delete and rewrite).
                tree.Replace(service, new ObjectInfo(index, (ulong)objectData.LongLength, stream.BaseAddress));
            }
            else
            {
                // 3) We execute insert operation.
                tree.Add(service, new ObjectInfo(index, (ulong)objectData.LongLength, stream.BaseAddress));
            }
        }
Beispiel #18
0
        private static void WriteBlockStream(ICompressionAlgorithm compressionAlgorithm, CacheHeader header,
                                             DemoCustomHeader customHeader, MemoryStream ms, string s)
        {
            using (var blockStream = new BlockStream(compressionAlgorithm, ms, CompressionMode.Compress, true))
                using (var writer = new ExtendedBinaryWriter(blockStream))
                {
                    CheckReadException(blockStream);

                    blockStream.WriteHeader(header.Write);

                    var bp = new BlockStream.BlockPosition();

                    // detect that we have written a block
                    blockStream.GetBlockPosition(bp);
                    writer.WriteOptAscii(s);
                    blockStream.GetBlockPosition(bp);

                    // here we write a test string that won't invoke a new block
                    blockStream.GetBlockPosition(customHeader.DemoPosition);
                    writer.WriteOptAscii(SmallString);
                    blockStream.GetBlockPosition(bp);

                    Assert.Equal(customHeader.DemoPosition.FileOffset, blockStream.Position);

                    blockStream.Flush();

                    // this will be flushed during dispose
                    writer.WriteOptAscii(FinalString);
                }
        }
        private void _httpServer_UnhandledRequestReceived(object sender, UnhandledRequestReceivedEventArgs args)
        {
            HttpRequestMessage requestMsg = args.Context.Request;

            if (requestMsg.Content is BlockStreamContent streamContent)
            {
                BlockStream stream = streamContent.Stream;
                FileStream  fs     = null;
                try
                {
                    fs = File.Open("d:\\test\\test.exe", FileMode.Create, FileAccess.Write);
                    stream.CopyTo(fs);
                }
                finally
                {
                    if (fs != null)
                    {
                        fs.Close();
                    }
                }

                HttpResponseMessage responseMsg = ResponseMsgHelper.CreateSimpleRepMsg();
                args.Context.Response = responseMsg;
            }
            else if (requestMsg.Content is ByteArrayContent byteContent)
            {
            }
        }
Beispiel #20
0
        public void BlockOffset()
        {
            BlockStream s;
            BlockArray  ba;

            s = new BlockStream(0, 10, 5);
            for (int i = 0; i < 20; i++)
            {
                s.WriteByte((byte)i);
            }

            ba = s.ToBlocks(false);
            Assert.Equal(4, ba.Count);
            for (int i = 0; i < ba.Count; i++)
            {
                Block b = ba.GetBlock(i);

                Assert.Equal(5, b.Length);
                Assert.Equal(5, b.Offset);
                for (int j = 0; j < 5; j++)
                {
                    Assert.Equal(i * 5 + j, (int)b.Buffer[b.Offset + j]);
                }
            }
        }
Beispiel #21
0
        public void ReadBlocks()
        {
            BlockStream s = new BlockStream(new Block(new byte[] { 0, 1, 2, 3, 4 }), new Block(new byte[] { 5, 6, 7, 8, 9 }));
            BlockArray  ba;

            Assert.Equal(0, s.Position);

            ba = s.ReadBlocks(10);
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, ba.ToByteArray());
            Assert.Equal(10, ba.Size);
            Assert.Equal(10, s.Position);

            s.Position = 5;
            ba         = s.ReadBlocks(10);
            Assert.Equal(new byte[] { 5, 6, 7, 8, 9 }, ba.ToByteArray());
            Assert.Equal(5, ba.Size);
            Assert.Equal(10, s.Position);

            s.Position = 3;
            ba         = s.ReadBlocks(5);
            Assert.Equal(new byte[] { 3, 4, 5, 6, 7 }, ba.ToByteArray());
            Assert.Equal(8, s.Position);

            s.Position = 0;
        }
Beispiel #22
0
        public void SetLength_NoModify()
        {
            BlockStream s;
            BlockArray  ba;

            byte[] buf;
            int    cb;

            ba = new BlockArray(new Block(new byte[] { 0, 1, 2, 3, 4 }), new Block(new byte[] { 5, 6, 7, 8, 9 }));
            s  = new BlockStream(ba);

            Assert.Equal(10, s.Length);
            s.Position = 10;
            s.SetLength(5, false);
            Assert.Equal(5, s.Length);
            Assert.Equal(5, s.Position);
            Assert.Equal(2, ba.Count);

            s.Position = 0;
            buf        = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            cb         = s.Read(buf, 0, 10);
            Assert.Equal(5, cb);
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 }, buf);

            s.Position = 0;
            s.SetLength(10, false);
            buf = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            cb  = s.Read(buf, 0, 10);
            Assert.Equal(10, cb);
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, buf);
        }
Beispiel #23
0
        public void ToByteArray()
        {
            BlockStream s = new BlockStream();

            s.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 10);
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s.ToArray());
        }
Beispiel #24
0
        public void ReadWriteByte()
        {
            BlockStream s;
            int         cb;

            s  = new BlockStream();
            cb = 1024 * 1024;

            Assert.Equal(-1, s.ReadByte());
            Assert.Equal(0, s.Length);
            Assert.Equal(0, s.Position);

            for (int i = 0; i < cb; i++)
            {
                s.WriteByte((byte)i);
            }

            s.Position = 0;

            for (int i = 0; i < cb; i++)
            {
                Assert.Equal((byte)i, s.ReadByte());
            }

            Assert.Equal(cb, s.Length);
            Assert.Equal(cb, s.Position);
            Assert.Equal(-1, s.ReadByte());
            Assert.Equal(cb, s.Length);
            Assert.Equal(cb, s.Position);
        }
Beispiel #25
0
        public void SetLength_Modify()
        {
            BlockStream s;

            byte[] r = new byte[10];
            byte[] w = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] c = new byte[10];

            s = new BlockStream();
            s.SetLength(100000, true);
            Assert.Equal(100000, s.Length);
            Assert.Equal(0, s.Position);

            s.Position = 50000;
            s.Write(w, 0, 10);
            Assert.Equal(50010, s.Position);

            s.SetLength(50005, true);
            Assert.Equal(50005, s.Length);
            Assert.Equal(50005, s.Position);

            s.Position = 50000;
            Zero(r);
            Assert.Equal(5, s.Read(r, 0, 10));
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 }, r);

            s.SetLength(0, true);
            Assert.Equal(0, s.Length);
            Assert.Equal(0, s.Position);
        }
 public TranscriptCacheWriter(Stream stream, CacheHeader header, bool leaveOpen = false)
 {
     _blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Compress);
     _writer      = new ExtendedBinaryWriter(_blockStream, Encoding.UTF8, leaveOpen);
     _header      = header;
     _leaveOpen   = leaveOpen;
 }
Beispiel #27
0
        public void ToArray([Values(1, 100, 200)] int count, [Values(1, 3, 10)] int batchSize)
        {
            var stream   = new BlockStream(count, 0x11843789);
            var fillInts = new WriteInts {
                Writer = stream
            };

            fillInts.Schedule(count, batchSize).Complete();

            var array     = stream.ToNativeArray <int>();
            int itemIndex = 0;

            for (int i = 0; i != count; ++i)
            {
                for (int j = 0; j < i; ++j)
                {
                    Assert.AreEqual(j, array[itemIndex]);
                    itemIndex++;
                }
            }

            array.Dispose();

            stream.Dispose();
        }
Beispiel #28
0
        public void Execute(uint stage, SharpMedia.Database.Physical.Journalling.IService service)
        {
            // 1) We read previous object placement and change it.
            ObjectInfo  info     = childrenTree.Find(service, (uint)prevName.GetHashCode());
            BlockStream stream   = BlockStream.FromBase(info.Address, service);
            ChildTag    childTag = Common.DeserializeFromArray(stream.Read(info.Size)) as ChildTag;

            childTag.Remove(prevName);

            // Remove it if empty.
            if (childTag.IsEmpty)
            {
                childrenTree.Remove(service, (uint)prevName.GetHashCode(), 1, false);
            }
            else
            {
                // Update the entry (now without this child).
                byte[] childTagData = Common.SerializeToArray(childTag);
                stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength);
                stream.Write(childTagData);

                childrenTree.Replace(service,
                                     new ObjectInfo((uint)prevName.GetHashCode(), (ulong)childTagData.LongLength, stream.BaseAddress));
            }

            // 3) We create new and insert it into tree.
            ObjectInfo info2 = childrenTree.Find(service, (uint)newName.GetHashCode());

            if (info2 == null)
            {
                // We create new tag.
                childTag = new ChildTag();
                childTag.Add(newName, info.Address);
                byte[] childTagData = Common.SerializeToArray(childTag);
                stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength);
                stream.Write(childTagData);

                // And we add child.
                childrenTree.Add(service,
                                 new ObjectInfo((uint)newName.GetHashCode(), (ulong)childTagData.LongLength, stream.BaseAddress));
            }
            else
            {
                // We append it and release previous tag.
                stream   = BlockStream.FromBase(info2.Address, service);
                childTag = Common.DeserializeFromArray(stream.Read(info2.Size)) as ChildTag;
                stream.Deallocate();

                // We modify and rewrite it.
                childTag.Add(newName, info.Address);
                byte[] childTagData = Common.SerializeToArray(childTag);
                stream = service.AllocationContext.CreateBlockStream((ulong)childTagData.LongLength);
                stream.Write(childTagData);

                // We insert into children tree.
                childrenTree.Replace(service,
                                     new ObjectInfo((uint)newName.GetHashCode(), (ulong)childTagData.LongLength, info.Address));
            }
        }
Beispiel #29
0
        private static FileHeader GetHeader(BlockStream blockStream, out DemoCustomHeader customHeader)
        {
            var headerType = FileHeader.GetHeader(0, GenomeAssembly.Unknown, new DemoCustomHeader(new BlockStream.BlockPosition()));
            var header     = (FileHeader)blockStream.ReadHeader(headerType);

            customHeader = header.Custom as DemoCustomHeader;
            return(header);
        }
Beispiel #30
0
 public void Write(Stream stream)
 {
     using (var blockStream = new BlockStream(new Zstandard(), stream, CompressionMode.Compress))
         using (var writer = new PredictionCacheWriter(blockStream, _header))
         {
             writer.Write(_header.LookupTable, _predictionsPerRef);
         }
 }
Beispiel #31
0
        public static void Main(string[] args)
        {
            var showHelp = false;
            string classFilter = null;

            var options = new OptionSet()
            {
                {
                    "c|class=",
                    "only unpack exports that are instances of specified class, ie Core.GFxUI.GFxMovieInfo",
                    v => classFilter = v
                },
                {
                    "h|help",
                    "show this message and exit", 
                    v => showHelp = v != null
                },
            };

            List<string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ -j input_pcc [output_pcc]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var inputPath = extras[0];
            var outputPath = extras.Count >= 2 ? extras[1] : Path.ChangeExtension(inputPath, null);

            using (var input = File.OpenRead(inputPath))
            {
                var magic = input.ReadValueU32(Endian.Little);
                if (magic != 0x9E2A83C1 &&
                    magic.Swap() != 0x9E2A83C1)
                {
                    throw new FormatException("not a package");
                }
                var endian = magic == 0x9E2A83C1 ?
                    Endian.Little : Endian.Big;
                var encoding = endian == Endian.Little ?
                    Encoding.Unicode : Encoding.BigEndianUnicode;

                var versionLo = input.ReadValueU16(endian);
                var versionHi = input.ReadValueU16(endian);

                if (versionLo != 684 &&
                    versionHi != 194)
                {
                    throw new FormatException("unsupported version");
                }

                input.Seek(4, SeekOrigin.Current);

                var folderNameLength = input.ReadValueS32(endian);
                var folderNameByteLength =
                    folderNameLength >= 0 ? folderNameLength : (-folderNameLength * 2);
                input.Seek(folderNameByteLength, SeekOrigin.Current);

                /*var packageFlagsOffset = input.Position;*/
                var packageFlags = input.ReadValueU32(endian);

                if ((packageFlags & 8) != 0)
                {
                    input.Seek(4, SeekOrigin.Current);
                }

                var nameCount = input.ReadValueU32(endian);
                var namesOffset = input.ReadValueU32(endian);
                var exportCount = input.ReadValueU32(endian);
                var exportInfosOffset = input.ReadValueU32(endian);
                var importCount = input.ReadValueU32(endian);
                var importInfosOffset = input.ReadValueU32(endian);

                Stream data;
                if ((packageFlags & 0x02000000) == 0)
                {
                    data = input;
                }
                else
                {
                    input.Seek(36, SeekOrigin.Current);

                    var generationsCount = input.ReadValueU32(endian);
                    input.Seek(generationsCount * 12, SeekOrigin.Current);

                    input.Seek(20, SeekOrigin.Current);

                    var blockCount = input.ReadValueU32(endian);
                    
                    var blockStream = new BlockStream(input);
                    for (int i = 0; i < blockCount; i++)
                    {
                        var uncompressedOffset = input.ReadValueU32(endian);
                        var uncompressedSize = input.ReadValueU32(endian);
                        var compressedOffset = input.ReadValueU32(endian);
                        var compressedSize = input.ReadValueU32(endian);
                        blockStream.AddBlock(
                            uncompressedOffset, uncompressedSize,
                            compressedOffset, compressedSize);
                    }

                    data = blockStream;
                }

                var names = new string[nameCount];
                
                var exportInfos = new ExportInfo[exportCount];
                for (uint i = 0; i < exportCount; i++)
                {
                    exportInfos[i] = new ExportInfo();
                }

                var importInfos = new ImportInfo[importCount];
                for (uint i = 0; i < importCount; i++)
                {
                    importInfos[i] = new ImportInfo();
                }

                data.Seek(namesOffset, SeekOrigin.Begin);
                for (uint i = 0; i < nameCount; i++)
                {
                    var nameLength = data.ReadValueS32(endian);

                    if (nameLength >= 0)
                    {
                        names[i] = data.ReadString(nameLength, true, Encoding.UTF8);
                    }
                    else
                    {
                        names[i] = data.ReadString(-nameLength * 2, true, encoding);
                    }
                }

                data.Seek(importInfosOffset, SeekOrigin.Begin);
                for (uint i = 0; i < importCount; i++)
                {
                    var importInfo = importInfos[i];

                    var packageNameIndex = data.ReadValueS32(endian);
                    importInfo.PackageName = names[packageNameIndex];

                    data.Seek(12, SeekOrigin.Current);

                    var outerIndex = data.ReadValueS32(endian);
                    importInfo.Outer = GetResource(exportInfos, importInfos, outerIndex);

                    var objectNameIndex = data.ReadValueS32(endian);
                    importInfo.ObjectName = names[objectNameIndex];

                    data.Seek(4, SeekOrigin.Current);
                }

                data.Seek(exportInfosOffset, SeekOrigin.Begin);
                for (uint i = 0; i < exportCount; i++)
                {
                    var exportInfo = exportInfos[i];

                    exportInfo.PackageName = Path.GetFileNameWithoutExtension(inputPath);

                    var classIndex = data.ReadValueS32(endian);
                    exportInfo.Class = GetResource(exportInfos, importInfos, classIndex);

                    data.Seek(4, SeekOrigin.Current);

                    var outerIndex = data.ReadValueS32(endian);
                    exportInfo.Outer = GetResource(exportInfos, importInfos, outerIndex);

                    var objectNameIndex = data.ReadValueS32(endian);
                    exportInfo.ObjectName = names[objectNameIndex];

                    data.Seek(16, SeekOrigin.Current);

                    exportInfo.DataSize = data.ReadValueU32(endian);
                    exportInfo.DataOffset = data.ReadValueU32(endian);

                    data.Seek(4, SeekOrigin.Current);
                    var count = data.ReadValueU32(endian);
                    data.Seek(count * 4, SeekOrigin.Current);
                    data.Seek(20, SeekOrigin.Current);
                }

                for (int i = 0; i < exportInfos.Length; i++)
                {
                    var exportInfo = exportInfos[i];

                    if (classFilter != null)
                    {
                        if (exportInfo.Class == null)
                        {
                            continue;
                        }

                        if (exportInfo.Class.FullName.ToLowerInvariant() !=
                            classFilter)
                        {
                            continue;
                        }
                    }

                    if (exportInfo.Class == null)
                    {
                        Console.WriteLine("{0}", exportInfo.FullName);
                    }
                    else
                    {
                        Console.WriteLine("({0}) {1}",
                            exportInfo.Class.FullName,
                            exportInfo.FullName);
                    }

                    var fullPath = exportInfo.FullPath;
                    fullPath = fullPath.Replace(":", "_");

                    var exportPath = Path.Combine(outputPath, fullPath + " [export#" + i.ToString(CultureInfo.InvariantCulture) + "].bin");
                    if (File.Exists(exportPath) == true)
                    {
                        throw new InvalidOperationException();
                    }

                    Directory.CreateDirectory(Path.GetDirectoryName(exportPath));

                    using (var output = File.Create(exportPath))
                    {
                        data.Seek(exportInfo.DataOffset, SeekOrigin.Begin);
                        output.WriteFromStream(data, exportInfo.DataSize);
                    }
                }
            }
        }