/** * Try to add r as a child to n, already in the tree * @param n the tree-node * @param r the new r-node */ static void dom_make_child( dom *d, node *n, node *r ) { if ( node_has_children(n) ) dom_add_node(d,node_first_child(n),r ); else node_add_child( n, r ); }
plist_t plist_dict_get_item(plist_t node, const char* key) { plist_t ret = NULL; if (node && PLIST_DICT == plist_get_node_type(node)) { plist_t current = NULL; for (current = (plist_t)node_first_child(node); current; current = (plist_t)node_next_sibling(node_next_sibling(current))) { plist_data_t data = plist_get_data(current); assert( PLIST_KEY == plist_get_node_type(current) ); if (data && !strcmp(key, data->strval)) { ret = (plist_t)node_next_sibling(current); break; } } } return ret; }
/** * Dispose of the whole tree recursively. node_dispose just kills one node * @param n the node to start from */ static void dom_dispose_node( node *n ) { node *next = node_next_sibling( n ); node *child = node_first_child( n ); node_dispose( n ); if ( next != NULL ) dom_dispose_node( next ); if ( child != NULL ) dom_dispose_node( child ); }
node_t* node_copy_deep(node_t* node, copy_func_t copy_func) { if (!node) return NULL; void *data = NULL; if (copy_func) { data = copy_func(node->data); } node_t* copy = node_create(NULL, data); node_t* ch; for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { node_t* cc = node_copy_deep(ch, copy_func); node_attach(copy, cc); } return copy; }
node_t* node_nth_child(struct node_t* node, unsigned int n) { if (!node || !node->children || !node->children->begin) return NULL; unsigned int node_index = 0; int found = 0; node_t *ch; for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { if (node_index++ == n) { found = 1; break; } } if (!found) { return NULL; } return ch; }
int node_child_position(struct node_t* parent, node_t* child) { if (!parent || !parent->children || !parent->children->begin || !child) return -1; int node_index = 0; int found = 0; node_t *ch; for (ch = node_first_child(parent); ch; ch = node_next_sibling(ch)) { if (ch == child) { found = 1; break; } node_index++; } if (!found) { return -1; } return node_index; }
/** * Check a single tree-node, recursively */ static int dom_check_node( node *n ) { int res = 1; int start = node_offset(n); int end = node_end(n); node *c = node_first_child(n); node *prev = NULL; while ( c != NULL ) { node *next = node_next_sibling( c ); if ( node_offset(c)<start ) { warning("dom: invalid offset %d < parent start %d\n",node_offset(c), start); return 0; } else if ( node_end(c)>end ) { warning("dom: invalid end %d (%s) > parent end %d (%s)\n", node_end(c), node_name(c), end, node_name(n) ); return 0; } else if ( prev != NULL && node_end(prev)>node_offset(c) ) { warning("dom: prev node ending %d encroaches on child node at %d\n", node_end(prev), node_offset(c)); return 0; } else if ( next != NULL && node_end(c)>node_offset(next) ) { warning("dom: next node starting %d encroaches on child node ending at %d\n", node_offset(next), node_end(c)); return 0; } else res = dom_check_node( c ); prev = c; c = node_next_sibling( c ); } return res; }
/** * If a range is inside a node's child call dom_range_inside_node again * @param dom the dom object * @param n the node already in the tree and possibly with child * @param r the range inside n but also maybe inside n's child * @return 1 if this was the case */ int dom_range_inside_node_child( dom *d, node *n, node *r ) { node *child = node_first_child(n); while ( child != NULL ) { if ( node_encloses_range(child,r) ) { dom_range_inside_node(d,child,r); return 1; } else if ( range_equals_node(child,r) && !dom_nests(d,node_name(r),node_name(n)) && dom_nests(d,node_name(r),node_name(child)) ) { dom_range_inside_node(d,child,r); return 1; } child = node_next_sibling(child); } return 0; }
/** * Print a single node and its children, siblings * @param d the dom in question * @param n the node to print */ static void dom_print_node( dom *d, node *n ) { node *c; int start,end; char *html_name = node_html_name(n); char *class_name = node_name(n); char attrs[128]; node_get_attributes( n, attrs, 128 ); if ( !node_empty(n) ) { if ( !node_is_root(n) ) dom_concat( d, "<%s%s class=\"%s\">", strlen(html_name) +strlen(class_name)+strlen(attrs)+11, html_name, attrs, class_name ); } c = node_first_child(n); start = node_offset(n); end = node_end(n); while ( c != NULL ) { int pos = node_offset( c ); if ( pos > start ) dom_print_text( d, start, pos-start ); dom_print_node( d, c ); start = node_end( c ); c = node_next_sibling( c ); } if ( end > start ) dom_print_text( d, start, end-start ); if ( !node_is_root(n) ) { if ( !node_empty(n) ) dom_concat(d, "</%s>",strlen(html_name)+3, html_name); else if ( node_rightmost(n) ) dom_concat(d,"<%s>",strlen(html_name)+2,html_name); } }