Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

dt_stream_tree.c

Go to the documentation of this file.
00001 
00004 #include "dt_stream_tree.h"
00005 #include "dt_stream_base.h"
00006 
00007 #include "dt_node_impl.h"
00008 
00009 #include <malloc.h>
00010 #include <ctype.h>
00011 #include <assert.h>
00012 
00013 
00014 dt_bool dt_stream_subtree( dt_stream_step* step, dt_node const* src, dt_writer* dst )
00015 {
00016    assert( dt_node_is_valid(src) );
00017    switch( src->kind )
00018    {
00019    default:
00020          return 0;
00021    case dt_leaf_node: {
00022          step->kind    = dt_leaf;
00023          step->val     = src->buf.begin;
00024          step->val_len = src->buf.strEnd - step->val;
00025          return dt_write( dst, step );
00026      }
00027    case dt_arr_node: {
00028          arr_item *scan, *end;
00029          step->kind    = dt_arr_in;
00030          step->val     = 00;
00031          step->val_len = 0;
00032          if( ! dt_write( dst, step ) ) return 0;
00033          
00034          assert( (src->buf.strEnd - src->buf.begin)%sizeof(arr_item) == 0 );
00035          scan = (arr_item*)src->buf.begin;
00036          end  = (arr_item*)src->buf.strEnd;
00037          step->key     = 00;
00038          step->key_len = 0;
00039          for(  ; scan != end ; ++scan )
00040             if( ! dt_stream_subtree( step, *scan, dst ) ) return 0;
00041          step->kind    = dt_arr_out;
00042          step->key     = 00;
00043          step->key_len = 0;
00044          step->val     = 00;
00045          step->val_len = 0;
00046          return dt_write( dst, step );
00047       }
00048    case dt_rec_node: {
00049          rec_item *scan, *end;
00050          step->kind    = dt_rec_in;
00051          step->val     = 00;
00052          step->val_len = 0;
00053          if( ! dt_write( dst, step ) ) return 0;
00054          
00055          assert( (src->buf.strEnd - src->buf.begin)%sizeof(rec_item) == 0 );
00056          scan = (rec_item*)src->buf.begin;
00057          end  = (rec_item*)src->buf.strEnd;
00058          for(  ; scan != end ; ++scan )
00059          {
00060             step->key     = scan->key;
00061             step->key_len = scan->key_len;
00062             if( ! dt_stream_subtree( step, scan->node, dst ) ) return 0;
00063          }         
00064          step->kind    = dt_rec_out;
00065          step->key     = 00;
00066          step->key_len = 0;
00067          step->val     = 00;
00068          step->val_len = 0;
00069          return dt_write( dst, step );
00070       }
00071    }
00072 }
00073 
00074 
00075 dt_bool dt_stream_tree( dt_node const* src, dt_writer* dst )
00076 {
00077    dt_stream_step step;
00078    step.key     = 00;
00079    step.key_len = 0;
00080    if( ! dt_stream_subtree( &step, src, dst ) ) return 0;
00081 
00082    step.kind    = dt_end;
00083    step.key     = 00;
00084    step.key_len = 0;
00085    step.val     = 00;
00086    step.val_len = 0;
00087    return dt_write( dst, &step );
00088 }
00089 
00090 
00092 typedef struct
00093 {
00094    dt_writer  base;  
00095    dt_node**  root;  
00096    dt_buf     stack; 
00097 } dt_writer_tree;
00098 
00100 static void    dt_writer_tree_free( dt_writer* obj );
00102 static dt_bool dt_writer_tree_write( dt_writer* obj, dt_stream_step const* step );
00103 
00104 dt_writer* dt_create_tree_writer( dt_node** root )
00105 {
00106    dt_writer_tree* ans = (dt_writer_tree*)malloc(sizeof(dt_writer_tree));
00107 
00108    assert( *root == 00 ); /* as caller will later have to assume that node is valid & to be destroyed */
00109 
00110    if( ans )
00111    {
00112       dt_init_writer_base( & ans->base, & dt_writer_tree_free, & dt_writer_tree_write );
00113       ans->root = root;
00114       if( dt_buf_init( & ans->stack ) )
00115          return & ans->base;
00116       free( ans );
00117    }
00118    return 00;
00119 }
00120 
00121 static void dt_writer_tree_free( dt_writer* obj )
00122 {
00123    dt_writer_tree* o = (dt_writer_tree*)obj;
00124    dt_buf_free( & o->stack );
00125    free( o );
00126 }
00127 
00128 static dt_bool dt_writer_tree_write( dt_writer* obj, dt_stream_step const* step )
00129 {
00130    dt_writer_tree* o = (dt_writer_tree*)obj;
00131    dt_node* node;
00132 
00133    switch( step->kind )
00134    {
00135    default:          return 0;
00136 
00137    case dt_leaf:     node = dt_make_leaf( step->val, step->val_len );
00138                      break;
00139 
00140    case dt_rec_in:   node = dt_make_rec();
00141                      break;
00142 
00143    case dt_arr_in:   node = dt_make_arr();
00144                      break;
00145 
00146    case dt_rec_out:
00147    case dt_arr_out:  if( o->stack.strEnd - o->stack.begin < sizeof(dt_node*) )
00148                         return 0;
00149                      o->stack.strEnd -= sizeof(dt_node*);
00150                      return 1;
00151 
00152    case dt_end:      return 1;
00153    }
00154 
00155    if( !! o->root ) /* first node is to be stored in root specified by caller */
00156    {
00157       *o->root = node; /* ownership of root node is now passed into caller-provided storate */
00158       o->root = 00;
00159    }
00160    else { /* node is to be stored within its parent */
00161       dt_node* parent;
00162 
00163       if( o->stack.strEnd - o->stack.begin < sizeof(dt_node*) )
00164          return 0;
00165 
00166       parent = ((dt_node**)o->stack.strEnd)[-1];
00167  
00168       if( !! step->key ) /* identifies whether we are in a record */
00169       {
00171          if( ! dt_rec_put( parent, step->key, step->key_len, node ) ) return 0;
00172       }
00173       else
00174          { if( ! dt_arr_append( parent, node ) ) return 0; }
00175       /* ownership of node has now been passed to parent, or it was released by failed call. */
00176    }
00177 
00178    return   ( step->kind == dt_leaf )
00179          || dt_buf_append_data( & o->stack, & node, sizeof(node) );
00180 }
00181 

Generated on Sun Jun 1 16:35:38 2003 for datatree by doxygen 1.3.1