Пример #1
0
        //  Signal all the matching pipes.
        public void Match(byte[] data, int size, MtrieDelegate func, Object arg)
        {
            Mtrie current = this;

            int idx = 0;

            while (true)
            {
                //  Signal the pipes attached to this node.
                if (current.m_pipes != null)
                {
                    foreach (Pipe it in current.m_pipes)
                    {
                        func(it, null, 0, arg);
                    }
                }

                //  If we are at the end of the message, there's nothing more to match.
                if (size == 0)
                {
                    break;
                }

                //  If there are no subnodes in the trie, return.
                if (current.m_count == 0)
                {
                    break;
                }

                byte c = data[idx];
                //  If there's one subnode (optimisation).
                if (current.m_count == 1)
                {
                    if (c != current.m_min)
                    {
                        break;
                    }
                    current = current.m_next[0];
                    idx++;
                    size--;
                    continue;
                }

                //  If there are multiple subnodes.
                if (c < current.m_min || c >=
                    current.m_min + current.m_count)
                {
                    break;
                }
                if (current.m_next[c - current.m_min] == null)
                {
                    break;
                }
                current = current.m_next[c - current.m_min];
                idx++;
                size--;
            }
        }
Пример #2
0
        public XPub(Ctx parent, int threadId, int sid)
            : base(parent, threadId, sid)
        {
            m_options.SocketType = ZmqSocketType.Xpub;
            m_verbose            = false;
            m_more = false;

            m_subscriptions = new Mtrie();
            m_dist          = new Dist();
            m_pending       = new Queue <Blob>();
        }
Пример #3
0
        public XPub(Ctx parent, int threadId, int sid)
            : base(parent, threadId, sid)
        {
            m_options.SocketType = ZmqSocketType.Xpub;
            m_verbose = false;
            m_more = false;

            m_subscriptions = new Mtrie();
            m_dist = new Dist();
            m_pending = new Queue<Blob>();
        }
Пример #4
0
        private bool AddHelper(byte[] prefix, int start, int size, Pipe pipe)
        {
            //  We are at the node corresponding to the prefix. We are done.
            if (size == 0)
            {
                bool result = m_pipes == null;
                if (m_pipes == null)
                {
                    m_pipes = new HashSet <Pipe>();
                }
                m_pipes.Add(pipe);
                return(result);
            }

            byte c = prefix[start];

            if (c < m_min || c >= m_min + m_count)
            {
                //  The character is out of range of currently handled
                //  charcters. We have to extend the table.
                if (m_count == 0)
                {
                    m_min   = c;
                    m_count = 1;
                    m_next  = null;
                }
                else if (m_count == 1)
                {
                    int   oldc = m_min;
                    Mtrie oldp = m_next[0];
                    m_count = (m_min < c ? c - m_min : m_min - c) + 1;
                    m_next  = new Mtrie[m_count];
                    m_min   = Math.Min(m_min, c);
                    m_next[oldc - m_min] = oldp;
                }
                else if (m_min < c)
                {
                    //  The new character is above the current character range.
                    m_count = c - m_min + 1;
                    m_next  = Realloc(m_next, m_count, true);
                }
                else
                {
                    //  The new character is below the current character range.
                    m_count = (m_min + m_count) - c;
                    m_next  = Realloc(m_next, m_count, false);
                    m_min   = c;
                }
            }

            //  If next node does not exist, create one.
            if (m_count == 1)
            {
                if (m_next == null)
                {
                    m_next    = new Mtrie[1];
                    m_next[0] = new Mtrie();
                    ++m_liveNodes;
                    //alloc_Debug.Assert(next.node);
                }
                return(m_next[0].AddHelper(prefix, start + 1, size - 1, pipe));
            }
            else
            {
                if (m_next[c - m_min] == null)
                {
                    m_next[c - m_min] = new Mtrie();
                    ++m_liveNodes;
                    //alloc_Debug.Assert(next.table [c - min]);
                }
                return(m_next[c - m_min].AddHelper(prefix, start + 1, size - 1, pipe));
            }
        }
Пример #5
0
        private bool RemovemHelper(byte[] prefix, int start, int size, Pipe pipe)
        {
            if (size == 0)
            {
                if (m_pipes != null)
                {
                    bool erased = m_pipes.Remove(pipe);
                    Debug.Assert(erased);
                    if (m_pipes.Count == 0)
                    {
                        m_pipes = null;
                    }
                }
                return(m_pipes == null);
            }

            byte c = prefix[start];

            if (m_count == 0 || c < m_min || c >= m_min + m_count)
            {
                return(false);
            }

            Mtrie nextNode =
                m_count == 1 ? m_next[0] : m_next[c - m_min];

            if (nextNode == null)
            {
                return(false);
            }

            bool ret = nextNode.RemovemHelper(prefix, start + 1, size - 1, pipe);

            if (nextNode.IsRedundant)
            {
                Debug.Assert(m_count > 0);

                if (m_count == 1)
                {
                    m_next  = null;
                    m_count = 0;
                    --m_liveNodes;
                    Debug.Assert(m_liveNodes == 0);
                }
                else
                {
                    m_next[c - m_min] = null;
                    Debug.Assert(m_liveNodes > 1);
                    --m_liveNodes;

                    //  Compact the table if possible
                    if (m_liveNodes == 1)
                    {
                        //  If there's only one live node in the table we can
                        //  switch to using the more compact single-node
                        //  representation
                        int i;
                        for (i = 0; i < m_count; ++i)
                        {
                            if (m_next[i] != null)
                            {
                                break;
                            }
                        }

                        Debug.Assert(i < m_count);
                        m_min  += i;
                        m_count = 1;
                        Mtrie old = m_next[i];
                        m_next = new Mtrie[] { old };
                    }
                    else if (c == m_min)
                    {
                        //  We can compact the table "from the left"
                        int i;
                        for (i = 1; i < m_count; ++i)
                        {
                            if (m_next[i] != null)
                            {
                                break;
                            }
                        }

                        Debug.Assert(i < m_count);
                        m_min   += i;
                        m_count -= i;
                        m_next   = Realloc(m_next, m_count, false);
                    }
                    else if (c == m_min + m_count - 1)
                    {
                        //  We can compact the table "from the right"
                        int i;
                        for (i = 1; i < m_count; ++i)
                        {
                            if (m_next[m_count - 1 - i] != null)
                            {
                                break;
                            }
                        }
                        Debug.Assert(i < m_count);
                        m_count -= i;
                        m_next   = Realloc(m_next, m_count, true);
                    }
                }
            }

            return(ret);
        }
Пример #6
0
        private bool RemoveHelper(Pipe pipe, byte[] buff, int buffsize, int maxbuffsize,
                                  MtrieDelegate func, Object arg)
        {
            //  Remove the subscription from this node.
            if (m_pipes != null && m_pipes.Remove(pipe) && m_pipes.Count == 0)
            {
                func(null, buff, buffsize, arg);
                m_pipes = null;
            }

            //  Adjust the buffer.
            if (buffsize >= maxbuffsize)
            {
                maxbuffsize = buffsize + 256;
                buff        = Utils.Realloc(buff, maxbuffsize);
            }

            //  If there are no subnodes in the trie, return.
            if (m_count == 0)
            {
                return(true);
            }

            //  If there's one subnode (optimisation).
            if (m_count == 1)
            {
                buff[buffsize] = (byte)m_min;
                buffsize++;
                m_next[0].RemoveHelper(pipe, buff, buffsize, maxbuffsize,
                                       func, arg);

                //  Prune the node if it was made redundant by the removal
                if (m_next[0].IsRedundant)
                {
                    m_next  = null;
                    m_count = 0;
                    --m_liveNodes;
                    Debug.Assert(m_liveNodes == 0);
                }
                return(true);
            }

            //  If there are multiple subnodes.
            //
            //  New min non-null character in the node table after the removal
            int newMin = m_min + m_count - 1;
            //  New max non-null character in the node table after the removal
            int newMax = m_min;

            for (int c = 0; c != m_count; c++)
            {
                buff[buffsize] = (byte)(m_min + c);
                if (m_next[c] != null)
                {
                    m_next[c].RemoveHelper(pipe, buff, buffsize + 1,
                                           maxbuffsize, func, arg);

                    //  Prune redundant nodes from the mtrie
                    if (m_next[c].IsRedundant)
                    {
                        m_next[c] = null;

                        Debug.Assert(m_liveNodes > 0);
                        --m_liveNodes;
                    }
                    else
                    {
                        //  The node is not redundant, so it's a candidate for being
                        //  the new min/max node.
                        //
                        //  We loop through the node array from left to right, so the
                        //  first non-null, non-redundant node encountered is the new
                        //  minimum index. Conversely, the last non-redundant, non-null
                        //  node encountered is the new maximum index.
                        if (c + m_min < newMin)
                        {
                            newMin = c + m_min;
                        }
                        if (c + m_min > newMax)
                        {
                            newMax = c + m_min;
                        }
                    }
                }
            }

            Debug.Assert(m_count > 1);

            //  Free the node table if it's no longer used.
            if (m_liveNodes == 0)
            {
                m_next  = null;
                m_count = 0;
            }
            //  Compact the node table if possible
            else if (m_liveNodes == 1)
            {
                //  If there's only one live node in the table we can
                //  switch to using the more compact single-node
                //  representation
                Debug.Assert(newMin == newMax);
                Debug.Assert(newMin >= m_min && newMin < m_min + m_count);
                Mtrie node = m_next[newMin - m_min];
                Debug.Assert(node != null);
                m_next  = null;
                m_next  = new Mtrie[] { node };
                m_count = 1;
                m_min   = newMin;
            }
            else if (m_liveNodes > 1 && (newMin > m_min || newMax < m_min + m_count - 1))
            {
                Debug.Assert(newMax - newMin + 1 > 1);

                Mtrie[] old_table = m_next;
                Debug.Assert(newMin > m_min || newMax < m_min + m_count - 1);
                Debug.Assert(newMin >= m_min);
                Debug.Assert(newMax <= m_min + m_count - 1);
                Debug.Assert(newMax - newMin + 1 < m_count);
                m_count = newMax - newMin + 1;
                m_next  = new Mtrie[m_count];

                Array.Copy(old_table, (newMin - m_min), m_next, 0, m_count);

                m_min = newMin;
            }
            return(true);
        }
Пример #7
0
 private Mtrie[] Realloc(Mtrie[] table, int size, bool ended)
 {
     return Utils.Realloc(table, size, ended);
 }
Пример #8
0
        private bool AddHelper(byte[] prefix, int start, Pipe pipe)
        {
            //  We are at the node corresponding to the prefix. We are done.
            if (prefix == null || prefix.Length == start) {
                bool result = m_pipes == null;
                if (m_pipes == null)
                    m_pipes = new HashSet<Pipe>();
                m_pipes.Add (pipe);
                return result;
            }

            byte c = prefix[start];
            if (c < m_min || c >= m_min + m_count) {

                //  The character is out of range of currently handled
                //  charcters. We have to extend the table.
                if (m_count == 0) {
                    m_min = c;
                    m_count = 1;
                    m_next = null;
                }
                else if (m_count == 1) {
                    int oldc = m_min;
                    Mtrie oldp = m_next[0];
                    m_count = (m_min < c ? c - m_min : m_min - c) + 1;
                    m_next = new Mtrie[m_count];
                    m_min = Math.Min (m_min, c);
                    m_next[oldc - m_min] = oldp;
                }
                else if (m_min < c) {

                    //  The new character is above the current character range.
                    m_count = c - m_min + 1;
                    m_next = Realloc(m_next, m_count, true);
                }
                else {

                    //  The new character is below the current character range.
                    m_count = (m_min + m_count) - c;
                    m_next = Realloc(m_next, m_count, false);
                    m_min = c;
                }
            }

            //  If next node does not exist, create one.
            if (m_count == 1) {
                if (m_next == null) {
                    m_next = new Mtrie[1];
                    m_next[0] = new Mtrie();
                    ++m_liveNodes;
                    //alloc_Debug.Assert(next.node);
                }
                return m_next[0].AddHelper (prefix, start + 1, pipe);
            }
            else {
                if (m_next[c - m_min] == null) {
                    m_next[c - m_min] = new Mtrie();
                    ++m_liveNodes;
                    //alloc_Debug.Assert(next.table [c - min]);
                }
                return m_next[c - m_min].AddHelper (prefix , start + 1, pipe);
            }
        }