#include "rbxs_dom.h" #include "rbxs_domnode.h" #include "rbxs_domnodeset.h" #include "rbxs_domattribute.h" //*********************************************************************************** // GC //*********************************************************************************** void rbxs_domnodeset_free(rbxs_domnodeset *prbxs_domnodeset) { if (prbxs_domnodeset != NULL) { xmlXPathFreeObject(prbxs_domnodeset->obj); prbxs_domnodeset->obj = NULL; prbxs_domnodeset->nodeset = NULL; free(prbxs_domnodeset); } } void rbxs_domnodeset_mark(rbxs_domnodeset *prbxs_domnodeset) { if (prbxs_domnodeset == NULL) return; if (!NIL_P(prbxs_domnodeset->doc)) rb_gc_mark(prbxs_domnodeset->doc); } //*********************************************************************************** // Methods //*********************************************************************************** VALUE createFromType(rbxs_domnodeset *prbxs_domnodeset, long num) { switch(prbxs_domnodeset->nodeset->nodeTab[num]->type) { case XML_ATTRIBUTE_NODE: return rbxs_domattribute_new(cSimpleDomAttribute, prbxs_domnodeset->doc, (xmlAttrPtr)prbxs_domnodeset->nodeset->nodeTab[num]); default: return rbxs_domnode_new(cSimpleDomNode, prbxs_domnodeset->doc, prbxs_domnodeset->nodeset->nodeTab[num]); } } VALUE rbxs_domnodeset_length(VALUE self) { rbxs_domnodeset *prbxs_domnodeset; Data_Get_Struct(self, rbxs_domnodeset, prbxs_domnodeset); if ((xmlXPathNodeSetIsEmpty(prbxs_domnodeset->nodeset)) || (prbxs_domnodeset->deleted == 1)) return(INT2NUM(0)); else return(INT2NUM(prbxs_domnodeset->nodeset->nodeNr)); } VALUE rbxs_domnodeset_empty(VALUE self) { rbxs_domnodeset *prbxs_domnodeset; Data_Get_Struct(self, rbxs_domnodeset, prbxs_domnodeset); if ((xmlXPathNodeSetIsEmpty(prbxs_domnodeset->nodeset)) || (prbxs_domnodeset->deleted == 1)) return(Qtrue); else return(Qfalse); } VALUE rbxs_domnodeset_get(VALUE self, VALUE num) { rbxs_domnodeset *prbxs_domnodeset; Check_Type(num, T_FIXNUM); Data_Get_Struct(self, rbxs_domnodeset, prbxs_domnodeset); if ((xmlXPathNodeSetIsEmpty(prbxs_domnodeset->nodeset)) || (prbxs_domnodeset->deleted == 1)) return(Qnil); if (NUM2INT(num) > -1) { if (prbxs_domnodeset->nodeset->nodeNr > NUM2INT(num)) return createFromType(prbxs_domnodeset,NUM2INT(num)); } else { if (prbxs_domnodeset->nodeset->nodeNr + NUM2INT(num) > -1) return createFromType(prbxs_domnodeset,prbxs_domnodeset->nodeset->nodeNr + NUM2INT(num)); } return(Qnil); } VALUE rbxs_domnodeset_first(VALUE self) { return rbxs_domnodeset_get(self,INT2NUM(0)); } VALUE rbxs_domnodeset_last(VALUE self) { return rbxs_domnodeset_get(self,INT2NUM(-1)); } VALUE rbxs_domnodeset_clear(VALUE self) { rbxs_domnodeset *prbxs_domnodeset; int i; Data_Get_Struct(self, rbxs_domnodeset, prbxs_domnodeset); if ((xmlXPathNodeSetIsEmpty(prbxs_domnodeset->nodeset)) || (prbxs_domnodeset->deleted == 1)) return(Qtrue); for (i = 0; i < prbxs_domnodeset->nodeset->nodeNr; i++) { xmlUnlinkNode(prbxs_domnodeset->nodeset->nodeTab[i]); xmlFreeNode (prbxs_domnodeset->nodeset->nodeTab[i]); } prbxs_domnodeset->deleted = 1; return(Qtrue); } VALUE rbxs_domnodeset_each(VALUE self) { rbxs_domnodeset *prbxs_domnodeset; VALUE obj; int i; Data_Get_Struct(self, rbxs_domnodeset, prbxs_domnodeset); if ((xmlXPathNodeSetIsEmpty(prbxs_domnodeset->nodeset)) || (prbxs_domnodeset->deleted == 1)) return(Qnil); for (i = 0; i < prbxs_domnodeset->nodeset->nodeNr; i++) { obj = createFromType(prbxs_domnodeset,i); rb_yield(obj); } return(self); } //*********************************************************************************** // Constructors //*********************************************************************************** VALUE rbxs_domnodeset_new(VALUE class, VALUE doc, xmlXPathObjectPtr obj) { rbxs_domnodeset *prbxs_domnodeset; prbxs_domnodeset = (rbxs_domnodeset *)malloc(sizeof(rbxs_domnodeset)); if (prbxs_domnodeset == NULL ) rb_raise(rb_eNoMemError, "No memory left for XML::Simple::NodeSet struct"); prbxs_domnodeset->doc = doc; prbxs_domnodeset->obj = obj; prbxs_domnodeset->nodeset = obj->nodesetval; prbxs_domnodeset->deleted = 0; return(Data_Wrap_Struct(class, rbxs_domnodeset_mark, rbxs_domnodeset_free, prbxs_domnodeset)); } //*********************************************************************************** // Initialize class Node //*********************************************************************************** VALUE cSimpleDomNodeSet; void init_rbxs_domnodeset(void) { cSimpleDomNodeSet = rb_define_class_under( cSimpleDom, "NodeSet", rb_cObject ); rb_define_method(cSimpleDomNodeSet, "length", rbxs_domnodeset_length, 0); rb_define_method(cSimpleDomNodeSet, "empty?", rbxs_domnodeset_empty, 0); rb_define_method(cSimpleDomNodeSet, "[]", rbxs_domnodeset_get, 1); rb_define_method(cSimpleDomNodeSet, "at", rbxs_domnodeset_get, 1); rb_define_method(cSimpleDomNodeSet, "first", rbxs_domnodeset_first, 0); rb_define_method(cSimpleDomNodeSet, "last", rbxs_domnodeset_last, 0); rb_define_method(cSimpleDomNodeSet, "clear", rbxs_domnodeset_clear, 0); rb_define_method(cSimpleDomNodeSet, "each", rbxs_domnodeset_each, 0); }