Commit b3a17db5 authored by Anton Bukov's avatar Anton Bukov

Boolinq 2.0.0

parent bc2b117c
Debug
/*.opensdf
*.sdf
*.user
[submodule "gmock"]
path = gmock
url = https://github.com/mgoral/googlemock
Copyright (C) 2013 by Anton Bukov (k06aaa@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
\ No newline at end of file
#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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "All.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,17 +15,17 @@ TEST(All, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_TRUE(all(rng));
EXPECT_TRUE(rng.all());
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_TRUE(rng.all([](int a){return a>0;}));
EXPECT_TRUE(rng.all([](int a){return a<4;}));
EXPECT_TRUE(rng.all([](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;}));
EXPECT_FALSE(rng.all([](int a){return a>2;}));
EXPECT_FALSE(rng.all([](int a){return a==1;}));
EXPECT_FALSE(rng.all([](int a){return a<3;}));
}
TEST(All, ThreeIntsSecond)
......@@ -36,15 +35,15 @@ TEST(All, ThreeIntsSecond)
src.push_back(1);
src.push_back(2);
auto rng = range(src);
auto rng = from(src);
EXPECT_FALSE(all(rng));
EXPECT_FALSE(rng.all());
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_TRUE(rng.all([](int a){return a>=0;}));
EXPECT_TRUE(rng.all([](int a){return a<=2;}));
EXPECT_TRUE(rng.all([](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;}));
EXPECT_FALSE(rng.all([](int a){return a>1;}));
EXPECT_FALSE(rng.all([](int a){return a==1;}));
EXPECT_FALSE(rng.all([](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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Any.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,19 +15,19 @@ TEST(Any, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_TRUE(any(rng));
EXPECT_TRUE(rng.any());
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_TRUE(rng.any([](int a){return a==1;}));
EXPECT_TRUE(rng.any([](int a){return a==2;}));
EXPECT_TRUE(rng.any([](int a){return a==3;}));
EXPECT_TRUE(rng.any([](int a){return a>1;}));
EXPECT_TRUE(rng.any([](int a){return a<3;}));
EXPECT_TRUE(rng.any([](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;}));
EXPECT_FALSE(rng.any([](int a){return a==0;}));
EXPECT_FALSE(rng.any([](int a){return a==4;}));
EXPECT_FALSE(rng.any([](int a){return a<1;}));
EXPECT_FALSE(rng.any([](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
......@@ -4,9 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Avg.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,9 +15,9 @@ TEST(Avg, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(2, avg(rng));
EXPECT_EQ(2, rng.avg<double>());
}
TEST(Avg, FiveInts)
......@@ -31,12 +29,12 @@ TEST(Avg, FiveInts)
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;});
auto rng = from(src);
auto dst0 = rng.where([](int a){return a%2 == 0;});
auto dst1 = rng.where([](int a){return a%2 == 1;});
EXPECT_EQ(3, avg(dst0));
EXPECT_EQ(3, avg(dst1));
EXPECT_EQ(3, dst0.avg<double>());
EXPECT_EQ(3, dst1.avg<double>());
}
TEST(Avg, FiveStringsLen)
......@@ -48,7 +46,7 @@ TEST(Avg, FiveStringsLen)
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(5, avg(rng,[](const std::string & str){return str.size();}));
EXPECT_EQ(5, rng.avg<int>([](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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "BitsRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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);
auto rng = from(src);
auto dst = rng.bits();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ 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);
auto rng = from(src);
auto dst = rng.bits(HighToLow);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ 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);
auto rng = from(src);
auto dst = rng.bits(LowToHigh);
CheckRangeEqArray(dst, ans);
}
......@@ -58,8 +57,8 @@ TEST(BitsRange, OneIntDefault)
0,0,0,1,0,0,1,0,
};
auto rng = range(src);
auto dst = bits(rng);
auto rng = from(src);
auto dst = rng.bits();
CheckRangeEqArray(dst, ans);
}
......@@ -75,8 +74,8 @@ TEST(BitsRange, OneIntHL)
0,0,0,1,0,0,1,0,
};
auto rng = range(src);
auto dst = bits<HighToLow>(rng);
auto rng = from(src);
auto dst = rng.bits(HighToLow);
CheckRangeEqArray(dst, ans);
}
......@@ -92,8 +91,9 @@ TEST(BitsRange, OneIntLH)
0,1,0,0,1,0,0,0,
};
auto rng = range(src);
auto dst = bits<LowToHigh,FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.bits(LowToHigh,FirstToLast);
auto vvv = dst.toVector();
CheckRangeEqArray(dst, ans);
}
......@@ -116,8 +116,8 @@ TEST(BitsRange, IntsDefault)
1,0,1,0,1,0,1,0, // AA
};
auto rng = range(src);
auto dst = bits(rng);
auto rng = from(src);
auto dst = rng.bits();
CheckRangeEqArray(dst, ans);
}
......@@ -138,8 +138,8 @@ TEST(BitsRange, IntsHL)
1,0,1,0,1,0,1,0, // AA
};
auto rng = range(src);
auto dst = bits<HighToLow>(rng);
auto rng = from(src);
auto dst = rng.bits(HighToLow);
CheckRangeEqArray(dst, ans);
}
......@@ -160,8 +160,8 @@ TEST(BitsRange, IntsLH)
0,1,0,1,0,1,0,1, // -AA
};
auto rng = range(src);
auto dst = bits<LowToHigh>(rng);
auto rng = from(src);
auto dst = rng.bits(LowToHigh);
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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "BytesRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ TEST(BytesRange, OneByteDefault)
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes(rng);
auto rng = from(src);
auto dst = rng.bytes();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ TEST(BytesRange, OneByteFL)
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.bytes(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ TEST(BytesRange, OneByteLF)
unsigned char src[] = {0xAA};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
auto rng = from(src);
auto dst = rng.bytes(LastToFirst);
CheckRangeEqArray(dst, ans);
}
......@@ -52,8 +51,8 @@ TEST(BytesRange, OneIntDefault)
int src[] = {0x12345678};
int ans[] = {0x78,0x56,0x34,0x12};
auto rng = range(src);
auto dst = bytes(rng);
auto rng = from(src);
auto dst = rng.bytes();
CheckRangeEqArray(dst, ans);
}
......@@ -63,8 +62,8 @@ TEST(BytesRange, OneIntFL)
int src[] = {0x12345678};
int ans[] = {0x78,0x56,0x34,0x12};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.bytes(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -74,8 +73,8 @@ TEST(BytesRange, OneIntLF)
int src[] = {0x12345678};
int ans[] = {0x12,0x34,0x56,0x78};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
auto rng = from(src);
auto dst = rng.bytes(LastToFirst);
CheckRangeEqArray(dst, ans);
}
......@@ -91,8 +90,8 @@ TEST(BytesRange, IntsDefault)
0xDD,0xCC,0xBB,0xAA,
};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.bytes(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -106,8 +105,8 @@ TEST(BytesRange, IntsFL)
0xDD,0xCC,0xBB,0xAA,
};
auto rng = range(src);
auto dst = bytes<FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.bytes(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -121,8 +120,8 @@ TEST(BytesRange, IntsLF)
0xAA,0xBB,0xCC,0xDD,
};
auto rng = range(src);
auto dst = bytes<LastToFirst>(rng);
auto rng = from(src);
auto dst = rng.bytes(LastToFirst);
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
#include <set>
//////////////////////////////////////////////////////////////////////////
// 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;});
}
for (int i = 0; i < N; i++)
EXPECT_EQ(f(ans[i]), f(dst.nextObject()));
template<typename R, typename T, int N>
void CheckRangeEqArrayBackFront(R dst, T (&ans)[N])
{
CheckRangeEqArrayBackFront(dst, ans, [](const T & a)->T{return a;});
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
template<typename R, typename T, int N>
void CheckRangeEqArray(R dst, T (&ans)[N])
{
CheckRangeEqArray(dst, ans, [](const T & a)->T{return a;});
}
for (int i = 0; i < N; i++)
EXPECT_EQ(ans[i], dst.nextObject());
//////////////////////////////////////////////////////////////////////////
// Compare Range with set
//////////////////////////////////////////////////////////////////////////
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
template<typename T, int N>
std::set<T> ArrayToSet(T (&ans)[N])
......@@ -122,90 +36,18 @@ std::set<T> ArrayToSet(T (&ans)[N])
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)
template<typename R, typename T, int N>
void CheckRangeEqSet(R dst, T (&ans)[N])
{
std::set<T> result;
while (!r.empty())
result.insert(f(r.popBack()));
std::set<T> expected = ArrayToSet(ans);
std::set<typename R::value_type> actual = dst.toSet();
EXPECT_EQ(ArrayToSet(ans),result);
}
EXPECT_EQ(expected.size(), actual.size());
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())
std::set<T>::iterator it1 = expected.begin();
std::set<typename R::value_type>::iterator it2 = actual.begin();
for(; it1 != expected.end() && it2 != actual.end(); it1++, it2++)
{
if (bit ^= 1)
result.insert(f(r.popFront()));
else
result.insert(f(r.popBack()));
EXPECT_EQ(*it2, *it1);
}
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;});
}
#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
......@@ -2,8 +2,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "ConcatRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -14,9 +13,9 @@ TEST(ConcatRange, ArrayArray)
int ans[] = {1,2,3,4,5,6,7,8,9};
auto rng1 = range(src1);
auto rng2 = range(src2);
auto dst = unionAll(rng1,rng2);
auto rng1 = from(src1);
auto rng2 = from(src2);
auto dst = rng1.concat(rng2);
CheckRangeEqArray(dst, ans);
}
......@@ -32,9 +31,9 @@ TEST(ConcatRange, ArrayVector)
int ans[] = {1,2,3,4,5,6,7,8,9};
auto rng1 = range(src1);
auto rng2 = range(src2);
auto dst = unionAll(rng1,rng2);
auto rng1 = from(src1);
auto rng2 = from(src2);
auto dst = rng1.concat(rng2);
CheckRangeEqArray(dst, ans);
}
......@@ -51,10 +50,10 @@ TEST(ConcatRange, ArrayVectorArray)
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);
auto rng1 = from(src1);
auto rng2 = from(src2);
auto rng3 = from(src3);
auto dst = rng1.concat(rng2).concat(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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Contains.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,14 +15,14 @@ TEST(Contains, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_TRUE(contains(rng,1));
EXPECT_TRUE(contains(rng,2));
EXPECT_TRUE(contains(rng,3));
EXPECT_TRUE(rng.contains(1));
EXPECT_TRUE(rng.contains(2));
EXPECT_TRUE(rng.contains(3));
EXPECT_FALSE(contains(rng,0));
EXPECT_FALSE(contains(rng,4));
EXPECT_FALSE(rng.contains(0));
EXPECT_FALSE(rng.contains(4));
}
TEST(Contains, FiveStrings)
......@@ -35,14 +34,14 @@ TEST(Contains, FiveStrings)
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
auto rng = from(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_TRUE(rng.contains("hello"));
EXPECT_TRUE(rng.contains("apple"));
EXPECT_TRUE(rng.contains("nokia"));
EXPECT_TRUE(rng.contains("oracle"));
EXPECT_TRUE(rng.contains("ponny"));
EXPECT_FALSE(contains(rng,"dino"));
EXPECT_FALSE(contains(rng,"lord"));
EXPECT_FALSE(rng.contains("dino"));
EXPECT_FALSE(rng.contains("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
......@@ -4,9 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Count.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,9 +15,9 @@ TEST(Count, ThreeIntsVector)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(3, count(rng));
EXPECT_EQ(3, rng.count());
}
TEST(Count, ThreeIntsList)
......@@ -29,9 +27,9 @@ TEST(Count, ThreeIntsList)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(3, count(rng));
EXPECT_EQ(3, rng.count());
}
TEST(Count, FiveInts)
......@@ -43,12 +41,12 @@ TEST(Count, FiveInts)
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;});
auto rng = from(src);
auto dst0 = rng.where([](int a){return a%2 == 0;});
auto dst1 = rng.where([](int a){return a%2 == 1;});
EXPECT_EQ(2, count(dst0));
EXPECT_EQ(3, count(dst1));
EXPECT_EQ(2, dst0.count());
EXPECT_EQ(3, dst1.count());
}
TEST(Count, OddCount)
......@@ -60,8 +58,8 @@ TEST(Count, OddCount)
src.push_back(0);
src.push_back(1);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(2, count(rng,0));
EXPECT_EQ(3, count(rng,1));
EXPECT_EQ(2, rng.count(0));
EXPECT_EQ(3, rng.count(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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "DistinctRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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);
auto rng = from(src);
auto dst = rng.distinct();
CheckRangeEqSet(dst, ans);
}
......@@ -28,8 +27,8 @@ 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);
auto rng = from(src);
auto dst = rng.distinct();
CheckRangeEqSet(dst, ans);
}
......@@ -39,8 +38,8 @@ TEST(DistinctRange, ManyEqualsFront)
int src[] = {1,1,1,1};
int ans[] = {1};
auto rng = range(src);
auto dst = distinct(rng);
auto rng = from(src);
auto dst = rng.distinct();
CheckRangeEqSet(dst, ans);
}
......@@ -50,8 +49,8 @@ TEST(DistinctRange, ManyEqualsWithOneFront)
int src[] = {1,1,2,1};
int ans[] = {1,2};
auto rng = range(src);
auto dst = distinct(rng);
auto rng = from(src);
auto dst = rng.distinct();
CheckRangeEqSet(dst, ans);
}
......@@ -68,6 +67,16 @@ TEST(DistinctRange, OneFieldFront)
return (name < man.name)
|| (name == man.name && age < man.age);
}
bool operator == (const Man & man) const
{
return (name == man.name);
}
bool operator == (const std::string & name) const
{
return (this->name == name);
}
};
Man src[] =
......@@ -80,25 +89,16 @@ TEST(DistinctRange, OneFieldFront)
{"Banan",1},
};
std::string ansF[] =
std::string ans[] =
{
"Banan",
"Anton",
"Taran",
"Poker",
"Agata",
};
std::string ansB[] =
{
"Taran",
"Poker",
"Agata",
"Banan",
};
auto rng = range(src);
auto dst = distinct(rng, [](const Man & man){return man.age;});
auto rng = from(src);
auto dst = rng.distinct([](const Man & man){return man.age;});
CheckRangeEqSetFront(dst, ansF, [](const Man & man){return man.name;});
CheckRangeEqSetBack(dst, ansB, [](const Man & man){return man.name;});
CheckRangeEqSet(dst, ans);
}
\ No newline at end of file
......@@ -28,8 +28,8 @@ TEST(DotCall, BytesRange)
};
auto dstFL1 = from(src).bytes();
auto dstFL2 = from(src).bytes<FirstToLast>();
auto dstLF1 = from(src).bytes<LastToFirst>();
auto dstFL2 = from(src).bytes(FirstToLast);
auto dstLF1 = from(src).bytes(LastToFirst);
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
......@@ -49,8 +49,8 @@ TEST(DotCall, UnbytesRange)
int ansLF[] = {0x78563412,0xDDCCBBAA};
auto dstFL1 = from(src).unbytes<int>();
auto dstFL2 = from(src).unbytes<int,FirstToLast>();
auto dstLF1 = from(src).unbytes<int,LastToFirst>();
auto dstFL2 = from(src).unbytes<int>(FirstToLast);
auto dstLF1 = from(src).unbytes<int>(LastToFirst);
CheckRangeEqArray(dstFL1, ansFL);
CheckRangeEqArray(dstFL2, ansFL);
......@@ -78,9 +78,9 @@ TEST(DotCall, BitsRangeHL)
};
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>();
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);
......@@ -106,9 +106,9 @@ TEST(DotCall, BitsRangeLH)
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>();
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);
......@@ -131,10 +131,10 @@ TEST(DotCall, UnbitsRangeHLFL)
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>();
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);
......
#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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ElementAt.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,11 +15,11 @@ TEST(ElementAt, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(1, elementAt(rng,0));
EXPECT_EQ(2, elementAt(rng,1));
EXPECT_EQ(3, elementAt(rng,2));
EXPECT_EQ(1, rng.elementAt(0));
EXPECT_EQ(2, rng.elementAt(1));
EXPECT_EQ(3, rng.elementAt(2));
}
TEST(ElementAt, FiveStrings)
......@@ -32,11 +31,11 @@ TEST(ElementAt, FiveStrings)
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
auto rng = from(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));
EXPECT_EQ("hello", rng.elementAt(0));
EXPECT_EQ("apple", rng.elementAt(1));
EXPECT_EQ("nokia", rng.elementAt(2));
EXPECT_EQ("oracle", rng.elementAt(3));
EXPECT_EQ("ponny", rng.elementAt(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
......@@ -5,8 +5,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ForEach.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -18,7 +17,7 @@ TEST(ForEach, ThreeCharsSum)
src.push_back('c');
std::string str = "";
for_each(range(src), [&](char a){str += a;});
from(src).foreach([&](char a){str += a;});
EXPECT_EQ("abc", str);
}
......@@ -31,7 +30,7 @@ TEST(ForEach, ThreeCharsUpperSum)
src.push_back('c');
std::string str = "";
for_each(range(src), [&](char a){str += a + ('A' - 'a');});
from(src).foreach([&](char a){str += a + ('A' - 'a');});
EXPECT_EQ("ABC", str);
}
......@@ -44,7 +43,7 @@ TEST(ForEach, ThreeIntsSum)
src.push_back(30);
int sum = 0;
for_each(range(src), [&](int a){sum += a;});
from(src).foreach([&](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
......@@ -5,14 +5,14 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "GroupByRange.h"
#include "Count.h"
#include "boolinq.h"
using namespace boolinq;
//////////////////////////////////////////////////////////////////////////
/*
TEST(GroupByRange, IntsFront)
{
int arr[] = {0,1,2,3,4,5,6,7,8,9};
......@@ -21,8 +21,8 @@ TEST(GroupByRange, IntsFront)
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;});
auto rng = from(arr);
auto dst = rng.groupBy([](int a){return a % 3;});
EXPECT_EQ(1, dst.front().key());
EXPECT_EQ(0, dst.back().key());
......@@ -42,7 +42,7 @@ TEST(GroupByRange, IntsFront)
CheckRangeEqArray(dst.back(), ans_0);
CheckRangeEqArray(dst.popFront(), ans_0);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(GroupByRange, IntsBack)
......@@ -53,7 +53,7 @@ TEST(GroupByRange, IntsBack)
int ans_2[] = {2,5,8};
int ans_0[] = {0,3,6,9};
auto rng = range(arr);
auto rng = from(arr);
auto dst = groupBy(rng, [](int a){return a % 3;});
EXPECT_EQ(1, dst.front().key());
......@@ -74,7 +74,7 @@ TEST(GroupByRange, IntsBack)
CheckRangeEqArray(dst.back(), ans_1);
CheckRangeEqArray(dst.popBack(), ans_1);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -114,7 +114,7 @@ TEST(GroupByRange, CountChildrenByAge)
{"Zamza", 13},
};
auto rng = range(children);
auto rng = from(children);
auto dst = groupBy(rng, [](const Child & a){return a.age < 14;});
EXPECT_EQ(false, dst.front().key());
......@@ -127,5 +127,7 @@ TEST(GroupByRange, CountChildrenByAge)
CheckRangeEqArray(dst.back(), ans_true);
CheckRangeEqArray(dst.popFront(), ans_true);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
*/
\ No newline at end of file
#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
......@@ -7,7 +7,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -24,9 +24,9 @@ TEST(IterRange, ListInt)
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);
CheckRangeEqArray(from(lst), ans);
CheckRangeEqArray(from<int>(lst.begin(), lst.end()), ans);
CheckRangeEqArray(from<int>(lst.cbegin(), lst.cend()), ans);
}
TEST(IterRange, DequeInt)
......@@ -40,9 +40,9 @@ TEST(IterRange, DequeInt)
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);
CheckRangeEqArray(from(dck), ans);
CheckRangeEqArray(from<int>(dck.begin(), dck.end()), ans);
CheckRangeEqArray(from<int>(dck.cbegin(), dck.cend()), ans);
}
TEST(IterRange, VectorInt)
......@@ -56,9 +56,9 @@ TEST(IterRange, VectorInt)
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);
CheckRangeEqArray(from(vec), ans);
CheckRangeEqArray(from<int>(vec.begin(), vec.end()), ans);
CheckRangeEqArray(from<int>(vec.cbegin(), vec.cend()), ans);
}
TEST(IterRange, ArrayInt)
......@@ -68,9 +68,9 @@ TEST(IterRange, ArrayInt)
int ans[] = {1,2,3,4,5};
CheckRangeEqArray(range(arr), ans);
CheckRangeEqArray(range(ptr, 5), ans);
CheckRangeEqArray(range(ptr, ptr+5), ans);
CheckRangeEqArray(from(arr), ans);
CheckRangeEqArray(from<int>(ptr, 5), ans);
CheckRangeEqArray(from<int>(ptr, ptr+5), ans);
}
//////////////////////////////////////////////////////////////////////////
......@@ -80,7 +80,7 @@ TEST(IterRange, OneElement)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto rng = from(src);
CheckRangeEqArray(rng, ans);
}
......@@ -89,7 +89,7 @@ TEST(IterRange, EmptyVector)
{
std::vector<int> src;
auto rng = range(src);
auto rng = from(src);
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
\ No newline at end of file
......@@ -26,12 +26,10 @@ TEST(Linq, WhereOdd)
for (int i = 1; i <= 5; i+=2)
{
EXPECT_FALSE(rng.empty());
EXPECT_EQ(i, rng.front());
EXPECT_EQ(i, rng.popFront());
EXPECT_EQ(i, rng.nextObject());
}
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
TEST(Linq, WhereOdd_WhereLess)
......@@ -51,12 +49,10 @@ TEST(Linq, WhereOdd_WhereLess)
for (int i = 1; i <= 3; i+=2)
{
EXPECT_FALSE(rng.empty());
EXPECT_EQ(i, rng.front());
EXPECT_EQ(i, rng.popFront());
EXPECT_EQ(i, rng.nextObject());
}
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
TEST(Linq, WhereLess_WhereOdd)
......@@ -72,7 +68,8 @@ TEST(Linq, WhereLess_WhereOdd)
src.push_back(8);
auto rng = from(src).where([](int a){return a < 4;})
.where([](int a){return a%2 == 1;});
.where([](int a){return a%2 == 1;})
.toVector();
std::vector<int> ans;
ans.push_back(1);
......@@ -95,7 +92,8 @@ TEST(Linq, WhereLess_WhereOdd_OrderByDesc)
auto rng = from(src).where([](int a){return a < 6;})
.where([](int a){return a%2 == 1;})
.orderBy([](int a){return -a;});
.orderBy([](int a){return -a;})
.toVector();
std::vector<int> ans;
ans.push_back(5);
......@@ -117,7 +115,8 @@ TEST(Linq, WhereOdd_ToVector)
src.push_back(7);
src.push_back(8);
auto dst = from(src).where([](int a){return a%2 == 1;});
auto dst = from(src).where([](int a){return a%2 == 1;})
.toVector();
std::vector<int> ans;
ans.push_back(1);
......@@ -210,34 +209,14 @@ TEST(Linq, Pointer_Front)
{
int src[] = {1,2,3,4,5};
auto dst = from((int*)src, (int*)src+5);
auto dst = from<int>((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_EQ(i, dst.nextObject());
}
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
......@@ -251,30 +230,10 @@ TEST(Linq, Array_Front)
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_EQ(i, dst.nextObject());
}
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());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -299,31 +258,18 @@ TEST(Linq, Creations)
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());
auto dst_ptr = from<int>(ptr, ptr+5);
auto dst_cptr = from<const int>(cptr, cptr+5);
auto dst_ptr_length = from<int>(ptr, 5);
auto dst_cptr_length = from<const int>(cptr, 5);
auto dst_vec_iter = from<int>(vec.begin(), vec.end());
auto dst_vec_citer = from<const int>(vec.cbegin(), vec.cend());
auto dst_cvec_iter = from<const int>(cvec.begin(), cvec.end());
auto dst_cvec_citer = from<const int>(cvec.cbegin(), cvec.cend());
}
//////////////////////////////////////////////////////////////////////////
......@@ -335,6 +281,13 @@ TEST(Linq, MessagesCountUniqueContacts)
std::string PhoneA;
std::string PhoneB;
std::string Text;
bool operator < (const Message & rhs) const
{
return (PhoneA < rhs.PhoneA)
|| (PhoneA == rhs.PhoneA) && (PhoneB < rhs.PhoneB)
|| (PhoneA == rhs.PhoneA) && (PhoneB == rhs.PhoneB) && (Text < rhs.Text);
}
};
Message messages[] =
......@@ -359,7 +312,7 @@ TEST(Linq, MessagesCountUniqueContacts)
TEST(Linq, ForwardIterating)
{
std::stringstream stream("0123456789");
auto dst = from(std::istream_iterator<char>(stream),
auto dst = from<char>(std::istream_iterator<char>(stream),
std::istream_iterator<char>())
.where( [](char a){return a % 2 == 0;})
.select([](char a){return std::string(1,a);})
......
#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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Max.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,10 +15,10 @@ TEST(Max, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(3, max(rng));
EXPECT_EQ(1, max(rng,[](int a){return -a;}));
EXPECT_EQ(3, rng.max());
EXPECT_EQ(1, rng.max([](int a){return -a;}));
}
TEST(Max, FiveStrings)
......@@ -29,8 +28,8 @@ TEST(Max, FiveStrings)
src.push_back("apple");
src.push_back("zip");
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ("zip", max(rng));
EXPECT_EQ("apple", max(rng,[](const std::string s){return s.size();}));
EXPECT_EQ("zip", rng.max());
EXPECT_EQ("apple", rng.max([](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
......@@ -4,8 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "Min.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -16,10 +15,10 @@ TEST(Min, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ(1, min(rng));
EXPECT_EQ(3, min(rng,[](int a){return -a;}));
EXPECT_EQ(1, rng.min());
EXPECT_EQ(3, rng.min([](int a){return -a;}));
}
TEST(Min, FiveStrings)
......@@ -29,8 +28,8 @@ TEST(Min, FiveStrings)
src.push_back("apple");
src.push_back("zip");
auto rng = range(src);
auto rng = from(src);
EXPECT_EQ("apple", min(rng));
EXPECT_EQ("zip", min(rng,[](const std::string & s){return s.size();}));
EXPECT_EQ("apple", rng.min());
EXPECT_EQ("zip", rng.min([](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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "OrderByRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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);
auto rng = from(src);
auto dst = rng.orderBy();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ TEST(OrderByRange, ReverseInts)
int src[] = {4,3,2,1};
int ans[] = {1,2,3,4};
auto rng = range(src);
auto dst = orderBy(rng);
auto rng = from(src);
auto dst = rng.orderBy();
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ TEST(OrderByRange, ThreeElements)
int src[] = {1,3,2};
int ans[] = {1,2,3};
auto rng = range(src);
auto dst = orderBy(rng);
auto rng = from(src);
auto dst = rng.orderBy();
CheckRangeEqArray(dst, ans);
}
......@@ -52,8 +51,8 @@ TEST(OrderByRange, OneElement)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = orderBy(rng);
auto rng = from(src);
auto dst = rng.orderBy();
CheckRangeEqArray(dst, ans);
}
......@@ -62,10 +61,10 @@ TEST(OrderByRange, NoElements)
{
std::vector<int> src;
auto rng = range(src);
auto dst = orderBy(rng);
auto rng = from(src);
auto dst = rng.orderBy();
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -92,8 +91,8 @@ TEST(OrderByRange, RandomStringByContent)
"sun",
};
auto rng = range(src);
auto dst = orderBy(rng);
auto rng = from(src);
auto dst = rng.orderBy();
CheckRangeEqArray(dst, ans);
}
......@@ -120,8 +119,8 @@ TEST(OrderByRange, RandomStringByLength)
"microsoft",
};
auto rng = range(src);
auto dst = orderBy(rng, [](std::string a){return a.size();});
auto rng = from(src);
auto dst = rng.orderBy([](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
......@@ -7,8 +7,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "ReverseRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ TEST(ReverseRange, IntVector)
int src[] = {1,2,3,4};
int ans[] = {4,3,2,1};
auto rng = range(src);
auto dst = reverse(rng);
auto rng = from(src);
auto dst = rng.reverse();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ TEST(ReverseRange, DoubleReverse)
int src[] = {1,2,3,4};
int ans[] = {1,2,3,4};
auto rng = range(src);
auto dst = reverse(reverse(rng));
auto rng = from(src);
auto dst = rng.reverse().reverse();
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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "SelectRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -15,8 +14,8 @@ 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;});
auto rng = from(src);
auto dst = rng.select([](int a){return a * 2;});
CheckRangeEqArray(dst, ans);
}
......@@ -26,8 +25,8 @@ 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');});
auto rng = from(src);
auto dst = rng.select([](int a){return (char)(a+'0');});
CheckRangeEqArray(dst, ans);
}
......@@ -44,8 +43,8 @@ TEST(SelectRange, MakeString)
"intel",
};
auto rng = range(src);
auto dst = select(rng, [](int a){return ans[a-1];});
auto rng = from(src);
auto dst = rng.select([](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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "SkipRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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);
auto rng = from(src);
auto dst = rng.skip(0);
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ 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);
auto rng = from(src);
auto dst = rng.skip(3);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ TEST(SkipRange, ManyToOne)
int src[] = {1,2,3,4,5,6};
int ans[] = {6};
auto rng = range(src);
auto dst = skip(rng, 5);
auto rng = from(src);
auto dst = rng.skip(5);
CheckRangeEqArray(dst, ans);
}
......@@ -49,20 +48,20 @@ TEST(SkipRange, ManyToZero)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = skip(rng, 6);
auto rng = from(src);
auto dst = rng.skip(6);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(SkipRange, ManyToZeroLess)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = skip(rng, 10);
auto rng = from(src);
auto dst = rng.skip(10);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -72,8 +71,8 @@ TEST(SkipRange, OneToOne)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = skip(rng, 0);
auto rng = from(src);
auto dst = rng.skip(0);
CheckRangeEqArray(dst, ans);
}
......@@ -82,40 +81,40 @@ TEST(SkipRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = skip(rng, 1);
auto rng = from(src);
auto dst = rng.skip(1);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(SkipRange, OneToZeroLess)
{
int src[] = {5};
auto rng = range(src);
auto dst = skip(rng, 2);
auto rng = from(src);
auto dst = rng.skip(2);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(SkipRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = skip(rng, 0);
auto rng = from(src);
auto dst = rng.skip(0);
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
TEST(SkipRange, ZeroToZeroLess)
{
std::vector<int> src;
auto rng = range(src);
auto dst = skip(rng, 2);
auto rng = from(src);
auto dst = rng.skip(2);
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -19,12 +19,11 @@ TEST(SpeedTest1, Init)
TEST(SpeedTest1, BoolinqCode)
{
double avgValue = from(vec).where( [](int a){return a%2 == 1;})
.cast<double>()
.avg();
.avg<double>();
double disper = from(vec).where( [](int a){return a%2 == 1;})
.select([=](int a){return (double)((a-avgValue)*(a-avgValue));})
.avg();
.avg<double>();
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
......@@ -4,9 +4,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "WhereRange.h"
#include "Sum.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,9 +15,9 @@ TEST(Sum, ThreeInts)
src.push_back(2);
src.push_back(3);
auto rng = range(src);
auto rng = from(src).sum();
EXPECT_EQ(6, sum(rng));
EXPECT_EQ(6, rng);
}
TEST(Sum, FiveInts)
......@@ -31,12 +29,12 @@ TEST(Sum, FiveInts)
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;});
auto rng = from(src);
auto dst0 = rng.where([](int a){return a%2 == 0;}).sum();
auto dst1 = rng.where([](int a){return a%2 == 1;}).sum();
EXPECT_EQ(6, sum(dst0));
EXPECT_EQ(9, sum(dst1));
EXPECT_EQ(6, dst0);
EXPECT_EQ(9, dst1);
}
TEST(Sum, BoolSum)
......@@ -48,10 +46,11 @@ TEST(Sum, BoolSum)
src.push_back(4);
src.push_back(5);
auto rng = range(src);
auto rng1 = from(src).sum<int>([](int a){return a%2 == 0;});
auto rng2 = from(src).sum<int>([](int a){return a%2 == 1;});
EXPECT_EQ(2, sum(rng,[](int a){return a%2 == 0;}));
EXPECT_EQ(3, sum(rng,[](int a){return a%2 == 1;}));
EXPECT_EQ(2, rng1);
EXPECT_EQ(3, rng2);
}
TEST(Sum, FiveStringsLen)
......@@ -63,9 +62,9 @@ TEST(Sum, FiveStringsLen)
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
auto rng = from(src).sum([](const std::string & str){return str.size();});
EXPECT_EQ(26, sum(rng,[](const std::string & str){return str.size();}));
EXPECT_EQ(26, rng);
}
TEST(Sum, FiveStringsData)
......@@ -77,9 +76,9 @@ TEST(Sum, FiveStringsData)
src.push_back("oracle");
src.push_back("ponny");
auto rng = range(src);
auto rng = from(src).sum();
std::string ans = "helloapplenokiaoracleponny";
EXPECT_EQ(ans, sum(rng));
EXPECT_EQ(ans, 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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "TakeRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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);
auto rng = from(src);
auto dst = rng.take(10);
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ 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);
auto rng = from(src);
auto dst = rng.take(6);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ 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);
auto rng = from(src);
auto dst = rng.take(3);
CheckRangeEqArray(dst, ans);
}
......@@ -50,8 +49,8 @@ TEST(TakeRange, ManyToOne)
int src[] = {1,2,3,4,5,6};
int ans[] = {1};
auto rng = range(src);
auto dst = take(rng, 1);
auto rng = from(src);
auto dst = rng.take(1);
CheckRangeEqArray(dst, ans);
}
......@@ -60,10 +59,10 @@ TEST(TakeRange, ManyToZero)
{
int src[] = {1,2,3,4,5,6};
auto rng = range(src);
auto dst = take(rng, 0);
auto rng = from(src);
auto dst = rng.take(0);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
......@@ -73,8 +72,8 @@ TEST(TakeRange, OneToMore)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = take(rng, 5);
auto rng = from(src);
auto dst = rng.take(5);
CheckRangeEqArray(dst, ans);
}
......@@ -84,8 +83,8 @@ TEST(TakeRange, OneToOne)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = take(rng, 1);
auto rng = from(src);
auto dst = rng.take(1);
CheckRangeEqArray(dst, ans);
}
......@@ -94,20 +93,20 @@ TEST(TakeRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = take(rng, 0);
auto rng = from(src);
auto dst = rng.take(0);
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(TakeRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = take(rng, 0);
auto rng = from(src);
auto dst = rng.take(0);
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
//////////////////////////////////////////////////////////////////////////
#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
#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
......@@ -3,8 +3,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToDeque.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -15,8 +14,8 @@ TEST(ToDeque, Deque2Deque)
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toDeque(rng);
auto rng = from(src);
auto dst = rng.toDeque();
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
......@@ -3,8 +3,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToList.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -15,8 +14,8 @@ TEST(ToList, List2List)
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toList(rng);
auto rng = from(src);
auto dst = rng.toList();
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
......@@ -3,8 +3,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToSet.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,10 +16,10 @@ TEST(ToSet, Vector2Set)
src.push_back(3);
src.push_back(2);
auto rng = range(src);
auto dst = toSet(rng);
auto rng = from(src);
auto dst = rng.toSet();
EXPECT_EQ(3,dst.size());
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
......@@ -3,8 +3,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "IterRange.h"
#include "ToVector.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -15,8 +14,8 @@ TEST(ToVector, Vector2Vector)
src.push_back(200);
src.push_back(300);
auto rng = range(src);
auto dst = toVector(rng);
auto rng = from(src);
auto dst = rng.toVector();
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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "UnbitsRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ TEST(UnbitsRange, OneByteDefault)
int src[] = {1,0,1,0,1,0,1,0};
int ans[] = {0xAA};
auto rng = range(src);
auto dst = unbits(rng);
auto rng = from(src);
auto dst = rng.unbits();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ 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);
auto rng = from(src);
auto dst = rng.unbits(HighToLow);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ 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);
auto rng = from(src);
auto dst = rng.unbits(LowToHigh);
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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "UnbytesRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ TEST(UnbytesRange, OneIntDefault)
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>();
CheckRangeEqArray(dst, ans);
}
......@@ -28,8 +27,8 @@ TEST(UnbytesRange, OneIntFL)
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int,FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -39,8 +38,8 @@ TEST(UnbytesRange, OneIntLF)
unsigned char src[] = {0xAA,0xBB,0xCC,0xDD};
int ans[] = {0xAABBCCDD};
auto rng = range(src);
auto dst = unbytes<int,LastToFirst>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>(LastToFirst);
CheckRangeEqArray(dst, ans);
}
......@@ -56,8 +55,8 @@ TEST(UnbytesRange, TwoIntsDefault)
};
int ans[] = {0x12345678,0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>();
CheckRangeEqArray(dst, ans);
}
......@@ -71,8 +70,8 @@ TEST(UnbytesRange, TwoIntsFL)
};
int ans[] = {0x12345678,0xDDCCBBAA};
auto rng = range(src);
auto dst = unbytes<int,FirstToLast>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>(FirstToLast);
CheckRangeEqArray(dst, ans);
}
......@@ -86,8 +85,8 @@ TEST(UnbytesRange, TwoIntsLF)
};
int ans[] = {0x78563412,0xAABBCCDD};
auto rng = range(src);
auto dst = unbytes<int,LastToFirst>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>(LastToFirst);
CheckRangeEqArray(dst, ans);
}
......@@ -98,8 +97,8 @@ TEST(UnbytesRange, EmptyDefault)
{
std::vector<unsigned char> src;
auto rng = range(src);
auto dst = unbytes<int>(rng);
auto rng = from(src);
auto dst = rng.unbytes<int>();
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
#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
......@@ -5,8 +5,7 @@
#include <gtest/gtest.h>
#include "CommonTests.h"
#include "IterRange.h"
#include "WhereRange.h"
#include "boolinq.h"
using namespace boolinq;
......@@ -17,8 +16,8 @@ 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;});
auto rng = from(src);
auto dst = rng.where([](int a){return a%2 == 1;});
CheckRangeEqArray(dst, ans);
}
......@@ -42,8 +41,8 @@ TEST(WhereRange, FirstLetterFront)
"adobe",
};
auto rng = range(src);
auto dst = where(rng, [](std::string a){return a[0] == 'a';});
auto rng = from(src);
auto dst = rng.where([](std::string a){return a[0] == 'a';});
CheckRangeEqArray(dst, ans);
}
......@@ -73,8 +72,8 @@ TEST(WhereRange, NameAgeLess)
{"man4",15},
};
auto rng = range(src);
auto dst = where(rng, [](const NameAge & a){return a.age < 18;});
auto rng = from(src);
auto dst = rng.where([](const NameAge & a){return a.age < 18;});
CheckRangeEqArray(dst, ans, [](const NameAge & a){return a.name;});
}
......@@ -86,8 +85,8 @@ TEST(WhereRange, MayToOne)
int src[] = {0,1,2};
int ans[] = {1};
auto rng = range(src);
auto dst = where(rng, [](int a){return a == 1;});
auto rng = from(src);
auto dst = rng.where([](int a){return a == 1;});
CheckRangeEqArray(dst, ans);
}
......@@ -97,8 +96,8 @@ TEST(WhereRange, OneToOne)
int src[] = {5};
int ans[] = {5};
auto rng = range(src);
auto dst = where(rng, [](int a){return a>0;});
auto rng = from(src);
auto dst = rng.where([](int a){return a>0;});
CheckRangeEqArray(dst, ans);
}
......@@ -107,28 +106,28 @@ TEST(WhereRange, ManyToZero)
{
int src[] = {0,1,2};
auto rng = range(src);
auto dst = where(rng, [](int a){return a == 5;});
auto rng = from(src);
auto dst = rng.where([](int a){return a == 5;});
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(WhereRange, OneToZero)
{
int src[] = {5};
auto rng = range(src);
auto dst = where(rng, [](int a){return a>10;});
auto rng = from(src);
auto dst = rng.where( [](int a){return a>10;});
EXPECT_TRUE(dst.empty());
EXPECT_THROW(dst.nextObject(), EnumeratorEndException);
}
TEST(WhereRange, ZeroToZero)
{
std::vector<int> src;
auto rng = range(src);
auto dst = where(rng, [](int a){return a>0;});
auto rng = from(src);
auto dst = rng.where( [](int a){return a>0;});
EXPECT_TRUE(rng.empty());
EXPECT_THROW(rng.nextObject(), EnumeratorEndException);
}
This diff is collapsed.
# ----------------------------------------------------
# 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
......@@ -100,7 +100,6 @@
<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" />
......@@ -114,38 +113,8 @@
<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">
......
......@@ -12,30 +12,18 @@
<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">
......@@ -53,9 +41,6 @@
<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>
......@@ -148,98 +133,8 @@
<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
# 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
Subproject commit 7aef63c873a1dc58860fc7736bda3cb961831bab
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