size_t Marshal::read_from_marshal(Marshal& m, size_t n) { assert(m.content_size() >= n); // require m.content_size() >= n > 0 size_t n_fetch = 0; if ((head_ == nullptr && tail_ == nullptr) || tail_->fully_written()) { // efficiently copy data by only copying pointers while (n_fetch < n) { // NOTE: The copied chunk is shared by 2 Marshal objects. Be careful // that only one Marshal should be able to write to it! For the // given 2 use cases, it works. chunk* chnk = m.head_->shared_copy(); if (n_fetch + chnk->content_size() > n) { // only fetch enough bytes we need chnk->write_idx -= (n_fetch + chnk->content_size()) - n; } size_t cnt = chnk->content_size(); assert(cnt > 0); n_fetch += cnt; verify(m.head_->discard(cnt) == cnt); if (head_ == nullptr) { head_ = tail_ = chnk; } else { tail_->next = chnk; tail_ = chnk; } if (m.head_->fully_read()) { if (m.tail_ == m.head_) { // deleted the only chunk m.tail_ = nullptr; } chunk* next = m.head_->next; delete m.head_; m.head_ = next; } } write_cnt_ += n_fetch; content_size_ += n_fetch; verify(m.content_size_ >= n_fetch); m.content_size_ -= n_fetch; } else { // number of bytes that need to be copied size_t copy_n = std::min(tail_->data->size - tail_->write_idx, n); char* buf = new char[copy_n]; n_fetch = m.read(buf, copy_n); verify(n_fetch == copy_n); verify(this->write(buf, n_fetch) == n_fetch); delete[] buf; size_t leftover = n - copy_n; if (leftover > 0) { verify(tail_->fully_written()); n_fetch += this->read_from_marshal(m, leftover); } } assert(n_fetch == n); assert(content_size_ == content_size_slow()); return n_fetch; }
dmz::Boolean dmz::NetModulePacketCodecBasic::_write_object ( const Handle ObjectHandle, const NetObjectEncodeEnum Mode, Marshal &outData) { Boolean result (False); EncodeObjectStruct *eos (_objTable.lookup (ObjectHandle)); if (eos && _headerCodec) { const Int32 Place (outData.get_place ()); if (_headerCodec->write_header (eos->PacketID, outData)) { if (eos->codec.encode_object (ObjectHandle, Mode, outData)) { outData.set_place (Place); result = _headerCodec->write_header (eos->PacketID, outData); } } } return result; }
dmz::Boolean dmz::NetExtPacketCodecObjectNative::encode_object ( const Handle ObjectHandle, const NetObjectEncodeEnum EncodeMode, Marshal &data) { Boolean result (False); if (_attrMod && _objMod) { UUID objectID; if (_objMod->lookup_uuid (ObjectHandle, objectID)) { data.set_next_uuid (_SysID); data.set_next_uuid (objectID); if (EncodeMode == NetObjectDeactivate) { data.set_next_int8 (0); result = True; } else { const ObjectType Type (_objMod->lookup_object_type (ObjectHandle)); ArrayUInt32 typeArray; if (_attrMod->to_net_object_type (Type, typeArray)) { const Int32 TypeSize (typeArray.get_size ()); data.set_next_int8 (Int8 (TypeSize)); for (Int32 ix = 0; ix < TypeSize; ix++) { data.set_next_uint8 (UInt8 (typeArray.get (ix))); } ObjectAttributeAdapter *current (_adapterList); while (current) { current->encode (ObjectHandle, *_objMod, data); current = current->next; } result = True; } _objMod->store_time_stamp ( ObjectHandle, _lnvHandle, _time.get_last_frame_time ()); } } } return result; }
template <class T> Boolean sizeElement<T>::write_element (const UInt32 PacketID, Marshal &data) { T value (0); value = T (data.get_length ()); MarshalWrap wrap (data); wrap.set_next (value); return True; }
dmz::Boolean dmz::NetModulePacketCodecBasic::encode_event ( const EventType &Type, const Handle EventHandle, Marshal &outData) { Boolean result (False); EncodeEventStruct *ees (_eventTypeTable.lookup (Type.get_handle ())); if (!ees) { EventType current (Type); current.become_parent (); while (!ees && current) { ees = _eventTypeTable.lookup (current.get_handle ()); current.become_parent (); } } if (ees && _headerCodec) { const Int32 Place (outData.get_place ()); if (_headerCodec->write_header (ees->PacketID, outData)) { if (ees->codec.encode_event (EventHandle, outData)) { outData.set_place (Place); result = _headerCodec->write_header (ees->PacketID, outData); } } } return result; }
dmz::Boolean dmz::NetExtPacketCodecObjectBasic::encode_object ( const Handle ObjectHandle, const NetObjectEncodeEnum EncodeMode, Marshal &data) { Boolean result (False); if (_attrMod && _objMod) { UUID uuid; if (_objMod->lookup_uuid (ObjectHandle, uuid)) { const ObjectType Type (_objMod->lookup_object_type (ObjectHandle)); ArrayUInt32 typeArray; if (_attrMod->to_net_object_type (Type, typeArray)) { Vector pos; Matrix ori; Vector vel; ArrayUInt32 stateArray; Mask state; _objMod->lookup_position (ObjectHandle, _defaultHandle, pos); _objMod->lookup_orientation (ObjectHandle, _defaultHandle, ori); _objMod->lookup_velocity (ObjectHandle, _defaultHandle, vel); _objMod->lookup_state (ObjectHandle, _defaultHandle, state); if (EncodeMode == NetObjectDeactivate) { state |= _deactivateState; } _attrMod->to_net_object_mask (Type, state, stateArray); data.set_next_uuid (_SysID); data.set_next_uuid (uuid); data.set_next_vector (pos); data.set_next_matrix (ori); data.set_next_vector (vel); data.set_next_uint32 (typeArray.get (0)); data.set_next_uint32 (typeArray.get (1)); data.set_next_uint32 (typeArray.get (2)); data.set_next_uint32 (stateArray.get (0)); const Int32 Place (data.get_place ()); data.set_next_uint32 (0); UInt32 scalarCount (0); HashTableHandleIterator it; ScalarStruct *ss (_scalarTable.get_first (it)); while (ss) { Float64 value (0.0); if (_objMod->lookup_scalar (ObjectHandle, ss->AttrHandle, value)) { data.set_next_uint32 (ss->NetHandle); data.set_next_float64 (value); scalarCount++; if (ss->LNVAttrHandle) { _objMod->store_scalar (ObjectHandle, ss->LNVAttrHandle, value); } } ss = _scalarTable.get_next (it); } const Int32 EndPlace (data.get_place ()); data.set_place (Place); data.set_next_uint32 (scalarCount); data.set_place (EndPlace); _objMod->store_time_stamp ( ObjectHandle, _lnvHandle, _time.get_last_frame_time ()); _objMod->store_position (ObjectHandle, _lnvHandle, pos); _objMod->store_orientation (ObjectHandle, _lnvHandle, ori); _objMod->store_velocity (ObjectHandle, _lnvHandle, vel); if (EncodeMode != NetObjectDeactivate) { _objMod->store_state (ObjectHandle, _lnvHandle, state); } result = True; } } } return result; }