void base_read_archive::read_object(Reader r, const str& name, variant& obj, schema* type) { //collect what we're saving schema_collector sc; type->visit(&sc); void* this_ = obj.get_pointer(); schema_collector::container::iterator it = sc.begin(); schema_collector::container::iterator nd = sc.end(); for(; it != nd; it++) { schema_item& item = it->second; if (item.flags & CONST) continue; if (item.set) { variant value; if (attributed_type(item.type)) { if (r->attribute(it->first, item.type, value)) { item.set->set(this_, value); } } else { Reader rr = r->create_node(it->first); if (rr) { read(rr, item.type, value); item.set->set(this_, value); } } } else if (item.flags & STATIC_FIELD) { //td: !!! resuse read_iterated & read_object assert(item.get); variant sf = item.get->get(this_); if (item.type->options() & TYPE_ITERATED) { read_iterated(r, it->first, sf); } else { read_object(r, it->first, sf, sf.get_schema()); } } } }
void base_write_archive::write( Writer w, const str& name, variant& v) { schema* type = true_type(v); void* this_ = v.get_pointer(); //3 use cases: //- we know the type as attibuted (ints, strings, things like that) // note the implementor is free to define its custom types // //- we are saving an iterable type // //- or we are saving an object, these seem to be reasonable assumptions. if (attributed_type(type)) { assert(!name.empty()); w->attribute(name, v); } else { size_t type_options = type->options(); if (type_options & TYPE_ITERATED) { iterable iter(v); iterator it = iter.begin(); iterator nd = iter.end(); WriteIterator wit = w->create_iterator(name, iter.iterated_type()); for(; it != nd; ++it) { variant iv = *it; Writer iw = wit->next(iv); if (iw) write(iw, "", iv); } } else { Writer writer_ = name.empty()? w : w->create_node(name); schema* otype = v.get_schema(); assert(otype); size_t oopt = otype->options(); if (oopt & TYPE_NON_INSTANTIABLE) { assert(type != otype); assert(types_); str class_id = types_->type_name(type); assert( !class_id.empty() ); w->attribute("class", class_id); } //collect what we're saving schema_collector sc; type->visit(&sc); schema_collector::container::iterator it = sc.begin(); schema_collector::container::iterator nd = sc.end(); for(; it != nd; it++) { schema_item& item = it->second; if (item.flags & CONST) continue; if (item.flags & TRANSIENT) continue; if (item.get) { variant value = item.get->get(this_); write(writer_, it->first, value); } } } } }
bool base_read_archive::read(Reader r, schema* type, variant& result) { if (!type || type->options() & TYPE_NON_INSTANTIABLE || type == type_schema<variant>()) { assert(types_); variant v; if (!r->attribute("class", type_schema<str>(), v)) { assert(false); //?? return false; } str class_id = v; type = types_->get_type(class_id); assert(type); } assert(type); //instantiate if (!type->create(result)) { return false; } void* this_ = result.get_pointer(); size_t type_options = type->options(); if (type_options & TYPE_ITERATED) { iterable iter(result); schema* iter_type = iter.iterated_type(); ReadIterator rit = r->create_iterator("", iter_type); Reader item_reader; variant item; while(rit->next(item_reader, item)) { variant result_item; if (item_reader) read(item_reader, iter_type, result_item); else result_item = item; iter.insert( result_item ); } } else { schema_collector sc; type->visit(&sc); schema_collector::container::iterator it = sc.begin(); schema_collector::container::iterator nd = sc.end(); for(; it != nd; it++) { schema_item& item = it->second; if (item.flags & CONST) continue; if (item.flags & TRANSIENT) continue; if (item.set) { variant value; if (attributed_type(item.type)) { if (r->attribute(it->first, item.type, value)) { item.set->set(this_, value); } } else { Reader rr = r->create_node(it->first); if (rr) { read(rr, item.type, value); item.set->set(this_, value); } } } else if (item.flags & STATIC_FIELD) { assert(item.get); variant sf = item.get->get(this_); if (item.type->options() & TYPE_ITERATED) { read_iterated(r, it->first, sf); } else { read_object(r, it->first, sf, sf.get_schema()); } } } if (type_options & TYPE_MUTABLE) { IDynamicObject* obj = result; mutable_reader mr(obj, *this); r->visit(&mr); obj = null; } } return true; }