/// <summary> /// Remove key from the trie. Returns true if the item is actually /// removed from the trie. /// </summary> /// <param name="prefix"></param> /// <param name="start"></param> /// <param name="size"></param> /// <returns></returns> public bool Remove(byte[] prefix, int start, int size) { if (size == 0) { if (m_referenceCount == 0) { return(false); } m_referenceCount--; return(m_referenceCount == 0); } byte currentCharacter = prefix[start]; if (m_count == 0 || currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count) { return(false); } Trie nextNode = m_count == 1 ? m_next[0] : m_next[currentCharacter - m_minCharacter]; if (nextNode == null) { return(false); } bool wasRemoved = nextNode.Remove(prefix, start + 1, size - 1); if (nextNode.IsRedundant()) { //delete next_node; 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[currentCharacter - m_minCharacter] = 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 Trie node = null; for (short i = 0; i < m_count; ++i) { if (m_next[i] != null) { node = m_next[i]; m_minCharacter = (byte)(i + m_minCharacter); break; } } Debug.Assert(node != null); m_next = null; m_next = new[] { node }; m_count = 1; } else if (currentCharacter == m_minCharacter) { // We can compact the table "from the left" byte newMin = m_minCharacter; for (short i = 1; i < m_count; ++i) { if (m_next[i] != null) { newMin = (byte)(i + m_minCharacter); break; } } Debug.Assert(newMin != m_minCharacter); Debug.Assert(newMin > m_minCharacter); Debug.Assert(m_count > newMin - m_minCharacter); m_count = (short)(m_count - (newMin - m_minCharacter)); m_next = m_next.Resize(m_count, false); m_minCharacter = newMin; } else if (currentCharacter == m_minCharacter + m_count - 1) { // We can compact the table "from the right" short newCount = m_count; for (short i = 1; i < m_count; ++i) { if (m_next[m_count - 1 - i] != null) { newCount = (short)(m_count - i); break; } } Debug.Assert(newCount != m_count); m_count = newCount; m_next = m_next.Resize(m_count, true); } } } return(wasRemoved); }
/// <summary> /// Add key to the trie. Returns true if this is a new item in the trie /// rather than a duplicate. /// </summary> /// <param name="prefix"></param> /// <param name="start"></param> /// <param name="size"></param> /// <returns></returns> public bool Add(byte[] prefix, int start, int size) { // We are at the node corresponding to the prefix. We are done. if (size == 0) { ++m_referenceCount; return(m_referenceCount == 1); } byte currentCharacter = prefix[start]; if (currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count) { // The character is out of range of currently handled // characters. We have to extend the table. if (m_count == 0) { m_minCharacter = currentCharacter; m_count = 1; m_next = null; } else if (m_count == 1) { byte oldc = m_minCharacter; Trie oldp = m_next[0]; m_count = (short)((m_minCharacter < currentCharacter ? currentCharacter - m_minCharacter : m_minCharacter - currentCharacter) + 1); m_next = new Trie[m_count]; m_minCharacter = Math.Min(m_minCharacter, currentCharacter); m_next[oldc - m_minCharacter] = oldp; } else if (m_minCharacter < currentCharacter) { // The new character is above the current character range. m_count = (short)(currentCharacter - m_minCharacter + 1); m_next = m_next.Resize(m_count, true); } else { // The new character is below the current character range. m_count = (short)((m_minCharacter + m_count) - currentCharacter); m_next = m_next.Resize(m_count, false); m_minCharacter = currentCharacter; } } // If next node does not exist, create one. if (m_count == 1) { if (m_next == null) { m_next = new Trie[1]; m_next[0] = new Trie(); ++m_liveNodes; //alloc_Debug.Assert(next.node); } return(m_next[0].Add(prefix, start + 1, size - 1)); } else { if (m_next[currentCharacter - m_minCharacter] == null) { m_next[currentCharacter - m_minCharacter] = new Trie(); ++m_liveNodes; //alloc_Debug.Assert(next.table [c - min]); } return(m_next[currentCharacter - m_minCharacter].Add(prefix, start + 1, size - 1)); } }
/// <summary> /// Add key to the trie. Returns true if this is a new item in the trie /// rather than a duplicate. /// </summary> /// <param name="prefix"></param> /// <param name="start"></param> /// <param name="size"></param> /// <returns></returns> public bool Add([NotNull] byte[] prefix, int start, int size) { // We are at the node corresponding to the prefix. We are done. if (size == 0) { ++m_referenceCount; return m_referenceCount == 1; } byte currentCharacter = prefix[start]; if (currentCharacter < m_minCharacter || currentCharacter >= m_minCharacter + m_count) { // The character is out of range of currently handled // characters. We have to extend the table. if (m_count == 0) { m_minCharacter = currentCharacter; m_count = 1; m_next = null; } else if (m_count == 1) { byte oldc = m_minCharacter; Trie oldp = m_next[0]; m_count = (short)((m_minCharacter < currentCharacter ? currentCharacter - m_minCharacter : m_minCharacter - currentCharacter) + 1); m_next = new Trie[m_count]; m_minCharacter = Math.Min(m_minCharacter, currentCharacter); m_next[oldc - m_minCharacter] = oldp; } else if (m_minCharacter < currentCharacter) { // The new character is above the current character range. m_count = (short)(currentCharacter - m_minCharacter + 1); m_next = m_next.Resize(m_count, true); } else { // The new character is below the current character range. m_count = (short)((m_minCharacter + m_count) - currentCharacter); m_next = m_next.Resize(m_count, false); m_minCharacter = currentCharacter; } } // If next node does not exist, create one. if (m_count == 1) { if (m_next == null) { m_next = new Trie[1]; m_next[0] = new Trie(); ++m_liveNodes; //alloc_Debug.Assert(next.node); } return m_next[0].Add(prefix, start + 1, size - 1); } else { if (m_next[currentCharacter - m_minCharacter] == null) { m_next[currentCharacter - m_minCharacter] = new Trie(); ++m_liveNodes; //alloc_Debug.Assert(next.table [c - min]); } return m_next[currentCharacter - m_minCharacter].Add(prefix, start + 1, size - 1); } }
public XSub([NotNull] Ctx parent, int threadId, int socketId) : base(parent, threadId, socketId) { m_options.SocketType = ZmqSocketType.Xsub; m_hasMessage = false; m_more = false; m_options.Linger = 0; m_fairQueueing = new FairQueueing(); m_distribution = new Distribution(); m_subscriptions = new Trie(); m_message = new Msg(); m_message.InitEmpty(); }