Commit fab5a780 authored by k06a's avatar k06a

Initial commit

parents

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boolinq", "boolinq\boolinq.vcxproj", "{65AA3851-4457-48AB-BD08-83250D523D49}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{65AA3851-4457-48AB-BD08-83250D523D49}.Debug|Win32.ActiveCfg = Debug|Win32
{65AA3851-4457-48AB-BD08-83250D523D49}.Debug|Win32.Build.0 = Debug|Win32
{65AA3851-4457-48AB-BD08-83250D523D49}.Release|Win32.ActiveCfg = Release|Win32
{65AA3851-4457-48AB-BD08-83250D523D49}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
#pragma once
namespace boolinq
{
// all(xxx) and all(xxx,lambda)
template<typename R, typename F>
bool all(R r, F f)
{
while (!r.empty())
if (!f(r.popFront()))
return false;
return true;
}
template<typename R>
bool all(R r)
{
typedef typename R::value_type value_type;
return all(r,[](const value_type & a)->value_type{return a;});
}
// xxx.all() and xxx.all(lambda)
template<template<typename> class TLinq, typename R>
class All_mixin
{
public:
bool all() const
{
return boolinq::all(((TLinq<R>*)this)->r);
}
template<typename F>
bool all(F f) const
{
return boolinq::all(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "All.h"
using namespace boolinq;
TEST(All, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_TRUE(all(rng));
EXPECT_TRUE(all(rng,[](int a){return a>0;}));
EXPECT_TRUE(all(rng,[](int a){return a<4;}));
EXPECT_TRUE(all(rng,[](int a){return a>0 && a<4;}));
EXPECT_FALSE(all(rng,[](int a){return a>2;}));
EXPECT_FALSE(all(rng,[](int a){return a==1;}));
EXPECT_FALSE(all(rng,[](int a){return a<3;}));
}
TEST(All, ThreeIntsSecond)
{
std::vector<int> src;
src.push_back(0);
src.push_back(1);
src.push_back(2);
auto rng = range(src);
EXPECT_FALSE(all(rng));
EXPECT_TRUE(all(rng,[](int a){return a>=0;}));
EXPECT_TRUE(all(rng,[](int a){return a<=2;}));
EXPECT_TRUE(all(rng,[](int a){return a>=0 && a<=2;}));
EXPECT_FALSE(all(rng,[](int a){return a>1;}));
EXPECT_FALSE(all(rng,[](int a){return a==1;}));
EXPECT_FALSE(all(rng,[](int a){return a<2;}));
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// any(xxx) and any(xxx,lambda)
template<typename R, typename F>
bool any(R r, F f)
{
while (!r.empty())
if (f(r.popFront()))
return true;
return false;
}
template<typename R>
bool any(R r)
{
typedef typename R::value_type value_type;
return any(r,[](const value_type & a)->value_type{return a;});
}
// xxx.any() and xxx.any(lambda)
template<template<typename> class TLinq, typename R>
class Any_mixin
{
public:
bool any() const
{
return boolinq::any(((TLinq<R>*)this)->r);
}
template<typename F>
bool any(F f) const
{
return boolinq::any(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Any.h"
using namespace boolinq;
TEST(Any, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_TRUE(any(rng));
EXPECT_TRUE(any(rng,[](int a){return a==1;}));
EXPECT_TRUE(any(rng,[](int a){return a==2;}));
EXPECT_TRUE(any(rng,[](int a){return a==3;}));
EXPECT_TRUE(any(rng,[](int a){return a>1;}));
EXPECT_TRUE(any(rng,[](int a){return a<3;}));
EXPECT_TRUE(any(rng,[](int a){return a!=2;}));
EXPECT_FALSE(any(rng,[](int a){return a==0;}));
EXPECT_FALSE(any(rng,[](int a){return a==4;}));
EXPECT_FALSE(any(rng,[](int a){return a<1;}));
EXPECT_FALSE(any(rng,[](int a){return a>3;}));
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// avg(xxx) and avg(xxx,lambda)
template<typename R, typename F>
auto avg(R r, F f) -> decltype(f(r.front()) + f(r.back()))
{
typedef decltype(f(r.front()) + f(r.back())) value_type;
value_type val = value_type();
int count = 0;
for (; !r.empty(); r.popFront())
{
val = val + f(r.front());
count++;
}
return val/count;
}
template<typename R>
auto avg(R r) -> decltype(r.front() + r.back())
{
typedef decltype(r.front() + r.back()) value_type;
return avg(r,[](const value_type & a)->value_type{return a;});
}
// xxx.avg() and xxx.avg(lambda)
template<template<typename> class TLinq, typename R>
class Avg_mixin
{
template<typename F, typename TArg>
static auto get_return_type(F * f = NULL, TArg * arg = NULL)
-> decltype((*f)(*arg));
public:
//TODO: Invalid return type ... should be (value_type + value_type)
typename R::value_type avg() const
{
return boolinq::avg(((TLinq<R>*)this)->r);
}
template<typename F>
auto avg(F f) const -> decltype(get_return_type<F,typename R::value_type>()
+ get_return_type<F,typename R::value_type>())
{
return boolinq::avg(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <list>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Avg.h"
using namespace boolinq;
TEST(Avg, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(2, avg(rng));
}
TEST(Avg, FiveInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
auto rng = range(src);
auto dst0 = where(rng, [](int a){return a%2 == 0;});
auto dst1 = where(rng, [](int a){return a%2 == 1;});
EXPECT_EQ(3, avg(dst0));
EXPECT_EQ(3, avg(dst1));
}
TEST(Avg, FiveStringsLen)
{
std::vector<std::string> src;
src.push_back("hello");
src.push_back("apple");
src.push_back("nokia");
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
EXPECT_EQ(5, avg(rng,[](const std::string & str){return str.size();}));
}
#pragma once
#include <limits.h>
#include "BytesRange.h"
namespace boolinq
{
enum BitOrder
{
HighToLow,
LowToHigh,
};
template<typename R, BitOrder bitOrder = HighToLow>
class BitsRange
{
typedef typename R::value_type old_value_type;
enum
{
startBit = (bitOrder == LowToHigh) ? 0 : (CHAR_BIT-1),
finishBit = (bitOrder == LowToHigh) ? (CHAR_BIT-1) : 0,
stepBit = (bitOrder == LowToHigh) ? 1 : -1,
};
public:
typedef int value_type;
BitsRange(R rng)
: r(rng)
, frontBit(startBit)
, backBit(finishBit)
, atEnd(r.empty())
{
}
bool empty()
{
return atEnd;
}
value_type popFront()
{
value_type tmp = front();
if (checkEmpty())
return tmp;
if (frontBit != finishBit)
frontBit += stepBit;
else
{
frontBit = startBit;
r.popFront();
}
return tmp;
}
value_type popBack()
{
value_type tmp = back();
if (checkEmpty())
return tmp;
if (backBit != startBit)
backBit -= stepBit;
else
{
backBit = finishBit;
r.popBack();
}
return tmp;
}
value_type front()
{
return (r.front() >> frontBit) & 1;
}
value_type back()
{
return (r.back() >> backBit) & 1;
}
private:
bool checkEmpty()
{
R tmp = r;
tmp.popFront();
atEnd = tmp.empty() && (frontBit == backBit);
return atEnd;
}
private:
R r;
int frontBit;
int backBit;
bool atEnd;
};
// bits(xxx)
// bits<BitOrder>(xxx)
// bits<BitOrder,ByteOrder>(xxx)
template<typename R>
BitsRange<BytesRange<R> > bits(R r)
{
return boolinq::bytes(r);
}
template<BitOrder bitOrder, typename R>
BitsRange<BytesRange<R>,bitOrder> bits(R r)
{
return boolinq::bytes(r);
}
template<BitOrder bitOrder, ByteOrder byteOrder, typename R>
BitsRange<BytesRange<R,byteOrder>,bitOrder> bits(R r)
{
return boolinq::bytes<byteOrder>(r);
}
// xxx.bits()
// xxx.bits<BitOrder>()
// xxx.bits<BitOrder,ByteOrder>()
template<template<typename> class TLinq, typename R>
class BitsRange_mixin
{
public:
TLinq<BitsRange<BytesRange<R> > > bits() const
{
return boolinq::bits(((TLinq<R>*)this)->r);
}
template<BitOrder bitOrder>
TLinq<BitsRange<BytesRange<R>,bitOrder> > bits() const
{
return boolinq::bits<bitOrder>(((TLinq<R>*)this)->r);
}
template<BitOrder bitOrder, ByteOrder byteOrder>
TLinq<BitsRange<BytesRange<R,byteOrder>,bitOrder> > bits() const
{
return boolinq::bits<bitOrder,byteOrder>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "BitsRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(BitsRange, OneByteDefault)
{
unsigned char src[] = {0xAA};
int ans[] = {1,0,1,0,1,0,1,0};
auto rng = range(src);
auto dst = bits(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, OneByteHL)
{
unsigned char src[] = {0xAA};
int ans[] = {1,0,1,0,1,0,1,0};
auto rng = range(src);
auto dst = bits<HighToLow>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, OneByteLH)
{
unsigned char src[] = {0xAA};
int ans[] = {0,1,0,1,0,1,0,1};
auto rng = range(src);
auto dst = bits<LowToHigh>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(BitsRange, OneIntDefault)
{
unsigned int src[] = {0x12345678};
int ans[] =
{
0,1,1,1,1,0,0,0,
0,1,0,1,0,1,1,0,
0,0,1,1,0,1,0,0,
0,0,0,1,0,0,1,0,
};
auto rng = range(src);
auto dst = bits(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, OneIntHL)
{
unsigned int src[] = {0x12345678};
int ans[] =
{
0,1,1,1,1,0,0,0,
0,1,0,1,0,1,1,0,
0,0,1,1,0,1,0,0,
0,0,0,1,0,0,1,0,
};
auto rng = range(src);
auto dst = bits<HighToLow>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, OneIntLH)
{
unsigned int src[] = {0x12345678};
int ans[] =
{
0,0,0,1,1,1,1,0,
0,1,1,0,1,0,1,0,
0,0,1,0,1,1,0,0,
0,1,0,0,1,0,0,0,
};
auto rng = range(src);
auto dst = bits<LowToHigh,FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(BitsRange, IntsDefault)
{
unsigned int src[] = {0x12345678,0xAABBCCDD};
int ans[] =
{
0,1,1,1,1,0,0,0, // 78
0,1,0,1,0,1,1,0, // 56
0,0,1,1,0,1,0,0, // 34
0,0,0,1,0,0,1,0, // 12
1,1,0,1,1,1,0,1, // DD
1,1,0,0,1,1,0,0, // CC
1,0,1,1,1,0,1,1, // BB
1,0,1,0,1,0,1,0, // AA
};
auto rng = range(src);
auto dst = bits(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, IntsHL)
{
unsigned int src[] = {0x12345678,0xAABBCCDD};
int ans[] =
{
0,1,1,1,1,0,0,0, // 78
0,1,0,1,0,1,1,0, // 56
0,0,1,1,0,1,0,0, // 34
0,0,0,1,0,0,1,0, // 12
1,1,0,1,1,1,0,1, // DD
1,1,0,0,1,1,0,0, // CC
1,0,1,1,1,0,1,1, // BB
1,0,1,0,1,0,1,0, // AA
};
auto rng = range(src);
auto dst = bits<HighToLow>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BitsRange, IntsLH)
{
unsigned int src[] = {0x12345678,0xAABBCCDD};
int ans[] =
{
0,0,0,1,1,1,1,0, // -87
0,1,1,0,1,0,1,0, // -65
0,0,1,0,1,1,0,0, // -43
0,1,0,0,1,0,0,0, // -21
1,0,1,1,1,0,1,1, // -DD
0,0,1,1,0,0,1,1, // -CC
1,1,0,1,1,1,0,1, // -BB
0,1,0,1,0,1,0,1, // -AA
};
auto rng = range(src);
auto dst = bits<LowToHigh>(rng);
CheckRangeEqArray(dst, ans);
}
#pragma once
namespace boolinq
{
enum ByteOrder
{
FirstToLast,
LastToFirst,
};
template<typename R, ByteOrder byteOrder = FirstToLast>
class BytesRange
{
typedef typename R::value_type old_value_type;
enum
{
startByte = (byteOrder == FirstToLast) ? 0 : (sizeof(old_value_type)-1),
finishByte = (byteOrder == FirstToLast) ? (sizeof(old_value_type)-1) : 0,
stepByte = (byteOrder == FirstToLast) ? 1 : -1,
};
public:
typedef unsigned char value_type;
BytesRange(R rng)
: r(rng)
, frontByte(startByte)
, backByte(finishByte)
, atEnd(r.empty())
{
}
bool empty()
{
return atEnd;
}
value_type popFront()
{
value_type tmp = front();
if (checkEmpty())
return tmp;
if (frontByte != finishByte)
frontByte += stepByte;
else
{
frontByte = startByte;
r.popFront();
}
return tmp;
}
value_type popBack()
{
value_type tmp = back();
if (checkEmpty())
return tmp;
if (backByte != startByte)
backByte -= stepByte;
else
{
backByte = finishByte;
r.popBack();
}
return tmp;
}
value_type front()
{
old_value_type val = r.front();
return ((unsigned char *)&val)[frontByte];
}
value_type back()
{
old_value_type val = r.back();
return ((unsigned char *)&val)[backByte];
}
private:
bool checkEmpty()
{
R tmp = r;
tmp.popFront();
atEnd = tmp.empty() && (frontByte == backByte);
return atEnd;
}
private:
R r;
int frontByte;
int backByte;
bool atEnd;
};
// bytes(xxx)
// bytes<ByteOrder>(xxx)
template<typename R>
BytesRange<R> bytes(R r)
{
return r;
}
template<ByteOrder byteOrder, typename R>
BytesRange<R,byteOrder> bytes(R r)
{
return r;
}
// xxx.bytes(...)
// xxx.bytes<ByteOrder>(...)
template<template<typename> class TLinq, typename R>
class BytesRange_mixin
{
public:
TLinq<BytesRange<R> > bytes() const
{
return boolinq::bytes(((TLinq<R>*)this)->r);
}
template<ByteOrder byteOrder>
TLinq<BytesRange<R,byteOrder> > bytes() const
{
return boolinq::bytes<byteOrder>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "BytesRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(BytesRange, OneByteDefault)
{
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, OneByteFL)
{
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, OneByteLF)
{
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(BytesRange, OneIntDefault)
{
int src[] = {0x12345678};
int ans[] = {0x78,0x56,0x34,0x12};
auto rng = range(src);
auto dst = bytes(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, OneIntFL)
{
int src[] = {0x12345678};
int ans[] = {0x78,0x56,0x34,0x12};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, OneIntLF)
{
int src[] = {0x12345678};
int ans[] = {0x12,0x34,0x56,0x78};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(BytesRange, IntsDefault)
{
int src[] = {0x12345678, 0xAABBCCDD};
int ans[] =
{
0x78,0x56,0x34,0x12,
0xDD,0xCC,0xBB,0xAA,
};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, IntsFL)
{
int src[] = {0x12345678, 0xAABBCCDD};
int ans[] =
{
0x78,0x56,0x34,0x12,
0xDD,0xCC,0xBB,0xAA,
};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(BytesRange, IntsLF)
{
int src[] = {0x12345678, 0xAABBCCDD};
int ans[] =
{
0x12,0x34,0x56,0x78,
0xAA,0xBB,0xCC,0xDD,
};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
CheckRangeEqArray(dst, ans);
}
\ No newline at end of file
#pragma once
namespace boolinq
{
template<typename T, typename R>
class CastRange
{
public:
typedef T value_type;
CastRange(R r)
: r(r)
{
}
bool empty() { return r.empty(); }
value_type popFront() { return r.popFront(); }
value_type popBack() { return r.popBack(); }
value_type front() { return r.front(); }
value_type back() { return r.back(); }
private:
R r;
};
// Cast<double>(Cast<int>(xxx))
template<typename T, typename R>
CastRange<T,R> cast(R r)
{
return r;
}
// xxx.Cast<int>().Cast<double>()
template<template<typename> class TLinq, typename R>
class CastRange_mixin
{
public:
template<typename T>
TLinq<CastRange<T,R> > cast() const
{
return boolinq::cast<T>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#pragma once
//////////////////////////////////////////////////////////////////////////
// Compare Range with array
//////////////////////////////////////////////////////////////////////////
template<typename R, typename T, int N, typename F>
void CheckRangeEqArrayFront(R dst, T (&ans)[N], F f)
{
for (int i = 0; i < N; i++)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(f(ans[i]), f(dst.front()));
EXPECT_EQ(f(ans[N-1]), f(dst.back()));
EXPECT_EQ(f(ans[i]), f(dst.popFront()));
}
EXPECT_TRUE(dst.empty());
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqArrayBack(R dst, T (&ans)[N], F f)
{
for (int i = N; i > 0; i--)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(f(ans[0]), f(dst.front()));
EXPECT_EQ(f(ans[i-1]), f(dst.back()));
EXPECT_EQ(f(ans[i-1]), f(dst.popBack()));
}
EXPECT_TRUE(dst.empty());
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqArrayTwisted(R dst, T (&ans)[N], F f, int bit)
{
int b = 0;
int e = N-1;
for (int i = 0; i < N; i++)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(f(ans[b]), f(dst.front()));
EXPECT_EQ(f(ans[e]), f(dst.back()));
if (bit ^= 1)
EXPECT_EQ(f(ans[b++]), f(dst.popFront()));
else
EXPECT_EQ(f(ans[e--]), f(dst.popBack()));
}
EXPECT_TRUE(dst.empty());
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqArrayFrontBack(R dst, T (&ans)[N], F f)
{
CheckRangeEqArrayTwisted(dst,ans,f,0);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqArrayBackFront(R dst, T (&ans)[N], F f)
{
CheckRangeEqArrayTwisted(dst,ans,f,1);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqArray(R dst, T (&ans)[N], F f)
{
CheckRangeEqArrayFront(dst,ans,f);
CheckRangeEqArrayBack(dst,ans,f);
CheckRangeEqArrayFrontBack(dst,ans,f);
CheckRangeEqArrayBackFront(dst,ans,f);
}
//////////////////////////////////////////////////////////////////////////
template<typename R, typename T, int N>
void CheckRangeEqArrayFront(R dst, T (&ans)[N])
{
CheckRangeEqArrayFront(dst, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqArrayBack(R dst, T (&ans)[N])
{
CheckRangeEqArrayBack(dst, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqArrayFrontBack(R dst, T (&ans)[N])
{
CheckRangeEqArrayFrontBack(dst, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqArrayBackFront(R dst, T (&ans)[N])
{
CheckRangeEqArrayBackFront(dst, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqArray(R dst, T (&ans)[N])
{
CheckRangeEqArray(dst, ans, [](const T & a)->T{return a;});
}
//////////////////////////////////////////////////////////////////////////
// Compare Range with set
//////////////////////////////////////////////////////////////////////////
template<typename T, int N>
std::set<T> ArrayToSet(T (&ans)[N])
{
std::set<T> res;
for(int i = 0; i < N; i++)
res.insert(ans[i]);
EXPECT_EQ(N, res.size());
return res;
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSetFront(R r, T (&ans)[N], F f)
{
std::set<T> result;
while (!r.empty())
result.insert(f(r.popFront()));
EXPECT_EQ(ArrayToSet(ans),result);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSetBack(R r, T (&ans)[N], F f)
{
std::set<T> result;
while (!r.empty())
result.insert(f(r.popBack()));
EXPECT_EQ(ArrayToSet(ans),result);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSetTwisted(R r, F f, T (&ans)[N], int bit)
{
std::set<T> result;
while (!r.empty())
{
if (bit ^= 1)
result.insert(f(r.popFront()));
else
result.insert(f(r.popBack()));
}
EXPECT_EQ(ArrayToSet(ans),result);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSetFrontBack(R r, T (&ans)[N], F f)
{
CheckRangeEqSetTwisted(r,f,ans,0);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSetBackFront(R r, T (&ans)[N], F f)
{
CheckRangeEqSetTwisted(r,f,ans,1);
}
template<typename R, typename T, int N, typename F>
void CheckRangeEqSet(R r, T (&ans)[N], F f)
{
CheckRangeEqSetFront(r,ans,f);
CheckRangeEqSetBack(r,ans,f);
CheckRangeEqSetFrontBack(r,ans,f);
CheckRangeEqSetBackFront(r,ans,f);
}
//////////////////////////////////////////////////////////////////////////
template<typename R, typename T, int N>
void CheckRangeEqSetFront(R r, T (&ans)[N])
{
CheckRangeEqSetFront(r, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqSetBack(R r, T (&ans)[N])
{
CheckRangeEqSetBack(r, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqSetFrontBack(R r, T (&ans)[N])
{
CheckRangeEqSetFrontBack(r, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqSetBackFront(R r, T (&ans)[N])
{
CheckRangeEqSetBackFront(r, ans, [](const T & a)->T{return a;});
}
template<typename R, typename T, int N>
void CheckRangeEqSet(R r, T (&ans)[N])
{
CheckRangeEqSet(r, ans, [](const T & a)->T{return a;});
}
\ No newline at end of file
#pragma once
#include <type_traits>
namespace boolinq
{
template<typename R1, typename R2>
class ConcatRange
{
static_assert(std::tr1::is_same<typename R1::value_type,
typename R2::value_type>::value,
"Error unioning ranges with different value types");
public:
typedef typename R1::value_type value_type;
ConcatRange(R1 r1, R2 r2)
: r1(r1), r2(r2)
{
}
bool empty()
{
return r1.empty() && r2.empty();
}
value_type popFront()
{
if (r1.empty())
return r2.popFront();
return r1.popFront();
}
value_type popBack()
{
if (r2.empty())
return r1.popBack();
return r2.popBack();
}
value_type front()
{
if (r1.empty())
return r2.front();
return r1.front();
}
value_type back()
{
if (r2.empty())
return r1.back();
return r2.back();
}
private:
R1 r1;
R2 r2;
};
/// unionAll(unionAll(xxx,yyy),zzz)
template<typename R1, typename R2>
ConcatRange<R1,R2> unionAll(R1 r1, R2 r2)
{
return ConcatRange<R1,R2>(r1,r2);
}
/// xxx.unionAll(yyy).unionAll(zzz)
template<template<typename> class TLinq, typename R1>
class ConcatRange_mixin
{
public:
template<typename R2>
TLinq<ConcatRange<R1,R2> > unionAll(R2 r) const
{
return boolinq::unionAll(((TLinq<R1>*)this)->r,r);
}
};
}
// namespace boolinq
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "ConcatRange.h"
using namespace boolinq;
TEST(ConcatRange, ArrayArray)
{
int src1[] = {1,2,3,4,5};
int src2[] = {6,7,8,9};
int ans[] = {1,2,3,4,5,6,7,8,9};
auto rng1 = range(src1);
auto rng2 = range(src2);
auto dst = unionAll(rng1,rng2);
CheckRangeEqArray(dst, ans);
}
TEST(ConcatRange, ArrayVector)
{
int src1[] = {1,2,3,4,5};
std::vector<int> src2;
src2.push_back(6);
src2.push_back(7);
src2.push_back(8);
src2.push_back(9);
int ans[] = {1,2,3,4,5,6,7,8,9};
auto rng1 = range(src1);
auto rng2 = range(src2);
auto dst = unionAll(rng1,rng2);
CheckRangeEqArray(dst, ans);
}
TEST(ConcatRange, ArrayVectorArray)
{
int src1[] = {1,2,3,4,5};
std::vector<int> src2;
src2.push_back(6);
src2.push_back(7);
src2.push_back(8);
src2.push_back(9);
int src3[] = {10,11,12,13,14,15};
int ans[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
auto rng1 = range(src1);
auto rng2 = range(src2);
auto rng3 = range(src3);
auto dst = unionAll(unionAll(rng1,rng2),rng3);
CheckRangeEqArray(dst, ans);
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// contains(xxx, value)
template<typename R, typename T>
bool contains(R r, const T & t)
{
while (!r.empty())
if (r.popFront() == t)
return true;
return false;
}
// xxx.contains(value)
template<template<typename> class TLinq, typename R>
class Contains_mixin
{
public:
template<typename T>
bool contains(const T & t) const
{
return boolinq::contains(((TLinq<R>*)this)->r,t);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Contains.h"
using namespace boolinq;
TEST(Contains, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_TRUE(contains(rng,1));
EXPECT_TRUE(contains(rng,2));
EXPECT_TRUE(contains(rng,3));
EXPECT_FALSE(contains(rng,0));
EXPECT_FALSE(contains(rng,4));
}
TEST(Contains, FiveStrings)
{
std::vector<std::string> src;
src.push_back("hello");
src.push_back("apple");
src.push_back("nokia");
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
EXPECT_TRUE(contains(rng,"hello"));
EXPECT_TRUE(contains(rng,"apple"));
EXPECT_TRUE(contains(rng,"nokia"));
EXPECT_TRUE(contains(rng,"oracle"));
EXPECT_TRUE(contains(rng,"ponny"));
EXPECT_FALSE(contains(rng,"dino"));
EXPECT_FALSE(contains(rng,"lord"));
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// count(xxx) and count(xxx,lambda)
template<typename R>
int count(R r)
{
int index = 0;
for (; !r.empty(); r.popFront())
index++;
return index;
}
template<typename R, typename T>
int count(R r, T t)
{
int index = 0;
for (; !r.empty(); r.popFront())
if (r.front() == t)
index++;
return index;
}
// xxx.count() and xxx.count(lambda)
template<template<typename> class TLinq, typename R>
class Count_mixin
{
public:
int count() const
{
return boolinq::count(((TLinq<R>*)this)->r);
}
template<typename T>
int count(T t) const
{
return boolinq::count(((TLinq<R>*)this)->r,t);
}
};
}
// namespace boolinq
#include <list>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Count.h"
using namespace boolinq;
TEST(Count, ThreeIntsVector)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(3, count(rng));
}
TEST(Count, ThreeIntsList)
{
std::list<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(3, count(rng));
}
TEST(Count, FiveInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
auto rng = range(src);
auto dst0 = where(rng, [](int a){return a%2 == 0;});
auto dst1 = where(rng, [](int a){return a%2 == 1;});
EXPECT_EQ(2, count(dst0));
EXPECT_EQ(3, count(dst1));
}
TEST(Count, OddCount)
{
std::vector<int> src;
src.push_back(1);
src.push_back(0);
src.push_back(1);
src.push_back(0);
src.push_back(1);
auto rng = range(src);
EXPECT_EQ(2, count(rng,0));
EXPECT_EQ(3, count(rng,1));
}
#pragma once
namespace boolinq
{
template<typename T>
struct JustReturn_dist
{
T operator()(const T & a) const
{
return a;
}
};
template<typename R, typename F = JustReturn_dist<typename R::value_type> >
class DistinctRange
{
public:
typedef typename R::value_type value_type;
DistinctRange(R r, F f = JustReturn_dist<typename R::value_type>())
: r(r), f(f)
, fullRange(r)
, leftIndex(0)
, rightIndex(0)
{
if (isDuplicate(f(r.front()),1,0))
popFront();
}
bool empty()
{
return r.empty();
}
value_type popFront()
{
R tmp = r;
do
{
r.popFront();
leftIndex++;
} while (!r.empty() && isDuplicate(f(r.front()),1,0));
return tmp.front();
}
value_type popBack()
{
R tmp = r;
do
{
r.popBack();
rightIndex++;
} while (!r.empty() && isDuplicate(f(r.back()),0,1));
return tmp.back();
}
value_type front()
{
return r.front();
}
value_type back()
{
return r.back();
}
private:
template<typename T>
bool isDuplicate(const T & value, int left, int right) const
{
R tmp = r;
tmp.popFront();
if (tmp.empty())
return false;
tmp = fullRange;
for(int i = 0 ; i < leftIndex + right; i++)
{
if (value == f(tmp.popFront()))
return true;
}
tmp = fullRange;
for(int i = 0 ; i < rightIndex + left; i++)
{
if (value == f(tmp.popBack()))
return true;
}
return false;
}
private:
R r;
F f;
R fullRange;
int leftIndex;
int rightIndex;
};
// distinct(distinct(xxx))
template<typename R>
DistinctRange<R> distinct(R r)
{
return r;
}
template<typename R, typename F>
DistinctRange<R,F> distinct(R r, F f)
{
return DistinctRange<R,F>(r,f);
}
// xxx.distinct().distinct()
template<template<typename> class TLinq, typename R>
class DistinctRange_mixin
{
public:
TLinq<DistinctRange<R> > distinct() const
{
return boolinq::distinct(((TLinq<R>*)this)->r);
}
template<typename F>
TLinq<DistinctRange<R,F> > distinct(F f) const
{
return boolinq::distinct(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "DistinctRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(DistinctRange, Ints1to6)
{
int src[] = {4,5,3,1,4,2,1,4,6};
int ans[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = distinct(rng);
CheckRangeEqSet(dst, ans);
}
TEST(DistinctRange, IntMirrorFront)
{
int src[] = {3,2,1,0,1,2,3};
int ans[] = {0,1,2,3};
auto rng = range(src);
auto dst = distinct(rng);
CheckRangeEqSet(dst, ans);
}
TEST(DistinctRange, ManyEqualsFront)
{
int src[] = {1,1,1,1};
int ans[] = {1};
auto rng = range(src);
auto dst = distinct(rng);
CheckRangeEqSet(dst, ans);
}
TEST(DistinctRange, ManyEqualsWithOneFront)
{
int src[] = {1,1,2,1};
int ans[] = {1,2};
auto rng = range(src);
auto dst = distinct(rng);
CheckRangeEqSet(dst, ans);
}
TEST(DistinctRange, OneFieldFront)
{
struct Man
{
std::string name;
int age;
bool operator < (const Man & man) const
{
return (name < man.name)
|| (name == man.name && age < man.age);
}
};
Man src[] =
{
{"Anton",1},
{"Taran",2},
{"Poker",3},
{"Agata",4},
{"Mango",2},
{"Banan",1},
};
std::string ansF[] =
{
"Banan",
"Taran",
"Poker",
"Agata",
};
std::string ansB[] =
{
"Taran",
"Poker",
"Agata",
"Banan",
};
auto rng = range(src);
auto dst = distinct(rng, [](const Man & man){return man.age;});
CheckRangeEqSetFront(dst, ansF, [](const Man & man){return man.name;});
CheckRangeEqSetBack(dst, ansB, [](const Man & man){return man.name;});
}
\ No newline at end of file
#include <list>
#include <deque>
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "boolinq.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(DotCall, BytesRange)
{
int src[] = {0x12345678,0xAABBCCDD};
int ansFL[] =
{
0x78,0x56,0x34,0x12,
0xDD,0xCC,0xBB,0xAA,
};
int ansLF[] =
{
0x12,0x34,0x56,0x78,
0xAA,0xBB,0xCC,0xDD,
};
auto dstFL1 = from(src).bytes();
auto dstFL2 = from(src).bytes<FirstToLast>();
auto dstLF1 = from(src).bytes<LastToFirst>();
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
CheckRangeEqArray(dstLF1, ansLF);
}
//////////////////////////////////////////////////////////////////////////
TEST(DotCall, UnbytesRange)
{
unsigned char src[] =
{
0x78,0x56,0x34,0x12,
0xDD,0xCC,0xBB,0xAA,
};
int ansFL[] = {0x12345678,0xAABBCCDD};
int ansLF[] = {0x78563412,0xDDCCBBAA};
auto dstFL1 = from(src).unbytes<int>();
auto dstFL2 = from(src).unbytes<int,FirstToLast>();
auto dstLF1 = from(src).unbytes<int,LastToFirst>();
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
CheckRangeEqArray(dstLF1, ansLF);
}
//////////////////////////////////////////////////////////////////////////
TEST(DotCall, BitsRangeHL)
{
int src[] = {0xAABBCCDD};
int ansFL[] =
{
1,1,0,1,1,1,0,1,
1,1,0,0,1,1,0,0,
1,0,1,1,1,0,1,1,
1,0,1,0,1,0,1,0,
};
int ansLF[] =
{
1,0,1,0,1,0,1,0,
1,0,1,1,1,0,1,1,
1,1,0,0,1,1,0,0,
1,1,0,1,1,1,0,1,
};
auto dstFL1 = from(src).bits();
auto dstFL2 = from(src).bits<HighToLow>();
auto dstFL3 = from(src).bits<HighToLow,FirstToLast>();
auto dstLF1 = from(src).bits<HighToLow,LastToFirst>();
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
CheckRangeEqArray(dstFL3, ansFL);
CheckRangeEqArray(dstLF1, ansLF);
}
TEST(DotCall, BitsRangeLH)
{
int src[] = {0xAABBCCDD};
int ansFL[] =
{
1,0,1,1,1,0,1,1,
0,0,1,1,0,0,1,1,
1,1,0,1,1,1,0,1,
0,1,0,1,0,1,0,1,
};
int ansLF[] =
{
0,1,0,1,0,1,0,1,
1,1,0,1,1,1,0,1,
0,0,1,1,0,0,1,1,
1,0,1,1,1,0,1,1,
};
auto dstFL1 = from(src).bits<LowToHigh>();
auto dstFL2 = from(src).bits<LowToHigh,FirstToLast>();
auto dstLF1 = from(src).bits<LowToHigh,LastToFirst>();
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
CheckRangeEqArray(dstLF1, ansLF);
}
//////////////////////////////////////////////////////////////////////////
TEST(DotCall, UnbitsRangeHLFL)
{
int src[] =
{
1,1,0,1,1,1,0,1,
1,1,0,0,1,1,0,0,
1,0,1,1,1,0,1,1,
1,0,1,0,1,0,1,0
};
int ans_4b[] = {0xDD,0xCC,0xBB,0xAA};
int ans_1i[] = {0xAABBCCDD};
int ansLF_1i[] = {0xDDCCBBAA};
auto dst1_4b = from(src).unbits();
auto dst2_4b = from(src).unbits<HighToLow>();
auto dst1_1i = from(src).unbits<int,HighToLow>();
auto dst2_1i = from(src).unbits<int,HighToLow,FirstToLast>();
auto dst3_1i = from(src).unbits<int,HighToLow,LastToFirst>();
CheckRangeEqArray(dst1_4b, ans_4b);
CheckRangeEqArray(dst2_4b, ans_4b);
CheckRangeEqArray(dst1_1i, ans_1i);
CheckRangeEqArray(dst2_1i, ans_1i);
CheckRangeEqArray(dst3_1i, ansLF_1i);
}
//TEST(DotCall, UnbitsRangeLH)
//{
// int src[] = {0xAABBCCDD};
// int ansFL[] =
// {
// 1,0,1,1,1,0,1,1,
// 0,0,1,1,0,0,1,1,
// 1,1,0,1,1,1,0,1,
// 0,1,0,1,0,1,0,1,
// };
// int ansLF[] =
// {
// 0,1,0,1,0,1,0,1,
// 1,1,0,1,1,1,0,1,
// 0,0,1,1,0,0,1,1,
// 1,0,1,1,1,0,1,1,
// };
//
// auto dstFL1 = from(src).bits<LowToHigh>();
// auto dstFL2 = from(src).bits<LowToHigh,FirstToLast>();
// auto dstLF1 = from(src).bits<LowToHigh,LastToFirst>();
//
// CheckRangeEqArray(dstFL1, ansFL);
// CheckRangeEqArray(dstFL2, ansFL);
// CheckRangeEqArray(dstLF1, ansLF);
//}
#pragma once
namespace boolinq
{
// elementAt(xxx, int)
template<typename R>
typename R::value_type elementAt(R r, int index)
{
while (index > 0)
{
r.popFront();
index--;
}
return r.front();
}
// xxx.elementAt(int)
template<template<typename> class TLinq, typename R>
class ElementAt_mixin
{
public:
typename R::value_type elementAt(int index) const
{
return boolinq::elementAt(((TLinq<R>*)this)->r,index);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ElementAt.h"
using namespace boolinq;
TEST(ElementAt, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(1, elementAt(rng,0));
EXPECT_EQ(2, elementAt(rng,1));
EXPECT_EQ(3, elementAt(rng,2));
}
TEST(ElementAt, FiveStrings)
{
std::vector<std::string> src;
src.push_back("hello");
src.push_back("apple");
src.push_back("nokia");
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
EXPECT_EQ("hello", elementAt(rng,0));
EXPECT_EQ("apple", elementAt(rng,1));
EXPECT_EQ("nokia", elementAt(rng,2));
EXPECT_EQ("oracle", elementAt(rng,3));
EXPECT_EQ("ponny", elementAt(rng,4));
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// for_each(for_each(xxx, ...), ...)
template<typename R, typename F>
void for_each(R r, F f)
{
while (!r.empty())
f(r.popFront());
}
// xxx.for_each(...).for_each(...)
template<template<typename> class TLinq, typename R>
class ForEach_mixin
{
public:
template<typename F>
void for_each(F f) const
{
return boolinq::for_each(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <list>
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ForEach.h"
using namespace boolinq;
TEST(ForEach, ThreeCharsSum)
{
std::vector<char> src;
src.push_back('a');
src.push_back('b');
src.push_back('c');
std::string str = "";
for_each(range(src), [&](char a){str += a;});
EXPECT_EQ("abc", str);
}
TEST(ForEach, ThreeCharsUpperSum)
{
std::vector<char> src;
src.push_back('a');
src.push_back('b');
src.push_back('c');
std::string str = "";
for_each(range(src), [&](char a){str += a + ('A' - 'a');});
EXPECT_EQ("ABC", str);
}
TEST(ForEach, ThreeIntsSum)
{
std::vector<int> src;
src.push_back(10);
src.push_back(20);
src.push_back(30);
int sum = 0;
for_each(range(src), [&](int a){sum += a;});
EXPECT_EQ(60, sum);
}
#pragma once
#include "DistinctRange.h"
#include "WhereRange.h"
namespace boolinq
{
template<typename F, typename TArg>
static auto get_return_type_gb(F * f = NULL, TArg * arg = NULL)
-> decltype((*f)(*arg));
template<typename T>
struct JustReturn_gb
{
T operator()(const T & a) const
{
return a;
}
};
template<typename T, typename F>
struct ReturnEquals_gb
{
typedef decltype(get_return_type_gb<F,T>()) value_type;
ReturnEquals_gb(const T & val, F f)
: val(f(val)), f(f)
{
}
bool operator()(const T & a) const
{
return val == f(a);
}
private:
value_type val;
F f;
};
template<typename R, typename F>
class WhereRange_withKey : public WhereRange<R, ReturnEquals_gb<typename R::value_type,F> >
{
public:
typedef typename R::value_type value_type;
typedef decltype(get_return_type_gb<F,value_type>()) TKey;
WhereRange_withKey(R r, F f, const value_type & key)
: WhereRange(r, ReturnEquals_gb<value_type,F>(key,f))
, k(f(key))
{
}
const TKey & key() const
{
return k;
}
private:
TKey k;
};
//////////////////////////////////////////////////////////////////////////
template<typename R, typename F = JustReturn_gb<typename R::value_type> >
class GroupByRange
{
public:
typedef typename R::value_type r_value_type;
typedef WhereRange_withKey<R,F> value_type;
GroupByRange(R r, F f = JustReturn_gb<r_value_type>())
: r(r), dr(r,f), f(f)
, _front(r,f,dr.front())
, _back(r,f,dr.back())
{
}
bool empty()
{
return dr.empty();
}
value_type popFront()
{
DistinctRange<R,F> tmp = dr;
dr.popFront();
if ((!empty()))
_front = value_type(r,f,dr.front());
return value_type(r,f,tmp.front());
}
value_type popBack()
{
DistinctRange<R,F> tmp = dr;
dr.popBack();
if ((!empty()))
_back = value_type(r,f,dr.back());
return value_type(r,f,tmp.back());
}
value_type & front()
{
return _front;
}
value_type & back()
{
return _back;
}
private:
R r;
DistinctRange<R,F> dr;
F f;
value_type _front;
value_type _back;
};
// groupBy(groupBy(xxx, ...), ...)
template<typename R, typename F>
GroupByRange<R,F> groupBy(R r, F f)
{
return GroupByRange<R,F>(r,f);
}
// xxx.groupBy(...).groupBy(...)
template<template<typename> class TLinq, typename R>
class GroupByRange_mixin
{
public:
template<typename F>
TLinq<GroupByRange<R,F> > groupBy(F f) const
{
return boolinq::groupBy(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "GroupByRange.h"
#include "Count.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(GroupByRange, IntsFront)
{
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int ans_1[] = {1,4,7};
int ans_2[] = {2,5,8};
int ans_0[] = {0,3,6,9};
auto rng = range(arr);
auto dst = groupBy(rng, [](int a){return a % 3;});
EXPECT_EQ(1, dst.front().key());
EXPECT_EQ(0, dst.back().key());
CheckRangeEqArray(dst.front(), ans_1);
CheckRangeEqArray(dst.back(), ans_0);
CheckRangeEqArray(dst.popFront(), ans_1);
EXPECT_EQ(2, dst.front().key());
EXPECT_EQ(0, dst.back().key());
CheckRangeEqArray(dst.front(), ans_2);
CheckRangeEqArray(dst.back(), ans_0);
CheckRangeEqArray(dst.popFront(), ans_2);
EXPECT_EQ(0, dst.front().key());
EXPECT_EQ(0, dst.back().key());
CheckRangeEqArray(dst.front(), ans_0);
CheckRangeEqArray(dst.back(), ans_0);
CheckRangeEqArray(dst.popFront(), ans_0);
EXPECT_TRUE(dst.empty());
}
TEST(GroupByRange, IntsBack)
{
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int ans_1[] = {1,4,7};
int ans_2[] = {2,5,8};
int ans_0[] = {0,3,6,9};
auto rng = range(arr);
auto dst = groupBy(rng, [](int a){return a % 3;});
EXPECT_EQ(1, dst.front().key());
EXPECT_EQ(0, dst.back().key());
CheckRangeEqArray(dst.front(), ans_1);
CheckRangeEqArray(dst.back(), ans_0);
CheckRangeEqArray(dst.popBack(), ans_0);
EXPECT_EQ(1, dst.front().key());
EXPECT_EQ(2, dst.back().key());
CheckRangeEqArray(dst.front(), ans_1);
CheckRangeEqArray(dst.back(), ans_2);
CheckRangeEqArray(dst.popBack(), ans_2);
EXPECT_EQ(1, dst.front().key());
EXPECT_EQ(1, dst.back().key());
CheckRangeEqArray(dst.front(), ans_1);
CheckRangeEqArray(dst.back(), ans_1);
CheckRangeEqArray(dst.popBack(), ans_1);
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(GroupByRange, CountChildrenByAge)
{
struct Child
{
std::string name;
int age;
bool operator == (const Child & rhs) const
{
return (name == rhs.name) && (age == rhs.age);
}
};
Child children[] =
{
{"Piter", 12},
{"Bella", 14},
{"Torry", 15},
{"Holly", 12},
{"Zamza", 13},
};
Child ans_false[] =
{
{"Bella", 14},
{"Torry", 15},
};
Child ans_true[] =
{
{"Piter", 12},
{"Holly", 12},
{"Zamza", 13},
};
auto rng = range(children);
auto dst = groupBy(rng, [](const Child & a){return a.age < 14;});
EXPECT_EQ(false, dst.front().key());
CheckRangeEqArray(dst.front(), ans_false);
CheckRangeEqArray(dst.back(), ans_true);
CheckRangeEqArray(dst.popFront(), ans_false);
EXPECT_EQ(true, dst.front().key());
CheckRangeEqArray(dst.front(), ans_true);
CheckRangeEqArray(dst.back(), ans_true);
CheckRangeEqArray(dst.popFront(), ans_true);
EXPECT_TRUE(dst.empty());
}
#pragma once
#include <iterator>
#include <assert.h>
namespace boolinq
{
template<typename TIter>
class IterRange
{
public:
typedef typename std::iterator_traits<TIter>::value_type value_type;
IterRange(TIter b, TIter e)
: b(b), e(e)
{
}
bool empty()
{
return (b == e);
}
value_type popFront()
{
assert(!empty());
return *(b++);
}
value_type popBack()
{
assert(!empty());
return *(--e);
}
value_type front()
{
assert(!empty());
return *b;
}
value_type back()
{
assert(!empty());
TIter tmp = e;
return *(--tmp);
}
private:
TIter b;
TIter e;
};
//////////////////////////////////////////////////////////////////////
template<typename T>
IterRange<typename T::const_iterator> range(const T & vec)
{
return IterRange<typename T::const_iterator>(vec.begin(), vec.end());
}
template<typename T, const int N>
IterRange<const T*> range(const T (&arr)[N])
{
return IterRange<const T*>((const T*)arr, (const T*)arr+N);
}
template<typename T>
IterRange<T> range(T b, T e)
{
return IterRange<T>(b,e);
}
template<typename T>
IterRange<const T*> range(const T * b, const T * e)
{
return IterRange<const T*>(b,e);
}
template<typename T>
IterRange<const T*> range(const T * b, int n)
{
return IterRange<const T*>(b,b+n);
}
}
// namespace boolinq
#include <list>
#include <deque>
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(IterRange, ListInt)
{
std::list<int> lst;
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
lst.push_back(4);
lst.push_back(5);
int ans[] = {1,2,3,4,5};
CheckRangeEqArray(range(lst), ans);
CheckRangeEqArray(range(lst.begin(), lst.end()), ans);
CheckRangeEqArray(range(lst.cbegin(), lst.cend()), ans);
}
TEST(IterRange, DequeInt)
{
std::deque<int> dck;
dck.push_back(1);
dck.push_back(2);
dck.push_back(3);
dck.push_back(4);
dck.push_back(5);
int ans[] = {1,2,3,4,5};
CheckRangeEqArray(range(dck), ans);
CheckRangeEqArray(range(dck.begin(), dck.end()), ans);
CheckRangeEqArray(range(dck.cbegin(), dck.cend()), ans);
}
TEST(IterRange, VectorInt)
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
int ans[] = {1,2,3,4,5};
CheckRangeEqArray(range(vec), ans);
CheckRangeEqArray(range(vec.begin(), vec.end()), ans);
CheckRangeEqArray(range(vec.cbegin(), vec.cend()), ans);
}
TEST(IterRange, ArrayInt)
{
int arr[] = {1,2,3,4,5};
int * ptr = (int*)arr;
int ans[] = {1,2,3,4,5};
CheckRangeEqArray(range(arr), ans);
CheckRangeEqArray(range(ptr, 5), ans);
CheckRangeEqArray(range(ptr, ptr+5), ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(IterRange, OneElement)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
CheckRangeEqArray(rng, ans);
}
TEST(IterRange, EmptyVector)
{
std::vector<int> src;
auto rng = range(src);
EXPECT_TRUE(rng.empty());
}
\ No newline at end of file
#include <list>
#include <deque>
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "boolinq.h"
using namespace boolinq;
// Where Tests
TEST(Linq, WhereOdd)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
auto rng = from(src).where([](int a){return a%2 == 1;});
for (int i = 1; i <= 5; i+=2)
{
EXPECT_FALSE(rng.empty());
EXPECT_EQ(i, rng.front());
EXPECT_EQ(i, rng.popFront());
}
EXPECT_TRUE(rng.empty());
}
TEST(Linq, WhereOdd_WhereLess)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto rng = from(src).where([](int a){return a%2 == 1;})
.where([](int a){return a < 4;});
for (int i = 1; i <= 3; i+=2)
{
EXPECT_FALSE(rng.empty());
EXPECT_EQ(i, rng.front());
EXPECT_EQ(i, rng.popFront());
}
EXPECT_TRUE(rng.empty());
}
TEST(Linq, WhereLess_WhereOdd)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto rng = from(src).where([](int a){return a < 4;})
.where([](int a){return a%2 == 1;});
std::vector<int> ans;
ans.push_back(1);
ans.push_back(3);
EXPECT_EQ(ans,rng);
}
TEST(Linq, WhereLess_WhereOdd_OrderByDesc)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto rng = from(src).where([](int a){return a < 6;})
.where([](int a){return a%2 == 1;})
.orderBy([](int a){return -a;});
std::vector<int> ans;
ans.push_back(5);
ans.push_back(3);
ans.push_back(1);
EXPECT_EQ(ans,rng);
}
TEST(Linq, WhereOdd_ToVector)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto dst = from(src).where([](int a){return a%2 == 1;});
std::vector<int> ans;
ans.push_back(1);
ans.push_back(3);
ans.push_back(5);
ans.push_back(7);
EXPECT_EQ(ans,dst);
}
TEST(Linq, WhereOdd_WhereLess_SelectMul2_ToVector)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto dst = from(src).where([](int a){return a%2 == 1;})
.where([](int a){return a < 6;})
.select([](int a){return a*2;})
.toVector();
std::vector<int> ans;
ans.push_back(2);
ans.push_back(6);
ans.push_back(10);
EXPECT_EQ(ans,dst);
}
TEST(Linq, WhereOdd_WhereLess_SelectMul2_Reverse_ToVector)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto dst = from(src).where([](int a){return a%2 == 1;})
.where([](int a){return a < 6;})
.select([](int a){return a*2;})
.reverse()
.toVector();
std::vector<int> ans;
ans.push_back(10);
ans.push_back(6);
ans.push_back(2);
EXPECT_EQ(ans,dst);
}
TEST(Linq, WhereOdd_Reverse_Reverse)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
src.push_back(6);
src.push_back(7);
src.push_back(8);
auto dst = from(src).where([](int a){return a%2 == 1;})
.reverse()
.where([](int a){return a < 4;})
.reverse()
.toVector();
std::vector<int> ans;
ans.push_back(1);
ans.push_back(3);
EXPECT_EQ(ans,dst);
}
//////////////////////////////////////////////////////////////////////////
TEST(Linq, Pointer_Front)
{
int src[] = {1,2,3,4,5};
auto dst = from((int*)src, (int*)src+5);
for(int i = 1; i <= 5; i++)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(i, dst.front());
EXPECT_EQ(5, dst.back());
EXPECT_EQ(i, dst.popFront());
}
EXPECT_TRUE(dst.empty());
}
TEST(Linq, Pointer_Back)
{
int src[] = {1,2,3,4,5};
auto dst = from((int*)src, (int*)src+5);
for(int i = 5; i >= 1; i--)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(1, dst.front());
EXPECT_EQ(i, dst.back());
EXPECT_EQ(i, dst.popBack());
}
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(Linq, Array_Front)
{
int src[] = {1,2,3,4,5};
auto dst = from(src);
for(int i = 1; i <= 5; i++)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(i, dst.front());
EXPECT_EQ(5, dst.back());
EXPECT_EQ(i, dst.popFront());
}
EXPECT_TRUE(dst.empty());
}
TEST(Linq, Array_Back)
{
int src[] = {1,2,3,4,5};
auto dst = from(src);
for(int i = 5; i >= 1; i--)
{
EXPECT_FALSE(dst.empty());
EXPECT_EQ(1, dst.front());
EXPECT_EQ(i, dst.back());
EXPECT_EQ(i, dst.popBack());
}
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(Linq, Creations)
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
int arr[] = {1,2,3,4,5};
int * ptr = (int*)arr;
std::vector<const int> cvec;
cvec.push_back(1);
cvec.push_back(2);
cvec.push_back(3);
cvec.push_back(4);
cvec.push_back(5);
const int carr[] = {1,2,3,4,5};
const int * cptr = (const int*)carr;
auto rng_vec = range(vec);
auto rng_cvec = range(cvec);
auto rng_arr = range(arr);
auto rng_carr = range(carr);
auto rng_ptr = range(ptr, ptr+5);
auto rng_cptr = range(cptr, cptr+5);
auto rng_ptr_length = range(ptr, 5);
auto rng_cptr_length = range(cptr, 5);
auto rng_vec_iter = range(vec.begin(), vec.end());
auto rng_vec_citer = range(vec.cbegin(), vec.cend());
auto rng_cvec_iter = range(cvec.begin(), cvec.end());
auto rng_cvec_citer = range(cvec.cbegin(), cvec.cend());
auto dst_vec = from(vec);
auto dst_cvec = from(cvec);
auto dst_arr = from(arr);
auto dst_carr = from(carr);
auto dst_ptr = from(ptr, ptr+5);
auto dst_cptr = from(cptr, cptr+5);
auto dst_ptr_length = from(ptr, 5);
auto dst_cptr_length = from(cptr, 5);
auto dst_vec_iter = from(vec.begin(), vec.end());
auto dst_vec_citer = from(vec.cbegin(), vec.cend());
auto dst_cvec_iter = from(cvec.begin(), cvec.end());
auto dst_cvec_citer = from(cvec.cbegin(), cvec.cend());
}
//////////////////////////////////////////////////////////////////////////
TEST(Linq, MessagesCountUniqueContacts)
{
struct Message
{
std::string PhoneA;
std::string PhoneB;
std::string Text;
};
Message messages[] =
{
{"Anton","Denis","Hello, friend!"},
{"Denis","Write","OLOLO"},
{"Anton","Papay","WTF?"},
{"Denis","Maloy","How r u?"},
{"Denis","Write","Param-pareram!"},
};
int DenisUniqueContactCount = from(messages)
.where( [](const Message & msg){return msg.PhoneA == "Denis";})
.distinct([](const Message & msg){return msg.PhoneB;})
.count();
EXPECT_EQ(2, DenisUniqueContactCount);
}
//////////////////////////////////////////////////////////////////////////
TEST(Linq, ForwardIterating)
{
std::stringstream stream("0123456789");
auto dst = from(std::istream_iterator<char>(stream),
std::istream_iterator<char>())
.where( [](char a){return a % 2 == 0;})
.select([](char a){return std::string(1,a);})
.sum();
EXPECT_EQ("02468", dst);
}
#pragma once
namespace boolinq
{
// max(xxx, int)
template<typename R, typename F>
typename R::value_type max(R r, F f)
{
R max = r;
while (!r.empty())
{
if (f(r.front()) > f(max.front()))
max = r;
r.popFront();
}
return max.front();
}
template<typename R>
typename R::value_type max(R r)
{
typedef typename R::value_type value_type;
return max(r,[](const value_type & a)->value_type{return a;});
}
// xxx.max(int)
template<template<typename> class TLinq, typename R>
class Max_mixin
{
public:
typename R::value_type max() const
{
return boolinq::max(((TLinq<R>*)this)->r);
}
template<typename F>
typename R::value_type max(F f) const
{
return boolinq::max(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Max.h"
using namespace boolinq;
TEST(Max, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(3, max(rng));
EXPECT_EQ(1, max(rng,[](int a){return -a;}));
}
TEST(Max, FiveStrings)
{
std::vector<std::string> src;
src.push_back("hell");
src.push_back("apple");
src.push_back("zip");
auto rng = range(src);
EXPECT_EQ("zip", max(rng));
EXPECT_EQ("apple", max(rng,[](const std::string s){return s.size();}));
}
\ No newline at end of file
#pragma once
namespace boolinq
{
// min(xxx, int)
template<typename R, typename F>
typename R::value_type min(R r, F f)
{
R min = r;
while (!r.empty())
{
if (f(r.front()) < f(min.front()))
min = r;
r.popFront();
}
return min.front();
}
template<typename R>
typename R::value_type min(R r)
{
typedef typename R::value_type value_type;
return min(r,[](const value_type & a)->value_type{return a;});
}
// xxx.min(int)
template<template<typename> class TLinq, typename R>
class Min_mixin
{
public:
typename R::value_type min() const
{
return boolinq::min(((TLinq<R>*)this)->r);
}
template<typename F>
typename R::value_type min(F f) const
{
return boolinq::min(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Min.h"
using namespace boolinq;
TEST(Min, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(1, min(rng));
EXPECT_EQ(3, min(rng,[](int a){return -a;}));
}
TEST(Min, FiveStrings)
{
std::vector<std::string> src;
src.push_back("hell");
src.push_back("apple");
src.push_back("zip");
auto rng = range(src);
EXPECT_EQ("apple", min(rng));
EXPECT_EQ("zip", min(rng,[](const std::string & s){return s.size();}));
}
#pragma once
#include "Count.h"
namespace boolinq
{
template<typename T>
struct JustReturn
{
T operator()(const T & a) const
{
return a;
}
};
template<typename R, typename F = JustReturn<typename R::value_type> >
class OrderByRange
{
public:
typedef typename R::value_type value_type;
OrderByRange(R r, F f = JustReturn<typename R::value_type>())
: r(r), f(f)
, atEnd(false)
, size(boolinq::count(r))
, minimumValue(r)
, maximumValue(r)
, minimumIndex(0)
, maximumIndex(0)
{
seekFirstMin();
seekFirstMax();
atEnd = (minimumIndex + maximumIndex == size);
}
bool empty()
{
return atEnd;
}
value_type popFront()
{
R tmp = minimumValue;
seekNextMin();
return tmp.front();
}
value_type popBack()
{
R tmp = maximumValue;
seekNextMax();
return tmp.back();
}
value_type front()
{
return minimumValue.front();
}
value_type back()
{
return maximumValue.back();
}
private:
void seekFirstMin()
{
R currentValue = r;
int currentIndex = 0;
while(!currentValue.empty())
{
if (f(currentValue.front()) < f(minimumValue.front()))
{
minimumValue = currentValue;
minimumIndex = currentIndex;
}
currentValue.popFront();
currentIndex++;
}
}
void seekFirstMax()
{
R currentValue = r;
int currentIndex = 0;
while(!currentValue.empty())
{
if (f(maximumValue.back()) < f(currentValue.back()))
{
maximumValue = currentValue;
maximumIndex = currentIndex;
}
currentValue.popBack();
currentIndex++;
}
}
void seekNextMin()
{
if (minimumIndex + maximumIndex + 1 == size)
{
atEnd = true;
return;
}
R cur_value = r;
R min_value = minimumValue;
int cur_index = 0;
int min_index = minimumIndex;
while(!cur_value.empty())
{
if ((f(cur_value.front()) < f(minimumValue.front()))
|| (f(cur_value.front()) == f(minimumValue.front())
&& cur_index <= minimumIndex))
{
cur_value.popFront();
cur_index++;
continue;
}
if (min_index == minimumIndex
&& cur_index != minimumIndex)
{
min_value = cur_value;
min_index = cur_index;
}
if (f(cur_value.front()) < f(min_value.front()))
{
min_value = cur_value;
min_index = cur_index;
}
if (f(cur_value.front()) == f(minimumValue.front())
&& minimumIndex < cur_index)
{
minimumValue = cur_value;
minimumIndex = cur_index;
return;
}
cur_value.popFront();
cur_index++;
}
minimumValue = min_value;
minimumIndex = min_index;
}
void seekNextMax()
{
if (minimumIndex + maximumIndex + 1 == size)
{
atEnd = true;
return;
}
R cur_value = r;
R max_value = maximumValue;
int cur_index = 0;
int max_index = maximumIndex;
while(!cur_value.empty())
{
if ((f(maximumValue.back()) < f(cur_value.back()))
|| (f(cur_value.back()) == f(maximumValue.back())
&& cur_index <= maximumIndex))
{
cur_value.popBack();
cur_index++;
continue;
}
if (max_index == maximumIndex
&& cur_index != maximumIndex)
{
max_value = cur_value;
max_index = cur_index;
}
if (f(max_value.back()) < f(cur_value.back()))
{
max_value = cur_value;
max_index = cur_index;
}
if (f(cur_value.back()) == f(maximumValue.back())
&& maximumIndex < cur_index)
{
maximumValue = max_value;
maximumIndex = max_index;
return;
}
cur_value.popBack();
cur_index++;
}
maximumValue = max_value;
maximumIndex = max_index;
}
private:
R r;
F f;
bool atEnd;
int size;
R minimumValue;
R maximumValue;
int minimumIndex;
int maximumIndex;
};
// orderBy(orderBy(xxx, ...), ...)
template<typename R>
OrderByRange<R> orderBy(R r)
{
return r;
}
template<typename R, typename F>
OrderByRange<R,F> orderBy(R r, F f)
{
return OrderByRange<R,F>(r,f);
}
// xxx.orderBy(...).orderBy(...)
template<template<typename> class TLinq, typename R>
class OrderByRange_mixin
{
public:
TLinq<OrderByRange<R> > orderBy() const
{
return boolinq::orderBy(((TLinq<R>*)this)->r);
}
template<typename F>
TLinq<OrderByRange<R,F> > orderBy(F f) const
{
return boolinq::orderBy(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "OrderByRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(OrderByRange, RandomIntsWithDuplicates)
{
int src[] = {4,5,3,1,4,2,1,4,6};
int ans[] = {1,1,2,3,4,4,4,5,6};
auto rng = range(src);
auto dst = orderBy(rng);
CheckRangeEqArray(dst, ans);
}
TEST(OrderByRange, ReverseInts)
{
int src[] = {4,3,2,1};
int ans[] = {1,2,3,4};
auto rng = range(src);
auto dst = orderBy(rng);
CheckRangeEqArray(dst, ans);
}
TEST(OrderByRange, ThreeElements)
{
int src[] = {1,3,2};
int ans[] = {1,2,3};
auto rng = range(src);
auto dst = orderBy(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(OrderByRange, OneElement)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = orderBy(rng);
CheckRangeEqArray(dst, ans);
}
TEST(OrderByRange, NoElements)
{
std::vector<int> src;
auto rng = range(src);
auto dst = orderBy(rng);
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(OrderByRange, RandomStringByContent)
{
std::string src[] =
{
"microsoft",
"intel",
"nokia",
"apple",
"oracle",
"sun",
};
std::string ans[] =
{
"apple",
"intel",
"microsoft",
"nokia",
"oracle",
"sun",
};
auto rng = range(src);
auto dst = orderBy(rng);
CheckRangeEqArray(dst, ans);
}
TEST(OrderByRange, RandomStringByLength)
{
std::string src[] =
{
"microsoft",
"intel",
"nokia",
"apple",
"oracle",
"sun",
};
std::string ans[] =
{
"sun",
"intel",
"nokia",
"apple",
"oracle",
"microsoft",
};
auto rng = range(src);
auto dst = orderBy(rng, [](std::string a){return a.size();});
CheckRangeEqArray(dst, ans, [](const std::string & s){return s.size();});
}
\ No newline at end of file
#pragma once
namespace boolinq
{
template<typename R>
class ReverseRange
{
public:
typedef typename R::value_type value_type;
ReverseRange(R r)
: r(r)
{
}
bool empty() { return r.empty(); }
value_type popFront() { return r.popBack(); }
value_type popBack() { return r.popFront(); }
value_type front() { return r.back(); }
value_type back() { return r.front(); }
template<typename R2>
friend R2 reverse(ReverseRange<R2> r); // smart needed
private:
R r;
};
// reverse(reverse(xxx))
template<typename R>
ReverseRange<R> reverse(R r)
{
return r;
}
// Unwrap for double-reverse case
template<typename R>
R reverse(ReverseRange<R> r)
{
return r.r; // smart
}
// xxx.reverse().reverse()
template<template<typename> class TLinq, typename R>
class ReverseRange_mixin
{
public:
TLinq<ReverseRange<R> > reverse() const
{
return boolinq::reverse(((TLinq<R>*)this)->r);
}
};
// Unwrap for double-reverse case
template<template<typename> class TLinq, typename T>
class ReverseRange_mixin<TLinq,ReverseRange<T> >
{
public:
TLinq<T> reverse() const
{
return boolinq::reverse(((TLinq<ReverseRange<T> >*)this)->r);
}
};
}
// namespace boolinq
#include <list>
#include <deque>
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "ReverseRange.h"
using namespace boolinq;
TEST(ReverseRange, IntVector)
{
int src[] = {1,2,3,4};
int ans[] = {4,3,2,1};
auto rng = range(src);
auto dst = reverse(rng);
CheckRangeEqArray(dst, ans);
}
TEST(ReverseRange, DoubleReverse)
{
int src[] = {1,2,3,4};
int ans[] = {1,2,3,4};
auto rng = range(src);
auto dst = reverse(reverse(rng));
CheckRangeEqArray(dst, ans);
}
\ No newline at end of file
#pragma once
#include <functional>
namespace boolinq
{
template<typename R, typename F>
class SelectRange
{
template<typename F, typename TArg>
static auto get_return_type(F * f = NULL, TArg * arg = NULL)
-> decltype((*f)(*arg));
public:
typedef decltype(get_return_type<F,typename R::value_type>()) value_type;
SelectRange(R r, F f)
: r(r), f(f)
{
}
bool empty() { return r.empty(); }
value_type popFront() { return f(r.popFront()); }
value_type popBack() { return f(r.popBack()); }
value_type front() { return f(r.front()); }
value_type back() { return f(r.back()); }
private:
R r;
F f;
};
// select(select(xxx, ...), ...)
template<typename R, typename F>
SelectRange<R,F> select(R r, F f)
{
return SelectRange<R,F>(r,f);
}
// xxx.select(...).select(...)
template<template<typename> class TLinq, typename R>
class SelectRange_mixin
{
public:
template<typename F>
TLinq<SelectRange<R,F> > select(F f) const
{
return boolinq::select(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "SelectRange.h"
using namespace boolinq;
TEST(SelectRange, Mul2)
{
int src[] = {1,2,3,4};
int ans[] = {2,4,6,8};
auto rng = range(src);
auto dst = select(rng, [](int a){return a * 2;});
CheckRangeEqArray(dst, ans);
}
TEST(SelectRange, MakeChar)
{
int src[] = {1,2,3,4};
char ans[] = {'1','2','3','4'};
auto rng = range(src);
auto dst = select(rng, [](int a){return (char)(a+'0');});
CheckRangeEqArray(dst, ans);
}
TEST(SelectRange, MakeString)
{
int src[] = {1,2,3,4};
static std::string ans[] =
{
"hello",
"world",
"apple",
"intel",
};
auto rng = range(src);
auto dst = select(rng, [](int a){return ans[a-1];});
CheckRangeEqArray(dst, ans);
}
#pragma once
#include "Count.h"
namespace boolinq
{
template<typename R>
class SkipRange
{
public:
typedef typename R::value_type value_type;
SkipRange(R rng, int n)
: r(rng)
{
for (int i = 0; !r.empty() && (i < n); i++)
r.popFront();
}
bool empty() { return r.empty(); }
value_type popFront() { return r.popFront(); }
value_type popBack() { return r.popBack(); }
value_type front() { return r.front(); }
value_type back() { return r.back(); }
private:
R r;
};
// skip(skip(xxx, ...), ...)
template<typename R>
SkipRange<R> skip(R r, int n)
{
return SkipRange<R>(r,n);
}
// xxx.skip(...).skip(...)
template<template<typename> class TLinq, typename R>
class SkipRange_mixin
{
public:
TLinq<SkipRange<R> > skip(int n) const
{
return boolinq::skip(((TLinq<R>*)this)->r,n);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "SkipRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(SkipRange, ManyToMany)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = skip(rng, 0);
CheckRangeEqArray(dst, ans);
}
TEST(SkipRange, ManyToLess)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {4,5,6};
auto rng = range(src);
auto dst = skip(rng, 3);
CheckRangeEqArray(dst, ans);
}
TEST(SkipRange, ManyToOne)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {6};
auto rng = range(src);
auto dst = skip(rng, 5);
CheckRangeEqArray(dst, ans);
}
TEST(SkipRange, ManyToZero)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = skip(rng, 6);
EXPECT_TRUE(dst.empty());
}
TEST(SkipRange, ManyToZeroLess)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = skip(rng, 10);
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(SkipRange, OneToOne)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = skip(rng, 0);
CheckRangeEqArray(dst, ans);
}
TEST(SkipRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = skip(rng, 1);
EXPECT_TRUE(dst.empty());
}
TEST(SkipRange, OneToZeroLess)
{
int src[] = {5};
auto rng = range(src);
auto dst = skip(rng, 2);
EXPECT_TRUE(dst.empty());
}
TEST(SkipRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = skip(rng, 0);
EXPECT_TRUE(rng.empty());
}
TEST(SkipRange, ZeroToZeroLess)
{
std::vector<int> src;
auto rng = range(src);
auto dst = skip(rng, 2);
EXPECT_TRUE(rng.empty());
}
//////////////////////////////////////////////////////////////////////////
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <iostream>
#include "boolinq.h"
using namespace boolinq;
std::vector<int> vec(1000000, 0);
TEST(SpeedTest1, Init)
{
srand(0xDEADBEEF);
for (unsigned i = 0; i < vec.size(); i++)
vec[i] = rand();
}
TEST(SpeedTest1, BoolinqCode)
{
double avgValue = from(vec).where( [](int a){return a%2 == 1;})
.cast<double>()
.avg();
double disper = from(vec).where( [](int a){return a%2 == 1;})
.select([=](int a){return (double)((a-avgValue)*(a-avgValue));})
.avg();
EXPECT_EQ(164004, (int)(avgValue*10));
EXPECT_EQ(89512454, (int)disper);
}
TEST(SpeedTest1, CppCode)
{
double sum = 0;
int count = 0;
for (unsigned i = 0; i < vec.size(); i++)
{
if (vec[i] % 2 == 1)
{
sum += vec[i];
count++;
}
}
double avgValue = sum / count;
double disperSum = 0;
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] % 2 == 1)
disperSum += (vec[i] - avgValue)*(vec[i] - avgValue);
double disper = disperSum / count;
EXPECT_EQ(164004, (int)(avgValue*10));
EXPECT_EQ(89512454, (int)disper);
}
TEST(SpeedTest1, CppIterCode)
{
double sum = 0;
int count = 0;
for (auto it = vec.begin(); it != vec.end(); ++it)
{
if (*it % 2 == 1)
{
sum += *it;
count++;
}
}
double avgValue = sum / count;
double disperSum = 0;
for (auto it = vec.begin(); it != vec.end(); ++it)
if (*it % 2 == 1)
disperSum += (*it - avgValue)*(*it - avgValue);
double disper = disperSum / count;
EXPECT_EQ(164004, (int)(avgValue*10));
EXPECT_EQ(89512454, (int)disper);
}
#pragma once
namespace boolinq
{
// sum(xxx) and sum(xxx,lambda)
template<typename R, typename F>
auto sum(R r, F f) -> decltype(f(r.front()) + f(r.back()))
{
typedef decltype(f(r.front()) + f(r.back())) value_type;
value_type val = value_type();
for (; !r.empty(); r.popFront())
val = val + f(r.front());
return val;
}
template<typename R>
auto sum(R r) -> decltype(r.front() + r.back())
{
typedef decltype(r.front() + r.back()) value_type;
return sum(r,[](const value_type & a)->value_type{return a;});
}
// xxx.sum() and xxx.sum(lambda)
template<template<typename> class TLinq, typename R>
class Sum_mixin
{
template<typename F, typename TArg>
static auto get_return_type(F * f = NULL, TArg * arg = NULL)
-> decltype((*f)(*arg));
public:
//TODO: Invalid return type ... should be (value_type + value_type)
typename R::value_type sum() const
{
return boolinq::sum(((TLinq<R>*)this)->r);
}
template<typename F>
auto sum(F f) const -> decltype(get_return_type<F,typename R::value_type>()
+ get_return_type<F,typename R::value_type>())
{
return boolinq::sum(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <list>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Sum.h"
using namespace boolinq;
TEST(Sum, ThreeInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
auto rng = range(src);
EXPECT_EQ(6, sum(rng));
}
TEST(Sum, FiveInts)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
auto rng = range(src);
auto dst0 = where(rng, [](int a){return a%2 == 0;});
auto dst1 = where(rng, [](int a){return a%2 == 1;});
EXPECT_EQ(6, sum(dst0));
EXPECT_EQ(9, sum(dst1));
}
TEST(Sum, BoolSum)
{
std::vector<int> src;
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(4);
src.push_back(5);
auto rng = range(src);
EXPECT_EQ(2, sum(rng,[](int a){return a%2 == 0;}));
EXPECT_EQ(3, sum(rng,[](int a){return a%2 == 1;}));
}
TEST(Sum, FiveStringsLen)
{
std::vector<std::string> src;
src.push_back("hello");
src.push_back("apple");
src.push_back("nokia");
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
EXPECT_EQ(26, sum(rng,[](const std::string & str){return str.size();}));
}
TEST(Sum, FiveStringsData)
{
std::vector<std::string> src;
src.push_back("hello");
src.push_back("apple");
src.push_back("nokia");
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
std::string ans = "helloapplenokiaoracleponny";
EXPECT_EQ(ans, sum(rng));
}
#pragma once
#include "Count.h"
namespace boolinq
{
template<typename R>
class TakeRange
{
public:
typedef typename R::value_type value_type;
TakeRange(R r, int n)
: r(r), n(n), backReady(false)
{
}
bool empty()
{
if ((n == 0) && !backReady)
return true;
return r.empty();
}
value_type popFront()
{
n--;
return r.popFront();
}
value_type popBack()
{
if (!backReady)
prepareBack();
return r.popBack();
}
value_type front()
{
return r.front();
}
value_type back()
{
if (!backReady)
prepareBack();
return r.back();
}
private:
void prepareBack()
{
int size = boolinq::count(r);
while (size > n)
{
r.popBack();
size--;
}
backReady = true;
}
private:
R r;
int n;
bool backReady;
};
// take(take(xxx, ...), ...)
template<typename R>
TakeRange<R> take(R r, int n)
{
return TakeRange<R>(r,n);
}
// xxx.take(...).take(...)
template<template<typename> class TLinq, typename R>
class TakeRange_mixin
{
public:
TLinq<TakeRange<R> > take(int n) const
{
return boolinq::take(((TLinq<R>*)this)->r,n);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "TakeRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(TakeRange, ManyToMore)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = take(rng, 10);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, ManyToMany)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = take(rng, 6);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, ManyToLess)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1,2,3};
auto rng = range(src);
auto dst = take(rng, 3);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, ManyToOne)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1};
auto rng = range(src);
auto dst = take(rng, 1);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, ManyToZero)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = take(rng, 0);
EXPECT_TRUE(dst.empty());
}
//////////////////////////////////////////////////////////////////////////
TEST(TakeRange, OneToMore)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = take(rng, 5);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, OneToOne)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = take(rng, 1);
CheckRangeEqArray(dst, ans);
}
TEST(TakeRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = take(rng, 0);
EXPECT_TRUE(dst.empty());
}
TEST(TakeRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = take(rng, 0);
EXPECT_TRUE(rng.empty());
}
//////////////////////////////////////////////////////////////////////////
#pragma once
#include <allocators>
namespace boolinq
{
// toContainer<std::vector>(xxx)
// toContainer<QList>(xxx)
template<template<typename> class X, typename R>
X<typename R::value_type> toContainer(R r)
{
X<typename R::value_type> result;
for (; !r.empty(); r.popFront())
result.push_back(r.front());
return result;
}
template<template<typename,typename> class X, typename R>
X<typename R::value_type, std::allocator<typename R::value_type> > toContainer(R r)
{
X<typename R::value_type, std::allocator<typename R::value_type> > result;
for (; !r.empty(); r.popFront())
result.push_back(r.front());
return result;
}
// xxx.toContainer<std::vector>()
// xxx.toContainer<QList>()
template<template<typename> class TLinq, typename R>
class ToContainer_mixin
{
typedef typename R::value_type value_type;
public:
template<template<typename> class X>
X<value_type> toContainer() const
{
return boolinq::toContainer<X>(((TLinq<R>*)this)->r);
}
template<template<typename,typename> class X>
X<value_type, std::allocator<value_type> > toContainer() const
{
return boolinq::toContainer<X>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <list>
#include <deque>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "ToContainer.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(ToContainer, Array2List)
{
int src[] = {100,200,300};
auto rng = range(src);
auto dst = toContainer<std::list>(rng);
EXPECT_EQ(3, dst.size());
EXPECT_EQ(100, dst.front()); dst.pop_front();
EXPECT_EQ(200, dst.front()); dst.pop_front();
EXPECT_EQ(300, dst.front()); dst.pop_front();
}
TEST(ToContainer, Array2Deque)
{
int src[] = {100,200,300};
auto rng = range(src);
auto dst = toContainer<std::deque>(rng);
EXPECT_EQ(3, dst.size());
EXPECT_EQ(100, dst.front()); dst.pop_front();
EXPECT_EQ(200, dst.front()); dst.pop_front();
EXPECT_EQ(300, dst.front()); dst.pop_front();
}
TEST(ToContainer, Array2Vector)
{
int src[] = {100,200,300};
auto rng = range(src);
auto dst = toContainer<std::vector>(rng);
EXPECT_EQ(3, dst.size());
EXPECT_EQ(100, dst[0]);
EXPECT_EQ(200, dst[1]);
EXPECT_EQ(300, dst[2]);
}
//////////////////////////////////////////////////////////////////////////
TEST(ToContainer, List2List)
{
std::list<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toContainer<std::list>(rng);
EXPECT_EQ(dst,src);
}
TEST(ToContainer, Deque2Deque)
{
std::deque<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toContainer<std::deque>(rng);
EXPECT_EQ(dst,src);
}
TEST(ToContainer, Vector2Vector)
{
std::vector<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toContainer<std::vector>(rng);
EXPECT_EQ(dst,src);
}
//////////////////////////////////////////////////////////////////////////
#pragma once
#include <deque>
namespace boolinq
{
// toVector(xxx)
template<typename R>
std::deque<typename R::value_type> toDeque(R r)
{
std::deque<typename R::value_type> result;
for (; !r.empty(); r.popFront())
result.push_back(r.front());
return result;
}
// xxx.toVector()
template<template<typename> class TLinq, typename R>
class ToDeque_mixin
{
public:
std::deque<typename R::value_type> toDeque() const
{
return boolinq::toDeque(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <deque>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToDeque.h"
using namespace boolinq;
TEST(ToDeque, Deque2Deque)
{
std::deque<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toDeque(rng);
EXPECT_EQ(dst,src);
}
#pragma once
#include <list>
namespace boolinq
{
// toList(xxx)
template<typename R>
std::list<typename R::value_type> toList(R r)
{
std::list<typename R::value_type> result;
for (; !r.empty(); r.popFront())
result.push_back(r.front());
return result;
}
// xxx.toList()
template<template<typename> class TLinq, typename R>
class ToList_mixin
{
public:
std::list<typename R::value_type> toList() const
{
return boolinq::toList(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <list>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToList.h"
using namespace boolinq;
TEST(ToList, List2List)
{
std::list<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toList(rng);
EXPECT_EQ(dst,src);
}
#pragma once
#include <set>
namespace boolinq
{
// toSet(xxx)
template<typename R>
std::set<typename R::value_type> toSet(R r)
{
std::set<typename R::value_type> result;
for (; !r.empty(); r.popFront())
result.insert(r.front());
return result;
}
// xxx.toSet()
template<template<typename> class TLinq, typename R>
class ToSet_mixin
{
public:
std::set<typename R::value_type> toSet() const
{
return boolinq::toSet(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToSet.h"
using namespace boolinq;
TEST(ToSet, Vector2Set)
{
std::vector<int> src;
src.push_back(1);
src.push_back(1);
src.push_back(2);
src.push_back(3);
src.push_back(2);
auto rng = range(src);
auto dst = toSet(rng);
EXPECT_EQ(3,dst.size());
EXPECT_NE(dst.end(), dst.find(1));
EXPECT_NE(dst.end(), dst.find(2));
EXPECT_NE(dst.end(), dst.find(3));
}
#pragma once
#include <vector>
namespace boolinq
{
// toVector(xxx)
template<typename R>
std::vector<typename R::value_type> toVector(R r)
{
std::vector<typename R::value_type> result;
for (; !r.empty(); r.popFront())
result.push_back(r.front());
return result;
}
// xxx.toVector()
template<template<typename> class TLinq, typename R>
class ToVector_mixin
{
public:
std::vector<typename R::value_type> toVector() const
{
return boolinq::toVector(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToVector.h"
using namespace boolinq;
TEST(ToVector, Vector2Vector)
{
std::vector<int> src;
src.push_back(100);
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toVector(rng);
EXPECT_EQ(dst,src);
}
#pragma once
#include "BitsRange.h"
#include "UnbytesRange.h"
namespace boolinq
{
template<typename R, BitOrder bitOrder = HighToLow>
class UnbitsRange
{
enum
{
startBit = (bitOrder == LowToHigh) ? 0 : (CHAR_BIT-1),
finishBit = (bitOrder == LowToHigh) ? (CHAR_BIT-1) : 0,
stepBit = (bitOrder == LowToHigh) ? 1 : -1,
};
public:
typedef unsigned char value_type;
UnbitsRange(R rng)
: r(rng)
, frontValue()
, backValue()
, preEnd(r.empty())
, atEnd(r.empty())
{
if (!atEnd)
{
popFront();
popBack();
}
}
bool empty()
{
return atEnd;
}
value_type popFront()
{
value_type tmp = front();
if (preEnd)
{
atEnd = true;
return tmp;
}
if (r.empty())
{
preEnd = true;
frontValue = backValue;
}
else
{
frontValue = 0;
for (int i = startBit; !r.empty() && i != finishBit+stepBit; i += stepBit)
frontValue |= ((r.popFront()&1) << i);
}
return tmp;
}
value_type popBack()
{
value_type tmp = back();
if (preEnd)
{
atEnd = true;
return tmp;
}
if (r.empty())
{
preEnd = true;
backValue = frontValue;
}
else
{
backValue = 0;
for (int i = finishBit; !r.empty() && i != startBit-stepBit; i -= stepBit)
backValue |= ((r.popBack()&1) << i);
}
return tmp;
}
value_type front()
{
return frontValue;
}
value_type back()
{
return backValue;
}
private:
R r;
value_type frontValue;
value_type backValue;
bool preEnd;
bool atEnd;
};
// unbits(xxx)
// unbits<BitOrder>(xxx)
// unbits<T>(xxx)
// unbits<T,BitOrder>(xxx)
// unbits<T,ByteOrder>(xxx)
// unbits<T,BitOrder,ByteOrder>(xxx)
template<typename R>
UnbitsRange<R> unbits(R r)
{
return r;
}
template<BitOrder bitOrder, typename R>
UnbitsRange<R,bitOrder> unbits(R r)
{
return r;
}
template<typename T, typename R>
UnbytesRange<UnbitsRange<R>,T> unbits(R r)
{
return r;
}
template<typename T, BitOrder bitOrder, typename R>
UnbytesRange<UnbitsRange<R,bitOrder>,T> unbits(R r)
{
return r;
}
//template<typename T, ByteOrder byteOrder, typename R>
//UnbytesRange<UnbitsRange<R>,T,byteOrder> unbits(R r)
//{
// return r;
//}
template<typename T, BitOrder bitOrder, ByteOrder byteOrder, typename R>
UnbytesRange<UnbitsRange<R,bitOrder>,T,byteOrder> unbits(R r)
{
return r;
}
// xxx.unbits()
// xxx.unbits<BitOrder>()
// xxx.unbits<T>()
// xxx.unbits<T,BitOrder>()
// xxx.unbits<T,ByteOrder>()
// xxx.unbits<T,BitOrder,ByteOrder>()
template<template<typename> class TLinq, typename R>
class UnbitsRange_mixin
{
public:
TLinq<UnbitsRange<R> > unbits() const
{
return boolinq::unbits(((TLinq<R>*)this)->r);
}
template<BitOrder bitOrder>
TLinq<UnbitsRange<R,bitOrder> > unbits() const
{
return boolinq::unbits<bitOrder>(((TLinq<R>*)this)->r);
}
template<typename T>
TLinq<UnbytesRange<UnbitsRange<R>,T> > unbits() const
{
return boolinq::unbits<T>(((TLinq<R>*)this)->r);
}
template<typename T, BitOrder bitOrder>
TLinq<UnbytesRange<UnbitsRange<R,bitOrder>,T> > unbits() const
{
return boolinq::unbits<T,bitOrder>(((TLinq<R>*)this)->r);
}
//template<typename T, ByteOrder byteOrder>
//TLinq<UnbytesRange<UnbitsRange<R>,T,byteOrder> > unbits() const
//{
// return boolinq::unbits<T,byteOrder>(((TLinq<R>*)this)->r);
//}
template<typename T, BitOrder bitOrder, ByteOrder byteOrder>
TLinq<UnbytesRange<UnbitsRange<R,bitOrder>,T,byteOrder> > unbits() const
{
return boolinq::unbits<T,bitOrder,byteOrder>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "UnbitsRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(UnbitsRange, OneByteDefault)
{
int src[] = {1,0,1,0,1,0,1,0};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = unbits(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbitsRange, OneByteHL)
{
int src[] = {1,0,1,0,1,0,1,0};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = unbits<HighToLow>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbitsRange, OneByteLH)
{
int src[] = {0,1,0,1,0,1,0,1};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = unbits<LowToHigh>(rng);
CheckRangeEqArray(dst, ans);
}
\ No newline at end of file
#pragma once
#include "BytesRange.h"
namespace boolinq
{
template<typename R, typename T, ByteOrder byteOrder = FirstToLast>
class UnbytesRange
{
enum
{
startByte = (byteOrder == FirstToLast) ? 0 : (sizeof(T)-1),
finishByte = (byteOrder == FirstToLast) ? (sizeof(T)-1) : 0,
stepByte = (byteOrder == FirstToLast) ? 1 : -1,
};
public:
typedef T value_type;
UnbytesRange(R rng)
: r(rng)
, frontValue()
, backValue()
, preEnd(r.empty())
, atEnd(r.empty())
{
if (!atEnd)
{
popFront();
popBack();
}
}
bool empty()
{
return atEnd;
}
value_type popFront()
{
value_type tmp = front();
if (preEnd)
{
atEnd = true;
return tmp;
}
if (r.empty())
{
preEnd = true;
frontValue = backValue;
}
else
{
for (int i = startByte; i != finishByte+stepByte; i += stepByte)
((unsigned char*)&frontValue)[i] = r.popFront();
}
return tmp;
}
value_type popBack()
{
value_type tmp = back();
if (preEnd)
{
atEnd = true;
return tmp;
}
if (r.empty())
{
preEnd = true;
backValue = frontValue;
}
else
{
for (int i = finishByte; i != startByte-stepByte; i -= stepByte)
((unsigned char*)&backValue)[i] = r.popBack();
}
return tmp;
}
value_type front()
{
return frontValue;
}
value_type back()
{
return backValue;
}
private:
R r;
value_type frontValue;
value_type backValue;
bool preEnd;
bool atEnd;
};
// unbytes(xxx)
// unbytes<ByteOrder>(xxx)
template<typename T, typename R>
UnbytesRange<R,T> unbytes(R r)
{
return r;
}
template<typename T, ByteOrder byteOrder, typename R>
UnbytesRange<R,T,byteOrder> unbytes(R r)
{
return r;
}
// xxx.unbytes(...)
// xxx.unbytes<ByteOrder>(...)
template<template<typename> class TLinq, typename R>
class UnbytesRange_mixin
{
public:
template<typename T>
TLinq<UnbytesRange<R,T> > unbytes() const
{
return boolinq::unbytes<T>(((TLinq<R>*)this)->r);
}
template<typename T, ByteOrder byteOrder>
TLinq<UnbytesRange<R,T,byteOrder> > unbytes() const
{
return boolinq::unbytes<T,byteOrder>(((TLinq<R>*)this)->r);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "UnbytesRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(UnbytesRange, OneIntDefault)
{
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbytesRange, OneIntFL)
{
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int,FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbytesRange, OneIntLF)
{
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xAABBCCDD};
auto rng = range(src);
auto dst = unbytes<int,LastToFirst>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(UnbytesRange, TwoIntsDefault)
{
unsigned char src[] =
{
0x78,0x56,0x34,0x12,
0xAA,0xBB,0xCC,0xDD,
};
int ans[] = {0x12345678,0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbytesRange, TwoIntsFL)
{
unsigned char src[] =
{
0x78,0x56,0x34,0x12,
0xAA,0xBB,0xCC,0xDD,
};
int ans[] = {0x12345678,0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int,FirstToLast>(rng);
CheckRangeEqArray(dst, ans);
}
TEST(UnbytesRange, TwoIntsLF)
{
unsigned char src[] =
{
0x78,0x56,0x34,0x12,
0xAA,0xBB,0xCC,0xDD,
};
int ans[] = {0x78563412,0xAABBCCDD};
auto rng = range(src);
auto dst = unbytes<int,LastToFirst>(rng);
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(UnbytesRange, EmptyDefault)
{
std::vector<unsigned char> src;
auto rng = range(src);
auto dst = unbytes<int>(rng);
EXPECT_TRUE(dst.empty());
}
#pragma once
namespace boolinq
{
template<typename R, typename F>
class WhereRange
{
public:
typedef typename R::value_type value_type;
WhereRange(R r, F f)
: r(r), f(f)
, frontReady(false)
, backReady(false)
{
}
bool empty()
{
if (!frontReady)
seekFront();
return r.empty();
}
value_type popFront()
{
if (!frontReady)
seekFront();
auto tmp = *this;
r.popFront();
frontReady = false;
return tmp.front();
}
value_type popBack()
{
if (!frontReady)
seekFront();
auto tmp = *this;
r.popBack();
backReady = false;
return tmp.back();
}
value_type front()
{
if (!frontReady)
seekFront();
return r.front();
}
value_type back()
{
if (!backReady)
seekBack();
return r.back();
}
private:
void seekFront()
{
while(!r.empty() && !f(r.front()))
r.popFront();
frontReady = true;
}
void seekBack()
{
while(!r.empty() && !f(r.back()))
r.popBack();
backReady = true;
}
private:
R r;
F f;
bool frontReady;
bool backReady;
};
// where(where(xxx, ...), ...)
template<typename R, typename F>
WhereRange<R,F> where(R r, F f)
{
return WhereRange<R,F>(r,f);
}
// xxx.where(...).where(...)
template<template<typename> class TLinq, typename R>
class WhereRange_mixin
{
public:
template<typename F>
TLinq<WhereRange<R,F> > where(F f) const
{
return boolinq::where(((TLinq<R>*)this)->r,f);
}
};
}
// namespace boolinq
#include <vector>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "WhereRange.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
TEST(WhereRange, IntOdd)
{
int src[] = {1,2,3,4,5,6};
int ans[] = {1, 3, 5};
auto rng = range(src);
auto dst = where(rng, [](int a){return a%2 == 1;});
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(WhereRange, FirstLetterFront)
{
std::string src[] =
{
"apple",
"blackberry",
"adobe",
"microsoft",
"nokia",
};
std::string ans[] =
{
"apple",
"adobe",
};
auto rng = range(src);
auto dst = where(rng, [](std::string a){return a[0] == 'a';});
CheckRangeEqArray(dst, ans);
}
//////////////////////////////////////////////////////////////////////////
TEST(WhereRange, NameAgeLess)
{
struct NameAge
{
std::string name;
int age;
};
NameAge src[] =
{
{"man1",20},
{"man2",15},
{"man3",30},
{"man4",14},
{"man5",18},
};
NameAge ans[] =
{
{"man2",20},
{"man4",15},
};
auto rng = range(src);
auto dst = where(rng, [](const NameAge & a){return a.age < 18;});
CheckRangeEqArray(dst, ans, [](const NameAge & a){return a.name;});
}
//////////////////////////////////////////////////////////////////////////
TEST(WhereRange, MayToOne)
{
int src[] = {0,1,2};
int ans[] = {1};
auto rng = range(src);
auto dst = where(rng, [](int a){return a == 1;});
CheckRangeEqArray(dst, ans);
}
TEST(WhereRange, OneToOne)
{
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = where(rng, [](int a){return a>0;});
CheckRangeEqArray(dst, ans);
}
TEST(WhereRange, ManyToZero)
{
int src[] = {0,1,2};
auto rng = range(src);
auto dst = where(rng, [](int a){return a == 5;});
EXPECT_TRUE(dst.empty());
}
TEST(WhereRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = where(rng, [](int a){return a>10;});
EXPECT_TRUE(dst.empty());
}
TEST(WhereRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = where(rng, [](int a){return a>0;});
EXPECT_TRUE(rng.empty());
}
#pragma once
#include "IterRange.h"
#include "CastRange.h"
#include "SkipRange.h"
#include "TakeRange.h"
#include "WhereRange.h"
#include "SelectRange.h"
#include "ReverseRange.h"
#include "OrderByRange.h"
#include "GroupByRange.h"
#include "DistinctRange.h"
#include "ConcatRange.h"
#include "All.h"
#include "Any.h"
#include "Sum.h"
#include "Avg.h"
#include "Min.h"
#include "Max.h"
#include "Count.h"
#include "ForEach.h"
#include "Contains.h"
#include "ElementAt.h"
#include "ToSet.h"
#include "ToList.h"
#include "ToDeque.h"
#include "ToVector.h"
#include "ToContainer.h"
#include "BytesRange.h"
#include "BitsRange.h"
#include "UnbytesRange.h"
#include "UnbitsRange.h"
namespace boolinq
{
template<typename R>
class Linq
: public CastRange_mixin<Linq,R>
, public SkipRange_mixin<Linq,R>
, public TakeRange_mixin<Linq,R>
, public WhereRange_mixin<Linq,R>
, public SelectRange_mixin<Linq,R>
, public ReverseRange_mixin<Linq,R>
, public OrderByRange_mixin<Linq,R>
, public GroupByRange_mixin<Linq,R>
, public DistinctRange_mixin<Linq,R>
, public ConcatRange_mixin<Linq,R>
, public All_mixin<Linq,R>
, public Any_mixin<Linq,R>
, public Sum_mixin<Linq,R>
, public Avg_mixin<Linq,R>
, public Min_mixin<Linq,R>
, public Max_mixin<Linq,R>
, public Count_mixin<Linq,R>
, public ForEach_mixin<Linq,R>
, public Contains_mixin<Linq,R>
, public ElementAt_mixin<Linq,R>
, public ToSet_mixin<Linq,R>
, public ToList_mixin<Linq,R>
, public ToDeque_mixin<Linq,R>
, public ToVector_mixin<Linq,R>
, public ToContainer_mixin<Linq,R>
, public BytesRange_mixin<Linq,R>
, public BitsRange_mixin<Linq,R>
, public UnbytesRange_mixin<Linq,R>
, public UnbitsRange_mixin<Linq,R>
{
public:
typedef typename R::value_type value_type;
Linq(const R & r)
: r(r)
{
}
operator R () const
{
return r;
}
operator R & ()
{
return r;
}
bool empty() { return r.empty(); }
value_type popFront() { return r.popFront(); }
value_type popBack() { return r.popBack(); }
value_type front() { return r.front(); }
value_type back() { return r.back(); }
public:
R r;
};
//////////////////////////////////////////////////////////////////////////
// from<CustomLinq>(xxx)
//////////////////////////////////////////////////////////////////////////
template<template<typename> class TLinq, typename X>
TLinq<IterRange<typename X::const_iterator> > from(const X & x)
{
return range(x);
}
template<template<typename> class TLinq, typename X, const int N>
TLinq<IterRange<const X*> > from(const X (&x)[N])
{
return range(x);
}
template<template<typename> class TLinq, typename X>
TLinq<IterRange<X> > from(X b, X e)
{
return range(b,e);
}
template<template<typename> class TLinq, typename X>
TLinq<IterRange<const X*> > from(const X * b, const X * e)
{
return range(b,e);
}
template<template<typename> class TLinq, typename X>
TLinq<IterRange<const X*> > from(const X * b, int n)
{
return range(b,n);
}
//////////////////////////////////////////////////////////////////////////
// from(xxx)
//////////////////////////////////////////////////////////////////////////
template<typename X>
Linq<IterRange<typename X::const_iterator> > from(const X & x)
{
return from<Linq>(x);
}
template<typename X, const int N>
Linq<IterRange<const X*> > from(const X (&x)[N])
{
return from<Linq>(x);
}
template<typename X>
Linq<IterRange<X> > from(X b, X e)
{
return from<Linq>(b,e);
}
template<typename X>
Linq<IterRange<const X*> > from(const X * b, const X * e)
{
return from<Linq>(b,e);
}
template<typename X>
Linq<IterRange<const X*> > from(const X * b, int n)
{
return from<Linq>(b,n);
}
//////////////////////////////////////////////////////////////////////////
// Linq equality operator for container and array
//////////////////////////////////////////////////////////////////////////
template<typename R, typename X>
bool operator == (const Linq<R> & rng, const X & x)
{
Linq<R> tmp = rng;
for (auto it = x.begin(); it != x.end(); ++it)
{
if (tmp.empty())
return false;
if (tmp.popFront() != *it)
return false;
}
return tmp.empty();
}
template<typename R, typename X>
bool operator == (const X & x, const Linq<R> & rng)
{
return rng == x;
}
template<typename R, typename X, const int N>
bool operator == (const Linq<R> & rng, const X (&x)[N])
{
Linq<R> tmp = rng;
for (int i = 0; i < N; i++)
{
if (tmp.empty())
return false;
if (tmp.popFront() != x[i])
return false;
}
return tmp.empty();
}
template<typename R, typename X, const int N>
bool operator == (const X (&x)[N], const Linq<R> & rng)
{
return rng == x;
}
}
// namespace boolinq
# ----------------------------------------------------
# This file is generated by the Qt Visual Studio Add-in.
# ------------------------------------------------------
TEMPLATE = app
TARGET = boolinq
DESTDIR = ../Debug
CONFIG += debug console
DEFINES += _CONSOLE
INCLUDEPATH += . \
../gmock \
../gmock/include \
../gmock/gtest \
../gmock/gtest/include
LIBS += -L"."
DEPENDPATH += .
OBJECTS_DIR += debug
QMAKE_CXXFLAGS += -std=c++0x
HEADERS += ./boolinq.h \
./SkipRange.h \
./TakeRange.h \
./ConcatRange.h \
./DistinctRange.h \
./GroupByRange.h \
./OrderByRange.h \
./IterRange.h \
./ReverseRange.h \
./SelectRange.h \
./WhereRange.h \
./ToSet.h \
./ToContainer.h \
./ToDeque.h \
./ToList.h \
./ToVector.h \
./All.h \
./Any.h \
./Avg.h \
./Contains.h \
./ElementAt.h \
./ForEach.h \
./Max.h \
./Min.h \
./Sum.h \
./Count.h \
./BytesRange.h \
./BitsRange.h \
./UnbitsRange.h \
./UnbytesRange.h \
./CommonTests.h
SOURCES += ./main.cpp \
./DotCallTest.cpp \
./LinqTest.cpp \
./ToContainerTest.cpp \
./ToDequeTest.cpp \
./ToListTest.cpp \
./ToSetTest.cpp \
./ToVectorTest.cpp \
./DistinctRangeTest.cpp \
./GroupByRangeTest.cpp \
./OrderByRangeTest.cpp \
./ReverseRangeTest.cpp \
./SelectRangeTest.cpp \
./SkipRangeTest.cpp \
./TakeRangeTest.cpp \
./IterRangeTest.cpp \
./ConcatRangeTest.cpp \
./WhereRangeTest.cpp \
./AllTest.cpp \
./AnyTest.cpp \
./AvgTest.cpp \
./ContainsTest.cpp \
./CountTest.cpp \
./ElementAtTest.cpp \
./ForEachTest.cpp \
./MaxTest.cpp \
./MinTest.cpp \
./SumTest.cpp \
./BytesRangeTest.cpp \
./BitsRangeTest.cpp \
./UnbitsRangeTest.cpp \
./UnbytesRangeTest.cpp \
../gmock/src/gmock-all.cc \
../gmock/gtest/src/gtest-all.cc
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{65AA3851-4457-48AB-BD08-83250D523D49}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>boolinq</RootNamespace>
<ProjectName>boolinq</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\gmock\;..\gmock\include;..\gmock\gtest\;..\gmock\gtest\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\gmock\;..\gmock\include;..\gmock\gtest\;..\gmock\gtest\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\gmock\gtest\src\gtest-all.cc" />
<ClCompile Include="..\gmock\src\gmock-all.cc" />
<ClCompile Include="AllTest.cpp" />
<ClCompile Include="AnyTest.cpp" />
<ClCompile Include="AvgTest.cpp" />
<ClCompile Include="ContainsTest.cpp" />
<ClCompile Include="CountTest.cpp" />
<ClCompile Include="DistinctRangeTest.cpp" />
<ClCompile Include="DotCallTest.cpp" />
<ClCompile Include="ElementAtTest.cpp" />
<ClCompile Include="ForEachTest.cpp" />
<ClCompile Include="GroupByRangeTest.cpp" />
<ClCompile Include="MaxTest.cpp" />
<ClCompile Include="MinTest.cpp" />
<ClCompile Include="OrderByRangeTest.cpp" />
<ClCompile Include="ReverseRangeTest.cpp" />
<ClCompile Include="SelectRangeTest.cpp" />
<ClCompile Include="SkipRangeTest.cpp" />
<ClCompile Include="SpeedTest.cpp" />
<ClCompile Include="SumTest.cpp" />
<ClCompile Include="TakeRangeTest.cpp" />
<ClCompile Include="BytesRangeTest.cpp" />
<ClCompile Include="BitsRangeTest.cpp" />
<ClCompile Include="ToContainerTest.cpp" />
<ClCompile Include="ToDequeTest.cpp" />
<ClCompile Include="ToListTest.cpp" />
<ClCompile Include="LinqTest.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="IterRangeTest.cpp" />
<ClCompile Include="ToSetTest.cpp" />
<ClCompile Include="ToVectorTest.cpp" />
<ClCompile Include="UnbitsRangeTest.cpp" />
<ClCompile Include="UnbytesRangeTest.cpp" />
<ClCompile Include="ConcatRangeTest.cpp" />
<ClCompile Include="WhereRangeTest.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="All.h" />
<ClInclude Include="Any.h" />
<ClInclude Include="Avg.h" />
<ClInclude Include="boolinq.h" />
<ClInclude Include="CastRange.h" />
<ClInclude Include="CommonTests.h" />
<ClInclude Include="Contains.h" />
<ClInclude Include="ElementAt.h" />
<ClInclude Include="ForEach.h" />
<ClInclude Include="Max.h" />
<ClInclude Include="Min.h" />
<ClInclude Include="SkipRange.h" />
<ClInclude Include="Sum.h" />
<ClInclude Include="TakeRange.h" />
<ClInclude Include="BytesRange.h" />
<ClInclude Include="BitsRange.h" />
<ClInclude Include="ToSet.h" />
<ClInclude Include="UnbitsRange.h" />
<ClInclude Include="UnbytesRange.h" />
<ClInclude Include="ConcatRange.h" />
<ClInclude Include="Count.h" />
<ClInclude Include="DistinctRange.h" />
<ClInclude Include="GroupByRange.h" />
<ClInclude Include="OrderByRange.h" />
<ClInclude Include="ToContainer.h" />
<ClInclude Include="ToDeque.h" />
<ClInclude Include="ToList.h" />
<ClInclude Include="IterRange.h" />
<ClInclude Include="ReverseRange.h" />
<ClInclude Include="SelectRange.h" />
<ClInclude Include="ToVector.h" />
<ClInclude Include="WhereRange.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Test Files">
<UniqueIdentifier>{6b58e162-6433-41da-b055-7101f6bb2b6d}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Ranges">
<UniqueIdentifier>{02f36613-1ddf-49e7-83aa-8816f01eff05}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Exports">
<UniqueIdentifier>{25f18c55-d4b1-4dfa-88ec-a54b129d1589}</UniqueIdentifier>
</Filter>
<Filter Include="Test Files\Exports">
<UniqueIdentifier>{eb563358-6445-4f61-bd6f-990c914f5ebf}</UniqueIdentifier>
</Filter>
<Filter Include="Test Files\Ranges">
<UniqueIdentifier>{7977c11f-757b-4c22-a388-d9c33a8ff0e8}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Aggregate">
<UniqueIdentifier>{5462829c-af51-4f8e-b5b8-a1ce71f2abda}</UniqueIdentifier>
</Filter>
<Filter Include="Test Files\Aggregate">
<UniqueIdentifier>{1b19ecdd-bb5e-41a2-9eee-86ef0975a2cd}</UniqueIdentifier>
</Filter>
<Filter Include="Test Files\Custom">
<UniqueIdentifier>{2d45ce7d-0cf5-4bd4-a512-fd034a68f701}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Custom">
<UniqueIdentifier>{d9678ae3-e775-4e2d-b21e-77e1a7cbee16}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\gmock\src\gmock-all.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\gmock\gtest\src\gtest-all.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LinqTest.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="ToDequeTest.cpp">
<Filter>Test Files\Exports</Filter>
</ClCompile>
<ClCompile Include="ToContainerTest.cpp">
<Filter>Test Files\Exports</Filter>
</ClCompile>
<ClCompile Include="ToListTest.cpp">
<Filter>Test Files\Exports</Filter>
</ClCompile>
<ClCompile Include="ToSetTest.cpp">
<Filter>Test Files\Exports</Filter>
</ClCompile>
<ClCompile Include="ToVectorTest.cpp">
<Filter>Test Files\Exports</Filter>
</ClCompile>
<ClCompile Include="ContainsTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="CountTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="ElementAtTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="DistinctRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="WhereRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="GroupByRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="IterRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="OrderByRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="ReverseRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="SelectRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="SumTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="AllTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="AnyTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="AvgTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="MinTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="MaxTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="TakeRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="SkipRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="BytesRangeTest.cpp">
<Filter>Test Files\Custom</Filter>
</ClCompile>
<ClCompile Include="BitsRangeTest.cpp">
<Filter>Test Files\Custom</Filter>
</ClCompile>
<ClCompile Include="UnbytesRangeTest.cpp">
<Filter>Test Files\Custom</Filter>
</ClCompile>
<ClCompile Include="UnbitsRangeTest.cpp">
<Filter>Test Files\Custom</Filter>
</ClCompile>
<ClCompile Include="DotCallTest.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="ConcatRangeTest.cpp">
<Filter>Test Files\Ranges</Filter>
</ClCompile>
<ClCompile Include="ForEachTest.cpp">
<Filter>Test Files\Aggregate</Filter>
</ClCompile>
<ClCompile Include="SpeedTest.cpp">
<Filter>Test Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="boolinq.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DistinctRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="GroupByRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="OrderByRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="ReverseRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="SelectRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="WhereRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="ToDeque.h">
<Filter>Header Files\Exports</Filter>
</ClInclude>
<ClInclude Include="ToContainer.h">
<Filter>Header Files\Exports</Filter>
</ClInclude>
<ClInclude Include="ToList.h">
<Filter>Header Files\Exports</Filter>
</ClInclude>
<ClInclude Include="ToSet.h">
<Filter>Header Files\Exports</Filter>
</ClInclude>
<ClInclude Include="ToVector.h">
<Filter>Header Files\Exports</Filter>
</ClInclude>
<ClInclude Include="Contains.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="Count.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="ElementAt.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="IterRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="Sum.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="All.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="Any.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="Avg.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="Min.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="Max.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="CommonTests.h">
<Filter>Test Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="TakeRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="SkipRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="BytesRange.h">
<Filter>Header Files\Custom</Filter>
</ClInclude>
<ClInclude Include="BitsRange.h">
<Filter>Header Files\Custom</Filter>
</ClInclude>
<ClInclude Include="UnbytesRange.h">
<Filter>Header Files\Custom</Filter>
</ClInclude>
<ClInclude Include="UnbitsRange.h">
<Filter>Header Files\Custom</Filter>
</ClInclude>
<ClInclude Include="ConcatRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
<ClInclude Include="ForEach.h">
<Filter>Header Files\Aggregate</Filter>
</ClInclude>
<ClInclude Include="CastRange.h">
<Filter>Header Files\Ranges</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
#include <gmock/gmock.h>
#include <gtest/gtest.h>
////////////////////////////////////////////////////////////////
/*
template<class R, class T>
R find(R r, T value)
{
for (; !r.empty(); r.popFront())
if (value == r.front()) break;
return r;
}
template<class R, class T>
R find_end(R r, T value)
{
return retro(find(retro(r), value));
}
*/
////////////////////////////////////////////////////////////////
int main(int argc, char * argv[])
{
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
\ No newline at end of file
# encoding: UTF-8
Dir.chdir "boolinq"
HeaderFile = Struct.new(:name, :links, :content)
include_std = [];
file_list = [];
for file in Dir.glob("*.h").sort!{|a,b| a.length <=> b.length}
puts "Processing file #{file} ..."
links = [];
content = [];
for line in File.open(file, "r")
if line.start_with?("#include <")
include_std << line
elsif line.start_with?("#include \"")
links << line[10..-3]
elsif line.start_with?("#pragma once")
else
content << line
end
end
file_list << HeaderFile.new(file,links,content)
end
# Rearrange files
index = 0
while index < file_list.count
max_index = index
for link in file_list[index].links
tmp_index = file_list.index{|f| f.name == link}
tmp_index = -1 if tmp_index == nil
max_index = [max_index,tmp_index].max
end
if max_index > index
puts "#{file_list.count} #{index} #{max_index}"
puts "#{file_list[index].name} #{file_list[max_index].name}"
tmp = file_list[index]
file_list.delete_at(index)
file_list.insert(max_index,tmp)
end
index += 1
end
# Output to single file
Dir.chdir ".."
ofile = File.open("boolinq-all.h", "w")
ofile.puts "#pragma once"
ofile.puts
puts
include_std.sort_by!{|a| a.size}
for inc in include_std
puts "#{inc}"
ofile.puts inc
end
puts
for file in file_list
puts "#include \"#{file.name}\""
ofile.puts file.content
end
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