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 );
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 )
00156 {
00157 *o->root = node;
00158 o->root = 00;
00159 }
00160 else {
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 )
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
00176 }
00177
00178 return ( step->kind == dt_leaf )
00179 || dt_buf_append_data( & o->stack, & node, sizeof(node) );
00180 }
00181