Browse Source

* implemented handle manager

* fixed some bugs in linq
own_hana
bergmann 6 years ago
parent
commit
c764a47d5e
5 changed files with 1405 additions and 112 deletions
  1. +1004
    -0
      src/cpputils/HandleManager.h
  2. +35
    -108
      src/cpputils/Linq.h
  3. +168
    -1
      src/cpputils/Misc.h
  4. +122
    -0
      test/HandleManagerTests.cpp
  5. +76
    -3
      test/LinqTests.cpp

+ 1004
- 0
src/cpputils/HandleManager.h
File diff suppressed because it is too large
View File


+ 35
- 108
src/cpputils/Linq.h View File

@@ -5,6 +5,7 @@
#include <list>
#include <vector>

#include "Misc.h"
#include "Nullable.h"
#include "Exception.h"
#include "MetaProgramming.h"
@@ -49,87 +50,11 @@ namespace linq
using mp_range_value_type = typename utl::mp_remove_ref<T>::value_type;

/* helper types **************************************************************************/
template<class T>
struct wrapper
{
using value_type = T;

value_type value;

inline value_type operator*() const
{ return value; }

inline wrapper& operator=(const wrapper& other)
{
value = other.value;
return *this;
}

inline wrapper& operator=(wrapper&& other)
{
value = std::move(other).value;
return *this;
}

template<class X>
inline wrapper(X&& v) :
value(std::forward<X>(v))
{ }

inline wrapper(const value_type& v) :
value(v)
{ }

inline wrapper(const wrapper& other) :
value(other.value)
{ }

inline wrapper(wrapper&& other) :
value(std::move(other.value))
{ }
};

template<class T>
struct wrapper<T&>
{
using value_type = T&;
using storage_type = T*;

storage_type value;

inline value_type operator*() const
{ return *value; }

inline wrapper& operator=(const wrapper& other)
{
value = other.value;
return *this;
}

inline wrapper& operator=(wrapper&& other)
{
value = std::move(other.value);
return *this;
}

inline wrapper(value_type v) :
value(&v)
{ }

inline wrapper(const wrapper& other) :
value(other.value)
{ }

inline wrapper(wrapper&& other) :
value(std::move(other.value))
{ }
};

template<class T, class TPredicate>
struct op_wrapper_less
{
using predicate_type = TPredicate;
using value_type = wrapper<T>;
using value_type = utl::wrapper<T>;

predicate_type predicate;

@@ -194,24 +119,19 @@ namespace linq
using clean_key_type = utl::mp_remove_ref<key_type>;
using value_type = TValue;
using this_type = lookup<key_type, value_type>;
using wrapped_key_type = wrapper<key_type>;
using wrapped_value_type = wrapper<value_type>;
using wrapped_key_type = utl::wrapper<key_type>;
using wrapped_value_type = utl::wrapper<value_type>;
using keys_value_type = std::pair<wrapped_key_type, size_t>;
using keys_type = std::vector<keys_value_type>;
using values_type = std::vector<wrapped_value_type>;
using range_indices_type = std::pair<size_t, size_t>;

private:
struct lookup_range;
struct lookup_key_value_range;

using lookup_range_wrapper = range_wrapper<lookup_range>;
using lookup_key_value_range_wrapper = range_wrapper<lookup_key_value_range>;

public:
using range_type = lookup_key_value_range_wrapper;

private:
struct lookup_range : public tag_range
{
using value_type = lookup::value_type;
@@ -223,10 +143,10 @@ namespace linq
Finished,
};

const values_type& values;
size_t current;
size_t end;
State state;
values_type& values;
size_t current;
size_t end;
State state;

inline value_type& front()
{
@@ -258,7 +178,7 @@ namespace linq
}
}

inline lookup_range(const values_type& v, size_t c, size_t e) :
inline lookup_range(values_type& v, size_t c, size_t e) :
values (v),
current (c),
end (e),
@@ -273,10 +193,10 @@ namespace linq
{ LINQ_COPY_CTOR(); }

inline lookup_range(lookup_range&& other) :
values (std::move(other.values)),
current (std::move(other.current)),
end (std::move(other.end)),
state (std::move(other.state))
values (std::move(other).values),
current (std::move(other).current),
end (std::move(other).end),
state (std::move(other).state)
{ LINQ_MOVE_CTOR(); }

inline ~lookup_range()
@@ -562,8 +482,9 @@ namespace linq
return (current != std::end(container));
}

inline container_range(container_type& c) noexcept :
container (c),
template<class C>
inline container_range(C&& c) noexcept :
container (std::forward<C>(c)),
initialized (false)
{ LINQ_CTOR(); }

@@ -737,8 +658,8 @@ namespace linq
template<class T>
struct __impl_make_inner_range
{
using iterator_type = decltype(std::begin(std::declval<T>()));
using type = iterator_range<iterator_type>;
using container_type = T;
using type = container_range<container_type>;
};

template<class T>
@@ -762,13 +683,13 @@ namespace linq

template<class T>
inline typename std::enable_if<std::is_base_of<tag_range, T>::value>::type
build_inner_range(T value)
build_inner_range(T&& value)
{ inner_range = value; }

template<class T>
inline typename std::enable_if<!std::is_base_of<tag_range, T>::value>::type
build_inner_range(T value)
{ inner_range = inner_range_type(std::begin(value), std::end(value)); }
build_inner_range(T&& value)
{ inner_range = inner_range_type(std::forward<T>(value)); }

inline value_type& front()
{
@@ -824,7 +745,7 @@ namespace linq
using less_predicate_type = TLessPredicate;
using this_type = order_by_range<range_type, select_predicate_type, less_predicate_type>;
using value_type = mp_range_value_type<range_type>;
using wrapped_value_type = wrapper<value_type>;
using wrapped_value_type = utl::wrapper<value_type>;
using vector_type = std::vector<wrapped_value_type>;

range_type range;
@@ -858,7 +779,7 @@ namespace linq
this->select_predicate(*l),
this->select_predicate(*r));
});
current = 0;
return true;
}
@@ -904,7 +825,7 @@ namespace linq
using less_predicate_type = TLessPredicate;
using this_type = distinct_range<range_type, less_predicate_type>;
using value_type = mp_range_value_type<range_type>;
using set_value_type = wrapper<value_type>;
using set_value_type = utl::wrapper<value_type>;
using set_less_type = op_wrapper_less<value_type, less_predicate_type>;
using set_type = std::set<set_value_type, set_less_type>;

@@ -1277,7 +1198,7 @@ namespace linq
inline auto build(TRange&& range)
{
using range_value_type = mp_range_value_type<TRange>;
using value_type = utl::mp_remove_ref<range_value_type>;
using value_type = utl::mp_remove_const<utl::mp_remove_ref<range_value_type>>;
using vector_type = std::vector<value_type>;

vector_type ret;
@@ -1418,11 +1339,11 @@ namespace linq
struct op_select_key_default
{
template<class TKey, class TValue>
inline auto operator()(std::pair<TKey, TValue>& p)
inline auto operator()(std::pair<TKey, TValue> p)
{ return p.first; }

template<class TKey, class TValue>
inline auto operator()(std::tuple<TKey, TValue>& t)
inline auto operator()(std::tuple<TKey, TValue> t)
{ return std::get<0>(t); }

template<class T>
@@ -1433,11 +1354,11 @@ namespace linq
struct op_select_value_default
{
template<class TKey, class TValue>
inline auto operator()(std::pair<TKey, TValue>& p)
inline auto operator()(std::pair<TKey, TValue> p)
{ return p.second; }

template<class TKey, class TValue>
inline auto operator()(std::tuple<TKey, TValue>& t)
inline auto operator()(std::tuple<TKey, TValue> t)
{ return std::get<1>(t); }

template<class T>
@@ -1570,4 +1491,10 @@ namespace linq

inline auto to_lookup()
{ return to_lookup(std::move(op_select_key_default()), std::move(op_select_value_default())); }

template <class TKey, class TValue>
using lookup_value_range_type = typename __impl::lookup<TKey, TValue>::lookup_range_wrapper;

template <class TKey, class TValue>
using lookup_key_value_range_type = typename __impl::lookup<TKey, TValue>::lookup_key_value_range_wrapper;
}

+ 168
- 1
src/cpputils/Misc.h View File

@@ -3,6 +3,17 @@
#include <cxxabi.h>
#include <iostream>

#if defined(__linux__)
# include <endian.h>
#elif defined(__FreeBSD__) || defined(__NetBSD__)
# include <sys/endian.h>
#elif defined(__OpenBSD__)
# include <sys/types.h>
# define be16toh(x) betoh16(x)
# define be32toh(x) betoh32(x)
# define be64toh(x) betoh64(x)
#endif

namespace utl
{

@@ -19,6 +30,104 @@ namespace utl
}
};

/* simple class that stores a value of type T */
template<class T>
struct wrapper
{
using value_type = T;

value_type value;

inline value_type& operator*()
{ return value; }

inline const value_type& operator*() const
{ return value; }

inline wrapper& operator=(const value_type v)
{
value = v;
return *this;
}

inline wrapper& operator=(const wrapper& other)
{
value = other.value;
return *this;
}

inline wrapper& operator=(wrapper&& other)
{
value = std::move(other).value;
return *this;
}

inline wrapper() :
value(value_type())
{ }

inline wrapper(const value_type& v) :
value(v)
{ }

inline wrapper(const wrapper& other) :
value(other.value)
{ }

inline wrapper(wrapper&& other) :
value(std::move(other.value))
{ }
};

template<class T>
struct wrapper<T&>
{
using value_type = T&;
using storage_type = T*;

storage_type value;

inline value_type operator*() const
{
assert(value != nullptr);
return *value;
}

inline wrapper& operator=(const value_type v)
{
value = &v;
return *this;
}

inline wrapper& operator=(const wrapper& other)
{
value = other.value;
return *this;
}

inline wrapper& operator=(wrapper&& other)
{
value = std::move(other.value);
return *this;
}

inline wrapper() :
value(nullptr)
{ }

inline wrapper(value_type v) :
value(&v)
{ }

inline wrapper(const wrapper& other) :
value(other.value)
{ }

inline wrapper(wrapper&& other) :
value(std::move(other.value))
{ }
};

/* Helper Methods ****************************************************************************/
inline int bitCount(uint32_t u)
{
@@ -29,12 +138,27 @@ namespace utl
}

template<class T, class S>
bool tryCast(T* t, S*& s)
inline bool tryCast(T* t, S*& s)
{
s = dynamic_cast<S*>(t);
return static_cast<bool>(s);
}

namespace __impl
{
template<class T, size_t N = sizeof(T)>
struct network_convert_helper;
}

template<class T>
inline T hton(const T& value)
{ return __impl::network_convert_helper<T>::hton(value); }

template<class T>
inline T ntoh(const T& value)
{ return __impl::network_convert_helper<T>::ntoh(value); }


/* Indent Stream *****************************************************************************/
namespace __impl
{
@@ -67,4 +191,47 @@ namespace utl
return os;
}

/* implementation ****************************************************************************/
namespace __impl
{
template<class T>
struct network_convert_helper<T, 1>
{
static inline T hton(const T& t)
{ return t; }

static inline T ntoh(const T& t)
{ return t; }
};

template<class T>
struct network_convert_helper<T, 2>
{
static inline T hton(const T& t)
{ return reinterpret_cast<T>(htobe16(reinterpret_cast<uint16_t>(t))); }

static inline T ntoh(const T& t)
{ return reinterpret_cast<T>(be16toh(reinterpret_cast<uint16_t>(t))); }
};

template<class T>
struct network_convert_helper<T, 4>
{
static inline T hton(const T& t)
{ return reinterpret_cast<T>(htobe32(reinterpret_cast<uint32_t>(t))); }

static inline T ntoh(const T& t)
{ return reinterpret_cast<T>(be32toh(reinterpret_cast<uint32_t>(t))); }
};

template<class T>
struct network_convert_helper<T, 8>
{
static inline T hton(const T& t)
{ return reinterpret_cast<T>(htobe64(reinterpret_cast<uint64_t>(t))); }

static inline T ntoh(const T& t)
{ return reinterpret_cast<T>(be64toh(reinterpret_cast<uint64_t>(t))); }
};
}
}

+ 122
- 0
test/HandleManagerTests.cpp View File

@@ -0,0 +1,122 @@
#include <gtest/gtest.h>
#include "../src/cpputils/StringHelper.h"
#include "../src/cpputils/HandleManager.h"

using namespace utl;

using HandleManagerInt = utl::HandleManager<int>;

TEST(HandleManagerTest, fromString_toString)
{
Handle handle;
EXPECT_FALSE(tryFromString("11-22-3344-5566778", handle));
EXPECT_TRUE (tryFromString("11-22-3344-55667788", handle));
EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle));
EXPECT_TRUE (tryFromString("1122-3344-55667788", handle));
EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle));
EXPECT_TRUE (tryFromString("11-223344-55667788", handle));
EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle));
EXPECT_TRUE (tryFromString("11-22-334455667788", handle));
EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle));
EXPECT_TRUE (tryFromString("1122334455667788", handle));
EXPECT_EQ (std::string("11-22-3344-55667788"), toString(handle));
}

TEST(HandleManagerTest, insert)
{
HandleManagerInt manager;
auto handle = manager.insert(0, 0, 123);
EXPECT_TRUE(static_cast<bool>(handle));
}

TEST(HandleManagerTest, remove)
{
HandleManagerInt manager;
auto handle = manager.insert(0, 0, 123);
EXPECT_FALSE(manager.remove(156161));
EXPECT_FALSE(manager.remove(1136));
EXPECT_FALSE(manager.remove(627624));
EXPECT_FALSE(manager.remove(0));
EXPECT_TRUE (manager.remove(handle));
}

TEST(HandleManagerTest, clear)
{
HandleManagerInt manager;
auto handle1 = manager.insert(0, 0, 123);
manager.clear();
auto handle2 = manager.insert(0, 0, 555);
EXPECT_EQ(handle1, handle2);
}

TEST(HandleManagerTest, isValid)
{
HandleManagerInt manager;
EXPECT_FALSE(manager.isValid(0));
EXPECT_FALSE(manager.isValid(123));
EXPECT_FALSE(manager.isValid(51627));
EXPECT_FALSE(manager.isValid(1513));
EXPECT_FALSE(manager.isValid(16621));

auto handle = manager.insert(0, 0, 123);
EXPECT_TRUE(manager.isValid(handle));
}

TEST(HandleManagerTest, tryGet)
{
int val;
HandleManagerInt manager;
EXPECT_FALSE(manager.tryGet(123, val));
EXPECT_FALSE(manager.tryGet(5132, val));
EXPECT_FALSE(manager.tryGet(6216, val));
EXPECT_FALSE(manager.tryGet(15616724, val));
EXPECT_FALSE(manager.tryGet(12353, val));

auto handle = manager.insert(1, 2, 555);
EXPECT_TRUE(manager.tryGet(handle, val));
EXPECT_EQ (555, val);
}

TEST(HandleManagerTest, get)
{
int val;
HandleManagerInt manager;
EXPECT_ANY_THROW(manager.get(123));
EXPECT_ANY_THROW(manager.get(5132));
EXPECT_ANY_THROW(manager.get(6216));
EXPECT_ANY_THROW(manager.get(15616724));
EXPECT_ANY_THROW(manager.get(12353));

auto handle = manager.insert(1, 2, 555);
EXPECT_EQ(555, manager.get(handle));
}

TEST(HandleManagerTest, update)
{
int val;
HandleManagerInt manager;
EXPECT_FALSE(manager.update(123, 555));
EXPECT_FALSE(manager.update(5132, 555));
EXPECT_FALSE(manager.update(6216, 555));
EXPECT_FALSE(manager.update(15616724, 555));
EXPECT_FALSE(manager.update(12353, 555));

auto handle = manager.insert(1, 2, 555);
EXPECT_TRUE(manager.update(handle, 554));
EXPECT_EQ (554, manager.get(handle));
}

TEST(HandleManagerTest, set)
{
HandleManagerInt manager;
auto handle = fromString<utl::Handle>("00-00-0001-00000000");
EXPECT_TRUE (manager.set(handle, 555));
EXPECT_EQ (555, manager.get(handle));

handle = fromString<utl::Handle>("00-00-0001-00000000");
EXPECT_TRUE (manager.set(handle, 554));
EXPECT_EQ (554, manager.get(handle));

EXPECT_FALSE(manager.set(fromString<utl::Handle>("00-00-0002-00000000"), 553));
EXPECT_EQ (554, manager.get(handle));
}

+ 76
- 3
test/LinqTests.cpp View File

@@ -488,11 +488,11 @@ TEST(LinqTest, to_lookup)
ASSERT_EQ (std::string("Str2-1"), range2.front());
ASSERT_FALSE(range2.next());

using lookup_type = decltype(lookup);
using key_value_range_type = linq::lookup_key_value_range_type<int&, std::string&>;
auto map = lookup
>> to_map([](lookup_type::range_type::value_type v){
>> to_map([](key_value_range_type::value_type v){
return v.first;
}, [](lookup_type::range_type::value_type v){
}, [](key_value_range_type::value_type v){
return v.second >> to_vector();
});

@@ -505,6 +505,79 @@ TEST(LinqTest, to_lookup)
EXPECT_EQ(expected, map);
}

struct StationMock
{
uint32_t id;
std::string name1;
std::string name2;
std::string name3;
std::string name4;
};

struct op_select_names
{
using pair_type = std::pair<std::string, uint32_t>;
using vector_type = std::vector<pair_type>;

inline void addToVec(vector_type& vec, const std::string& name, uint32_t sID)
{
if (name.empty())
return;
bool exists = from_container(vec)
>> select(op_select_key_default())
>> contains(name);
if (!exists)
vec.emplace_back(name, sID);
}

inline vector_type operator()(StationMock& s)
{
vector_type ret;
addToVec(ret, s.name1, s.id);
addToVec(ret, s.name2, s.id);
addToVec(ret, s.name3, s.id);
addToVec(ret, s.name4, s.id);
return ret;
}
};

void checkMapEntry(std::map<std::string, std::vector<uint32_t>>& map, std::string name, std::vector<uint32_t> ids)
{
auto it = map.find(name);
ASSERT_NE(it, map.end());
EXPECT_EQ(name, it->first);
EXPECT_EQ(ids, it->second);
}

TEST(LinqTest, to_lookup_2)
{
std::vector<StationMock> stations ({
{ 1, "sname11" , "sname12", "sname13", "sname14" },
{ 2, "sname21" , "sname21", "sname23", "sname24" },
{ 3, "sname11" , "sname31", "sname33", "sname34" },
});

using key_value_range_type = linq::lookup_key_value_range_type<std::string, uint32_t>;
auto myMap = linq::from_container(stations)
>> linq::select_many(op_select_names())
>> linq::to_lookup()
>> linq::to_map([](key_value_range_type::value_type p) {
return p.first;
}, [](key_value_range_type::value_type p) {
return p.second >> linq::to_vector();
});
checkMapEntry(myMap, "sname11", { 1, 3 });
checkMapEntry(myMap, "sname12", { 1 });
checkMapEntry(myMap, "sname13", { 1 });
checkMapEntry(myMap, "sname14", { 1 });
checkMapEntry(myMap, "sname21", { 2 });
checkMapEntry(myMap, "sname23", { 2 });
checkMapEntry(myMap, "sname24", { 2 });
checkMapEntry(myMap, "sname31", { 3 });
checkMapEntry(myMap, "sname33", { 3 });
checkMapEntry(myMap, "sname34", { 3 });
}

TEST(LinqTest, moveable_objects)
{
std::vector<MoveOnlyData> data;


Loading…
Cancel
Save