Commit c9a4440f authored by Anton Bukov's avatar Anton Bukov

Improve code and add tests

parent 08fb44cc
...@@ -429,7 +429,7 @@ namespace boolinq { ...@@ -429,7 +429,7 @@ namespace boolinq {
int count() const int count() const
{ {
int index = 0; int index = 0;
for_each([&index](T /**/a) { index++; }); for_each([&index](T /*a*/) { index++; });
return index; return index;
} }
...@@ -482,15 +482,14 @@ namespace boolinq { ...@@ -482,15 +482,14 @@ namespace boolinq {
T elect(std::function<T(T, T)> accumulate) const T elect(std::function<T(T, T)> accumulate) const
{ {
Linq<S, T> linq = *this;
T result; T result;
try { for_each_i([accumulate, &result](T value, int i) {
result = linq.next(); if (i == 0) {
while (true) { result = value;
result = accumulate(result, linq.next()); } else {
result = accumulate(result, value);
} }
} });
catch (LinqEndException &) {}
return result; return result;
} }
...@@ -534,7 +533,7 @@ namespace boolinq { ...@@ -534,7 +533,7 @@ namespace boolinq {
T first() const T first() const
{ {
return next(); return Linq<S, T>(*this).next();
} }
T firstOrDefault(std::function<bool(T)> predicate) const T firstOrDefault(std::function<bool(T)> predicate) const
...@@ -548,15 +547,25 @@ namespace boolinq { ...@@ -548,15 +547,25 @@ namespace boolinq {
T firstOrDefault() const T firstOrDefault() const
{ {
firstOrDefault([](T /*value*/) { return true; }); try {
return Linq<S, T>(*this).next();
}
catch (LinqEndException &) {}
return T();
} }
T last(std::function<bool(T)> predicate) const T last(std::function<bool(T)> predicate) const
{ {
T res; T res;
for_each([&res](T value) { int index = -1;
where(predicate).for_each_i([&res, &index](T value, int i) {
res = value; res = value;
index = i;
}); });
if (index == -1) {
throw LinqEndException();
}
return res; return res;
} }
...@@ -567,11 +576,11 @@ namespace boolinq { ...@@ -567,11 +576,11 @@ namespace boolinq {
T lastOrDefault(std::function<bool(T)> predicate) const T lastOrDefault(std::function<bool(T)> predicate) const
{ {
try { T res = T();
return last(predicate); where(predicate).for_each([&res](T value) {
} res = value;
catch (LinqEndException &) {} });
return T(); return res;
} }
T lastOrDefault() const T lastOrDefault() const
...@@ -769,10 +778,10 @@ namespace boolinq { ...@@ -769,10 +778,10 @@ namespace boolinq {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
template<typename T> template<typename T>
Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type> from(T begin, T end) Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type> from(const T & begin, const T & end)
{ {
return Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type>( return Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type>(
{begin, end}, std::make_pair(begin, end),
[](std::pair<T, T> &pair) { [](std::pair<T, T> &pair) {
if (pair.first == pair.second) { if (pair.first == pair.second) {
throw LinqEndException(); throw LinqEndException();
...@@ -783,60 +792,60 @@ namespace boolinq { ...@@ -783,60 +792,60 @@ namespace boolinq {
} }
template<typename T> template<typename T>
Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type> from(T it, int n) Linq<std::pair<T, T>, typename std::iterator_traits<T>::value_type> from(const T & it, int n)
{ {
return from(it, it + n); return from(it, it + n);
} }
template<typename T, int N> template<typename T, int N>
Linq<std::pair<T *, T *>, T> from(T (&array)[N]) Linq<std::pair<const T *, const T *>, T> from(T (&array)[N])
{ {
return from((T *)(&array), (T *)(&array) + N); return from((const T *)(&array), (const T *)(&array) + N);
} }
template<template<class> class TV, typename TT> template<template<class> class TV, typename TT>
auto from(const TV<TT> & container) auto from(const TV<TT> & container)
-> decltype(from(std::begin(container), std::end(container))) -> decltype(from(std::cbegin(container), std::cend(container)))
{ {
return from(std::begin(container), std::end(container)); return from(std::cbegin(container), std::cend(container));
} }
// std::list, std::vector, std::dequeue // std::list, std::vector, std::dequeue
template<template<class, class> class TV, typename TT, typename TU> template<template<class, class> class TV, typename TT, typename TU>
auto from(const TV<TT, TU> & container) auto from(const TV<TT, TU> & container)
-> decltype(from(std::begin(container), std::end(container))) -> decltype(from(std::cbegin(container), std::cend(container)))
{ {
return from(std::begin(container), std::end(container)); return from(std::cbegin(container), std::cend(container));
} }
// std::set // std::set
template<template<class, class, class> class TV, typename TT, typename TS, typename TU> template<template<class, class, class> class TV, typename TT, typename TS, typename TU>
auto from(const TV<TT, TS, TU> & container) auto from(const TV<TT, TS, TU> & container)
-> decltype(from(std::begin(container), std::end(container))) -> decltype(from(std::cbegin(container), std::cend(container)))
{ {
return from(std::begin(container), std::end(container)); return from(std::cbegin(container), std::cend(container));
} }
// std::map // std::map
template<template<class, class, class, class> class TV, typename TK, typename TT, typename TS, typename TU> template<template<class, class, class, class> class TV, typename TK, typename TT, typename TS, typename TU>
auto from(const TV<TK, TT, TS, TU> & container) auto from(const TV<TK, TT, TS, TU> & container)
-> decltype(from(std::begin(container), std::end(container))) -> decltype(from(std::cbegin(container), std::cend(container)))
{ {
return from(std::begin(container), std::end(container)); return from(std::cbegin(container), std::cend(container));
} }
// std::array // std::array
template<template<class, size_t> class TV, typename TT, size_t TL> template<template<class, size_t> class TV, typename TT, size_t TL>
auto from(const TV<TT, TL> & container) auto from(const TV<TT, TL> & container)
-> decltype(from(std::begin(container), std::end(container))) -> decltype(from(std::cbegin(container), std::cend(container)))
{ {
return from(std::begin(container), std::end(container)); return from(std::cbegin(container), std::cend(container));
} }
template<typename T> template<typename T>
Linq<std::pair<T, int>, T> repeat(T value, int count) { Linq<std::pair<T, int>, T> repeat(const T & value, int count) {
return Linq<std::pair<T, int>, T>( return Linq<std::pair<T, int>, T>(
{value, count}, std::make_pair(value, count),
[](std::pair<T, int> &pair) { [](std::pair<T, int> &pair) {
if (pair.second > 0) { if (pair.second > 0) {
pair.second--; pair.second--;
...@@ -848,12 +857,18 @@ namespace boolinq { ...@@ -848,12 +857,18 @@ namespace boolinq {
} }
template<typename T> template<typename T>
Linq<std::pair<std::pair<T, T>, T>, T> range(T start, T end, T step) { Linq<std::tuple<T, T, T>, T> range(const T & start, const T & end, const T & step) {
return Linq<std::pair<std::pair<T, T>, T>, T>( return Linq<std::tuple<T, T, T>, T>(
{{start, end}, step}, std::make_tuple(start, end, step),
[](std::pair<std::pair<T, T>, T> &tuple) { [](std::tuple<T, T, T> &tuple) {
if (tuple.first.first < tuple.first.second) { T &start = std::get<0>(tuple);
return *(tuple.first.first += tuple.second); T &end = std::get<1>(tuple);
T &step = std::get<2>(tuple);
T value = start;
if (value < end) {
start += step;
return value;
} }
throw LinqEndException(); throw LinqEndException();
} }
......
...@@ -32,14 +32,17 @@ SET ( ...@@ -32,14 +32,17 @@ SET (
${PROJECT_SOURCE_DIR}/test/DistinctTest.cpp ${PROJECT_SOURCE_DIR}/test/DistinctTest.cpp
${PROJECT_SOURCE_DIR}/test/DotCallTest.cpp ${PROJECT_SOURCE_DIR}/test/DotCallTest.cpp
${PROJECT_SOURCE_DIR}/test/ElementAtTest.cpp ${PROJECT_SOURCE_DIR}/test/ElementAtTest.cpp
${PROJECT_SOURCE_DIR}/test/FirstTest.cpp
${PROJECT_SOURCE_DIR}/test/ForEachTest.cpp ${PROJECT_SOURCE_DIR}/test/ForEachTest.cpp
${PROJECT_SOURCE_DIR}/test/GroupByTest.cpp ${PROJECT_SOURCE_DIR}/test/GroupByTest.cpp
${PROJECT_SOURCE_DIR}/test/CtorTest.cpp ${PROJECT_SOURCE_DIR}/test/CtorTest.cpp
${PROJECT_SOURCE_DIR}/test/LastTest.cpp
${PROJECT_SOURCE_DIR}/test/LinqTest.cpp ${PROJECT_SOURCE_DIR}/test/LinqTest.cpp
${PROJECT_SOURCE_DIR}/test/MaxTest.cpp ${PROJECT_SOURCE_DIR}/test/MaxTest.cpp
${PROJECT_SOURCE_DIR}/test/MinTest.cpp ${PROJECT_SOURCE_DIR}/test/MinTest.cpp
${PROJECT_SOURCE_DIR}/test/OrderByTest.cpp ${PROJECT_SOURCE_DIR}/test/OrderByTest.cpp
${PROJECT_SOURCE_DIR}/test/PrependTest.cpp ${PROJECT_SOURCE_DIR}/test/PrependTest.cpp
${PROJECT_SOURCE_DIR}/test/RangeTest.cpp
${PROJECT_SOURCE_DIR}/test/ReverseTest.cpp ${PROJECT_SOURCE_DIR}/test/ReverseTest.cpp
${PROJECT_SOURCE_DIR}/test/SelectTest.cpp ${PROJECT_SOURCE_DIR}/test/SelectTest.cpp
${PROJECT_SOURCE_DIR}/test/SelectManyTest.cpp ${PROJECT_SOURCE_DIR}/test/SelectManyTest.cpp
......
#include <list>
#include <vector>
#include <string>
#include <gtest/gtest.h>
#include "boolinq.h"
using namespace boolinq;
TEST(First, ThreeElements)
{
std::vector<int> src = {1,2,3};
EXPECT_EQ(1, from(src).first());
EXPECT_EQ(2, from(src).first([](int a){return a%2 == 0;}));
EXPECT_EQ(1, from(src).firstOrDefault());
EXPECT_EQ(2, from(src).firstOrDefault([](int a){return a%2 == 0;}));
}
TEST(First, OneElement)
{
std::vector<int> src = {1};
EXPECT_EQ(1, from(src).first());
EXPECT_THROW(from(src).first([](int a){return a%2 == 0;}), LinqEndException);
EXPECT_EQ(1, from(src).firstOrDefault());
EXPECT_EQ(0, from(src).firstOrDefault([](int a){return a%2 == 0;}));
}
TEST(First, NoneElements)
{
std::vector<int> src = {};
EXPECT_THROW(from(src).first(), LinqEndException);
EXPECT_THROW(from(src).first([](int a){return a%2 == 0;}), LinqEndException);
EXPECT_EQ(0, from(src).firstOrDefault());
EXPECT_EQ(0, from(src).firstOrDefault([](int a){return a%2 == 0;}));
}
#include <list>
#include <vector>
#include <string>
#include <gtest/gtest.h>
#include "boolinq.h"
using namespace boolinq;
TEST(Last, ThreeElements)
{
std::vector<int> src = {1,2,3};
EXPECT_EQ(3, from(src).last());
EXPECT_EQ(2, from(src).last([](int a){return a%2 == 0;}));
EXPECT_EQ(3, from(src).lastOrDefault());
EXPECT_EQ(2, from(src).lastOrDefault([](int a){return a%2 == 0;}));
}
TEST(Last, OneElement)
{
std::vector<int> src = {1};
EXPECT_EQ(1, from(src).last());
EXPECT_THROW(from(src).last([](int a){return a%2 == 0;}), LinqEndException);
EXPECT_EQ(1, from(src).lastOrDefault());
EXPECT_EQ(0, from(src).lastOrDefault([](int a){return a%2 == 0;}));
}
TEST(Last, NoneElements)
{
std::vector<int> src = {};
EXPECT_THROW(from(src).last(), LinqEndException);
EXPECT_THROW(from(src).last([](int a){return a%2 == 0;}), LinqEndException);
EXPECT_EQ(0, from(src).lastOrDefault());
EXPECT_EQ(0, from(src).lastOrDefault([](int a){return a%2 == 0;}));
}
...@@ -246,7 +246,7 @@ TEST(Linq, Creations) ...@@ -246,7 +246,7 @@ TEST(Linq, Creations)
vec.push_back(4); vec.push_back(4);
vec.push_back(5); vec.push_back(5);
int arr[] = {1,2,3,4,5}; int arr[] = {1,2,3,4,5};
// const int carr[] = {1,2,3,4,5}; //const int carr[] = {1,2,3,4,5};
int * ptr = static_cast<int *>(arr); int * ptr = static_cast<int *>(arr);
//const int * cptr = const_cast<int *>(arr); //const int * cptr = const_cast<int *>(arr);
......
#include <vector>
#include <string>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "boolinq.h"
using namespace boolinq;
TEST(Range, OneToFive)
{
int ans[] = {1,2,3,4};
CheckRangeEqArray(range(1,5,1), ans);
}
TEST(Range, OneToFiveStep2)
{
int ans[] = {1,3};
CheckRangeEqArray(range(1,5,2), ans);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment