1
0
Fork 0

move encoding functions into their own file

This commit is contained in:
jsteemann 2017-02-14 12:57:15 +01:00
parent be77decb2d
commit 8a2e353f3d
11 changed files with 115 additions and 71 deletions

View File

@ -28,6 +28,7 @@
#include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h"
#include "Basics/encoding.h"
#include "Basics/process-utils.h"
#include "Cluster/ClusterMethods.h"
#include "Logger/Logger.h"
@ -158,9 +159,9 @@ int MMFilesCollection::OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* m
int64_t size = static_cast<int64_t>(MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT) + VPackSlice(vpack).byteSize());
dfi->numberAlive--;
dfi->sizeAlive -= MMFilesDatafileHelper::AlignedSize<int64_t>(size);
dfi->sizeAlive -= encoding::alignedSize<int64_t>(size);
dfi->numberDead++;
dfi->sizeDead += MMFilesDatafileHelper::AlignedSize<int64_t>(size);
dfi->sizeDead += encoding::alignedSize<int64_t>(size);
}
state->_dfi->numberAlive++;
@ -228,12 +229,12 @@ int MMFilesCollection::OpenIteratorHandleDeletionMarker(TRI_df_marker_t const* m
TRI_ASSERT(old.dataptr() != nullptr);
uint8_t const* vpack = static_cast<uint8_t const*>(old.dataptr());
int64_t size = MMFilesDatafileHelper::AlignedSize<int64_t>(MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT) + VPackSlice(vpack).byteSize());
int64_t size = encoding::alignedSize<int64_t>(MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT) + VPackSlice(vpack).byteSize());
dfi->numberAlive--;
dfi->sizeAlive -= MMFilesDatafileHelper::AlignedSize<int64_t>(size);
dfi->sizeAlive -= encoding::alignedSize<int64_t>(size);
dfi->numberDead++;
dfi->sizeDead += MMFilesDatafileHelper::AlignedSize<int64_t>(size);
dfi->sizeDead += encoding::alignedSize<int64_t>(size);
state->_dfi->numberDeletions++;
state->_primaryIndex->removeKey(trx, oldRevisionId, VPackSlice(vpack), state->_mmdr);
@ -1350,7 +1351,7 @@ void MMFilesCollection::removeRevision(TRI_voc_rid_t revisionId, bool updateStat
if (old && !old.pointsToWal() && old.fid() != 0) {
TRI_ASSERT(old.dataptr() != nullptr);
uint8_t const* vpack = static_cast<uint8_t const*>(old.dataptr());
int64_t size = MMFilesDatafileHelper::AlignedSize<int64_t>(MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT) + VPackSlice(vpack).byteSize());
int64_t size = encoding::alignedSize<int64_t>(MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT) + VPackSlice(vpack).byteSize());
_datafileStatistics.increaseDead(old.fid(), 1, size);
}
} else {

View File

@ -27,6 +27,7 @@
#include "Basics/MutexLocker.h"
#include "Basics/ReadLocker.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/encoding.h"
#include "Basics/hashes.h"
#include "Basics/memory-map.h"
#include "Logger/Logger.h"
@ -591,12 +592,12 @@ void MMFilesCollectorThread::processCollectionMarker(
if (wasAdjusted) {
// revision is still active
dfi.numberAlive++;
dfi.sizeAlive += MMFilesDatafileHelper::AlignedSize<int64_t>(datafileMarkerSize);
dfi.sizeAlive += encoding::alignedSize<int64_t>(datafileMarkerSize);
} else {
// somebody inserted a new revision of the document or the revision
// was already moved by the compactor
dfi.numberDead++;
dfi.sizeDead += MMFilesDatafileHelper::AlignedSize<int64_t>(datafileMarkerSize);
dfi.sizeDead += encoding::alignedSize<int64_t>(datafileMarkerSize);
}
} else if (type == TRI_DF_MARKER_VPACK_REMOVE) {
auto& dfi = cache->createDfi(fid);
@ -616,7 +617,7 @@ void MMFilesCollectorThread::processCollectionMarker(
found.revisionId() > revisionId) {
// somebody re-created the document with a newer revision
dfi.numberDead++;
dfi.sizeDead += MMFilesDatafileHelper::AlignedSize<int64_t>(datafileMarkerSize);
dfi.sizeDead += encoding::alignedSize<int64_t>(datafileMarkerSize);
}
}
}

View File

@ -26,6 +26,7 @@
#include "Basics/FileUtils.h"
#include "Basics/StaticStrings.h"
#include "Basics/StringUtils.h"
#include "Basics/encoding.h"
#include "Basics/files.h"
#include "Basics/hashes.h"
#include "Basics/memory-map.h"
@ -456,7 +457,7 @@ bool TRI_IsValidMarkerDatafile(TRI_df_marker_t const* marker) {
int MMFilesDatafile::reserveElement(TRI_voc_size_t size, TRI_df_marker_t** position,
TRI_voc_size_t maximalJournalSize) {
*position = nullptr;
size = MMFilesDatafileHelper::AlignedSize<TRI_voc_size_t>(size);
size = encoding::alignedSize<TRI_voc_size_t>(size);
if (_state != TRI_DF_STATE_WRITE) {
if (_state == TRI_DF_STATE_READ) {
@ -1327,7 +1328,7 @@ bool MMFilesDatafile::check(bool ignoreFailures) {
bool nextMarkerOk = false;
if (size > 0) {
auto next = reinterpret_cast<char const*>(marker) + MMFilesDatafileHelper::AlignedSize<size_t>(size);
auto next = reinterpret_cast<char const*>(marker) + encoding::alignedSize<size_t>(size);
auto p = next;
if (p < end) {
@ -1434,7 +1435,7 @@ void MMFilesDatafile::printMarker(TRI_df_marker_t const* marker, TRI_voc_size_t
LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "type: " << TRI_NameMarkerDatafile(marker) << ", size: " << marker->getSize() << ", crc: " << marker->getCrc();
LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "(expected layout: size (4 bytes), crc (4 bytes), type and tick (8 bytes), payload following)";
char const* p = reinterpret_cast<char const*>(marker);
char const* e = reinterpret_cast<char const*>(marker) + MMFilesDatafileHelper::AlignedSize<size_t>(size);
char const* e = reinterpret_cast<char const*>(marker) + encoding::alignedSize<size_t>(size);
if (e + 16 < end) {
// add some extra bytes for following data

View File

@ -25,6 +25,7 @@
#define ARANGOD_STORAGE_ENGINE_MMFILES_DATAFILE_HELPER_H 1
#include "Basics/Common.h"
#include "Basics/encoding.h"
#include "MMFiles/MMFilesDatafile.h"
namespace arangodb {
@ -55,15 +56,6 @@ constexpr inline TRI_voc_size_t JournalOverhead() {
return sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the 8-byte aligned size for the value
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static constexpr inline T AlignedSize(T value) {
return (value + 7) - ((value + 7) & 7);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the 8-byte aligned size for the marker
////////////////////////////////////////////////////////////////////////////////
@ -74,35 +66,6 @@ static inline T AlignedMarkerSize(TRI_df_marker_t const* marker) {
return static_cast<T>((value + 7) - ((value + 7) & 7));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief portably and safely reads a number
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static inline T ReadNumber(uint8_t const* source, uint32_t length) {
T value = 0;
uint64_t x = 0;
uint8_t const* end = source + length;
do {
value += static_cast<T>(*source++) << x;
x += 8;
} while (source < end);
return value;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief portably and safely stores a number
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static inline void StoreNumber(uint8_t* dest, T value, uint32_t length) {
uint8_t* end = dest + length;
do {
*dest++ = static_cast<uint8_t>(value & 0xff);
value >>= 8;
} while (dest < end);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the marker-specific offset to the vpack payload
/// note that this function is also used to determine the base length of a
@ -182,7 +145,7 @@ static inline TRI_voc_tick_t DatabaseId(TRI_df_marker_t const* marker) noexcept
type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return ReadNumber<TRI_voc_tick_t>(reinterpret_cast<uint8_t const*>(marker) + DatabaseIdOffset(type), sizeof(TRI_voc_tick_t));
return encoding::readNumber<TRI_voc_tick_t>(reinterpret_cast<uint8_t const*>(marker) + DatabaseIdOffset(type), sizeof(TRI_voc_tick_t));
}
return 0;
}
@ -217,7 +180,7 @@ static inline TRI_voc_tick_t CollectionId(TRI_df_marker_t const* marker) noexcep
type == TRI_DF_MARKER_VPACK_CHANGE_COLLECTION ||
type == TRI_DF_MARKER_VPACK_CREATE_INDEX ||
type == TRI_DF_MARKER_VPACK_DROP_INDEX) {
return ReadNumber<TRI_voc_cid_t>(reinterpret_cast<uint8_t const*>(marker) + CollectionIdOffset(type), sizeof(TRI_voc_cid_t));
return encoding::readNumber<TRI_voc_cid_t>(reinterpret_cast<uint8_t const*>(marker) + CollectionIdOffset(type), sizeof(TRI_voc_cid_t));
}
return 0;
}
@ -250,7 +213,7 @@ static inline TRI_voc_tick_t TransactionId(TRI_df_marker_t const* marker) noexce
type == TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_COMMIT_TRANSACTION ||
type == TRI_DF_MARKER_VPACK_ABORT_TRANSACTION) {
return ReadNumber<TRI_voc_tid_t>(reinterpret_cast<uint8_t const*>(marker) + TransactionIdOffset(type), sizeof(TRI_voc_tid_t));
return encoding::readNumber<TRI_voc_tid_t>(reinterpret_cast<uint8_t const*>(marker) + TransactionIdOffset(type), sizeof(TRI_voc_tid_t));
}
return 0;
}
@ -304,8 +267,8 @@ static inline TRI_df_prologue_marker_t CreatePrologueMarker(TRI_voc_tick_t datab
TRI_df_prologue_marker_t header;
InitMarker(reinterpret_cast<TRI_df_marker_t*>(&header), TRI_DF_MARKER_PROLOGUE, sizeof(TRI_df_prologue_marker_t));
StoreNumber<decltype(databaseId)>(reinterpret_cast<uint8_t*>(&header) + DatabaseIdOffset(TRI_DF_MARKER_PROLOGUE), databaseId, sizeof(decltype(databaseId)));
StoreNumber<decltype(collectionId)>(reinterpret_cast<uint8_t*>(&header) + CollectionIdOffset(TRI_DF_MARKER_PROLOGUE), collectionId, sizeof(decltype(collectionId)));
encoding::storeNumber<decltype(databaseId)>(reinterpret_cast<uint8_t*>(&header) + DatabaseIdOffset(TRI_DF_MARKER_PROLOGUE), databaseId, sizeof(decltype(databaseId)));
encoding::storeNumber<decltype(collectionId)>(reinterpret_cast<uint8_t*>(&header) + CollectionIdOffset(TRI_DF_MARKER_PROLOGUE), collectionId, sizeof(decltype(collectionId)));
return header;
}

View File

@ -29,6 +29,7 @@
#include "Basics/StringUtils.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h"
#include "Basics/encoding.h"
#include "Basics/files.h"
#include "Random/RandomGenerator.h"
#include "RestServer/DatabaseFeature.h"
@ -1870,7 +1871,7 @@ bool MMFilesEngine::checkDatafileHeader(MMFilesDatafile* datafile, std::string c
// skip the datafile header
ptr +=
MMFilesDatafileHelper::AlignedSize<size_t>(sizeof(TRI_df_header_marker_t));
encoding::alignedSize<size_t>(sizeof(TRI_df_header_marker_t));
TRI_col_header_marker_t const* cm =
reinterpret_cast<TRI_col_header_marker_t const*>(ptr);
@ -2199,7 +2200,7 @@ char* MMFilesEngine::nextFreeMarkerPosition(
TRI_df_marker_type_t type, TRI_voc_size_t size, MMFilesCollectorCache* cache) {
// align the specified size
size = MMFilesDatafileHelper::AlignedSize<TRI_voc_size_t>(size);
size = encoding::alignedSize<TRI_voc_size_t>(size);
char* dst = nullptr; // will be modified by reserveJournalSpace()
MMFilesDatafile* datafile = nullptr; // will be modified by reserveJournalSpace()

View File

@ -23,6 +23,7 @@
#include "MMFilesWalLogfile.h"
#include "Basics/FileUtils.h"
#include "Basics/encoding.h"
#include "Basics/files.h"
#include "MMFiles/MMFilesDatafileHelper.h"
@ -92,6 +93,6 @@ MMFilesWalLogfile* MMFilesWalLogfile::openExisting(std::string const& filename,
/// @brief reserve space and update the current write position
char* MMFilesWalLogfile::reserve(size_t size) {
return _df->advanceWritePosition(MMFilesDatafileHelper::AlignedSize<size_t>(size));
return _df->advanceWritePosition(encoding::alignedSize<size_t>(size));
}

View File

@ -25,6 +25,7 @@
#define ARANGOD_STORAGE_ENGINE_MMFILES_WAL_MARKER_H 1
#include "Basics/Common.h"
#include "Basics/encoding.h"
#include "MMFiles/MMFilesDatafile.h"
#include "MMFiles/MMFilesDatafileHelper.h"
#include "VocBase/voc-types.h"
@ -148,7 +149,7 @@ class MMFilesCrudMarker : public MMFilesWalMarker {
/// @brief store the marker in the memory region starting at mem
void store(char* mem) const override final {
// store transaction id
MMFilesDatafileHelper::StoreNumber<decltype(_transactionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::TransactionIdOffset(_type), _transactionId, sizeof(decltype(_transactionId)));
encoding::storeNumber<decltype(_transactionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::TransactionIdOffset(_type), _transactionId, sizeof(decltype(_transactionId)));
// store VPack
memcpy(mem + MMFilesDatafileHelper::VPackOffset(_type), _data.begin(), static_cast<size_t>(_data.byteSize()));
}
@ -192,7 +193,7 @@ class MMFilesDatabaseMarker : public MMFilesWalMarker {
/// @brief store the marker in the memory region starting at mem
void store(char* mem) const override final {
// store database id
MMFilesDatafileHelper::StoreNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
encoding::storeNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
// store VPack
memcpy(mem + MMFilesDatafileHelper::VPackOffset(_type), _data.begin(), static_cast<size_t>(_data.byteSize()));
}
@ -237,9 +238,9 @@ class MMFilesCollectionMarker : public MMFilesWalMarker {
/// @brief store the marker in the memory region starting at mem
void store(char* mem) const override final {
// store database id
MMFilesDatafileHelper::StoreNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
encoding::storeNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
// store collection id
MMFilesDatafileHelper::StoreNumber<decltype(_collectionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::CollectionIdOffset(_type), _collectionId, sizeof(decltype(_collectionId)));
encoding::storeNumber<decltype(_collectionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::CollectionIdOffset(_type), _collectionId, sizeof(decltype(_collectionId)));
// store VPack
memcpy(mem + MMFilesDatafileHelper::VPackOffset(_type), _data.begin(), static_cast<size_t>(_data.byteSize()));
}
@ -283,9 +284,9 @@ class MMFilesTransactionMarker : public MMFilesWalMarker {
/// @brief store the marker in the memory region starting at mem
void store(char* mem) const override final {
// store database id
MMFilesDatafileHelper::StoreNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
encoding::storeNumber<decltype(_databaseId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::DatabaseIdOffset(_type), _databaseId, sizeof(decltype(_databaseId)));
// store transaction id
MMFilesDatafileHelper::StoreNumber<decltype(_transactionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::TransactionIdOffset(_type), _transactionId, sizeof(decltype(_transactionId)));
encoding::storeNumber<decltype(_transactionId)>(reinterpret_cast<uint8_t*>(mem) + MMFilesDatafileHelper::TransactionIdOffset(_type), _transactionId, sizeof(decltype(_transactionId)));
}
private:

View File

@ -24,15 +24,16 @@
#include "MMFilesWalSlots.h"
#include "Basics/ConditionLocker.h"
#include "Basics/MutexLocker.h"
#include "Basics/encoding.h"
#include "Logger/Logger.h"
#include "MMFiles/MMFilesDatafile.h"
#include "MMFiles/MMFilesDatafileHelper.h"
#include "VocBase/ticks.h"
#include "MMFiles/MMFilesLogfileManager.h"
#include "VocBase/ticks.h"
using namespace arangodb;
static uint32_t const PrologueSize = MMFilesDatafileHelper::AlignedSize<uint32_t>(sizeof(TRI_df_prologue_marker_t));
static uint32_t const PrologueSize = encoding::alignedSize<uint32_t>(sizeof(TRI_df_prologue_marker_t));
/// @brief create the slots
MMFilesWalSlots::MMFilesWalSlots(MMFilesLogfileManager* logfileManager, size_t numberOfSlots,
@ -130,7 +131,7 @@ MMFilesWalSlotInfo MMFilesWalSlots::nextUnused(TRI_voc_tick_t databaseId, TRI_vo
uint32_t size) {
// we need to use the aligned size for writing
uint32_t alignedSize = MMFilesDatafileHelper::AlignedSize<uint32_t>(size);
uint32_t alignedSize = encoding::alignedSize<uint32_t>(size);
int iterations = 0;
bool hasWaited = false;
bool mustWritePrologue = false;

View File

@ -32,13 +32,13 @@
#include "Basics/StringUtils.h"
#include "Basics/Timers.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/encoding.h"
#include "Cluster/ClusterComm.h"
#include "Cluster/ClusterMethods.h"
#include "Cluster/FollowerInfo.h"
#include "Cluster/ServerState.h"
#include "Indexes/Index.h"
#include "Logger/Logger.h"
#include "MMFiles/MMFilesDatafileHelper.h"
#include "MMFiles/MMFilesLogfileManager.h"
#include "MMFiles/MMFilesPrimaryIndex.h"
#include "MMFiles/MMFilesIndexElement.h"
@ -690,7 +690,7 @@ std::string transaction::Methods::makeIdFromCustom(CollectionNameResolver const*
TRI_ASSERT(id.isCustom() && id.head() == 0xf3);
TRI_ASSERT(key.isString());
uint64_t cid = MMFilesDatafileHelper::ReadNumber<uint64_t>(id.begin() + 1, sizeof(uint64_t));
uint64_t cid = encoding::readNumber<uint64_t>(id.begin() + 1, sizeof(uint64_t));
std::string resolved = resolver->getCollectionNameCluster(cid);
#ifdef USE_ENTERPRISE

View File

@ -32,6 +32,7 @@
#include "Basics/Timers.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h"
#include "Basics/encoding.h"
#include "Basics/process-utils.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterMethods.h"
@ -2697,10 +2698,10 @@ int LogicalCollection::newObjectForInsert(
// _statisticsRaw and _statistics15 (which are the only system
// collections)
// must not be treated as shards but as local collections
MMFilesDatafileHelper::StoreNumber<uint64_t>(p, _planId, sizeof(uint64_t));
encoding::storeNumber<uint64_t>(p, _planId, sizeof(uint64_t));
} else {
// local server
MMFilesDatafileHelper::StoreNumber<uint64_t>(p, _cid, sizeof(uint64_t));
encoding::storeNumber<uint64_t>(p, _cid, sizeof(uint64_t));
}
// _from and _to

73
lib/Basics/encoding.h Normal file
View File

@ -0,0 +1,73 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_BASICS_ENCODING_H
#define ARANGODB_BASICS_ENCODING_H 1
#include "Basics/Common.h"
namespace arangodb {
namespace encoding {
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the 8-byte aligned size for the value
////////////////////////////////////////////////////////////////////////////////
template <typename T, size_t alignment = 8>
static constexpr inline T alignedSize(T value) {
return (value + (alignment - 1)) - ((value + (alignment - 1)) & (alignment - 1));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief portably and safely reads a number
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static inline T readNumber(uint8_t const* source, uint32_t length) {
T value = 0;
uint64_t x = 0;
uint8_t const* end = source + length;
do {
value += static_cast<T>(*source++) << x;
x += 8;
} while (source < end);
return value;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief portably and safely stores a number
////////////////////////////////////////////////////////////////////////////////
template <typename T>
static inline void storeNumber(uint8_t* dest, T value, uint32_t length) {
uint8_t* end = dest + length;
do {
*dest++ = static_cast<uint8_t>(value & 0xff);
value >>= 8;
} while (dest < end);
}
}
}
#endif