Click here to Skip to main content
15,881,172 members
Articles / Desktop Programming / Windows Forms

.NET Native Multiple File Compression

Rate me:
Please Sign up or sign in to vote.
4.83/5 (16 votes)
16 Jan 2012CPOL5 min read 36.6K   2K   33  
Multiple-file, searchable, streaming compression library implemented natively in .NET.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace General.Hierarchy
{
    /// <summary>
    /// Represents a single node within a tree.
    /// 
    /// when added to a Tree, the node becomes searchable from within the tree, and new nodes added/updated in the 
    /// tree will be reflected in the node.
    /// Changing the parent node value will update the children of the new parent.
    /// 
    /// The TreeNode does not need to be added to a tree to form a hierarchy. New nodes can be created and set as the 
    /// parent of any existing node.
    /// 
    /// The hierarchy enumerations on the node will navigate through the hierarchy generated by the linked nodes
    /// and their children, - these methods do not require the TreeNode to be in a Tree.
    /// 
    /// 
    /// 
    /// 
    /// </summary>
    /// <typeparam name="V">
    /// 
    /// </typeparam>
    [Serializable]
    public class TreeNode<V>
    {
        #region Fields

        /// <summary>
        /// the owning Tree
        /// </summary>
        protected Tree<V> _owner = null;

        /// <summary>
        /// the owning parent.
        /// </summary>
        protected TreeNode<V> _parent = null;

        /// <summary>
        /// local cache of child objects:
        /// </summary>
        private List<TreeNode<V>> _children = new List<TreeNode<V>>();

        /// <summary>
        /// handler for the parent object node added event.
        /// </summary>
        private Tree<V>.NodeEvent _nodeAddedHandler = null;

        #endregion

        #region Constructor

        /// <summary>
        /// default parameterless constructor.
        /// </summary>
        public TreeNode()
        {
            _nodeAddedHandler = new Tree<V>.NodeEvent(_owner_NodeAdded);
        }

        #endregion

        #region Properties

        /// <summary>
        /// owner property.
        /// </summary>
        public Tree<V> Owner { get { return _owner; } }

        /// <summary>
        /// parent property.
        /// </summary>
        public TreeNode<V> Parent
        {
            get { return _parent; }
            set
            {
                if (_parent == null)
                {
                    _parent = value;
                    if (!_parent._children.Contains(this))
                        _parent._children.Add(this);
                }
                else
                {
                    // change the parent of this node:
                    _parent._children.Remove(this);
                    _parent = value;
                    if (!_parent._children.Contains(this))
                        _parent._children.Add(this);
                }
            }

        }

        /// <summary>
        /// value property.
        /// </summary>
        public V Value { get; set; }

        /// <summary>
        /// the index within the parent tree collection.
        /// </summary>
        public int Index { get; set; }

        /// <summary>
        /// query the children of this node.
        /// </summary>
        public IEnumerable<TreeNode<V>> Children
        {
            get
            {
                return (from c in _children 
                        select c);
            }
        }

        /// <summary>
        /// query this nodes siblings.
        /// </summary>
        public IEnumerable<TreeNode<V>> Siblings
        {
            get
            {
                if (_parent == null)
                    yield break;
                else
                {
                    foreach (var sibling in _parent.Children)
                        if (sibling != this)
                            yield return sibling;
                }
            }
        }

        /// <summary>
        /// returns the parent of this node, it's parent and so on until the top of the tree is reached.
        /// </summary>
        public IEnumerable<TreeNode<V>> PathToTop 
        {
            get {
                var node = this._parent;
                while (node != null)
                {
                    yield return node;
                    node = node._parent;
                }
            }
        }

        /// <summary>
        /// returns all the descendents of the current node in hierarchy order.
        /// </summary>
        public IEnumerable<TreeNode<V>> Descendents
        {
            get
            {
                foreach (var node in _children)
                {
                    yield return node;
                    foreach (var descendent in node.Descendents)
                        yield return descendent;
                }
            }
        }

        /// <summary>
        /// hierarchy path for this node.
        /// </summary>
        public String Path
        {
            get
            {
                if (_parent == null)
                    return this.Value.ToString();
                else
                    return _parent.Path + "\\" + this.Value.ToString();
            }
        }

        #endregion

        #region Collection Modification Methods

        /// <summary>
        /// set the owning tree. the tree must already contain the node.
        /// </summary>
        /// <param name="owner"></param>
        public void SetOwner(Tree<V> owner)
        {
            if (_owner != null && _owner != owner)
                throw new ApplicationException("This node already belongs to a different tree!");

            if (!owner.Contains(this))
                throw new ApplicationException("Owner does not contain this node!");
            
            // set the owner and index:
            this._owner = owner;
            this.Index = owner.IndexOf(this);

            // attach an event-handler to the tree's node-added event to keep the children up to date.
            this._owner.NodeAdded += _nodeAddedHandler;

        }

        /// <summary>
        /// detach this node from it's owning tree.
        /// </summary>
        public void Detach()
        {
            RemoveFromTree(_owner);
        }

        /// <summary>
        /// remove this node, and all it's parents from the tree. the node cannot have children.
        /// </summary>
        /// <param name="owner"></param>
        public void RemoveFromTree(Tree<V> owner)
        {
            if (_children.Count > 0)
                throw new ApplicationException("Cannot remove a node with children!");
            if (_owner == null)
                throw new ApplicationException("This node does not have an owner to remove");

            if (Parent != null)
                Parent.RemoveFromTree(owner);

            if (_owner != null && _owner == owner)
            {
                _owner.Remove(this);
                _owner = null;
            }
        }

        /// <summary>
        /// add this node to the specified tree. the parent node must already be
        /// in the collection.
        /// </summary>
        /// <param name="tree"></param>
        public void AddToTree(Tree<V> tree)
        {
            if (_owner != null && _owner != tree)
                throw new ApplicationException("This node already belongs to a different tree!");

            if (!tree.Contains(this))
                 tree.Add(this);

        }

        /// <summary>
        /// update this nodes' internal list of children from the Tree's GetChildren method.
        /// </summary>
        public void UpdateChildren()
        {
            if (_owner != null)
            {
                _children.Clear();
                foreach (var node in _owner.GetChildren(this))
                {
                    _children.Add(node);
                }
            }
            else
                throw new ApplicationException("Tree node must have an Owner!");
        }

        #endregion

        #region Handlers

        /// <summary>
        /// Handle the "NodeAdded" event from the owning Tree object;
        /// if the added node is a parent to this node, add the new node to this node's children collection.
        /// </summary>
        /// <param name="sender">this will be the Tree control</param>
        /// <param name="node">
        /// the newly added node.
        /// </param>
        void _owner_NodeAdded(object sender, TreeNode<V> node)
        {
            if (node.Parent == this)
            {
                if (!_children.Contains(node))
                     _children.Add(node);
            }
        }

        #endregion

        /// <summary>
        /// a node is unique from it's index....
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            // generate the hash from the parent and value and index
            if (_parent != null)
            {
                return (_parent.Value.ToString() + Value.ToString()).GetHashCode() + Index;
            }
            else
                return Value.ToString().GetHashCode() + Index;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Decipha
Australia Australia
Wrote his first computer game in Microsoft Basic, on a Dragon 32 at age 7. It wasn't very good.
Has been working as a consultant and developer for the last 15 years,
Discovered C# shortly after it was created, and hasn't looked back.
Feels weird talking about himself in the third person.

Comments and Discussions