void PropertyMapReader::Read (InputStream& stream) { try { const PropertyMapHeader& header = stream.Read<PropertyMapHeader> (); //синхронизация лэйаута Impl::LayoutDescPtr layout_desc; object_id_t layout_id = 0; if (header.has_layout) { layout_desc = impl->ReadLayout (stream); layout_id = layout_desc->source_id; } else if (header.has_layout_id) { layout_id = read (stream, xtl::type<object_id_t> ()); } //синхронизация карты свойств Impl::MapDescMap::iterator map_iter = impl->property_maps.find (header.id); Impl::MapDescPtr map_desc; if (map_iter != impl->property_maps.end ()) { map_desc = map_iter->second; if (!(header.has_layout_id || header.has_layout) || (!layout_desc && map_desc->layout->source_id == layout_id && map_desc->layout_hash == map_desc->layout->layout.Hash ())) { layout_desc = map_desc->layout; } else { Impl::LayoutMap::iterator iter = impl->layouts.find (layout_id); if (iter == impl->layouts.end ()) throw xtl::format_operation_exception ("", "Internal error: can't find layout %llu to update property map %llu", layout_id, header.id); layout_desc = iter->second; //обновление лэйаута существующей карты const common::PropertyLayout& layout = layout_desc->layout; map_desc->properties.Reset (layout); map_desc->layout = layout_desc; map_desc->layout_hash = layout.Hash (); } } else { //поиск лэйаута Impl::LayoutMap::iterator iter = impl->layouts.find (layout_id); if (iter == impl->layouts.end ()) throw xtl::format_operation_exception ("", "Internal error: no layout %llu for new property map %llu", layout_id, header.id); layout_desc = iter->second; //новая карта свойств map_desc = Impl::MapDescPtr (new Impl::MapDesc (layout_desc), false); } //синхронизация карты свойств common::PropertyMap& properties = map_desc->properties; try { //синхронизация буфера карты свойств size_t src_buffer_size = stream.Read<uint32> (); const void* src_buffer = stream.ReadData (src_buffer_size); if (src_buffer_size != properties.BufferSize ()) throw xtl::format_operation_exception ("", "Internal error: can't sync property map %llu. Incoming buffer data size is %u but actual is %u", header.id, src_buffer_size, properties.BufferSize ()); properties.SetBufferData (src_buffer); //синхронизация строк for (IndexArray::iterator iter=layout_desc->string_indices.begin (), end=layout_desc->string_indices.end (); iter!=end; ++iter) { const char* string = read (stream, xtl::type<const char*> ()); properties.SetProperty (*iter, string); } } catch (...) { //reset strings, because SetBufferData is atomic operation const common::PropertyDesc* property = properties.Layout ().Properties (); for (size_t i=0, count=properties.Layout ().Size (); i<count; i++, property++) { if (property->type == common::PropertyType_String) properties.SetProperty (i, ""); } throw; } //обновление структур данных if (map_iter == impl->property_maps.end ()) impl->property_maps.insert_pair (header.id, map_desc); } catch (xtl::exception& e) { e.touch ("render::scene::interchange::PropertyMapReader::Read"); throw; } }