예제 #1
0
 protected override void OnTargetChanged(Actor actor, BitCode code)
 {
     if (this.matches.Contains(actor.Id))
     {
         OnActorChanged(actor);
     }
 }
예제 #2
0
        public void TestCompositeAddContains(uint index1, uint index2)
        {
            var a = new BitCode(index1);
            var b = new BitCode(index2);

            var c = BitCode.CompositeCode.Create();

            c.Add(a);
            c.Add(b);

            Assert.IsTrue(c.Contains(a));
            Assert.IsTrue(c.Contains(b));
        }
예제 #3
0
        public void OnBitCodeTargetChanged(Actor target, BitCode code)
        {
            var filters = this.quickFilters[code.Index];

            if (null != filters && filters.Count > 0)
            {
                var filter = filters.First;
                while (null != filter)
                {
                    filter.Value.OnBitCodeTargetChanged(target, code);

                    filter = filter.Next;
                }
            }
        }
예제 #4
0
 public void OnBitCodeTargetRemoved(Actor actor, BitCode code)
 {
     if (this.locked)
     {
         this.actions.Enqueue(new TargetAction
         {
             ActionType = TargetActionType.Removed,
             Actor      = actor,
             Code       = code,
         });
     }
     else
     {
         OnTargetRemoved(actor, code);
     }
 }
예제 #5
0
 protected override void OnTargetRemoved(Actor actor, BitCode code)
 {
     if (null != this.actor)
     {
         if (this.Matcher.MatchCode.Contains(code))
         {
             OnActorUnmatched(actor);
         }
     }
     else
     {
         if (actor.CompositeCode.Contains(this.Matcher.MatchCode) &&
             !actor.CompositeCode.Intersect(this.Matcher.ExceptCode))
         {
             OnActorMatched(actor);
         }
     }
 }
예제 #6
0
 protected override void OnTargetAdded(Actor actor, BitCode code)
 {
     if (this.matches.Contains(actor.Id))
     {
         if (this.Matcher.ExceptCode.Contains(code))
         {
             this.matches.Remove(actor.Id);
             OnActorUnmatched(actor);
         }
     }
     else
     {
         if (actor.CompositeCode.Contains(this.Matcher.MatchCode) &&
             !actor.CompositeCode.Intersect(this.Matcher.ExceptCode))
         {
             this.matches.Add(actor.Id);
             OnActorMatched(actor);
         }
     }
 }
예제 #7
0
        private BitCode[] BuildTable()
        {
            var bitvalues = GetBitValues();
            var codes     = new BitCode[256];

            uint code = 7;
            byte bits = 3;

            foreach (var values in bitvalues)
            {
                for (var i = 0; i < values.Length; i++)
                {
                    var value = values[i];
                    codes[value] = new BitCode(bits, code, value);
                    --code;
                }
                code = code << 1 | 1;
                ++bits;
            }

            return(codes);
        }
예제 #8
0
 protected override void OnTargetChanged(Actor actor, BitCode code)
 {
     OnActorChanged(actor);
 }
예제 #9
0
 public void OnBitCodeTargetChanged(Actor target, BitCode code)
 {
     this.filters.OnBitCodeTargetChanged(target, code);
 }
예제 #10
0
        private BitCode[] BuildCompressionTable(byte[] data, int offset, int length, out ushort max, out CopyData copy)
        {
            const byte   WRITE_ADD_LIMIT = 15;
            const byte   CODE_LIMIT      = 7;
            const ushort COPY_LIMIT      = WRITE_ADD_LIMIT + 1 + CODE_LIMIT;

            var nodes  = new Node[264]; //0-255 normal 256-284 special (264+ not used here)
            var zeroes = new Dictionary <int, List <int> >();
            var count  = 0;

            //build array of most common bytes
            for (var i = offset; i < length; i++)
            {
                var b = data[i];
                var n = nodes[b];

                if (n == null)
                {
                    nodes[b] = n = new Node()
                    {
                        value = b,
                    };
                    ++count;
                }

                ++n.weight;

                if (b == 0)
                {
                    //some files contain a lot of empty data, searching for zeroes

                    var zerocount = i;

                    while (i < length - 1 && data[i + 1] == b)
                    {
                        ++i;
                    }

                    zerocount = i - zerocount;
                    n.weight += (uint)zerocount;

                    //zeroes will probably be compressed to 1 bit, whereas the copy code will probably be 10+ bits, so it'll take more than 10 to be worthwhile
                    if (zerocount > 10)
                    {
                        ++zerocount;
                        List <int> l;
                        if (!zeroes.TryGetValue(zerocount, out l))
                        {
                            zeroes[zerocount] = l = new List <int>();
                        }
                        l.Add(i - zerocount + 1);
                    }

                    zerocount = 0;
                }
            }

            if (zeroes.Count > 0)
            {
                var zcounts = new int[zeroes.Count];
                zeroes.Keys.CopyTo(zcounts, 0);
                Array.Sort(zcounts);

                var zrt    = 0;
                var zct    = 0;
                var zri    = -1;
                var pcount = 0;

                for (var i = zcounts.Length - 1; i >= 0; --i)
                {
                    //find how many zeroes will make the most worthwhile reduction,
                    //assuming zeroes are compressed as 1 bit and copy codes are 10+
                    //thus at least 11+ zeroes are needed (+1 to act as the reference)

                    var zi = zcounts[i];
                    var zc = zi - 1;
                    var pc = zeroes[zi].Count;
                    int zr;

                    if (zc > COPY_LIMIT) //max limit
                    {
                        //check if the limit or splitting is more worthwhile

                        zr = pc * (COPY_LIMIT - 10);

                        zc = zc / (zc / COPY_LIMIT + 1);
                        var pc2 = (zi - 1) / zc * pc;
                        var zr2 = pc2 * (zc - 10);

                        if (zr2 > zr)
                        {
                            zr = zr2;
                            pc = pc2;
                        }
                        else
                        {
                            zc = COPY_LIMIT;
                        }
                    }
                    else
                    {
                        zr = pc * (zc - 10);
                    }

                    for (var j = i + 1; j < zcounts.Length; ++j)
                    {
                        zi = zcounts[j];
                        var c = (zi - 1) / zc * zeroes[zi].Count;
                        pc += c;
                        zr += c * (zc - 10);
                    }

                    if (zr > zrt)
                    {
                        zct    = zc;
                        zrt    = zr;
                        zri    = i;
                        pcount = pc;
                    }
                }

                if (zri != -1)
                {
                    //create ordered array of copy positions

                    var positions = new int[pcount];
                    var i         = 0;

                    for (var j = zri; j < zcounts.Length; ++j)
                    {
                        var zi = zcounts[j];
                        var z  = zeroes[zi];

                        for (var k = 0; k < z.Count; ++k)
                        {
                            var l  = z[k] + 1;
                            var zc = zi - 1;

                            while (zc >= zct)
                            {
                                positions[i++] = l;

                                l  += zct;
                                zc -= zct;
                            }
                        }
                    }

                    Array.Sort(positions);

                    var add   = zct - 1;
                    var index = 256;
                    if (add > WRITE_ADD_LIMIT)
                    {
                        index += add - WRITE_ADD_LIMIT;
                        add    = WRITE_ADD_LIMIT;
                    }

                    //nodes[0].weight -= (uint)(positions.Length * (zct - 1));

                    nodes[index] = new Node()
                    {
                        value  = (ushort)index,
                        weight = (uint)i,
                    };

                    copy = new CopyData()
                    {
                        count     = (ushort)i,
                        value     = 0,
                        length    = (ushort)zct,
                        positions = positions,
                        index     = (ushort)index,
                        add       = (byte)add,
                    };

                    ++count;
                }
                else
                {
                    copy = null;
                }
            }
            else
            {
                copy = null;
            }

            //sort by least to most common
            Array.Sort(nodes,
                       delegate(Node a, Node b)
            {
                if (a != null && b != null)
                {
                    int c = (int)a.weight - (int)b.weight;
                    if (c == 0)
                    {
                        c = a.value - b.value;
                    }
                    return(c);
                }
                else if (a == b)
                {
                    return(0);
                }
                else if (a != null)
                {
                    return(-1);
                }
                else
                {
                    return(1);
                }
            });

            //build tree
            var q1 = new Queue <Node>(count);
            var q2 = new Queue <Node>(count / 2);

            for (var i = 0; i < count; i++)
            {
                q1.Enqueue(nodes[i]);
            }

            while (q1.Count + q2.Count > 1)
            {
                var a = Dequeue(q1, q2);
                var b = Dequeue(q1, q2);

                var parent = new Node()
                {
                    weight = a.weight + b.weight,
                    n0     = a,
                    n1     = b,
                };

                q2.Enqueue(parent);
            }

            var root  = Dequeue(q1, q2);
            var table = new BitCode[264];

            q1.Enqueue(root);

            byte   bits     = 0;
            uint   code     = 0;
            ushort queued   = 0;
            var    comparer = Comparer <Node> .Create(
                delegate(Node a, Node b)
            {
                return(a.value - b.value);
            });

            max   = 0;
            count = 1;

            //build bit code table
            do
            {
                var n = q1.Dequeue();

                if (n.n0 == n.n1)
                {
                    nodes[queued++] = n;
                }
                else
                {
                    if (n.n0 != null)
                    {
                        q1.Enqueue(n.n0);
                    }
                    if (n.n1 != null)
                    {
                        q1.Enqueue(n.n1);
                    }
                }

                if (--count == 0)
                {
                    if (queued > 0)
                    {
                        Array.Sort(nodes, 0, queued, comparer);
                        for (var i = 0; i < queued; i++)
                        {
                            n = nodes[i];
                            table[n.value] = new BitCode(bits, code, n.value);
                            --code;
                        }
                        var v = nodes[queued - 1].value;
                        if (v > max)
                        {
                            max = v;
                        }
                        queued = 0;
                    }

                    ++bits;
                    count = q1.Count;

                    code = code << 1 | 1;
                }
            }while (count > 0);

            return(table);
        }
예제 #11
0
 protected virtual void OnTargetChanged(Actor actor, BitCode code)
 {
 }
예제 #12
0
 protected virtual void OnTargetRemoved(Actor actor, BitCode code)
 {
 }