static ERL_NIF_TERM element_to(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int as_string) { ErlNifBinary output; ERL_NIF_TERM result; struct buf *rbuf; if (argc == 1) { rbuf = init_buf(env); if (make_element(env, rbuf, argv[0])) { if (as_string) { (rbuf->b)[rbuf->len] = 0; result = enif_make_string(env, (char *) rbuf->b, ERL_NIF_LATIN1); destroy_buf(env, rbuf); return result; } else { if (ENIF_ALLOC_BINARY(rbuf->len, &output)) { memcpy(output.data, rbuf->b, rbuf->len); result = enif_make_binary(env, &output); destroy_buf(env, rbuf); return result; }; }; }; destroy_buf(env, rbuf); }; return enif_make_badarg(env); }
static int make_elements(ErlNifEnv* env, struct buf *rbuf, ERL_NIF_TERM els) { ERL_NIF_TERM head, tail; int ret = 0; while (enif_get_list_cell(env, els, &head, &tail)) { ret = make_element(env, rbuf, head); if (ret) { els = tail; } else { break; }; }; return ret; }
// // Generate indexes using our own internal method: // void generate_indexes() { for(boost::tiny_xml::element_list::const_iterator i = indexes.begin(); i != indexes.end(); ++i) { boost::tiny_xml::element_ptr node = *i; const std::string* category = find_attr(node, "type"); bool has_title = false; for(boost::tiny_xml::element_list::const_iterator k = (*i)->elements.begin(); k != (*i)->elements.end(); ++k) { if((**k).name == "title") { has_title = true; break; } } boost::tiny_xml::element_ptr navbar = make_element("para"); node->elements.push_back(navbar); index_entry_set::const_iterator m = index_entries.begin(); index_entry_set::const_iterator n = m; boost::tiny_xml::element_ptr vlist = make_element("variablelist"); node->elements.push_back(vlist); while(n != index_entries.end()) { char current_letter = std::toupper((*n)->key[0]); std::string id_name = get_next_index_id(); boost::tiny_xml::element_ptr entry = add_attribute(make_element("varlistentry"), "id", id_name); boost::tiny_xml::element_ptr term = make_element("term"); term->content = std::string(1, current_letter); entry->elements.push_back(term); boost::tiny_xml::element_ptr item = make_element("listitem"); entry->elements.push_back(item); while((n != index_entries.end()) && (std::toupper((*n)->key[0]) == current_letter)) ++n; std::pair<index_entry_set::const_iterator, index_entry_set::const_iterator> range(m, n); item->elements.push_back(generate_entry(range, category)); if(item->elements.size() && (*item->elements.begin())->elements.size()) { vlist->elements.push_back(entry); boost::tiny_xml::element_ptr p = make_element(""); p->content = " "; if(navbar->elements.size()) { navbar->elements.push_back(p); } p = add_attribute(make_element("link"), "linkend", id_name); p->content = current_letter; navbar->elements.push_back(p); } m = n; } node->name = internal_index_type; boost::tiny_xml::element_ptr p(node->parent); while(p->name.empty()) p = boost::tiny_xml::element_ptr(p->parent); check_index_type_and_placement(p->name, node->name); node->attributes.clear(); if(!has_title) { boost::tiny_xml::element_ptr t = make_element("title"); t->content = "Index"; node->elements.push_front(t); } } }
boost::tiny_xml::element_ptr generate_entry(const Range& range, const std::string* pcategory, int level = 0, const boost::regex* primary_key = 0) { boost::tiny_xml::element_ptr list = add_attribute(add_attribute(::add_attribute(make_element("itemizedlist"), "mark", "none"), "spacing", "compact"), "role", "index"); for(typename boost::range_iterator<Range>::type i = boost::begin(range); i != boost::end(range);) { std::string key = (*i)->key; index_entry_set entries; bool preferred = false; std::string id; bool collapse = false; // // Create a regular expression for comparing key to other key's: // boost::regex key_regex; if(level == 0) { key_regex = make_primary_key_matcher(key); primary_key = &key_regex; } // // Begin by consolidating entries with identical keys but possibly different categories: // while((i != boost::end(range)) && ((*i)->key == key)) { if((0 == pcategory) || (pcategory->size() == 0) || (pcategory && (**i).category == *pcategory)) { entries.insert((*i)->sub_keys.begin(), (*i)->sub_keys.end()); if((*i)->preferred) preferred = true; if((*i)->id.size()) { if(id.size()) { std::cerr << "WARNING: two identical index terms have different link destinations!!" << std::endl; } id = (*i)->id; } } ++i; } // // Only actually generate content if we have anything in the entries set: // if(entries.size() || id.size()) { // // See if we can collapse any sub-entries into this one: // if(entries.size() == 1) { if((regex_match((*entries.begin())->key, *primary_key) || ((*entries.begin())->key == key)) && ((*entries.begin())->id.size()) && ((*entries.begin())->id != id)) { collapse = true; id = (*entries.begin())->id; } } // // See if this key is the same as the primary key, if it is then make it prefered: // if(level && regex_match(key, *primary_key)) { preferred = true; } boost::tiny_xml::element_ptr item = make_element("listitem"); boost::tiny_xml::element_ptr para = make_element("para"); item->elements.push_back(para); list->elements.push_back(item); if(preferred) { para->elements.push_back(make_element("emphasis")); para = para->elements.back(); } if(id.size()) { boost::tiny_xml::element_ptr link = add_attribute(make_element("link"), "linkend", id); para->elements.push_back(link); para = link; } std::string classname = (boost::format("index-entry-level-%1%") % level).str(); para->elements.push_back(add_attribute(make_element("phrase"), "role", classname)); para = para->elements.back(); para->content = key; if(!collapse && entries.size()) { std::pair<index_entry_set::const_iterator, index_entry_set::const_iterator> subrange(entries.begin(), entries.end()); item->elements.push_back(generate_entry(subrange, 0, level+1, primary_key)); } } } return list; }