root/ext/fastxml_nodelist.c

Revision 3743ad075234ad77e4d34c81771003bd38d4a24e, 4.9 KB (checked in by Mark Guzman <segfault@…>, 6 months ago)

adding some more initial documentation
specified that copyright is defined in the LICENSE file

  • Property mode set to 100644
Line 
1/*
2 * Document-class: FastXml::NodeList
3 *
4 * call-seq:
5 *  doc = FastXml( docfile ) # from FastXml::Doc
6 *  list = doc.root.children # pull the FastXml::NodeList comprised of the Element's children
7 *  puts "The document root element has %d children." % list.length
8 *  list.each { |e| puts e.name } # iterate over each element and print it's name
9 *  puts list[3]                  # print the 4th element in the list
10 */
11// Please see the LICENSE file for copyright, licensing and distribution information
12
13#include "fastxml.h"
14#include "fastxml_node.h"
15#include "fastxml_doc.h"
16#include "fastxml_nodelist.h"
17
18/* {{{ fastxml_nodelist
19 */
20void Init_fastxml_nodelist()
21{
22        #ifdef RDOC_SHOULD_BE_SMARTER__THIS_IS_NEVER_RUN
23    rb_mFastXml = rb_define_module( "FastXml" );
24        #endif
25    rb_cFastXmlNodeList = rb_define_class_under( rb_mFastXml, "NodeList", rb_cObject );
26       
27    rb_include_module( rb_cFastXmlNodeList, rb_mEnumerable );   
28    rb_define_method( rb_cFastXmlNodeList, "initialize", fastxml_nodelist_initialize, 0 );
29    rb_define_method( rb_cFastXmlNodeList, "length", fastxml_nodelist_length, 0 );
30    rb_define_method( rb_cFastXmlNodeList, "each", fastxml_nodelist_each, 0 );
31    rb_define_method( rb_cFastXmlNodeList, "entry", fastxml_nodelist_entry, 1 );
32        rb_define_method( rb_cFastXmlNodeList, "to_ary", fastxml_nodelist_entry, 0 );
33}
34
35VALUE fastxml_nodelist_inspect(VALUE self)
36{
37    VALUE dv;
38    VALUE *argv;
39    fxml_data_t *data;
40
41    dv = rb_iv_get( self, "@lxml_doc" );   
42    Data_Get_Struct( dv, fxml_data_t, data );
43
44    argv = ALLOCA_N( VALUE, 4 );
45    argv[0] = rb_str_new2( "#<%s:0x%x %d>" );
46    argv[1] = CLASS_OF( self );
47    argv[2] = rb_obj_id( self );
48    argv[3] = fastxml_nodelist_length( self );
49    return rb_f_sprintf( 4, argv );
50}
51
52VALUE fastxml_nodelist_initialize(VALUE self)
53{
54    return self;
55}
56
57/* Return the length of the FastXml::NodeList
58 *
59 * call-seq:
60 *   puts doc.children.length
61 */
62VALUE fastxml_nodelist_length(VALUE self)
63{
64    VALUE dv;
65    xmlNodePtr cur;
66    fxml_data_t *data;
67
68    dv = rb_iv_get( self, "@lxml_doc" );   
69    Data_Get_Struct( dv, fxml_data_t, data );
70       
71        if (data->list_len == EMPTY_NODELIST) {             
72                data->list_len = 0;
73               
74        cur = data->list;
75                while (cur != NULL) {
76                        data->list_len++;
77                        cur = cur->next;
78                }
79        }
80       
81        return rb_int2inum( data->list_len );
82}
83
84VALUE fastxml_nodelist_obj_to_ary(fxml_data_t *root)
85{
86        VALUE ret;
87    xmlNodePtr cur = root->list;       
88       
89        ret = rb_ary_new();
90    while (cur != NULL) {       
91        rb_ary_push( ret, fastxml_raw_node_to_obj( cur ) );
92                cur = cur->next;
93        }       
94       
95        return ret;
96}
97
98VALUE fastxml_nodeset_obj_to_ary(fxml_data_t *root)
99{
100        VALUE ret;
101        xmlNodePtr cur, sub = NULL;
102        int i;
103
104        ret = rb_ary_new();
105    if (root->xpath_obj->nodesetval->nodeTab != NULL) {
106        cur = *root->xpath_obj->nodesetval->nodeTab;   
107        for (i = 0; i < root->list_len; i++) {
108            if (cur->type != XML_ELEMENT_NODE)
109                continue;
110           
111            rb_ary_push( ret, fastxml_raw_node_to_obj( cur ) );
112            sub = cur->next;
113            while (sub != NULL) {
114                rb_ary_push( ret, fastxml_raw_node_to_obj( sub ) );
115                sub = sub->next;
116            }
117                    cur++;
118        }
119    }
120   
121       
122        return ret;
123}
124
125VALUE fastxml_nodelist_gen_list(VALUE self, fxml_data_t *data)
126{
127        VALUE lst = rb_iv_get( self, "@list" );
128
129        if (lst == Qnil) {
130        if (data->xpath_obj != NULL) {
131                        lst = fastxml_nodeset_obj_to_ary( data );
132                        rb_iv_set( self, "@list", lst );
133                } else {
134                        lst = fastxml_nodelist_obj_to_ary( data );
135                        rb_iv_set( self, "@list", lst );
136                }
137        }
138
139        return lst;
140}
141
142VALUE fastxml_nodelist_to_ary(VALUE self)
143{
144        VALUE dv;
145        fxml_data_t *data;
146       
147        dv = rb_iv_get( self, "@lxml_doc" );
148        Data_Get_Struct( dv, fxml_data_t, data );       
149        return fastxml_nodelist_gen_list( self, data );         
150}
151
152/* Iterate over the list yielding each FastXml::Node contained
153 *
154 * call-seq:
155 *   puts doc.children.each { |e| puts e.name }
156 */
157VALUE fastxml_nodelist_each(VALUE self)
158{
159        VALUE lst, dv;
160        fxml_data_t *data;
161        int i;
162       
163        dv = rb_iv_get( self, "@lxml_doc" );
164        Data_Get_Struct( dv, fxml_data_t, data );       
165        lst = fastxml_nodelist_gen_list( self, data );
166       
167        for (i=0; i<RARRAY(lst)->len; i++) {
168                rb_yield( RARRAY(lst)->ptr[i] );
169    }
170       
171        return self;
172}
173
174/* Returns the element (FastXml::Node) from the FastXml::NodeList at idx
175 * position. 0-based indexing. Ranges are not supported as of yet
176 * (Patches welcome).
177 *
178 * call-seq:
179 *   puts doc.children[0]  #
180 *   puts doc.children[-1] # last element in the list
181 */
182VALUE fastxml_nodelist_entry(VALUE self, long idx)
183{
184        VALUE lst, dv;
185        fxml_data_t *data;
186       
187        dv = rb_iv_get( self, "@lxml_doc" );
188        Data_Get_Struct( dv, fxml_data_t, data );       
189        lst = fastxml_nodelist_gen_list( self, data );
190        if (idx > 0) // this comes in offset by 1
191                idx = idx-1;
192        // TODO: find out why this is provided offset by 1 and not 0-based
193
194        return rb_ary_entry( lst, idx );
195}
196
197/* }}} fastxml_nodelist
198 */
Note: See TracBrowser for help on using the browser.