[base] id generator is added

This commit is contained in:
Arsentiy Milchakov 2020-05-27 12:00:53 +03:00 committed by mpimenov
parent e525c3d7ae
commit 0c73ac5fea
4 changed files with 104 additions and 0 deletions

View file

@ -33,6 +33,7 @@ set(
get_time.hpp
gmtime.cpp
gmtime.hpp
id_generator.hpp
internal/message.cpp
internal/message.hpp
levenshtein_dfa.cpp

View file

@ -17,6 +17,7 @@ set(
condition_test.cpp
containers_test.cpp
control_flow_tests.cpp
id_generator_tests.cpp
fifo_cache_test.cpp
file_name_utils_tests.cpp
geo_object_id_tests.cpp

View file

@ -0,0 +1,33 @@
#include "testing/testing.hpp"
#include "base/id_generator.hpp"
#include <limits>
#include <string>
#include <vector>
UNIT_TEST(IdGenerator_Smoke)
{
auto const initial = base::IdGenerator<uint8_t>::GetInitialId();
TEST_EQUAL(initial, "1", ());
auto constexpr kOverflowCount = 5;
auto constexpr kItemsCount = std::numeric_limits<uint8_t>::max();
auto id = initial;
auto i = 2;
for (auto k = 0; k < kOverflowCount; ++k)
{
for (; i <= kItemsCount; ++i)
{
std::string target;
for (auto j = 0; j < k; ++j)
target += std::to_string(kItemsCount);
target += std::to_string(i);
id = base::IdGenerator<uint8_t>::GetNextId(id);
TEST_EQUAL(target, id, ());
}
i = 1;
}
}

69
base/id_generator.hpp Normal file
View file

@ -0,0 +1,69 @@
#pragma once
#include "base/string_utils.hpp"
#include <string>
#include <type_traits>
#include <vector>
namespace base
{
// Simple id generator which increments received value and concatenates when
// BaseIntegralUnsigned max value is reached.
template <typename BaseIntegralUnsigned = uint64_t>
class IdGenerator
{
public:
static_assert(std::is_integral<BaseIntegralUnsigned>::value, "Integral types is supported only");
static_assert(std::is_unsigned<BaseIntegralUnsigned>::value, "Unsigned types is supported only");
using Id = std::string;
static Id GetInitialId()
{
return std::to_string(kMinIdInternal);
}
static Id GetNextId(Id const & id)
{
std::vector<Id> idParts;
auto first = id.begin();
auto last = id.end();
while (last - first > kMaxSymbolsIdInternal)
{
idParts.emplace_back(first, first + kMaxSymbolsIdInternal);
first += kMaxSymbolsIdInternal;
}
idParts.emplace_back(first, last);
IdInternal internalId;
if (!strings::to_any(idParts.back(), internalId))
return {};
auto const newId = MakeNextInternalId(internalId);
if (newId < internalId)
idParts.emplace_back(std::to_string(newId));
else
idParts.back() = std::to_string(newId);
return strings::JoinAny(idParts, "");
}
private:
using IdInternal = BaseIntegralUnsigned;
static IdInternal constexpr kIncorrectId = 0;
static IdInternal constexpr kMinIdInternal = 1;
static IdInternal constexpr kMaxIdInternal = std::numeric_limits<IdInternal>::max();
static auto constexpr kMaxSymbolsIdInternal = std::numeric_limits<IdInternal>::digits10 + 1;
static constexpr IdInternal MakeNextInternalId(IdInternal id)
{
if (id == kMaxIdInternal)
return kMinIdInternal;
return ++id;
}
};
} // namespace base