size_t DictionaryEncoding::decompress(void const* src, size_t size, Chunk& chunk) { size_t chunkSize = chunk.getSize(); uint8_t* dst = (uint8_t *)chunk.getData(); ByteInputItr in((uint8_t *) src, size); uint32_t i; uint32_t code = 0; std::string value; TypeId type = chunk.getAttributeDesc().getType(); size_t elementSize = TypeLibrary::getType(type).byteSize(); size_t nElems = chunkSize / elementSize; if(elementSize == 0 || elementSize > 8 || chunk.isRLE() || !chunk.getArrayDesc().isImmutable() || chunk.isSparse()) { nElems = chunkSize; elementSize = 1; } if(!nElems) { return size; } rebuildDictionary(in, elementSize); assert(_entriesPerCode); uint32_t blocks = floor(nElems / _entriesPerCode); uint32_t remainderSize = (nElems % _entriesPerCode) * elementSize; // in bytes size_t blockValueSize = _entriesPerCode * elementSize; for(i = 0; i < blocks; ++i) { if(in.getArray((uint8_t *) &code, _codeLength) == -1) { return 0; } value = _decodeDictionary[code]; memcpy(dst, value.data(), blockValueSize); dst += blockValueSize; } // edge case - last few vals if(remainderSize) { if(in.getArray((uint8_t *) &code, _codeLength) == -1) { return 0; } value = _decodeDictionary[code]; memcpy(dst, value.data(), remainderSize); dst += remainderSize; } return dst - (uint8_t *) chunk.getData(); } // end decompress
Serializer& DefaultSerializer::operator<<(const dtn::data::BundleFragment &obj) { // rebuild the dictionary rebuildDictionary(obj._bundle); PrimaryBlock prim = obj._bundle; prim.set(dtn::data::PrimaryBlock::FRAGMENT, true); // set the application length according to the payload block size dtn::data::Bundle::const_iterator it = obj._bundle.find(dtn::data::PayloadBlock::BLOCK_TYPE); if (it != obj._bundle.end()) { const dtn::data::PayloadBlock &payload = dynamic_cast<const dtn::data::PayloadBlock&>(**it); prim.appdatalength = payload.getLength(); } else { prim.appdatalength = 0; } // set the fragmentation offset prim.fragmentoffset += obj._offset; // serialize the primary block (*this) << prim; // serialize all secondary blocks bool post_payload = false; for (Bundle::const_iterator iter = obj._bundle.begin(); iter != obj._bundle.end(); ++iter) { const Block &b = (**iter); try { // test if this is the payload block const dtn::data::PayloadBlock &payload = dynamic_cast<const dtn::data::PayloadBlock&>(b); // serialize the clipped block serialize(payload, obj._offset, obj._length); // we had serialized the payload block post_payload = true; } catch (const std::bad_cast&) { // serialize this block if // ... this block is before the payload block and marked as replicated in every fragment // ... this block is after the payload block and all remaining bytes of the payload block are included if (post_payload || b.get(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT)) { (*this) << b; } } } return (*this); }
size_t DictionaryEncoding::Dictionary::decompress(void const* src, size_t size, Chunk& chunk) { size_t chunkSize = chunk.getSize(); uint8_t* writePtr = (uint8_t *)chunk.getData(); ByteInputItr in((uint8_t *) src, size); uint32_t i; uint8_t code = 0; uint64_t value = 0; TypeId type = chunk.getAttributeDesc().getType(); size_t elementSize = TypeLibrary::getType(type).byteSize(); size_t nElems; if(elementSize == 0 || elementSize > 8 || chunk.isSparse() || !chunk.getArrayDesc().isImmutable() || chunk.isRLE() || chunk.getAttributeDesc().isNullable()) { nElems = chunkSize; elementSize = 1; } else { nElems = chunkSize / elementSize; } uint32_t uniques = (uint32_t ) rebuildDictionary(in, elementSize); BitInputItr inBits(&in); size_t codeLength; uniques <= 2 ? codeLength = 1 : codeLength = ceil(log2(uniques-1))+1; size_t codesSize = (nElems * codeLength + 7) >> 3; size_t totalCompressed = 1 + uniques * elementSize + codesSize; if(totalCompressed != size || !uniques) // malformed compression, don't work on it { return 0; } for(i = 0; i < nElems; ++i) { inBits.get(code, codeLength); value = _decodeDictionary[code]; memcpy(writePtr, (uint8_t *) &value, elementSize); writePtr += elementSize; } return chunkSize; }
Length DefaultSerializer::getLength(const dtn::data::Bundle &obj) { // rebuild the dictionary rebuildDictionary(obj); Length len = 0; len += getLength( (PrimaryBlock&)obj ); // add size of all blocks for (Bundle::const_iterator iter = obj.begin(); iter != obj.end(); ++iter) { const Block &b = (**iter); len += getLength( b ); } return len; }