void variant::swap(variant &other) noexcept { using std::swap; auto thisEmpty = this->empty(); auto otherEmpty = other.empty(); if (thisEmpty && otherEmpty) return; if (thisEmpty && !otherEmpty) { other.manager->f_move(other.storage, storage); manager = other.manager; other.manager = internal::variant_function_table_for<void>(); other.storage = storage_t{}; return; } if (!thisEmpty && otherEmpty) { manager->f_move(storage, other.storage); other.manager = manager; manager = internal::variant_function_table_for<void>(); storage = storage_t{}; return; } storage_t temporary; manager->f_move(storage, temporary); other.manager->f_move(other.storage, storage); manager->f_move(temporary, other.storage); swap(manager, other.manager); }
void xml_writer_impl::write_element(const variant& element) { try { if (element.is<variant::Collection>() && element.empty() && element.type() != variant::DataTable) { write_empty_element(); return; } switch(element.type()) { case variant::None: { write_empty_element(); break; } case variant::Any: case variant::String: { if (element.as<std::string>().empty()) { write_empty_element(); break; } } case variant::Float: case variant::Double: case variant::Int32: case variant::UInt32: case variant::Int64: case variant::UInt64: case variant::Boolean: case variant::Date: case variant::Time: case variant::DateTime: { m_os << start_tag(); write_text(element); m_os << end_tag(); break; } case variant::Dictionary: case variant::Bag: { if ((m_mode & xml_mode::Preserve)!=0) { if (element.has_key(xml_attributes)) { m_stack.top().m_attributes = element[xml_attributes]; if (element.size()==1) { write_empty_element(); break; } } m_os << start_tag(); bool prev_is_text = false; variant::const_iterator it, end(element.end()); for (it=element.begin(); it!=end; ++it) { if (it.key()==xml_attributes) { continue; } else if (it.key()==xml_text) { write_text(it.value()); prev_is_text = true; } else if (it.key()==xml_instruction) { push(it.key()); if (!prev_is_text) { m_os << indent(); } write_instruction(it.value()); prev_is_text = false; pop(); } else if (it.key()==xml_comment) { push(it.key()); if (!prev_is_text) { m_os << indent(); } write_comment(it.value()); prev_is_text = false; pop(); } else { push(it.key()); if (!prev_is_text) { m_os << indent(); } write_element(it.value()); prev_is_text = false; pop(); } } if (!prev_is_text) { m_os << indent(); } m_os << end_tag(); } else { m_os << start_tag(); variant::const_iterator it, end(element.end()); for (it=element.begin(); it!=end; ++it) { push(it.key()); m_os << indent(); write_variant(it.value()); pop(); } m_os << indent() << end_tag(); } break; } case variant::List: { m_os << start_tag(); BOOST_FOREACH(const variant& item, element) { push(); m_os << indent(); write_variant(item); pop(); } m_os << indent(); m_os << end_tag(); break; } case variant::Tuple: { m_stack.top().m_attributes.insert("size", variant(element.size())); m_os << start_tag(); BOOST_FOREACH(const variant& item, element) { push(); m_os << indent(); write_variant(item); pop(); } m_os << indent(); m_os << end_tag(); break; } case variant::TimeSeries: { m_os << start_tag(); variant::const_iterator it, end = element.end(); for (it=element.begin(); it!=end; ++it) { push().insert("time", variant(it.time())); m_os << indent(); write_variant(it.value()); pop(); } m_os << indent(); m_os << end_tag(); break; } case variant::DataTable: { const data_table& dt = element.m_value.get<variant::DataTable>(); m_stack.top().m_attributes .insert("rows", variant(dt.size())) .insert("columns", variant(dt.columns().size())); m_os << start_tag(); if (!dt.columns().empty()) { push("Columns"); m_os << indent() << start_tag(); for (data_table::column_container_type::const_iterator column_iter = dt.columns().begin() ; column_iter != dt.columns().end() ; ++column_iter) { push("Column") .insert("name", variant(column_iter->name())) .insert("type", variant(variant::enum_to_string(column_iter->type()))); m_os << indent(); write_empty_element(); pop(); } m_os << indent() << end_tag(); pop(); } for (data_table::column_container_type::const_iterator column_iter = dt.columns().begin() ; column_iter != dt.columns().end() ; ++column_iter) { push("Column").insert("name", variant(column_iter->name())); m_os << indent() << start_tag(); if (column_iter->type() & variant_base::Primitive) { boost::scoped_ptr<data_table_column_writer> column_writer( make_data_table_column_stream_writer(*column_iter, m_os) ); while (column_writer->has_next()) { push("V"); m_os << indent() << start_tag(); column_writer->write(); m_os << end_tag(); pop(); column_writer->advance(); } } else { variant::const_iterator iter(column_iter->begin()); variant::const_iterator end(column_iter->end()); while (iter != end) { push("V"); m_os << indent(); write_variant(*(iter++)); pop(); } } m_os << indent() << end_tag(); pop(); } m_os << indent(); m_os << end_tag(); break; } case variant::Buffer: { m_os << start_tag(); const void *data = element.as<void*>(); size_t size = element.size(); if (data!=nullptr && size>0) { unsigned int n = 0; boost::scoped_ptr<char> b64(detail::b64_encode((const char*)data, (unsigned int)size, &n)); if (!b64.get()) { boost::throw_exception(variant_error("Unable to base64 encode data")); } m_os << b64.get(); } m_os << end_tag(); break; } case variant::Object: { const object& obj(element.as<object>()); // write class name m_stack.top().m_attributes .insert("class", variant(obj.name())) .insert("version", variant(obj.version())); m_os << start_tag(); // write parameter dictionary variant params; obj.deflate(params); push("params"); m_os << indent(); write_variant(params); pop(); m_os << indent(); m_os << end_tag(); break; } case variant::Exception: { m_os << start_tag(); exception_data e(element.as<exception_data>()); push("type"); m_os << indent(); write_element(variant(e.type())); pop(); push("message"); m_os << indent(); write_element(variant(e.message())); pop(); if (!e.source().empty()) { push("source"); m_os << indent(); write_element(variant(e.source())); pop(); } if (!e.stack().empty()) { push("stack"); m_os << indent(); write_element(variant(e.stack())); pop(); } m_os << indent(); m_os << end_tag(); break; } case variant::Array: { const typed_array& a(element.as<typed_array>()); m_stack.top().m_attributes .insert("size", variant(a.size())) .insert("type", variant(variant::enum_to_string(a.type()))); m_os << start_tag(); for (size_t i=0; i<a.size(); ++i) { push(); m_os << indent(); write_element(variant(a[i])); pop(); } m_os << indent(); m_os << end_tag(); break; } default: boost::throw_exception(variant_error("Case exhaustion: " + variant::enum_to_string(element.type()))); }