mFAST fast_type_gen流程详解
来源:互联网 发布:公司数据库 编辑:程序博客网 时间:2024/06/17 22:20
先打开xml模板文件并将文件内容读入一个名为xml的string:
std::ifstream ifs(argv[i]);
std::string xml((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
获取不带扩展名的文件名filebase,以后作为namespace名:
path f(path(argv[i]).stem()); //boost 功能,只取文件名,不带路径和扩展名 std::string filebase = f.string();
根据xml的内容生成一个名为des的dynamic_templates_description对象:
mfast::dynamic_templates_description desc(xml.c_str(), filebase.c_str(), ®istry);
dynamic_templates_description的构造函数如下,调用tinyxml2,创建一个XMLDoucument类的对象document用以解析xml内容。
dynamic_templates_description::dynamic_templates_description(const char* xml_content, const char* cpp_ns, template_registry* registry) { XMLDocument document; if (document.Parse(xml_content) == 0) { xml_parser::templates_builder builder(this, cpp_ns, registry); document.Accept(&builder); } else { BOOST_THROW_EXCEPTION(std::runtime_error("XML parse error")); } }
解析成功的话创建一个templates_builer类的对象builder用以初始化遍历document,该类继承自public XMLVisitor、boost::base_from_member和field_builder_base。Accept函数在tinyxml2中定义,对于不同的XML元素类型定义不同。对XMLDocument的定义如下,利用一对VisITEnter/VisitExit函数作为出入口。
bool XMLDocument::Accept( XMLVisitor* visitor ) const{ TIXMLASSERT( visitor ); if ( visitor->VisitEnter( *this ) ) { for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { if ( !node->Accept( visitor ) ) { break; } } } return visitor->VisitExit( *this );}
这里调用的应该是templates_builder的visit函数,定义如下。参数为XMLDocument的visitenter函数没有重载,直接返回TRUE。
然后调用参数为XMLElement的visitenter函数,代码如下。先获取element名称,如果是templates(xml文件根元素),则配置des的ns_、template_ns_和dictionary三个成员变量,然后返回TRUE,继续accept过程处理子节点。项目中templates节点的子节点为template,利用templates_builder和template元素创建field_builder类的对象builder,调用build函数,创建field。
bool templates_builder::VisitEnter (const XMLElement & element, const XMLAttribute*) { const char* element_name = element.Name(); if (std::strcmp(element_name, "templates") == 0 ) { definition_->ns_ = string_dup(get_optional_attr(element, "ns", ""), alloc()); resolved_ns_= string_dup(get_optional_attr(element, "templateNs", ""), alloc()); definition_->template_ns_ = resolved_ns_; definition_->dictionary_ = string_dup(get_optional_attr(element, "dictionary", ""), alloc()); return true; } else if (strcmp(element_name, "define") == 0) { const char* name = get_optional_attr(element, "name", 0); const XMLElement* elem = element.FirstChildElement(); if (name && elem) { field_builder builder(this, *elem, name); builder.build(); } } else if (strcmp(element_name, "template") == 0) { field_builder builder(this, element); builder.build(); } else if (strcmp(element_name, "view") == 0) { view_info_builder builder(alloc()); const group_field_instruction* inst = dynamic_cast<const group_field_instruction*>(this->find_type( get_optional_attr(element,"ns", resolved_ns_), get_optional_attr(element,"reference", ""))); if (inst == 0) BOOST_THROW_EXCEPTION(fast_static_error("Invalid view specification")); definition_->view_infos_.push_back( builder.build(element, inst) ); } return false; } bool templates_builder::VisitExit (const XMLElement & element) { if (std::strcmp(element.Name(), "templates") == 0 ) { typedef const template_instruction* const_template_instruction_ptr_t; definition_->instructions_ = new (alloc())const_template_instruction_ptr_t[this->num_instructions()]; std::copy(templates_.begin(), templates_.end(), definition_->instructions_); definition_->instructions_count_ = static_cast<uint32_t>(templates_.size()); } return true; }
field_builder的构造函数如下。第一个参数为field_builder_base类型的,调用的时候传入的为templates_builder,为其子类。
field_builder::field_builder(field_builder_base* parent, const XMLElement& element) : fast_xml_attributes(element.FirstAttribute()) , field_builder_base(parent->registry(), parent->local_types()) , element_(element) , parent_(parent) { }
其基类fast_xml_attributes利用element(此处为template类型)的第一个attribute初始化,该基类的构造函数如下。可以看到,根据此attribute的类型,设置fast_xml_attributes的相应属性,本项目中一般为name属性。
fast_xml_attributes(const XMLAttribute* attr) { name_ = 0; id_ = 0; ns_ = 0; templateNs_ = 0; dictionary_ = 0; presence_ = 0; charset_ = 0; tag_ = 0; decimal_place_ = 0; set(attr); } void set(const XMLAttribute* attr) { while (attr != 0) { const char* name = attr->Name(); if (std::strcmp(name, "name") == 0) name_ = attr->Value(); else if (std::strcmp(name, "ns") == 0) ns_ = attr->Value(); else if (std::strcmp(name, "templateNs") == 0) templateNs_ = attr->Value(); else if (std::strcmp(name, "dictionary") == 0) dictionary_ = attr->Value(); else if (std::strcmp(name, "id") == 0) id_ = attr->Value(); else if (std::strcmp(name, "presence") == 0) presence_ = attr->Value(); else if (std::strcmp(name, "charset") == 0) charset_ = attr->Value(); else if (std::strcmp(name, "mfast:tag") == 0) tag_ = attr->Value(); else if (std::strcmp(name, "decimalPlaces") == 0) decimal_place_ = attr->Value(); attr = attr->Next(); } }
下一步调用build过程,代码如下。首先获取节点名称template,然后从本类型或事先注册的map里面检索对应名称的instruction,这一步原理还不清楚。然后调用instruction的accept过程,实质是调用field_builder的visit函数,visit再调用相应类型的built函数,或者直接调用parent_->add_instruction过程,讲此过程注册进templates_builder,即注册进dynamic_templates_description。至此,完成一个template的解析。
void field_builder::build() { const field_instruction* prototype = find_prototype(resolve_field_type(element_)); if (prototype) { prototype->accept(*this, 0); } } const char* field_builder::resolve_field_type(const XMLElement& element) { field_type_name_ = element.Name(); content_element_ = &element; if (std::strcmp(field_type_name_, "field") == 0 ) { content_element_ = element.FirstChildElement(); if (content_element_) { field_type_name_ = content_element_->Name(); if (strcmp(field_type_name_, "type")==0) { field_type_name_ = name_; name_ = 0; fast_xml_attributes::set(content_element_->FirstAttribute()); if (name_ == 0) throw std::runtime_error("type element does not have a name"); std::swap(field_type_name_, name_); } else { fast_xml_attributes::set(content_element_->FirstAttribute()); } } else { throw std::runtime_error("field element must have a child element"); } } resolved_ns_ = ns_; //ns_继承自fast_xml_attributes,resolved_ns_继承自field_builder_base if (resolved_ns_ == 0 && parent_) { resolved_ns_ = parent_->resolved_ns(); } return field_type_name_; }const field_instruction* field_builder::find_prototype(const char* type_name) { if (type_name == 0) { BOOST_THROW_EXCEPTION(fast_static_error("S1") << reason_info("no field type specified")); } const field_instruction* instruction = 0; if (std::strcmp(type_name, "string") == 0) { if (this->charset_ == 0) this->charset_ = get_optional_attr(element_, "charset", "ascii"); if (std::strcmp(this->charset_, "unicode") == 0 ) { static unicode_field_instruction prototype (operator_none,presence_mandatory,0,0,"",0, string_value_storage(), 0, "", ""); instruction = &prototype; } } else if (std::strcmp(type_name, "templateRef") == 0) { return templateref_instruction::default_instruction()[0]; } else if (std::strcmp(type_name, "typeRef") == 0 || std::strcmp(type_name, "length") == 0) { return 0; } if (instruction == 0) { instruction = this->find_type(ns_, type_name); } if ( instruction == 0 ) { BOOST_THROW_EXCEPTION(fast_static_error("S1") << reason_info((std::string("Invalid field type specified : ") + type_name))); } return instruction; }
- mFAST fast_type_gen流程详解
- MAC 下安装mFAST步骤
- gcc mthumb + O2 + mfast-math 选项测试
- JavaME 开发流程详解
- 驱动程序开发流程详解
- JavaME开发流程详解
- linux 启动流程详解
- linux中断流程详解
- linux 启动流程详解
- LINUX开机流程详解
- X264编码流程详解
- stageFright流程详解
- Push机制流程详解
- 详解Magento执行流程
- 详解MapReduce工作流程
- linux中断流程详解
- Android poweroff 流程详解
- 详解MapReduce工作流程
- bzoj 3864 Hero meet devil
- POJ 1845 Sumdiv 笔记
- 初识node 创建或者删除一个文件目录
- 在ATL项目中添加WTL界面
- 面试题25:二叉树中和为某一值的路径
- mFAST fast_type_gen流程详解
- 《使用python进行自然语言理解》学习笔记二
- 论android等平台回音消除解决方案
- 类似QQ空间,微信朋友圈,微博主页等,展示图片的九宫格控件
- JavaScript基础
- meta标签用法
- Bzoj 3662: Clever Rabbit
- Java基础学习笔记 第二部分 part 1
- List 四种遍历方法测试