108 lines
3.7 KiB
C++
108 lines
3.7 KiB
C++
#include <cstdlib>
|
|
#include <string>
|
|
#include <istream>
|
|
|
|
namespace pit{
|
|
template<typename T>
|
|
class passthrough{
|
|
T underlying;
|
|
public:
|
|
passthrough<T>(T underlying): underlying(underlying){}
|
|
passthrough<T>(passthrough<T>& from): underlying(from.underlying){}
|
|
passthrough<T> operator+(std::size_t amount){
|
|
return passthrough<T>(this->underlying+amount);
|
|
}
|
|
void operator+=(std::size_t amount){
|
|
this->underlying += amount;
|
|
}
|
|
passthrough<T> operator-(std::size_t amount){
|
|
return passthrough<T>(this->underlying-amount);
|
|
}
|
|
void operator-=(std::size_t amount){
|
|
this->underlying -= amount;
|
|
}
|
|
T const& operator*(){
|
|
return this->underlying;
|
|
}
|
|
bool operator==(passthrough<T> const& rhs){
|
|
return this->underlying == rhs.underlying;
|
|
}
|
|
};
|
|
template<typename T>
|
|
class range{
|
|
private:
|
|
T beginning;
|
|
T ending;
|
|
public:
|
|
range<T>(T begin, T end):beginning(begin), ending(end){}
|
|
passthrough<T> begin(){
|
|
return passthrough<T>(this->beginning);
|
|
}
|
|
passthrough<T> end(){
|
|
return passthrough<T>(this->ending);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class repeat{
|
|
T val;
|
|
public:
|
|
// noops
|
|
repeat operator+(std::size_t ){}
|
|
repeat operator-(std::size_t ){}
|
|
void operator+=(std::size_t ){}
|
|
void operator-=(std::size_t ){}
|
|
// always return false on equality to ensure it repeats forever
|
|
bool operator==(repeat const& rhs){return false;}
|
|
// if T isn't copyable then make the template arg a reference
|
|
T operator*(){
|
|
return this->val;
|
|
}
|
|
// convenience for for loops and what not
|
|
repeat begin(){
|
|
return *this;
|
|
}
|
|
repeat end(){
|
|
return *this;
|
|
}
|
|
repeat rbegin(){
|
|
return *this;
|
|
}
|
|
repeat rend(){
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
// Allocator could be generic on just * with + and += using a stack buf and the istream getline method but lazy
|
|
template<class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
|
|
class basic_stream_split {
|
|
bool ended;
|
|
std::basic_istream<CharT, Traits>& stream;
|
|
CharT delim;
|
|
public:
|
|
// there's no reason to specify the ending argument unless you want to manually construct the .end state of this iterator
|
|
basic_stream_split(std::basic_istream<CharT, Traits>& stream, CharT delim, bool ending=false): stream(stream), ended(ending), delim(delim){}
|
|
bool operator==(basic_stream_split const& rhs){
|
|
return this->ended == rhs;
|
|
}
|
|
std::basic_string<CharT, Traits, Allocator> operator*(){
|
|
std::basic_string<CharT, Traits, Allocator> s;
|
|
std::getline(this->stream, s, this->delim);
|
|
return s;
|
|
}
|
|
// can't do -, or -= there's no reasonable way to undo istream reads
|
|
// can't do + without storing a line
|
|
void operator+=(std::size_t rhs){
|
|
std::basic_string<CharT, Traits, Allocator> s;
|
|
for(size_t i =0;i<rhs-1;i++)std::getline(this->stream, s, this->delim);
|
|
return *this;
|
|
}
|
|
};
|
|
using stream_split = basic_stream_split<char>;
|
|
using wstream_split = basic_stream_split<wchar_t>;
|
|
|
|
template<class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
|
|
basic_stream_split<CharT,Traits, Allocator> split_stream(std::basic_istream<CharT, Traits>& stream){
|
|
|
|
}
|
|
}
|