📄 array2tree.c
字号:
/*** HTML::Tree** array2tree.c**** Copyright (C) 2001 Paul J. Lucas**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "HTML_Tree.h"// standard#include <cstring>// local#include "util.h" /* must go first */#include "blessed.h"#include "container4perl.h"#include "string4perl.h"#ifndef PJL_NO_NAMESPACESusing namespace HTML_Tree;using namespace std;#endif//*****************************************************************************//// SYNOPSIS// void array2tree( SV *array_ref, Content_Node *parent )//// DESCRIPTION//// Given a reference to a Perl array-of-hashes data structure, build the// internal C++ tree representation and attach it to the given node as the// parent.//// PARAMETERS//// array_ref A reference to an array.//// parent A pointer to a node to use as the parent.////*****************************************************************************{ dTHX; if ( !is_array_ref( array_ref ) ) croak( "Bad data: array reference expected" ); AV *const av = (AV*)SvRV( array_ref ); STRLEN len; for ( int i = 0; i <= av_len( av ); ++i ) { register SV **sv_ptr = av_fetch( av, i, 0 ); if ( !sv_ptr ) continue; register SV *const sv = *sv_ptr; if ( !SvROK( sv ) ) { // // The SV is not a reference so we interpret it as a // string and make either a Comment_Node or Text_Node // for it. // char const *const s = SvPV( sv, len ); if ( !::strcmp( s, "<!--" ) ) new Comment_Node( s, s + len, parent ); else new Text_Node( s, s + len, parent ); continue; } // // If the SV is a reference, it must be a reference to a hash. // if ( SvTYPE( SvRV( sv ) ) != SVt_PVHV ) croak( "Bad data: hash reference expected" ); register HV *hv = (HV*)SvRV( sv ); // // Get the node's name. // if ( !hv_exists( hv, "name", 4 ) || !(sv_ptr = hv_fetch( hv, "name", 4, 0 )) ) croak( "Bad data: name key expected in hash for node" ); char const *const name = SvPV( *sv_ptr, len ); // // Look up the element. // static element_map const &elements = element_map::instance(); element_map::const_iterator const e = elements.find( name ); if ( e == elements.end() ) croak( "Bad data: \"%s\": illegal HTML element", name ); // // If the node has a content attribute, then call ourselves // recursively. // Element_Node *new_node; if ( hv_exists( hv, "content", 7 ) ) { if ( e->second.end_tag == element::forbidden ) croak( "Bad data: \"%s\": content illegal", name ); if ( sv_ptr = hv_fetch( hv, "content", 7, 0 ) ) { new_node = new Content_Node( e->first, e->second, parent ); if ( *sv_ptr ) array2tree( *sv_ptr, dynamic_cast< Content_Node* >( new_node ) ); } } else new_node = new Element_Node( e->first, e->second, parent ); // // See if the node has an "atts" key for attributes. // if ( !hv_exists( hv, "atts", 4 ) || !(sv_ptr = hv_fetch( hv, "atts", 4, 0 )) ) continue; // // The node has an "atts" key, but ensure it's a reference to // a hash for attributes. // if ( !is_hash_ref( *sv_ptr ) ) croak( "Bad data: atts expected to be hash reference" ); // // The node does indeed have attributes: iterate through them // and add them to the C++ node. // hv = (HV*)SvRV( *sv_ptr ); hv_iterinit( hv ); char *key; SV *value; I32 len32; Element_Node::attribute_map &atts = new_node->attributes; while ( value = hv_iternextsv( hv, &key, &len32 ) ) atts[ key ] = SvPV( value, len ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -