1/*
2 * node.c
3 *
4 * $Author: why $
5 * $Date: 2005-09-17 02:59:53 +0800 (六, 17  9 2005) $
6 *
7 * Copyright (C) 2003 why the lucky stiff
8 */
9
10#include "syck.h"
11
12/*
13 * Node allocation functions
14 */
15SyckNode *
16syck_alloc_node( enum syck_kind_tag type )
17{
18    SyckNode *s;
19
20    s = S_ALLOC( SyckNode );
21    s->kind = type;
22    s->id = 0;
23    s->type_id = NULL;
24    s->anchor = NULL;
25    s->shortcut = NULL;
26
27    return s;
28}
29
30void
31syck_free_node( SyckNode *n )
32{
33    syck_free_members( n );
34    if ( n->type_id != NULL )
35    {
36        S_FREE( n->type_id );
37        n->type_id = NULL;
38    }
39    if ( n->anchor != NULL )
40    {
41        S_FREE( n->anchor );
42        n->anchor = NULL;
43    }
44    S_FREE( n );
45}
46
47SyckNode *
48syck_alloc_map()
49{
50    SyckNode *n;
51    struct SyckMap *m;
52
53    m = S_ALLOC( struct SyckMap );
54    m->style = map_none;
55    m->idx = 0;
56    m->capa = ALLOC_CT;
57    m->keys = S_ALLOC_N( SYMID, m->capa );
58    m->values = S_ALLOC_N( SYMID, m->capa );
59
60    n = syck_alloc_node( syck_map_kind );
61    n->data.pairs = m;
62
63    return n;
64}
65
66SyckNode *
67syck_alloc_seq()
68{
69    SyckNode *n;
70    struct SyckSeq *s;
71
72    s = S_ALLOC( struct SyckSeq );
73    s->style = seq_none;
74    s->idx = 0;
75    s->capa = ALLOC_CT;
76    s->items = S_ALLOC_N( SYMID, s->capa );
77
78    n = syck_alloc_node( syck_seq_kind );
79    n->data.list = s;
80
81    return n;
82}
83
84SyckNode *
85syck_alloc_str()
86{
87    SyckNode *n;
88    struct SyckStr *s;
89
90    s = S_ALLOC( struct SyckStr );
91    s->len = 0;
92    s->ptr = NULL;
93    s->style = scalar_none;
94
95    n = syck_alloc_node( syck_str_kind );
96    n->data.str = s;
97
98    return n;
99}
100
101SyckNode *
102syck_new_str( const char *str, enum scalar_style style )
103{
104    return syck_new_str2( str, strlen( str ), style );
105}
106
107SyckNode *
108syck_new_str2( const char *str, long len, enum scalar_style style )
109{
110    SyckNode *n;
111
112    n = syck_alloc_str();
113    n->data.str->ptr = S_ALLOC_N( char, len + 1 );
114    n->data.str->len = len;
115    n->data.str->style = style;
116    memcpy( n->data.str->ptr, str, len );
117    n->data.str->ptr[len] = '\0';
118
119    return n;
120}
121
122void
123syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
124{
125    syck_replace_str2( n, str, strlen( str ), style );
126}
127
128void
129syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
130{
131    if ( n->data.str != NULL )
132    {
133        S_FREE( n->data.str->ptr );
134        n->data.str->ptr = NULL;
135        n->data.str->len = 0;
136    }
137    n->data.str->ptr = S_ALLOC_N( char, len + 1 );
138    n->data.str->len = len;
139    n->data.str->style = style;
140    memcpy( n->data.str->ptr, str, len );
141    n->data.str->ptr[len] = '\0';
142}
143
144void
145syck_str_blow_away_commas( SyckNode *n )
146{
147    char *go, *end;
148
149    go = n->data.str->ptr;
150    end = go + n->data.str->len;
151    while ( *(++go) != '\0' )
152    {
153        if ( *go == ',' )
154        {
155            n->data.str->len -= 1;
156            memmove( go, go + 1, end - go );
157            end -= 1;
158        }
159    }
160}
161
162char *
163syck_str_read( SyckNode *n )
164{
165    ASSERT( n != NULL );
166    return n->data.str->ptr;
167}
168
169SyckNode *
170syck_new_map( SYMID key, SYMID value )
171{
172    SyckNode *n;
173
174    n = syck_alloc_map();
175    syck_map_add( n, key, value );
176
177    return n;
178}
179
180void
181syck_map_empty( SyckNode *n )
182{
183    struct SyckMap *m;
184    ASSERT( n != NULL );
185    ASSERT( n->data.list != NULL );
186
187    S_FREE( n->data.pairs->keys );
188    S_FREE( n->data.pairs->values );
189    m = n->data.pairs;
190    m->idx = 0;
191    m->capa = ALLOC_CT;
192    m->keys = S_ALLOC_N( SYMID, m->capa );
193    m->values = S_ALLOC_N( SYMID, m->capa );
194}
195
196void
197syck_map_add( SyckNode *map, SYMID key, SYMID value )
198{
199    struct SyckMap *m;
200    long idx;
201
202    ASSERT( map != NULL );
203    ASSERT( map->data.pairs != NULL );
204
205    m = map->data.pairs;
206    idx = m->idx;
207    m->idx += 1;
208    if ( m->idx > m->capa )
209    {
210        m->capa += ALLOC_CT;
211        S_REALLOC_N( m->keys, SYMID, m->capa );
212        S_REALLOC_N( m->values, SYMID, m->capa );
213    }
214    m->keys[idx] = key;
215    m->values[idx] = value;
216}
217
218void
219syck_map_update( SyckNode *map1, SyckNode *map2 )
220{
221    struct SyckMap *m1, *m2;
222    long new_idx, new_capa;
223    ASSERT( map1 != NULL );
224    ASSERT( map2 != NULL );
225
226    m1 = map1->data.pairs;
227    m2 = map2->data.pairs;
228    if ( m2->idx < 1 ) return;
229
230    new_idx = m1->idx;
231    new_idx += m2->idx;
232    new_capa = m1->capa;
233    while ( new_idx > new_capa )
234    {
235        new_capa += ALLOC_CT;
236    }
237    if ( new_capa > m1->capa )
238    {
239        m1->capa = new_capa;
240        S_REALLOC_N( m1->keys, SYMID, m1->capa );
241        S_REALLOC_N( m1->values, SYMID, m1->capa );
242    }
243    for ( new_idx = 0; new_idx < m2->idx; m1->idx++, new_idx++ )
244    {
245        m1->keys[m1->idx] = m2->keys[new_idx];
246        m1->values[m1->idx] = m2->values[new_idx];
247    }
248}
249
250long
251syck_map_count( SyckNode *map )
252{
253    ASSERT( map != NULL );
254    ASSERT( map->data.pairs != NULL );
255    return map->data.pairs->idx;
256}
257
258void
259syck_map_assign( SyckNode *map, enum map_part p, long idx, SYMID id )
260{
261    struct SyckMap *m;
262
263    ASSERT( map != NULL );
264    m = map->data.pairs;
265    ASSERT( m != NULL );
266    if ( p == map_key )
267    {
268        m->keys[idx] = id;
269    }
270    else
271    {
272        m->values[idx] = id;
273    }
274}
275
276SYMID
277syck_map_read( SyckNode *map, enum map_part p, long idx )
278{
279    struct SyckMap *m;
280
281    ASSERT( map != NULL );
282    m = map->data.pairs;
283    ASSERT( m != NULL );
284    if ( p == map_key )
285    {
286        return m->keys[idx];
287    }
288    else
289    {
290        return m->values[idx];
291    }
292}
293
294SyckNode *
295syck_new_seq( SYMID value )
296{
297    SyckNode *n;
298
299    n = syck_alloc_seq();
300    syck_seq_add( n, value );
301
302    return n;
303}
304
305void
306syck_seq_empty( SyckNode *n )
307{
308    struct SyckSeq *s;
309    ASSERT( n != NULL );
310    ASSERT( n->data.list != NULL );
311
312    S_FREE( n->data.list->items );
313    s = n->data.list;
314    s->idx = 0;
315    s->capa = ALLOC_CT;
316    s->items = S_ALLOC_N( SYMID, s->capa );
317}
318
319void
320syck_seq_add( SyckNode *arr, SYMID value )
321{
322    struct SyckSeq *s;
323    long idx;
324
325    ASSERT( arr != NULL );
326    ASSERT( arr->data.list != NULL );
327
328    s = arr->data.list;
329    idx = s->idx;
330    s->idx += 1;
331    if ( s->idx > s->capa )
332    {
333        s->capa += ALLOC_CT;
334        S_REALLOC_N( s->items, SYMID, s->capa );
335    }
336    s->items[idx] = value;
337}
338
339long
340syck_seq_count( SyckNode *seq )
341{
342    ASSERT( seq != NULL );
343    ASSERT( seq->data.list != NULL );
344    return seq->data.list->idx;
345}
346
347void
348syck_seq_assign( SyckNode *seq, long idx, SYMID id )
349{
350    struct SyckSeq *s;
351
352    ASSERT( map != NULL );
353    s = seq->data.list;
354    ASSERT( m != NULL );
355    s->items[idx] = id;
356}
357
358SYMID
359syck_seq_read( SyckNode *seq, long idx )
360{
361    struct SyckSeq *s;
362
363    ASSERT( seq != NULL );
364    s = seq->data.list;
365    ASSERT( s != NULL );
366    return s->items[idx];
367}
368
369void
370syck_free_members( SyckNode *n )
371{
372    if ( n == NULL ) return;
373
374    switch ( n->kind  )
375    {
376        case syck_str_kind:
377            if ( n->data.str != NULL )
378            {
379                S_FREE( n->data.str->ptr );
380                n->data.str->ptr = NULL;
381                n->data.str->len = 0;
382                S_FREE( n->data.str );
383                n->data.str = NULL;
384            }
385        break;
386
387        case syck_seq_kind:
388            if ( n->data.list != NULL )
389            {
390                S_FREE( n->data.list->items );
391                S_FREE( n->data.list );
392                n->data.list = NULL;
393            }
394        break;
395
396        case syck_map_kind:
397            if ( n->data.pairs != NULL )
398            {
399                S_FREE( n->data.pairs->keys );
400                S_FREE( n->data.pairs->values );
401                S_FREE( n->data.pairs );
402                n->data.pairs = NULL;
403            }
404        break;
405    }
406}
407
408