示例#1
0
        static public byte[] Pack(byte[] ibuf)
        {
            P($"Request to pack {ibuf.Length}");
            if (ibuf.Length < 1024)
            {
                return(cpy(ibuf));
            }
            var  d64  = new List <long>();
            var  d32  = new List <int>();
            var  d16  = new List <short>();
            var  bank = new BlitzBank(ibuf, BlitzEndian.Little, true);
            byte mod64;
            byte mod32;
            byte mod16;

            // 64 bit
            P("Creating Dictionary for 64 bit");
            for (int i = 0; i < ibuf.Length - 8; i += 8)
            {
                var p = bank.PeekLong(i);
                if (!d64.Contains(p))
                {
                    d64.Add(p);
                }
            }
            mod64 = (byte)(ibuf.Length % 8);
            P($"64 bit result (Entries {d64.Count}; Full: {ibuf.Length} Div: {(int)(ibuf.Length / 8)}; Mod: {mod64}; Pb: {needbit(d64.Count)} ");

            // 32 bit
            P("Creating Dictionary for 32 bit");
            for (int i = 0; i < ibuf.Length - 4; i += 4)
            {
                var p = bank.PeekInt(i);
                if (!d32.Contains(p))
                {
                    d32.Add(p);
                }
            }
            mod32 = (byte)(ibuf.Length % 4);
            P($"32 bit result (Entries {d32.Count}; Full: {ibuf.Length} Div: {(int)(ibuf.Length / 4)}; Mod: {mod32}; Pb: {needbit(d32.Count)} ");


            // 16 bit
            P("Creating Dictionary for 16 bit");
            for (int i = 0; i < ibuf.Length - 2; i += 2)
            {
                var p = bank.PeekShort(i);
                if (!d16.Contains(p))
                {
                    d16.Add(p);
                }
            }
            mod16 = (byte)(ibuf.Length % 2);
            P($"16 bit result (Entries {d16.Count}; Full: {ibuf.Length} Div: {(int)(ibuf.Length / 2)}; Mod: {mod16}; Pb: {needbit(d16.Count)} ");

            byte ubit = 64;
            byte pbit = 64;
            byte uinc = 8;
            //byte pinc = 8;
            int  dsiz  = 0;
            var  rat64 = Ratio(d64.Count, ibuf.Length / 8);
            var  rat32 = Ratio(d32.Count, ibuf.Length / 4);
            var  rat16 = Ratio(d16.Count, ibuf.Length / 2);
            byte rest  = 0;

            P($"Ratio   64:{rat64}; 32:{rat32}; 16:{rat16}");

            if (rat16 < rat64 && rat16 < rat32 && needbit(d16.Count) < 16)
            {
                ubit = 16; pbit = needbit(d16.Count); dsiz = (int)d16.Count; rest = mod16; uinc = 2;
            }
            else if (rat32 < rat64 && needbit(d32.Count) < 32)
            {
                ubit = 32; pbit = needbit(d32.Count); dsiz = (int)d32.Count; rest = mod32; uinc = 4;
            }
            P($"Chosen: {ubit} => {pbit}");
            if (pbit == 64 || pbit == ubit)
            {
                P("Packing not possible, so let's get outta here!");
                return(cpy(ibuf));
            }
            var Dict          = new Dictionary <long, long>();
            var PureMemStream = new MemoryStream();
            var MS            = new QuickStream(PureMemStream);

            MS.WriteString("JXSDA\x1a", true);
            MS.WriteByte(ubit);
            MS.WriteByte(pbit);
            MS.WriteByte(rest);
            MS.WriteInt(dsiz);
            for (int i = 0; i < dsiz; i++)
            {
                switch (ubit)
                {
                case 32:
                    Dict[d32[i]] = i;
                    MS.WriteInt(d32[i]);
                    break;

                case 64:
                    Dict[d64[i]] = i;
                    MS.WriteLong(d64[i]);
                    break;

                case 16:
                    P($"Dict create {i}/{dsiz}/{d16.Count}");
                    Dict[d16[i]] = i;
                    MS.WriteLong(d16[i]);
                    break;

                default:
                    throw new Exception("Unknown bit setting in creating dictionary (bug?)");
                }
            }
            for (int p = ibuf.Length - rest; p < ibuf.Length; p++)
            {
                MS.WriteByte(ibuf[p]);
            }
            for (int p = 0; p < ibuf.Length - uinc; p += uinc)
            {
                long value;
                switch (ubit)
                {
                case 64:
                    value = bank.PeekLong(p);
                    break;

                case 32:
                    value = bank.PeekInt(p);
                    break;

                case 16:
                    value = bank.PeekShort(p);
                    break;

                default:
                    throw new Exception("Unknown bit setting in reading bytes to pack (bug?)");
                }
                switch (pbit)
                {
                case 64:
                    throw new Exception("64 bit output invalid! (bug?)");

                case 32:
                    MS.WriteInt((int)Dict[value]);
                    break;

                case 16:
                    MS.WriteShort((short)Dict[value]);
                    break;

                case 8:
                    MS.WriteByte((byte)Dict[value]);
                    break;

                default:
                    throw new Exception("Unknown bit setting in writing bytes to pack (bug?)");
                }
            }
            var ret = PureMemStream.ToArray();

            MS.Close();
            return(ret); // temp
        }