<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: tree code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Sat, 26 Jul 2008 15:23:01 GMT</pubDate>
    <description>DZone Snippets: tree code</description>
    <item>
      <title>Numbering left and right attributes of a nested set</title>
      <link>http://snippets.dzone.com/posts/show/5604</link>
      <description>Uses a hash to model a tree that numbers the left and right attributes of a nested set.&lt;br /&gt;&lt;br /&gt;# test case for depth_first traversal&lt;br /&gt;#&lt;br /&gt;# tree = { :electronics =&gt; { &lt;br /&gt;#     :televisions =&gt;   { :tube =&gt; {}, &lt;br /&gt;#                         :lcd =&gt; {},&lt;br /&gt;#                         :plasma =&gt; {} },&lt;br /&gt;#     :portable_elec =&gt; { :mp3_players =&gt; {&lt;br /&gt;#                           :flash =&gt; { } &lt;br /&gt;#                         },&lt;br /&gt;#                         :cd_player =&gt; { }, &lt;br /&gt;#                         :two_way_radio =&gt; { }&lt;br /&gt;#                       } &lt;br /&gt;#   }&lt;br /&gt;# }&lt;br /&gt;#&lt;br /&gt;# tree.depth_first do |name, parent_name, lft, rgt|&lt;br /&gt;#   puts "#{parent_name}/#{name}: #{lft} - #{rgt}"&lt;br /&gt;# end&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Hash&lt;br /&gt;  def depth_first(&amp;block)&lt;br /&gt;    root_node = self.keys.first&lt;br /&gt;    root_children = self[root_node]&lt;br /&gt;    depth_first_helper(root_node, root_children, nil, 1, &amp;block)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  private&lt;br /&gt;  def depth_first_helper(name, children, parent_name, lft, &amp;block)&lt;br /&gt;    if children.empty?&lt;br /&gt;      rgt = lft + 1&lt;br /&gt;    else&lt;br /&gt;      children_lft = lft + 1&lt;br /&gt;      children.each do |child_name, grandchildren|&lt;br /&gt;        rgt = depth_first_helper(child_name, grandchildren, name, children_lft, &amp;block)&lt;br /&gt;        children_lft = rgt&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    block.call(name, parent_name, lft, rgt)&lt;br /&gt;    return rgt + 1&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Fri, 06 Jun 2008 19:29:00 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5604</guid>
      <author>iamwil (wilhelm)</author>
    </item>
    <item>
      <title>Disjoint Set Class in Ruby</title>
      <link>http://snippets.dzone.com/posts/show/5124</link>
      <description>A disjoint Set can be used for creating minimal spanning trees.&lt;br /&gt;The union-find algorithm is fast, faster than linked lists for some uses. &lt;br /&gt;See: &lt;a href = "http://en.wikipedia.org/wiki/Disjoint-set_data_structure"&gt;Wikipedia Disjoint Set&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's fast and simple. Just add a DisjointSetNode object to the &lt;br /&gt;objects that you want to create a tree of. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# This is a disjoint set implementing union-find&lt;br /&gt;# It can be used for generating a minimal spanning&lt;br /&gt;# tree using Kruskal's algorithm.&lt;br /&gt;# http://en.wikipedia.org/wiki/Kruskal's_algorithm&lt;br /&gt;&lt;br /&gt;class DisjointSetNode&lt;br /&gt;  attr_accessor :parent, :rank&lt;br /&gt;&lt;br /&gt;  def initialize&lt;br /&gt;    @parent = self&lt;br /&gt;    @rank = 0&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # An optimised union by rank. Attaches smaller tree to larger.&lt;br /&gt;  def union(other)&lt;br /&gt;    self_root = self.find&lt;br /&gt;    other_root = other.find&lt;br /&gt;    if self_root.rank &gt; other_root.rank&lt;br /&gt;      other_root.parent = self_root&lt;br /&gt;    elsif self_root.rank &lt; other_root.rank&lt;br /&gt;      self_root.parent = other_root&lt;br /&gt;    elsif self_root != other_root&lt;br /&gt;      other_root.parent = self_root&lt;br /&gt;      self_root.rank += 1&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def find&lt;br /&gt;    if self.parent === self&lt;br /&gt;      self&lt;br /&gt;    else&lt;br /&gt;      self.parent = self.parent.find&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end   # class DisjointSetNode&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Some simple test code:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;require 'disjointsetnode'&lt;br /&gt;require 'test/unit'&lt;br /&gt;require 'test/unit/ui/console/testrunner'&lt;br /&gt;&lt;br /&gt;    class DisjointSetTest &lt; Test::Unit::TestCase&lt;br /&gt;      N_Nodes = 1000&lt;br /&gt;&lt;br /&gt;      def setup&lt;br /&gt;        @nodes = Array.new&lt;br /&gt;        (1..N_Nodes).each do |node|&lt;br /&gt;        @nodes &lt;&lt; DisjointSetNode.new&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      # def teardown&lt;br /&gt;      # end&lt;br /&gt;&lt;br /&gt;      def test_creation&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          assert !node.nil?, "A Node is nil!"&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_initial_values&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          assert node.parent === node, "self #{node}, parent #{node.parent} not equal."&lt;br /&gt;          assert node.rank == 0, " A node's rtank is not 0."&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_union&lt;br /&gt;        # Join all nodes in sequence&lt;br /&gt;        @nodes.each do |node|&lt;br /&gt;          if !@lastnode.nil?&lt;br /&gt;            node.union(@lastnode)&lt;br /&gt;            node_f = node.find&lt;br /&gt;            lnode_f = @lastnode.find&lt;br /&gt;            assert node_f == lnode_f, "Join not completed: node_f: #{node_f}, lnode_f: #{lnode_f}"&lt;br /&gt;          end&lt;br /&gt;          @lastnode = node&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def test_random_union&lt;br /&gt;        (1..N_Nodes-1).each do |n|&lt;br /&gt;          node = @nodes[n]&lt;br /&gt;          other = @nodes[rand(N_Nodes-1)]&lt;br /&gt;          node.union(other)&lt;br /&gt;          node_f = node.find&lt;br /&gt;          onode_f = other.find&lt;br /&gt;          assert node_f == onode_f, "Join not completed: node_f: #{node_f}, onode_f: #{onode_f}"&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;# This runs the tests for ya! &lt;br /&gt;Test::Unit::UI::Console::TestRunner.run(DisjointSetTest)&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Sun, 10 Feb 2008 02:49:59 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5124</guid>
      <author>dr_saturn (Stuart Coyle)</author>
    </item>
    <item>
      <title>Prim's Algorithm for Finding Minimum Spanning Trees in C</title>
      <link>http://snippets.dzone.com/posts/show/4743</link>
      <description>The is a straight-forward implementation of Prim's Algorithm for finding the minimum spanning tree of a graph.&lt;br /&gt;&lt;br /&gt;A detailed explanation is given &lt;a href="http://compprog.wordpress.com/2007/11/09/minimal-spanning-trees-prims-algorithm/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;	The input file (weight.txt) look something like this&lt;br /&gt;		4&lt;br /&gt;		0 0 0 21&lt;br /&gt;		0 0 8 17&lt;br /&gt;		0 8 0 16&lt;br /&gt;		21 17 16 0&lt;br /&gt;&lt;br /&gt;	The first line contains n, the number of nodes.&lt;br /&gt;	Next is an nxn matrix containg the distances between the nodes&lt;br /&gt;	NOTE: The distance between a node and itself should be 0&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;int n; /* The number of nodes in the graph */&lt;br /&gt;&lt;br /&gt;int weight[100][100]; /* weight[i][j] is the distance between node i and node j;&lt;br /&gt;			if there is no path between i and j, weight[i][j] should&lt;br /&gt;			be 0 */&lt;br /&gt;&lt;br /&gt;char inTree[100]; /* inTree[i] is 1 if the node i is already in the minimum&lt;br /&gt;			spanning tree; 0 otherwise*/&lt;br /&gt;&lt;br /&gt;int d[100]; /* d[i] is the distance between node i and the minimum spanning&lt;br /&gt;		tree; this is initially infinity (100000); if i is already in&lt;br /&gt;		the tree, then d[i] is undefined;&lt;br /&gt;		this is just a temporary variable. It's not necessary but speeds&lt;br /&gt;		up execution considerably (by a factor of n) */&lt;br /&gt;&lt;br /&gt;int whoTo[100]; /* whoTo[i] holds the index of the node i would have to be&lt;br /&gt;			linked to in order to get a distance of d[i] */&lt;br /&gt;&lt;br /&gt;/* updateDistances(int target)&lt;br /&gt;	should be called immediately after target is added to the tree;&lt;br /&gt;	updates d so that the values are correct (goes through target's&lt;br /&gt;	neighbours making sure that the distances between them and the tree&lt;br /&gt;	are indeed minimum)&lt;br /&gt;*/&lt;br /&gt;void updateDistances(int target) {&lt;br /&gt;	int i;&lt;br /&gt;	for (i = 0; i &lt; n; ++i)&lt;br /&gt;		if ((weight[target][i] != 0) &amp;&amp; (d[i] &gt; weight[target][i])) {&lt;br /&gt;			d[i] = weight[target][i];&lt;br /&gt;			whoTo[i] = target;&lt;br /&gt;		}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[]) {&lt;br /&gt;	FILE *f = fopen("dist.txt", "r");&lt;br /&gt;	fscanf(f, "%d", &amp;n);&lt;br /&gt;	int i, j;&lt;br /&gt;	for (i = 0; i &lt; n; ++i)&lt;br /&gt;		for (j = 0; j &lt; n; ++j)&lt;br /&gt;			fscanf(f, "%d", &amp;weight[i][j]);&lt;br /&gt;	fclose(f);&lt;br /&gt;&lt;br /&gt;	/* Initialise d with infinity */&lt;br /&gt;	for (i = 0; i &lt; n; ++i)&lt;br /&gt;		d[i] = 100000;&lt;br /&gt;&lt;br /&gt;	/* Mark all nodes as NOT beeing in the minimum spanning tree */&lt;br /&gt;	for (i = 0; i &lt; n; ++i)&lt;br /&gt;		inTree[i] = 0;&lt;br /&gt;&lt;br /&gt;	/* Add the first node to the tree */&lt;br /&gt;	printf("Adding node %c\n", 0 + 'A');&lt;br /&gt;	inTree[0] = 1;&lt;br /&gt;	updateDistances(0);&lt;br /&gt;&lt;br /&gt;	int total = 0;&lt;br /&gt;	int treeSize;&lt;br /&gt;	for (treeSize = 1; treeSize &lt; n; ++treeSize) {&lt;br /&gt;		/* Find the node with the smallest distance to the tree */&lt;br /&gt;		int min = -1;&lt;br /&gt;		for (i = 0; i &lt; n; ++i)&lt;br /&gt;			if (!inTree[i])&lt;br /&gt;				if ((min == -1) || (d[min] &gt; d[i]))&lt;br /&gt;					min = i;&lt;br /&gt;&lt;br /&gt;		/* And add it */&lt;br /&gt;		printf("Adding edge %c-%c\n", whoTo[min] + 'A', min + 'A');&lt;br /&gt;		inTree[min] = 1;&lt;br /&gt;		total += d[min];&lt;br /&gt;&lt;br /&gt;		updateDistances(min);&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	printf("Total distance: %d\n", total);&lt;br /&gt;&lt;br /&gt;	return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Fri, 09 Nov 2007 12:31:11 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/4743</guid>
      <author>scvalex (Alexandru Scvortov)</author>
    </item>
    <item>
      <title>Expression tree builder</title>
      <link>http://snippets.dzone.com/posts/show/4188</link>
      <description>EvalExp(s) turns the string s into an expression tree and returns it.&lt;br /&gt;&lt;br /&gt;Inorder, preorder and postorder can then be used to turn transform the tree into inorder, preorder or postorder expressions.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function inorder(T) {&lt;br /&gt;  if ((T.cargo  == '+') || (T.cargo  == '-') || (T.cargo  == '*') || (T.cargo  == '/'))&lt;br /&gt;    return [].concat(inorder(T.left)).concat(T.cargo).concat(inorder(T.right));&lt;br /&gt;&lt;br /&gt;  return new Array(T.cargo);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function preorder(T) {&lt;br /&gt;  if ((T.cargo  == '+') || (T.cargo  == '-') || (T.cargo  == '*') || (T.cargo  == '/'))&lt;br /&gt;    return [].concat(T.cargo).concat(preorder(T.left)).concat(preorder(T.right));&lt;br /&gt;&lt;br /&gt;  return new Array(T.cargo);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function postorder(T) {&lt;br /&gt;  if ((T.cargo  == '+') || (T.cargo  == '-') || (T.cargo  == '*') || (T.cargo  == '/'))&lt;br /&gt;    return [].concat(postorder(T.left)).concat(postorder(T.right)).concat(T.cargo);&lt;br /&gt;&lt;br /&gt;  return new Array(T.cargo);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function Tree(cargo, left, right) {&lt;br /&gt;  this.cargo = cargo;&lt;br /&gt;  this.left = left;&lt;br /&gt;  this.right = right;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function split(s) {&lt;br /&gt;  var r = [];&lt;br /&gt;  var cur = '';&lt;br /&gt;  for (var i = 0; i &lt; s.length; ++i) {&lt;br /&gt;    var c = s.charAt(i);&lt;br /&gt;    if ((c == '+') || (c == '-') || (c == '*') || (c == '/') || (c == '(') || (c == ')')) {&lt;br /&gt;      cur.replace(" ", "");&lt;br /&gt;      if (cur.length &gt; 0) {&lt;br /&gt;        r.push(cur);&lt;br /&gt;        cur = '';&lt;br /&gt;      }&lt;br /&gt;      r.push(c);&lt;br /&gt;    } else {&lt;br /&gt;      cur += c;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  if (cur.length &gt; 0)&lt;br /&gt;    r.push(cur);&lt;br /&gt;&lt;br /&gt;  return r;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getToken(tokens, expected) {&lt;br /&gt;  if (tokens[0] == expected) {&lt;br /&gt;    tokens.splice(0, 1);&lt;br /&gt;    return true;&lt;br /&gt;  }&lt;br /&gt;    return false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getVar(tokens) {&lt;br /&gt;  if (getToken(tokens, '(')) {&lt;br /&gt;    var a = getSum(tokens);&lt;br /&gt;    getToken(tokens, ')');&lt;br /&gt;&lt;br /&gt;    return a;&lt;br /&gt;  } else {&lt;br /&gt;    var aux = tokens[0];&lt;br /&gt;    tokens.splice(0, 1);&lt;br /&gt;&lt;br /&gt;    return new Tree(aux, undefined, undefined);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getProduct(tokens) {&lt;br /&gt;  var a = getVar(tokens);&lt;br /&gt;&lt;br /&gt;  if (getToken(tokens, '*')) {&lt;br /&gt;    var b = getProduct(tokens);&lt;br /&gt;&lt;br /&gt;    return new Tree('*', a, b);&lt;br /&gt;  } else if (getToken(tokens, '/')) {&lt;br /&gt;    var b = getProduct(tokens);&lt;br /&gt;&lt;br /&gt;    return new Tree('/', a, b);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return a;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getSum(tokens) {&lt;br /&gt;  var a = getProduct(tokens);&lt;br /&gt;&lt;br /&gt;  if (getToken(tokens, '+')) {&lt;br /&gt;    var b = getSum(tokens);&lt;br /&gt;&lt;br /&gt;    return new Tree('+', a, b);&lt;br /&gt;  } else if (getToken(tokens, '-')) {&lt;br /&gt;    var b = getSum(tokens);&lt;br /&gt;&lt;br /&gt;    return new Tree('-', a, b);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return a;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function evalExp(s) {&lt;br /&gt;  var tokens = split(s);&lt;br /&gt;&lt;br /&gt;  //alert(tokens);&lt;br /&gt;&lt;br /&gt;  return t = getSum(tokens);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Fri, 22 Jun 2007 14:21:31 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/4188</guid>
      <author>scvalex (Alexandru Scvortov)</author>
    </item>
    <item>
      <title>Visit Python Abstract Syntax Tree</title>
      <link>http://snippets.dzone.com/posts/show/3360</link>
      <description>Simplest AST visitor. More on this blog post :&lt;br /&gt;&lt;a href="http://www.biais.org/blog/index.php/2007/01/10/9-visit-python-abstract-syntax-tree"&gt;http://www.biais.org/blog/index.php/2007/01/10/9-visit-python-abstract-syntax-tree&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import compiler&lt;br /&gt; &lt;br /&gt;class CodePrinter:&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.src = ''&lt;br /&gt; &lt;br /&gt;    def visitName(self,t):&lt;br /&gt;        self.src += t.name&lt;br /&gt; &lt;br /&gt;    def visitConst(self,t):&lt;br /&gt;        self.src += str(t.value)&lt;br /&gt; &lt;br /&gt;    def visitStmt(self, t):&lt;br /&gt;        for i in t:&lt;br /&gt;            a = pretty_print(i)&lt;br /&gt;            self.src += a + "\n"&lt;br /&gt; &lt;br /&gt;    def visitAssName(self, t):&lt;br /&gt;        self.src += t.name + " = "&lt;br /&gt; &lt;br /&gt;def pretty_print(node):&lt;br /&gt;    myvisitor = CodePrinter()&lt;br /&gt;    # compiler.walk return the visitor instance : 2nd arg&lt;br /&gt;    return compiler.walk(node, myvisitor).src&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Wed, 24 Jan 2007 13:03:54 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/3360</guid>
      <author>maxme (Maxime Biais)</author>
    </item>
    <item>
      <title>Acts As Tree Category Display</title>
      <link>http://snippets.dzone.com/posts/show/1919</link>
      <description>You should have a categories table with a parent_id field.  Root categories should have the parent_id of 0.&lt;br /&gt;&lt;br /&gt;I modified this post:&lt;br /&gt;http://www.bigbold.com/snippets/posts/show/296&lt;br /&gt;&lt;br /&gt;because the first one worked if you did stuff in your view to make the root categories come up, but I agree with the commenter that things should be contained to the helper - however I've managed to break the DRY rule in doing so.  If anyone has any suggestions for a better way around this I'd love to hear it, so please comment.  So anyway.. this should list your root categories ONLY and NOT your other sub-cats as well so that you have a very pretty little tree.&lt;br /&gt;&lt;br /&gt;Slap this in your view:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;%= display_categories(@categories) %&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And put this in a helper file.  You'll need it in the application helper most likely since you'll want to call it from multiple views.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;      def display_categories(categories)&lt;br /&gt;	    	   ret = "&lt;ul&gt;"&lt;br /&gt;	   for category in categories&lt;br /&gt;		   if category.parent_id == 0&lt;br /&gt;			ret += "&lt;li&gt;"&lt;br /&gt;			ret += link_to category.name&lt;br /&gt;			ret += find_all_subcategories(category)&lt;br /&gt;			ret += "&lt;/li&gt;"&lt;br /&gt;		   end&lt;br /&gt;		   &lt;br /&gt;	   end&lt;br /&gt;	   ret += "&lt;/ul&gt;"&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;   def find_all_subcategories(category)&lt;br /&gt;    if category.children.size &gt; 0&lt;br /&gt;      ret = '&lt;ul&gt;'&lt;br /&gt;      category.children.each { |subcat| &lt;br /&gt;        if subcat.children.size &gt; 0&lt;br /&gt;          ret += '&lt;li&gt;'&lt;br /&gt;          ret += link_to h(subcat.name), :action =&gt; 'edit', :id =&gt; subcat&lt;br /&gt;          ret += find_all_subcategories(subcat)&lt;br /&gt;          ret += '&lt;/li&gt;'&lt;br /&gt;        else&lt;br /&gt;          ret += '&lt;li&gt;'&lt;br /&gt;          ret += link_to h(subcat.name), :action =&gt; 'edit', :id =&gt; subcat &lt;br /&gt;          ret += '&lt;/li&gt;'&lt;br /&gt;        end&lt;br /&gt;        }&lt;br /&gt;      ret += '&lt;/ul&gt;'&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Sun, 16 Apr 2006 15:32:57 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/1919</guid>
      <author>ioda006 ()</author>
    </item>
    <item>
      <title>a binary tree structure "PersistentTree"</title>
      <link>http://snippets.dzone.com/posts/show/436</link>
      <description>unit StreamAdapter.pas&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;//+ Jonas Raoni Soares Silva&lt;br /&gt;//@ http://jsfromhell.com&lt;br /&gt;&lt;br /&gt;unit StreamAdapter;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  Classes;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  IStream = interface( IInterface )&lt;br /&gt;    ['{FBEF199A-09BC-4B61-89EA-1EF8B22C93A5}']&lt;br /&gt;    function Read(var Buffer; const Count: Longint): Longint;&lt;br /&gt;    function Write(const Buffer; const Count: Longint): Longint;&lt;br /&gt;    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;&lt;br /&gt;    procedure ReadBuffer(var Buffer; const Count: Longint);&lt;br /&gt;    procedure WriteBuffer(const Buffer; const Count: Longint);&lt;br /&gt;    function CopyFrom(Source: TStream; const Count: Int64): Int64;&lt;br /&gt;    function WriteTo(Dest: TStream; const Count: Int64): Int64;&lt;br /&gt;&lt;br /&gt;    procedure SetPosition( const Value: Int64 );&lt;br /&gt;    procedure SetSize( const Value: Int64 );&lt;br /&gt;    function GetPosition: Int64;&lt;br /&gt;    function GetSize: Int64;&lt;br /&gt;&lt;br /&gt;    property Position: Int64 read GetPosition write SetPosition;&lt;br /&gt;    property Size: Int64 read GetSize write SetSize;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TStreamAdapter = class( TInterfacedObject, IStream )&lt;br /&gt;  private&lt;br /&gt;    FStream: TStream;&lt;br /&gt;    procedure SetPosition( const Value: Int64 );&lt;br /&gt;    procedure SetSize( const Value: Int64 );&lt;br /&gt;    function GetPosition: Int64;&lt;br /&gt;    function GetSize: Int64;&lt;br /&gt;&lt;br /&gt;  public&lt;br /&gt;    constructor Create( Stream: TStream );&lt;br /&gt;    destructor Destroy; override;&lt;br /&gt;&lt;br /&gt;    function Read(var Buffer; const Count: Longint): Longint;&lt;br /&gt;    function Write(const Buffer; const Count: Longint): Longint;&lt;br /&gt;&lt;br /&gt;    procedure ReadBuffer(var Buffer; const Count: Longint);&lt;br /&gt;    procedure WriteBuffer(const Buffer; const Count: Longint);&lt;br /&gt;&lt;br /&gt;    function CopyFrom(Source: TStream; const Count: Int64): Int64;&lt;br /&gt;    function WriteTo(Dest: TStream; const Count: Int64): Int64;&lt;br /&gt;&lt;br /&gt;    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;&lt;br /&gt;&lt;br /&gt;    property Position: Int64 read GetPosition write SetPosition;&lt;br /&gt;    property Size: Int64 read GetSize write SetSize;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;{ TStreamAdapter }&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.CopyFrom(Source: TStream; const Count: Int64): Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.CopyFrom( Source, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;constructor TStreamAdapter.Create(Stream: TStream);&lt;br /&gt;begin&lt;br /&gt;  FStream := Stream;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;destructor TStreamAdapter.Destroy;&lt;br /&gt;begin&lt;br /&gt;  FStream.Free;&lt;br /&gt;  inherited;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.GetPosition: Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.Position;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.GetSize: Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.Size;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.Read(var Buffer; const Count: Integer): Longint;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.Read( Buffer, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TStreamAdapter.ReadBuffer(var Buffer; const Count: Integer);&lt;br /&gt;begin&lt;br /&gt;  FStream.ReadBuffer( Buffer, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.Seek(const Offset: Int64;&lt;br /&gt;  Origin: TSeekOrigin): Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.Seek( Offset, Origin );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TStreamAdapter.SetPosition(const Value: Int64);&lt;br /&gt;begin&lt;br /&gt;  FStream.Position := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TStreamAdapter.SetSize(const Value: Int64);&lt;br /&gt;begin&lt;br /&gt;  FStream.Size := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.Write(const Buffer; const Count: Integer): Longint;&lt;br /&gt;begin&lt;br /&gt;  Result := FStream.Write( Buffer, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TStreamAdapter.WriteBuffer(const Buffer; const Count: Integer);&lt;br /&gt;begin&lt;br /&gt;  FStream.WriteBuffer( Buffer, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TStreamAdapter.WriteTo(Dest: TStream; const Count: Int64): Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := Dest.CopyFrom( FStream, Count );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;unit PersistentTree.pas&lt;br /&gt;&lt;code&gt;&lt;br /&gt;//+ Jonas Raoni Soares Silva&lt;br /&gt;//@ http://jsfromhell.com&lt;br /&gt;&lt;br /&gt;unit PersistentTree;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  Windows, Classes, SysUtils, StreamAdapter;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  EPersistentTree = class( Exception );&lt;br /&gt;&lt;br /&gt;  TPersistentTree = class;&lt;br /&gt;&lt;br /&gt;  TPersistentTreeClass = class of TPersistentTree;&lt;br /&gt;&lt;br /&gt;  TPersistentTree = class( TStream )&lt;br /&gt;  private&lt;br /&gt;    FStream: IStream;&lt;br /&gt;    FList: TList;&lt;br /&gt;    FBaseClass: TPersistentTreeClass;&lt;br /&gt;    FOwner, FParent: TPersistentTree;&lt;br /&gt;    FOwnStream: Boolean;&lt;br /&gt;    FDataFilename, FFilename: string;&lt;br /&gt;    FLastPosition, FDataBegin, FDataLength: Int64;&lt;br /&gt;&lt;br /&gt;    function GetItem(const Index: Integer): TPersistentTree;&lt;br /&gt;    function GetCount: Integer;&lt;br /&gt;    function GetStream: TStream;&lt;br /&gt;    function Import( Item: TPersistentTree ): Boolean;&lt;br /&gt;    procedure ClearData;&lt;br /&gt;    procedure RecreateStream( const Pos: Int64; const Deep: Boolean = False );&lt;br /&gt;    procedure Synchronize;&lt;br /&gt;&lt;br /&gt;  protected&lt;br /&gt;    //override to provide writing/reading notifications&lt;br /&gt;    procedure Loaded; virtual;&lt;br /&gt;    procedure Saving; virtual;&lt;br /&gt;&lt;br /&gt;    //derived from TStream&lt;br /&gt;    function GetSize: Int64; override;&lt;br /&gt;    procedure SetSize(NewSize: Longint); override;&lt;br /&gt;    procedure SetSize(const NewSize: Int64); override;&lt;br /&gt;&lt;br /&gt;  public&lt;br /&gt;    constructor Create; virtual;&lt;br /&gt;    destructor Destroy; override;&lt;br /&gt;&lt;br /&gt;    //derived from TStream&lt;br /&gt;    function Read( var Buffer; Count: Longint ): Longint; override;&lt;br /&gt;    function Write( const Buffer; Count: Longint ): Longint; override;&lt;br /&gt;    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;&lt;br /&gt;&lt;br /&gt;    function Truncate: Int64;&lt;br /&gt;    function ReadString: string;&lt;br /&gt;    procedure WriteString( const Data: string );&lt;br /&gt;&lt;br /&gt;    procedure Save( const AFilename: string ); overload;&lt;br /&gt;    procedure Save( Stream: TStream ); overload;&lt;br /&gt;    procedure Load( const AFilename: string ); overload;&lt;br /&gt;    procedure Load( Stream: IStream ); overload;&lt;br /&gt;    procedure Load( Stream: TStream ); overload;&lt;br /&gt;&lt;br /&gt;    function Add: TPersistentTree; overload;&lt;br /&gt;    function Add( Item: TPersistentTree ): Integer; overload;&lt;br /&gt;    procedure Insert( const Index: Integer; Item: TPersistentTree);&lt;br /&gt;    function IndexOf( Item: TPersistentTree ): Integer;&lt;br /&gt;    function Remove( Item: TPersistentTree ): Integer;&lt;br /&gt;    procedure Delete( const Index: Integer);&lt;br /&gt;    function Extract( Item: TPersistentTree ): TPersistentTree;&lt;br /&gt;    procedure Exchange( const IndexA, IndexB: Integer );&lt;br /&gt;    procedure Move(const CurIndex, NewIndex: Integer);&lt;br /&gt;    procedure Clear;&lt;br /&gt;&lt;br /&gt;    property Items[ const Index: Integer ]: TPersistentTree read GetItem; default;&lt;br /&gt;    property Count: Integer read GetCount;&lt;br /&gt;    property Owner: TPersistentTree read FOwner;&lt;br /&gt;    property Parent: TPersistentTree read FParent;&lt;br /&gt;    property Filename: string read FFilename;&lt;br /&gt;    property BaseClass: TPersistentTreeClass read FBaseClass write FBaseClass;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TPersistentTreeHeader = packed record&lt;br /&gt;    Sig: array[0..4] of Char;&lt;br /&gt;    Ver: Word;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;const&lt;br /&gt;  PERSISTENT_TREE_HEADER: TPersistentTreeHeader = ( Sig: 'PTREE'; Ver: 1 );&lt;br /&gt;&lt;br /&gt;function GetTempFile: string;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;function GetTempFile: string;&lt;br /&gt;var&lt;br /&gt;  Path: array[0..MAX_PATH-1] of Char;&lt;br /&gt;begin&lt;br /&gt;  GetTempPath( MAX_PATH, Path );&lt;br /&gt;  GetTempFileName( Path, 'BUF', 0, Path );&lt;br /&gt;  Result := Path;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TPersistentTree }&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Clear;&lt;br /&gt;var&lt;br /&gt;  I: Integer;&lt;br /&gt;begin&lt;br /&gt;  for I := FList.Count - 1 downto 0 do&lt;br /&gt;  begin&lt;br /&gt;    TPersistentTree( FList[I] ).Free;&lt;br /&gt;    FList.Delete( I );&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;constructor TPersistentTree.Create;&lt;br /&gt;begin&lt;br /&gt;  FBaseClass := TPersistentTreeClass( Self.ClassType );&lt;br /&gt;  FList := TList.Create;&lt;br /&gt;  FStream := TStreamAdapter.Create( GetStream );&lt;br /&gt;  FOwnStream := True;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;destructor TPersistentTree.Destroy;&lt;br /&gt;begin&lt;br /&gt;  ClearData;&lt;br /&gt;  FList.Free;&lt;br /&gt;  inherited;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Exchange(const IndexA, IndexB: Integer);&lt;br /&gt;begin&lt;br /&gt;  FList.Exchange( IndexA, IndexB );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.GetCount: Integer;&lt;br /&gt;begin&lt;br /&gt;  Result := FList.Count;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.GetItem(const Index: Integer): TPersistentTree;&lt;br /&gt;begin&lt;br /&gt;  Result := FList[ Index ];&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.IndexOf(&lt;br /&gt;  Item: TPersistentTree): Integer;&lt;br /&gt;begin&lt;br /&gt;  Result := FList.IndexOf( Item );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Load(const AFilename: string);&lt;br /&gt;var&lt;br /&gt;  FS: TFileStream;&lt;br /&gt;  //Header: TPersistentTreeHeader;&lt;br /&gt;begin&lt;br /&gt;  FS := TFileStream.Create( AFilename, fmOpenRead or fmShareDenyWrite );&lt;br /&gt;  try&lt;br /&gt;    //FS.Read( Header, SizeOf( TPersistentTreeHeader ) );&lt;br /&gt;    //if not CompareMem( @Header, @PERSISTENT_TREE_HEADER, SizeOf( TPersistentTreeHeader ) ) then&lt;br /&gt;    //  raise EPersistentTree.CreateFmt( '%s.LoadFromFile :: "%s" Not Recognized', [ClassName, AFilename] );&lt;br /&gt;    Load( FS );&lt;br /&gt;    FFilename := AFilename;&lt;br /&gt;  except&lt;br /&gt;    FS.Free;&lt;br /&gt;    raise;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Load(Stream: TStream);&lt;br /&gt;begin&lt;br /&gt;  Load( TStreamAdapter.Create( Stream ) );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Remove(Item: TPersistentTree): Integer;&lt;br /&gt;begin&lt;br /&gt;  Result := FList.Remove( Item );&lt;br /&gt;  if Result &gt;= 0 then&lt;br /&gt;    Item.Free;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Save( const AFilename: string );&lt;br /&gt;var&lt;br /&gt;  FS: TFileStream;&lt;br /&gt;begin&lt;br /&gt;  FS := TFileStream.Create( AFilename, fmCreate or fmShareDenyWrite );&lt;br /&gt;  try&lt;br /&gt;    //FS.Write( PERSISTENT_TREE_HEADER, SizeOf( TPersistentTreeHeader ) );&lt;br /&gt;    Save( FS );&lt;br /&gt;  finally&lt;br /&gt;    FS.Free;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Save(Stream: TStream);&lt;br /&gt;var&lt;br /&gt;  I: LongInt;&lt;br /&gt;begin&lt;br /&gt;  Seek( 0, soBeginning );&lt;br /&gt;  Saving;&lt;br /&gt;&lt;br /&gt;  FDataLength := Size;&lt;br /&gt;  Stream.Write( FDataLength, SizeOf( FDataLength ) );&lt;br /&gt;  Stream.CopyFrom( Self, 0 );&lt;br /&gt;&lt;br /&gt;  I := FList.Count;&lt;br /&gt;  Stream.Write( I, SizeOf( I ) );&lt;br /&gt;  for I := 0 to FList.Count-1 do&lt;br /&gt;    Self[I].Save( Stream );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Write( const Buffer; Count: Longint ): Longint;&lt;br /&gt;begin&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    Result := FStream.Write( Buffer, Count )&lt;br /&gt;  else&lt;br /&gt;  begin&lt;br /&gt;    Synchronize;&lt;br /&gt;    if Position + Count &gt; Size then&lt;br /&gt;      RecreateStream( Position );&lt;br /&gt;    Result := FStream.Write( Buffer, Count );&lt;br /&gt;    FLastPosition := FStream.Position;          &lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Read( var Buffer; Count: Longint): Longint;&lt;br /&gt;begin&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    Result := FStream.Read( Buffer, Count )&lt;br /&gt;  else&lt;br /&gt;  begin&lt;br /&gt;    Synchronize;&lt;br /&gt;    if Count &lt; 0 then&lt;br /&gt;      Count := 0&lt;br /&gt;    else if Count &gt; Size - Position then&lt;br /&gt;      Count := Size - Position;&lt;br /&gt;    Result := FStream.Read( Buffer, Count );&lt;br /&gt;    FLastPosition := FStream.Position;&lt;br /&gt;  end&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Seek(const Offset: Int64;&lt;br /&gt;  Origin: TSeekOrigin): Int64;&lt;br /&gt;begin&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    Result := FStream.Seek( Offset, Origin )&lt;br /&gt;  else&lt;br /&gt;  begin&lt;br /&gt;    Synchronize;&lt;br /&gt;    case Origin of&lt;br /&gt;      soBeginning: Result := FDataBegin + Offset;&lt;br /&gt;      soCurrent: Result := FStream.Position + Offset;&lt;br /&gt;      soEnd: Result := FDataBegin + Size - Offset;&lt;br /&gt;    else&lt;br /&gt;      Result := 0;&lt;br /&gt;    end;&lt;br /&gt;    if Result &gt; -1 then&lt;br /&gt;      if Result &lt;= FDataBegin + Size then&lt;br /&gt;        Result := FStream.Seek( Result, soBeginning ) - FDataBegin&lt;br /&gt;      else&lt;br /&gt;      begin&lt;br /&gt;        RecreateStream( Size );&lt;br /&gt;        Result := FStream.Seek( Result, soBeginning );&lt;br /&gt;      end;&lt;br /&gt;    FLastPosition := FStream.Position;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.SetSize(const NewSize: Int64);&lt;br /&gt;begin&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    FStream.Size := NewSize&lt;br /&gt;  else begin&lt;br /&gt;    if NewSize &lt;= 0 then&lt;br /&gt;      RecreateStream( 0 )&lt;br /&gt;    else if NewSize &gt; Size then&lt;br /&gt;      RecreateStream( Size )&lt;br /&gt;    else&lt;br /&gt;    begin&lt;br /&gt;      FDataLength := NewSize;&lt;br /&gt;      Seek( 0, soEnd );&lt;br /&gt;    end;&lt;br /&gt;    FLastPosition := FStream.Position;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Synchronize;&lt;br /&gt;begin&lt;br /&gt;  if not FOwnStream and ( ( FStream.Position &lt; FDataBegin ) or ( FStream.Position - FDataBegin &gt; FDataLength ) ) then&lt;br /&gt;    FStream.Seek( FLastPosition, soBeginning );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Load( Stream: IStream);&lt;br /&gt;var&lt;br /&gt;  I: LongInt;&lt;br /&gt;begin&lt;br /&gt;  ClearData;&lt;br /&gt;&lt;br /&gt;  FStream := Stream;&lt;br /&gt;  FOwnStream := False;&lt;br /&gt;&lt;br /&gt;  Stream.Read( FDataLength, SizeOf( FDataLength ) );&lt;br /&gt;  FDataBegin := FStream.Position;&lt;br /&gt;  FLastPosition := FDataBegin;&lt;br /&gt;&lt;br /&gt;  Stream.Seek( FDataLength, soCurrent );&lt;br /&gt;&lt;br /&gt;  Stream.Read( I, SizeOf( I ) );&lt;br /&gt;  for I := I - 1 downto 0 do&lt;br /&gt;    Add.Load( FStream );&lt;br /&gt;&lt;br /&gt;  //Seek( 0, soBeginning ); it isnt needed since synchonize will do it anyway&lt;br /&gt;  Loaded;&lt;br /&gt;  FStream.Seek( FDataBegin + FDataLength + SizeOf( I ), soBeginning );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Extract( Item: TPersistentTree): TPersistentTree;&lt;br /&gt;begin&lt;br /&gt;  Result := FList.Extract( Item );&lt;br /&gt;  if Assigned( Result ) then begin&lt;br /&gt;    Result.FParent := nil;&lt;br /&gt;    Result.FOwner := nil;&lt;br /&gt;    Result.RecreateStream( Size, True );&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.GetSize: Int64;&lt;br /&gt;begin&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    Result := FStream.Size&lt;br /&gt;  else&lt;br /&gt;    Result := FDataLength;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.WriteString(const Data: string);&lt;br /&gt;var&lt;br /&gt;  I: LongWord;&lt;br /&gt;begin&lt;br /&gt;  I := Length( Data );&lt;br /&gt;  Write( I, SizeOf( I ) );&lt;br /&gt;  Write( Pointer( Data )^, I );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.ReadString: string;&lt;br /&gt;var&lt;br /&gt;  I: LongWord;&lt;br /&gt;begin&lt;br /&gt;  Read( I, SizeOf( I ) );&lt;br /&gt;  SetLength( Result, I );&lt;br /&gt;  Read( Pointer( Result )^, I );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.SetSize(NewSize: Integer);&lt;br /&gt;begin&lt;br /&gt;  SetSize( Int64( NewSize ) );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.RecreateStream( const Pos: Int64; const Deep: Boolean );&lt;br /&gt;var&lt;br /&gt;  FS: TStream;&lt;br /&gt;  I: Integer;&lt;br /&gt;begin&lt;br /&gt;  if not FOwnStream then&lt;br /&gt;  begin&lt;br /&gt;    FS := GetStream;&lt;br /&gt;    if Pos &gt; 0 then&lt;br /&gt;    begin&lt;br /&gt;      Seek( 0, soBeginning );&lt;br /&gt;      FS.CopyFrom( Self, Pos );&lt;br /&gt;    end;&lt;br /&gt;    FStream := TStreamAdapter.Create( FS );&lt;br /&gt;    FOwnStream := True;&lt;br /&gt;  end;&lt;br /&gt;  if Deep then&lt;br /&gt;    for I := 0 to FList.Count - 1 do&lt;br /&gt;      Self[I].RecreateStream( Self[I].Size, True );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.ClearData;&lt;br /&gt;begin&lt;br /&gt;  FStream := nil;&lt;br /&gt;  if FOwnStream then&lt;br /&gt;    DeleteFile( FDataFilename );&lt;br /&gt;  Clear;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.GetStream: TStream;&lt;br /&gt;begin&lt;br /&gt;  FDataFilename := GetTempFile;&lt;br /&gt;  Result := TFileStream.Create( FDataFilename, fmCreate or fmShareDenyWrite );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Add: TPersistentTree;&lt;br /&gt;begin&lt;br /&gt;  Result := TPersistentTreeClass( FBaseClass ).Create;&lt;br /&gt;  Add( Result );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Add( Item: TPersistentTree): Integer;&lt;br /&gt;begin&lt;br /&gt;  if Import( Item ) then&lt;br /&gt;    Result := FList.Add( Item )&lt;br /&gt;  else&lt;br /&gt;    Result := FList.IndexOf( Item );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Delete(const Index: Integer);&lt;br /&gt;begin&lt;br /&gt;  TPersistentTree( FList[Index] ).Free;&lt;br /&gt;  FList.Delete( Index );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Insert(const Index: Integer; Item: TPersistentTree);&lt;br /&gt;begin&lt;br /&gt;  if Import( Item ) then&lt;br /&gt;    FList.Insert( Index, Item )&lt;br /&gt;  else&lt;br /&gt;    FList.Move( FList.IndexOf( Item ), Index );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Move(const CurIndex, NewIndex: Integer);&lt;br /&gt;begin&lt;br /&gt;  FList.Move( CurIndex, NewIndex );&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Truncate: Int64;&lt;br /&gt;begin&lt;br /&gt;  Result := Position;&lt;br /&gt;  Size := Result;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TPersistentTree.Import(Item: TPersistentTree): Boolean;&lt;br /&gt;begin&lt;br /&gt;  Result := not Assigned( Item.FParent ) or ( ( Item.FParent &lt;&gt; Self ) and Assigned( Item.FParent.Extract( Item ) ) );&lt;br /&gt;  if Result then&lt;br /&gt;  begin&lt;br /&gt;    Item.FParent := Self;&lt;br /&gt;    if FOwner &lt;&gt; nil then&lt;br /&gt;      Item.FOwner := FOwner&lt;br /&gt;    else&lt;br /&gt;      Item.FOwner := Self;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Saving;&lt;br /&gt;begin&lt;br /&gt;//override to provide extra save features&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TPersistentTree.Loaded;&lt;br /&gt;begin&lt;br /&gt;//override to provide extra load features&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Sat, 02 Jul 2005 03:50:02 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/436</guid>
      <author>jonasraoni (Jonas Raoni Soares Silva)</author>
    </item>
  </channel>
</rss>
