1607 lines
40 KiB
C++
1607 lines
40 KiB
C++
#pragma once
|
||
|
||
//IO²Ù×÷¿â
|
||
//20191212-1034X
|
||
|
||
#include <cstdint>
|
||
#include <cassert>
|
||
|
||
#include <iostream>
|
||
#include <fstream>
|
||
|
||
#include <limits>
|
||
#include <type_traits>
|
||
#include <algorithm>
|
||
#include <initializer_list>
|
||
#include <utility>
|
||
#include <tuple>
|
||
#include <iterator>
|
||
|
||
#include <string>
|
||
#include <vector>
|
||
#include <array>
|
||
#include <deque>
|
||
#include <list>
|
||
#include <set>
|
||
#include <map>
|
||
#include <unordered_set>
|
||
#include <unordered_map>
|
||
|
||
#include <exception>
|
||
#include <stdexcept>
|
||
|
||
#include <mutex>
|
||
|
||
|
||
//¿â¹ØÁªÐèÇóÎļþ
|
||
#include "TypeExtend.h"
|
||
|
||
|
||
|
||
|
||
//°´¸ñʽ¶ÁȡһÐв¢·µ»Ø×Ö·û´®
|
||
inline bool _LineStringToInit(const std::string &strIn, std::string &strField,
|
||
std::string &strValue)
|
||
{
|
||
//Èô"(\t1)abc(\t2)(\t3)def(\t4)(\t5)ghi\r\n"
|
||
//ÕÒÓÐЧ×Ö·ûÍ·
|
||
auto itSt = std::find_if_not(strIn.begin(), strIn.end(), IsBlankChar);//a
|
||
//ÅжϿջò×¢ÊÍ'#'';'"//"
|
||
if(itSt==strIn.end() || *itSt=='#' || *itSt==';'
|
||
||(*itSt=='/' && itSt+1!=strIn.end() && itSt[1]=='/'))
|
||
return false;
|
||
//ÕÒ×Ö¶Î⣬²»ÒªÇóºóÐø
|
||
auto itGap = std::find_if(itSt+1, strIn.end(), IsBlankChar);//\t2
|
||
strField.assign(itSt, itGap);
|
||
//ÕÒºóÐø´Ê
|
||
auto itWordSt = std::find_if_not(itGap, strIn.end(), IsBlankChar);//d
|
||
auto ritWordEd = std::find_if_not(strIn.rbegin(),
|
||
std::string::const_reverse_iterator(itWordSt), IsBlankChar);//i
|
||
//´æ´¢Öµ£¬¿ÉÄÜΪ¿Õ
|
||
if(itWordSt!=strIn.end() && itWordSt<ritWordEd.base())
|
||
strValue.assign(itWordSt, ritWordEd.base());
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÓÐÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡·¶Î§ÄÚµÄÖµ£¬·µ»ØÎ´ÕÒµ½µÄµÚÒ»¸ö×Ö¶Î
|
||
//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ
|
||
//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó
|
||
//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö
|
||
template<typename Ty1, typename Ty2>
|
||
inline Ty2 StreamReadPredefInit(std::istream &is, Ty1 &table,
|
||
Ty2 itFieldSt, Ty2 itFieldEd, bool bReplace= true, bool bCheckNull= true)
|
||
{
|
||
//½«¹Ø¼ü×Ö¶ÎдÈë
|
||
Ty2 itField;
|
||
std::set<std::string> bstField;
|
||
for(itField=itFieldSt; itField!=itFieldEd; ++itField) {
|
||
bstField.emplace(*itField);
|
||
}
|
||
//´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î
|
||
std::string strIn, strField, strValue;
|
||
while(std::getline(is, strIn)) {
|
||
//½âÎöÐдæÈë¶ÔÓ¦×Ö·û´®
|
||
if(!_LineStringToInit(strIn, strField, strValue))
|
||
continue;
|
||
//ÅжÏÔÚ±íÖÐ
|
||
if(bstField.find(strField)==bstField.end())
|
||
continue;
|
||
//ÅжÏֵΪ¿Õ
|
||
if(bCheckNull && strValue.empty())
|
||
continue;
|
||
//Ìæ»»Ä£Ê½ÏÂ
|
||
if(bReplace) {
|
||
auto itRes = table.find(strField);
|
||
if(itRes==table.end())
|
||
table.emplace(std::move(strField), std::move(strValue));
|
||
else
|
||
itRes->second = std::move(strValue);
|
||
}
|
||
//ÎÞ¶¯×÷ģʽÏÂ
|
||
else {
|
||
table.emplace(std::move(strField), std::move(strValue));
|
||
}
|
||
}
|
||
//ÅжÏÌî³äÍê±Ï
|
||
for(itField=itFieldSt; itField!=itFieldEd; ++itField) {
|
||
std::string strTmp = *itField;
|
||
auto res = table.find(strTmp);
|
||
//ÈôûÕÒµ½×ֶλò¼ì²é¿ÕÇÒ×ֶοÕ
|
||
if(res==table.end())
|
||
break;
|
||
}
|
||
return itField;
|
||
}
|
||
|
||
|
||
//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÎÞÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡ËùÓÐÎļþµÄÖµ£¬·µ»Ø¶ÁÈ¡¸öÊý
|
||
//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ
|
||
//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó
|
||
//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö
|
||
template<typename Ty1>
|
||
inline int StreamReadAllInit(std::istream &is, Ty1 &table,
|
||
bool bReplace= true, bool bCheckNull= true)
|
||
{
|
||
//´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î
|
||
std::string strIn, strField, strValue;
|
||
while(std::getline(is, strIn)) {
|
||
//½âÎöÐдæÈë¶ÔÓ¦×Ö·û´®
|
||
if(!_LineStringToInit(strIn, strField, strValue))
|
||
continue;
|
||
//ÅжÏֵΪ¿Õ
|
||
if(bCheckNull && strValue.empty())
|
||
continue;
|
||
//Ìæ»»Ä£Ê½ÏÂ
|
||
if(bReplace) {
|
||
auto itRes = table.find(strField);
|
||
if(itRes==table.end())
|
||
table.emplace(std::move(strField), std::move(strValue));
|
||
else
|
||
itRes->second = std::move(strValue);
|
||
}
|
||
//ÎÞ¶¯×÷ģʽÏÂ
|
||
else {
|
||
table.emplace(std::move(strField), std::move(strValue));
|
||
}
|
||
}
|
||
return (int)table.size();
|
||
}
|
||
|
||
|
||
|
||
//ÊäÈëÁ÷¸¨Öúº¯Êý
|
||
//ʹÓÃflushË¢ÐÂÒ»ÐУ¬Ê¹ÓÃendsÇå¿Õ״̬£¬Ê¹ÓÃendlͬʱÍê³ÉˢкÍÇå¿Õ
|
||
inline bool operator >>(std::istream &is,
|
||
std::basic_ostream<char> &(*func)(std::basic_ostream<char> &))
|
||
{
|
||
bool res = (bool)is;
|
||
if(func==&std::flush<char, std::char_traits<char>>)
|
||
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||
else if(func==&std::ends<char, std::char_traits<char>>)
|
||
is.clear();
|
||
else if(func==&std::endl<char, std::char_traits<char>>) {
|
||
is.clear();
|
||
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||
}
|
||
else
|
||
assert(false);
|
||
return res;
|
||
}
|
||
|
||
|
||
////»ñÈ¡ÍêÕûÐÐ×÷Ϊ×Ö·û´®ÊäÈëÁ÷£¬Èç¹û»ñÈ¡ÍêisΪfailÔòÖ÷µ»ØÁ÷Ϊfail
|
||
//inline std::istringstream GetLineAsStream(std::istream &is, char gap= '\n')
|
||
//{
|
||
// std::string strTmp;
|
||
// std::istringstream iss;
|
||
// if(!std::getline(is, strTmp, gap))
|
||
// iss.setstate(std::ios_base::failbit);
|
||
// else
|
||
// iss.str(std::move(strTmp));
|
||
// return std::move(iss);
|
||
//}
|
||
|
||
|
||
|
||
//Êä³öÁ÷±£³ÖÀà
|
||
//ÓÃÓÚÔÚÊä³öºó¸½¼Ó¿ØÖƸñʽ£¬¶þ´ÎÊä³öÊ±ÕæÕýÊä³ö£¬ÐèÍâ²¿ÖØÔØÔËËã·û
|
||
template<typename Ty>
|
||
class OstreamHold
|
||
{
|
||
OstreamHold()
|
||
= delete;
|
||
};
|
||
//Êä³öÁ÷±£³ÖÀà×óÖµÒýÓÃÌØ»¯
|
||
template<typename Ty>
|
||
class OstreamHold<Ty &>
|
||
{
|
||
private:
|
||
std::ostream &os;//´æ´¢os
|
||
Ty &ref;//´æ´¢ÒýÓÃ
|
||
public:
|
||
//¹¹Ô캯Êý
|
||
explicit OstreamHold(std::ostream &o_os, Ty &o_ref):
|
||
os(o_os), ref(o_ref)
|
||
{
|
||
}
|
||
//ɾ³ý¿½±´
|
||
OstreamHold(const OstreamHold<Ty &> &)
|
||
= delete;
|
||
OstreamHold<Ty &> &operator =(const OstreamHold<Ty &> &)
|
||
= delete;
|
||
//ĬÈÏÒÆ¶¯
|
||
OstreamHold(OstreamHold<Ty &> &&)
|
||
= default;
|
||
OstreamHold<Ty &> &operator =(OstreamHold<Ty &> &&)
|
||
= default;
|
||
//Á÷ÒýÓÃ
|
||
std::ostream &operator()() const
|
||
{
|
||
return os;
|
||
}
|
||
//ÒýÓúͳÉÔ±ÒýÓÃ
|
||
Ty &operator *() const
|
||
{
|
||
return ref;
|
||
}
|
||
Ty *operator ->() const
|
||
{
|
||
return &ref;
|
||
}
|
||
//ת»»³£ÀàÐͰ汾
|
||
operator OstreamHold<const Ty &>() const
|
||
{
|
||
return OstreamHold<const Ty &>(os, ref);
|
||
}
|
||
};
|
||
//Êä³öÁ÷±£³ÖÀàÓÒÖµÒýÓÃÌØ»¯
|
||
template<typename Ty>
|
||
class OstreamHold<Ty &&>
|
||
{
|
||
private:
|
||
std::ostream &os;//´æ´¢os
|
||
Ty data;//´æ´¢ÒýÓÃ
|
||
public:
|
||
//¹¹Ô캯Êý
|
||
explicit OstreamHold(std::ostream &o_os, Ty &&o_data):
|
||
os(o_os), data(std::move(o_data))
|
||
{
|
||
}
|
||
//ɾ³ý¿½±´
|
||
OstreamHold(const OstreamHold<Ty &&> &)
|
||
= delete;
|
||
OstreamHold<Ty &&> &operator =(const OstreamHold<Ty &&> &)
|
||
= delete;
|
||
//ĬÈÏÒÆ¶¯
|
||
OstreamHold(OstreamHold<Ty &&> &&)
|
||
= default;
|
||
OstreamHold<Ty &&> &operator =(OstreamHold<Ty &&> &&)
|
||
= default;
|
||
//ת»»×óÖµÁ÷
|
||
OstreamHold<const Ty &> operator()() const
|
||
{
|
||
return OstreamHold<const Ty &>(os, data);
|
||
}
|
||
OstreamHold<Ty &> operator()()
|
||
{
|
||
return OstreamHold<Ty &>(os, data);
|
||
}
|
||
//ÒýÓúͳÉÔ±ÒýÓÃ
|
||
Ty &operator *() const
|
||
{
|
||
return data;
|
||
}
|
||
Ty *operator ->() const
|
||
{
|
||
return &data;
|
||
}
|
||
};
|
||
|
||
|
||
|
||
//Êä³öÁ÷¼¯ºÏÎÞËø±êÖ¾£¬×÷ΪÁ÷Êä³ö±íʾÎÞËø
|
||
class OstreamSetNoLock
|
||
{
|
||
};
|
||
|
||
//Êä³öÁ÷¼¯ºÏÀà
|
||
//ÓÃÓÚ¶à¸öÊä³öÁ÷ͬʱÊä³ö£¬Ö§³Ö·ÇÁ÷ÒýÓ÷µ»ØÖµµÄ´«µÝÁ÷²Ù×÷
|
||
//¸½¼Ó»¥³âËø¹¦Äܽӿڣ¬ÒªÇó²ÎÊý¿ÉËøÀàÐÍ£¬Í¬Ê±´ËÀàÒ²Âú×ã¿ÉËø
|
||
//ÈôÓÐËøÔòÁ÷²Ù×÷×Ô¶¯£¬³ý·Ç´«µÝ·ÇËø±êÖ¾£¬ÔÚÒ»´®Á÷²Ù×÷¿ªÊ¼½áÊøÊ±½øÐÐËø¶¨½âËø
|
||
template<typename TyMtx= std::mutex>
|
||
class OstreamSet
|
||
{
|
||
public:
|
||
//Êä³ö¼¯ºÏ´«µÝÀàÐÍ
|
||
template<typename TyRes>
|
||
class Hold;
|
||
|
||
public:
|
||
std::vector<std::ostream *> vecPOs;//Êä³öÁ÷£¬¸ü¸Ä·ÇḬ̈߳²È«
|
||
std::vector<TyMtx *> vecPMtx;//Ëø£¬¸ü¸Ä·ÇḬ̈߳²È«
|
||
|
||
public:
|
||
//ĬÈϹ¹Ôì
|
||
OstreamSet()
|
||
= default;
|
||
//ɾ³ý¿½±´
|
||
OstreamSet(const OstreamSet &)
|
||
= delete;
|
||
OstreamSet &operator =(const OstreamSet &)
|
||
= delete;
|
||
//ĬÈÏÒÆ¶¯£¬·ÇḬ̈߳²È«
|
||
OstreamSet(OstreamSet &&)
|
||
= default;
|
||
OstreamSet &operator =(OstreamSet &&)
|
||
= default;
|
||
//ÁÐ±í¹¹Ôì
|
||
explicit OstreamSet(std::initializer_list<std::ostream *> intlOs,
|
||
std::initializer_list<TyMtx *> intlMtx = {}
|
||
): vecPOs(intlOs), vecPMtx(intlMtx)
|
||
{
|
||
}
|
||
//µü´úÆ÷¹¹Ôì
|
||
template<typename TyItOs, typename TyItMtx>
|
||
explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd,
|
||
TyItMtx itMtxSt, TyItMtx itMtxEd)
|
||
{
|
||
for(; itOsSt!=itOsEd; ++itOsSt)
|
||
vecPOs.push_back(&*itOsSt);
|
||
for(; itMtxSt!=itMtxEd; ++itMtxSt)
|
||
vecPMtx.push_back(&*itMtxSt);
|
||
}
|
||
template<typename TyItOs>
|
||
explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd):
|
||
OstreamSet(itOsSt, itOsEd, (TyMtx *)nullptr, (TyMtx *)nullptr)
|
||
{
|
||
}
|
||
public:
|
||
//ת·¢Á÷²Ù×÷£¬Ḭ̈߳²È«£¬°´Ë³Ðòµ÷ÓÃËø£¬Ðè±£Ö¤²»ËÀËø
|
||
template<typename Ty>
|
||
auto operator <<(Ty &&arg) const->
|
||
Hold<decltype(*vecPOs.front()<<std::forward<Ty>(arg))>
|
||
{
|
||
//Á÷½á¹ûÀàÐÍÊý×é
|
||
using TyRes = decltype(*vecPOs.front()<<std::forward<Ty>(arg));
|
||
std::vector<TypeHolder<TyRes>> vecRes;
|
||
vecRes.reserve(vecPOs.size());
|
||
//µ÷ÓÃËø¶¨
|
||
Lock();
|
||
//Êä³ö²¢´æ´¢
|
||
for(auto pOs : vecPOs) {
|
||
vecRes.emplace_back(*pOs <<std::forward<Ty>(arg));
|
||
}
|
||
//Éú³É½á¹ûµÄHoldÀàÐÍ
|
||
return Hold<TyRes>(std::move(vecRes), vecPMtx.empty()? nullptr:this);
|
||
}
|
||
//¶Ô²Ù×÷·û½øÐÐת·¢
|
||
template<int c_blank =0>
|
||
auto operator <<(std::ios_base &(*func)(std::ios_base &)) const->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
template<int c_blank =0>
|
||
auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &)) const->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
template<int c_blank =0>
|
||
auto operator <<(
|
||
std::basic_ostream<char> &(*func)(std::basic_ostream<char> &)) const->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
//¶Ô²»Ëø±êÖ¾½øÐÐÁ÷²Ù×÷£¬Á÷Êä³ö½«²»½øÐÐËø¶¨ºÍ½âËø
|
||
Hold<std::ostream &> operator <<(OstreamSetNoLock) const
|
||
{
|
||
//Á÷½á¹ûÀàÐÍÊý×é
|
||
using TyRes = std::ostream &;
|
||
std::vector<TypeHolder<TyRes>> vecRes;
|
||
vecRes.reserve(vecPOs.size());
|
||
//´æ´¢ÀàÐÍ
|
||
for(auto pOs : vecPOs) {
|
||
vecRes.emplace_back(*pOs);
|
||
}
|
||
//Éú³É½á¹ûµÄHoldÀàÐÍ
|
||
return Hold<TyRes>(std::move(vecRes), nullptr);
|
||
}
|
||
//µ÷ÓÃostreamµÄ³ÉÔ±º¯Êý£¬½øÐÐËø¶¨£¬ºöÂÔ·µ»ØÖµ
|
||
template<typename Ty, typename ...Tys>
|
||
void operator()(const Ty &pmf, Tys &&...args) const
|
||
{
|
||
//µ÷ÓÃËø¶¨
|
||
Lock();
|
||
//µ÷ÓóÉÔ±º¯Êý
|
||
for(auto pOs : vecPOs) {
|
||
(pOs->*pmf)(std::forward<Tys>(args)...);
|
||
}
|
||
//µ÷ÓýâËø
|
||
Unlock();
|
||
}
|
||
//µ÷ÓÃËø¶¨
|
||
void Lock() const
|
||
{
|
||
//˳Ðòµ÷ÓÃËø
|
||
for(auto pMtx : vecPMtx)
|
||
pMtx->lock();
|
||
}
|
||
void lock() const
|
||
{
|
||
Lock();
|
||
}
|
||
//µ÷ÓýâËø
|
||
void Unlock() const
|
||
{
|
||
//·´Ðò½âËø
|
||
for(auto rit =vecPMtx.rbegin(); rit!=vecPMtx.rend(); ++rit)
|
||
(*rit)->unlock();
|
||
}
|
||
void unlock() const
|
||
{
|
||
Unlock();
|
||
}
|
||
//³¢ÊÔËø¶¨
|
||
bool TryLock() const
|
||
{
|
||
//˳Ðòµ÷Óó¢ÊÔËø
|
||
unsigned i;
|
||
for(i =0; i<vecPMtx.size(); ++i) {
|
||
if(!vecPMtx[i]->try_lock())
|
||
break;
|
||
}
|
||
//³¢ÊÔʧ°ÜÔò½âËø
|
||
if(i!=vecPMtx.size()) {
|
||
for(--i; i>=0; --i)
|
||
vecPMtx[i]->unlock();
|
||
return false;
|
||
}
|
||
else
|
||
return true;
|
||
}
|
||
bool try_lock() const
|
||
{
|
||
return TryLock();
|
||
}
|
||
};
|
||
|
||
//Êä³öÁ÷¼¯ºÏ´«µÝÀàÐÍ
|
||
template<typename TyMtx>
|
||
template<typename TyRes>
|
||
class OstreamSet<TyMtx>::Hold
|
||
{
|
||
friend class OstreamSet<TyMtx>;
|
||
private:
|
||
std::vector<TypeHolder<TyRes>> vecRes;//Êä³öÁ÷µÄ½á¹ûÊý×é
|
||
const OstreamSet<TyMtx> *pSet;//Êä³öÁ÷¼¯ºÏÖ¸Õ룬Îö¹¹½âËø±êÖ¾
|
||
|
||
private:
|
||
//¹¹Ô죬Êä³ö¼¯ºÏÒýÓóõʼ»¯
|
||
explicit Hold(std::vector<TypeHolder<TyRes>> &&o_vecRes,
|
||
const OstreamSet<TyMtx> *o_pSet
|
||
): vecRes(std::move(o_vecRes)), pSet(o_pSet)
|
||
{
|
||
}
|
||
//ɾ³ý¿½±´
|
||
Hold(const Hold &)
|
||
= delete;
|
||
Hold &operator =(const Hold &)
|
||
= delete;
|
||
//ÒÆ¶¯²Ù×÷£¬ÒƳöÊý¾Ý²»ÐèÎö¹¹½âËø±êÖ¾
|
||
Hold(Hold &&other) noexcept
|
||
{
|
||
this->operator =(std::move(other));
|
||
}
|
||
Hold &operator =(Hold &&other) noexcept
|
||
{
|
||
if(this!=&other) {
|
||
vecRes = std::move(other.vecRes);
|
||
pSet = std::move(other.pSet);
|
||
other.pSet = nullptr;
|
||
}
|
||
return *this;
|
||
}
|
||
public:
|
||
//Îö¹¹º¯Êý£¬¸ù¾Ý±êÖ¾½øÐнâËø£¬·´Ðò½âËø
|
||
~Hold()
|
||
{
|
||
if(pSet!=nullptr) {
|
||
//µ÷ÓýâËø
|
||
pSet->Unlock();
|
||
}
|
||
}
|
||
public:
|
||
//ת·¢Á÷²Ù×÷£¬×ª·¢ºóÈ¥³ý½âËø±êÖ¾
|
||
template<typename Ty>
|
||
auto operator <<(Ty &&arg)->
|
||
Hold<decltype(vecRes.front().hold<<std::forward<Ty>(arg))>
|
||
{
|
||
//´Ë¶ÔÏó²»ÐèÎö¹¹½âËø
|
||
auto ptr = pSet;
|
||
pSet = nullptr;
|
||
//еÄÁ÷²Ù×÷½á¹ûÀàÐÍ
|
||
using TyResTmp = decltype(vecRes.front().hold<<std::forward<Ty>(arg));
|
||
std::vector<TypeHolder<TyResTmp>> vecResTmp;
|
||
vecResTmp.reserve(vecRes.size());
|
||
//Á÷Êä³ö²¢´æ´¢
|
||
for(auto &refRes : vecRes) {
|
||
vecResTmp.emplace_back(refRes.hold <<std::forward<Ty>(arg));
|
||
}
|
||
//¹¹ÔìеÄHoldÀàÐÍ£¬×ªÒåÎö¹¹½âËø±êÖ¾
|
||
return Hold<TyResTmp>(std::move(vecResTmp), ptr);
|
||
}
|
||
//¶Ô²Ù×÷·û½øÐÐת·¢
|
||
template<int c_blank =0>
|
||
auto operator <<(std::ios_base &(*func)(std::ios_base &))->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
template<int c_blank =0>
|
||
auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &))->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
template<int c_blank =0>
|
||
auto operator <<(
|
||
std::basic_ostream<char> &(*func)(std::basic_ostream<char> &))->
|
||
decltype(this->operator << <decltype((func))>(func))
|
||
{
|
||
return operator << <decltype((func))>(func);
|
||
}
|
||
};
|
||
|
||
|
||
|
||
//¶ÏÑÔ²Ù×÷ÀàÊä³öÑ¡Ïî
|
||
enum class AssertOption
|
||
{
|
||
thrw_log,//Å׳öÒì³£²¢Êä³öÈÕÖ¾
|
||
thrw,//Å׳öÒì³£
|
||
asst_log,//µ÷ÊÔ¶ÏÑÔ²¢Êä³öÈÕÖ¾
|
||
asst,//µ÷ÊÔ¶ÏÑÔ
|
||
log,//Êä³öÈÕÖ¾
|
||
none,//ÎÞ²Ù×÷
|
||
};
|
||
|
||
//¶ÏÑÔ²Ù×÷Àà
|
||
template<typename TyOs= std::ostream>
|
||
class AssertOperator
|
||
{
|
||
private:
|
||
//·Ç²¶»ñÒì³£
|
||
class NoCatchError:
|
||
private std::runtime_error
|
||
{
|
||
//¼Ì³Ð»ùÀ๹Ô캯Êý£¨³ýĬÈÏ¿½±´¹¹Ô죩
|
||
using std::runtime_error::runtime_error;
|
||
public:
|
||
//ĬÈϹ¹Ôì
|
||
NoCatchError():
|
||
std::runtime_error("")
|
||
{
|
||
}
|
||
//ʹÓü̳Ðwhat
|
||
using std::runtime_error::what;
|
||
//Ê¡ÂԺϳÉ5¿½±´
|
||
};
|
||
|
||
private:
|
||
TyOs &os;//Êä³öÀà
|
||
public:
|
||
AssertOption option;//Êä³öÑ¡Ïî
|
||
|
||
public:
|
||
//¹¹Ôì
|
||
AssertOperator() =
|
||
delete;
|
||
explicit AssertOperator(TyOs &o_os, AssertOption o_option):
|
||
os(o_os), option(o_option)
|
||
{
|
||
}
|
||
public:
|
||
//Ö¸¶¨Ñ¡Ïî½øÐжÏÑÔ
|
||
bool operator()(AssertOption optionTmp,
|
||
bool bCond, const std::string &str= "") const
|
||
{
|
||
if(bCond)
|
||
return true;
|
||
//°´Ñ¡Ïî½øÐвÙ×÷
|
||
if(optionTmp==AssertOption::thrw_log) {
|
||
os <<str <<std::flush;
|
||
throw NoCatchError(str);
|
||
}
|
||
else if(optionTmp==AssertOption::thrw) {
|
||
throw NoCatchError(str);
|
||
}
|
||
else if(optionTmp==AssertOption::asst_log) {
|
||
os <<str <<std::flush;
|
||
assert(false);
|
||
}
|
||
else if(optionTmp==AssertOption::asst) {
|
||
assert(false);
|
||
}
|
||
else if(optionTmp==AssertOption::log) {
|
||
os <<str <<std::flush;
|
||
}
|
||
else if(optionTmp==AssertOption::none) {
|
||
}
|
||
return false;
|
||
}
|
||
//ʹÓÃĬÈÏÑ¡Ïî½øÐжÏÑÔ
|
||
bool operator()(bool bCond, const std::string &str= "") const
|
||
{
|
||
return operator()(option, bCond, str);
|
||
}
|
||
};
|
||
|
||
|
||
|
||
//дÀàÐͶþ½øÖÆÎļþÀà
|
||
//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿
|
||
class BinWriteFile
|
||
{
|
||
public:
|
||
std::ofstream ofs;//ÎļþÁ÷
|
||
|
||
public:
|
||
//¹¹Ôì
|
||
BinWriteFile()
|
||
= default;
|
||
explicit BinWriteFile(const std::string &name, bool o_bAfter=false)
|
||
{
|
||
Open(name, o_bAfter);
|
||
}
|
||
//Îö¹¹
|
||
~BinWriteFile()
|
||
= default;
|
||
//ɾ³ý¿½±´
|
||
BinWriteFile(const BinWriteFile &)
|
||
= delete;
|
||
BinWriteFile &operator =(BinWriteFile &)
|
||
= delete;
|
||
//ÒÆ¶¯¹¹Ôì
|
||
BinWriteFile(BinWriteFile &&file)
|
||
= default;
|
||
//ÒÆ¶¯¸³Öµ
|
||
BinWriteFile &operator =(BinWriteFile &&file)
|
||
= default;
|
||
|
||
public:
|
||
//´ò¿ªÎļþ£¬o_bAfterÊÇ·ñ×·¼Óд
|
||
BinWriteFile &Open(const std::string &name, bool o_bAfter=false)
|
||
{
|
||
ofs.close();
|
||
if(o_bAfter)
|
||
ofs.open(name, std::ios::binary|std::ios::app);
|
||
else
|
||
ofs.open(name, std::ios::binary);
|
||
if(!ofs.is_open())
|
||
throw std::runtime_error("Can't Open Write File");
|
||
return *this;
|
||
}
|
||
//¹Ø±ÕÎļþ
|
||
bool Close()
|
||
{
|
||
ofs.close();
|
||
if(ofs.bad())
|
||
throw std::runtime_error("Can't Close File");
|
||
return true;
|
||
}
|
||
//·µ»Ø´ò¿ª×´Ì¬
|
||
bool isopen() const
|
||
{
|
||
return ofs.is_open();
|
||
}
|
||
//ÎļþÁ÷¿ÉÓã¬Ò»¶¨¿ÉÓÃ
|
||
bool IsFail() const
|
||
{
|
||
return !ofs.good();
|
||
}
|
||
operator bool() const
|
||
{
|
||
return ofs.good();
|
||
}
|
||
//Çå³ý´íÎó±êÖ¾
|
||
void Clear()
|
||
{
|
||
ofs.clear();
|
||
}
|
||
//Ë¢ÐÂÎļþ»º³åÇø
|
||
BinWriteFile &Fflush()
|
||
{
|
||
ofs.flush();
|
||
return *this;
|
||
}
|
||
//ÖØ¶¨Î»Î»ÖÃ
|
||
BinWriteFile &Seekp(std::ofstream::pos_type pos)
|
||
{
|
||
ofs.seekp(pos);
|
||
return *this;
|
||
}
|
||
BinWriteFile &Seekp(std::ofstream::off_type off, std::ios_base::seekdir dir)
|
||
{
|
||
ofs.seekp(off, dir);
|
||
return *this;
|
||
}
|
||
//²éѯλÖÃ
|
||
std::ofstream::pos_type Tellp()
|
||
{
|
||
return ofs.tellp();
|
||
}
|
||
//¶Ô»º³åÇø½øÐÐÎļþдÈë
|
||
BinWriteFile &WriteBuf(const void *buf, size_t size)
|
||
{
|
||
ofs.write(reinterpret_cast<const char *>(buf), size);
|
||
if(ofs.bad())
|
||
throw std::runtime_error("Can't Write File");
|
||
return *this;
|
||
}
|
||
//¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::Type WriteArray(const Ty *pt, size_t count)
|
||
{
|
||
WriteBuf(pt, sizeof(Ty)*count);
|
||
return *this;
|
||
}
|
||
//¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
|
||
template<typename Ty>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::Type WriteArray(const Ty *pt, size_t count)
|
||
{
|
||
for(; count!=0; --count, ++pt)
|
||
*this <<*pt;
|
||
return *this;
|
||
}
|
||
public:
|
||
//¶ÔÄÚÖÃÀàÐͽøÐÐÎļþдÈ룬°üÀ¨ÄÚÖÃÀàÐÍÊý×é
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<
|
||
typename std::remove_all_extents<Ty>::type>::value, BinWriteFile &
|
||
>::type operator <<(const Ty &r)
|
||
{
|
||
WriteBuf(&r, sizeof(r));
|
||
return *this;
|
||
}
|
||
//¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþдÈë
|
||
template<typename Ty, size_t N>
|
||
typename std::enable_if<!std::is_scalar<
|
||
typename std::remove_all_extents<Ty>::type>::value, BinWriteFile &
|
||
>::type operator <<(const Ty (&arrStr)[N])
|
||
{
|
||
for(int64_t i=0; i<N; ++i)
|
||
*this <<arrStr[i];
|
||
return *this;
|
||
}
|
||
//¶Ôpair½øÐÐÎļþдÈë
|
||
template<typename Ty1, typename Ty2>
|
||
BinWriteFile &operator <<(const std::pair<Ty1, Ty2> &pr)
|
||
{
|
||
*this <<pr.first <<pr.second;
|
||
return *this;
|
||
}
|
||
//¶Ôtuple½øÐÐÎļþдÈë
|
||
template<typename ...Tys>
|
||
BinWriteFile &operator <<(const std::tuple<Tys...> &tup)
|
||
{
|
||
TupleWrite<sizeof...(Tys)-1>(tup);
|
||
return *this;
|
||
}
|
||
template<int index, typename ...Tys>
|
||
typename std::enable_if<(index>=0), void
|
||
>::type TupleWrite(const std::tuple<Tys...> &tup)
|
||
{
|
||
*this <<std::get<index>(tup);
|
||
TupleWrite<index-1>(tup);
|
||
}
|
||
template<int index, typename Ty>
|
||
void TupleWrite(const Ty &tup)
|
||
{
|
||
}
|
||
//¶Ôstring½øÐÐÎļþдÈë
|
||
template<typename Ty>
|
||
BinWriteFile &operator <<(const std::basic_string<Ty> &str)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = str.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
WriteBuf(&str[0], (size_t)(size*sizeof(Ty)));
|
||
return *this;
|
||
}
|
||
//¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþдÈë
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::type operator <<(const std::vector<Ty> &vec)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = vec.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
WriteBuf(vec.data(), size*sizeof(Ty));
|
||
return *this;
|
||
}
|
||
//¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë
|
||
template<typename Ty>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::type operator <<(const std::vector<Ty> &vec)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = vec.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : vec)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþдÈë
|
||
template<typename Ty, size_t c_size>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::type operator <<(const std::array<Ty, c_size> &arr)
|
||
{
|
||
//дÊý¾Ý
|
||
WriteBuf(arr.data(), c_size*sizeof(Ty));
|
||
return *this;
|
||
}
|
||
//¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë
|
||
template<typename Ty, size_t c_size>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
|
||
>::type operator <<(const std::array<Ty, c_size> &arr)
|
||
{
|
||
//дÊý¾Ý
|
||
for(auto &r : arr)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ôdeque½øÐÐÎļþдÈë
|
||
template<typename Ty>
|
||
BinWriteFile &operator <<(const std::deque<Ty> &deq)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = deq.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : deq)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ôlist½øÐÐÎļþдÈë
|
||
template<typename Ty>
|
||
BinWriteFile &operator <<(const std::list<Ty> &lis)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = lis.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : lis)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ô¶þ²æÊ÷½øÐÐÎļþдÈë
|
||
template<typename Ty, typename TyComp>
|
||
BinWriteFile &operator <<(const std::set<Ty, TyComp> &bst)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = bst.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : bst)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþдÈë
|
||
template<typename Ty, typename TyComp>
|
||
BinWriteFile &operator <<(const std::multiset<Ty, TyComp> &bst)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = bst.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : bst)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë
|
||
template<typename Ty1, typename Ty2, typename TyComp>
|
||
BinWriteFile &operator <<(const std::map<Ty1, Ty2, TyComp> &bst)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = bst.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : bst)
|
||
*this <<r.first <<r.second;
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë
|
||
template<typename Ty1, typename Ty2, typename TyComp>
|
||
BinWriteFile &operator <<(const std::multimap<Ty1, Ty2, TyComp> &bst)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = bst.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : bst)
|
||
*this <<r.first <<r.second;
|
||
return *this;
|
||
}
|
||
//¶Ô¹þÏ£±í½øÐÐÎļþдÈë
|
||
template<typename Ty, typename TyHash, typename TyComp>
|
||
BinWriteFile &operator <<(const std::unordered_set<Ty, TyHash, TyComp> &htb)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = htb.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : htb)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþдÈë
|
||
template<typename Ty, typename TyHash, typename TyComp>
|
||
BinWriteFile &operator <<(const std::unordered_multiset<Ty, TyHash, TyComp> &htb)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = htb.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : htb)
|
||
*this <<r;
|
||
return *this;
|
||
}
|
||
//¶Ô¹þÏ£±í¶Ô½øÐÐÎļþдÈë
|
||
template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
|
||
BinWriteFile &operator <<(const std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = htb.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : htb)
|
||
*this <<r.first <<r.second;
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþдÈë
|
||
template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
|
||
BinWriteFile &operator <<(const std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb)
|
||
{
|
||
//д³ß´ç
|
||
int64_t size = htb.size();
|
||
operator <<(size);
|
||
//дÊý¾Ý
|
||
for(auto &r : htb)
|
||
*this <<r.first <<r.second;
|
||
return *this;
|
||
}
|
||
};
|
||
|
||
//дÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷
|
||
//ÊÇÊä³öµü´úÆ÷
|
||
template<typename Ty>
|
||
class BinWriteFileIter:
|
||
public std::iterator<std::output_iterator_tag, void,
|
||
void, void, void>
|
||
{
|
||
private://Êý¾Ý
|
||
BinWriteFile *pBwf;//¹ØÁªÎļþ
|
||
|
||
public://»ù±¾º¯Êý
|
||
//ûÓÐĬÈϹ¹Ôì
|
||
BinWriteFileIter()
|
||
= delete;
|
||
//¹ØÁª¹¹Ôì
|
||
BinWriteFileIter(BinWriteFile &bwf):
|
||
pBwf(&bwf)
|
||
{
|
||
}
|
||
public://ÔËËã·ûÖØÔØ
|
||
//½âÒýÓòÙ×÷£¬·µ»Ø×ÔÉí
|
||
BinWriteFileIter &operator *() const
|
||
{
|
||
return *this;
|
||
}
|
||
//µÝÔö²Ù×÷£¬Ê²Ã´Ò²²»×ö£¬·µ»Ø×ÔÉí
|
||
BinWriteFileIter &operator ++()
|
||
{
|
||
return *this;
|
||
}
|
||
BinWriteFileIter &operator ++(int)
|
||
{
|
||
return *this;
|
||
}
|
||
//¸³Öµ²Ù×÷£¬½øÐÐÊä³ö
|
||
BinWriteFileIter &operator =(const Ty &data)
|
||
{
|
||
*pBwf <<data;
|
||
return *this;
|
||
}
|
||
};
|
||
|
||
|
||
template<typename Ty>
|
||
class BinReadFileIter;
|
||
//¶ÁÀàÐͶþ½øÖÆÎļþÀà
|
||
//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿
|
||
class BinReadFile
|
||
{
|
||
public:
|
||
std::ifstream ifs;//ÎļþÁ÷
|
||
bool bFast = false;//¿ìËÙģʽ£¬£¬Ò»´ÎÉêÇë×ã¹»Äڴ棬Êý×é¼Ç¼´íÎó¿ÉÄÜÔì³ÉÄÚ´æ²»×㣬¿ÉÔÚÈκÎʱºò¸ü¸Ä
|
||
bool bSave = false;//½ÚԼģʽ£¬ÉêÇëÄÚ´æÊ±²»ÉêÇë¶îÍâÁ¿£¬½ö¿ìËÙģʽÓ㬿ÉÔÚÈκÎʱºò¸ü¸Ä
|
||
static constexpr int64_t bufSize = 4096;//¶ÁÈ¡»º´æ´óС
|
||
|
||
public:
|
||
//¹¹Ôì
|
||
explicit BinReadFile(bool o_bFast= false, bool o_bSave= false):
|
||
bFast(o_bFast), bSave(o_bSave)
|
||
{
|
||
}
|
||
//´ò¿ªÎļþ¹¹Ôì
|
||
template<typename Ty, typename= typename std::enable_if<
|
||
IsRemoveCVRefSameSzOrString<Ty>::value>::type
|
||
> explicit BinReadFile(Ty &&name, bool o_bFast= false, bool o_bSave= false):
|
||
bFast(o_bFast), bSave(o_bSave)
|
||
{
|
||
Open(std::forward<Ty>(name));
|
||
}
|
||
//Îö¹¹
|
||
~BinReadFile()
|
||
= default;
|
||
//ɾ³ý¿½±´
|
||
BinReadFile(const BinReadFile &)
|
||
= delete;
|
||
BinReadFile &operator =(BinReadFile &)
|
||
= delete;
|
||
//ÒÆ¶¯¹¹Ôì
|
||
BinReadFile(BinReadFile &&file)
|
||
= default;
|
||
//ÒÆ¶¯¸³Öµ
|
||
BinReadFile &operator =(BinReadFile &&file)
|
||
= default;
|
||
|
||
public:
|
||
//´ò¿ªÎļþ
|
||
BinReadFile &Open(const std::string &name)
|
||
{
|
||
ifs.close();
|
||
ifs.open(name, std::ios::binary);
|
||
if(ifs.bad())
|
||
throw std::runtime_error("Open Read File Bad Error");
|
||
return *this;
|
||
}
|
||
//¸²¸ÇCloseº¯Êý£¬Èô¼ì²â½áβÔò·µ»Ø¼ì²â½á¹û
|
||
bool Close(bool bTestEnd = false)
|
||
{
|
||
bool res = !bTestEnd;
|
||
//¼ì²â½áβ
|
||
if(bTestEnd) {
|
||
res = TestEof();
|
||
}
|
||
ifs.close();
|
||
if(ifs.bad())
|
||
throw std::runtime_error("Can't Close File");
|
||
return res;
|
||
}
|
||
//·µ»Ø´ò¿ª×´Ì¬
|
||
bool IsOpen() const
|
||
{
|
||
return ifs.is_open();
|
||
}
|
||
//ÎļþÁ÷¿ÉÓÃ
|
||
bool IsFail() const
|
||
{
|
||
return !ifs.good();
|
||
}
|
||
operator bool() const
|
||
{
|
||
return ifs.good();
|
||
}
|
||
//Çå³ý´íÎó±êÖ¾
|
||
void Clear()
|
||
{
|
||
ifs.clear();
|
||
}
|
||
//¼ì²â½á⣬»á½øÐÐÒ»´Î¶ÁÈ¡²Ù×÷
|
||
bool TestEof()
|
||
{
|
||
ifs.get();
|
||
if(ifs.bad())
|
||
throw std::runtime_error("Read File Bad Error");
|
||
return ifs.eof();
|
||
}
|
||
//ÖØ¶¨Î»Î»ÖÃ
|
||
BinReadFile &Seekg(std::ifstream::pos_type pos)
|
||
{
|
||
ifs.seekg(pos);
|
||
return *this;
|
||
}
|
||
BinReadFile &Seekg(std::ifstream::off_type off, std::ios_base::seekdir dir)
|
||
{
|
||
ifs.seekg(off, dir);
|
||
return *this;
|
||
}
|
||
//²éѯλÖÃ
|
||
std::ifstream::pos_type Tellg()
|
||
{
|
||
return ifs.tellg();
|
||
}
|
||
//¶Ô»º³åÇø½øÐÐÎļþ¶ÁÈ¡
|
||
BinReadFile &ReadBuf(void *buf, size_t size)
|
||
{
|
||
ifs.read(reinterpret_cast<char *>(buf), size);
|
||
if(ifs.bad())
|
||
throw std::runtime_error("Read File Bad Error");
|
||
return *this;
|
||
}
|
||
//¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
|
||
>::Type ReadArray(Ty *pt, size_t count)
|
||
{
|
||
ReadBuf(pt, sizeof(Ty)*count);
|
||
return *this;
|
||
}
|
||
//¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
|
||
template<typename Ty>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile &
|
||
>::Type ReadArray(Ty *pt, size_t count)
|
||
{
|
||
for(; count!=0; --count, ++pt) {
|
||
if(ifs.fail())
|
||
return;
|
||
*this >>*pt;
|
||
}
|
||
return *this;
|
||
}
|
||
public:
|
||
//¶ÔÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬°üÀ¨ÄÚÖÃÀàÐÍÊý×é
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<
|
||
typename std::remove_all_extents<Ty>::type>::value, BinReadFile &
|
||
>::type operator >>(Ty &r)
|
||
{
|
||
ReadBuf(&r, sizeof(r));
|
||
return *this;
|
||
}
|
||
//¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty, size_t N>
|
||
typename std::enable_if<!std::is_scalar<
|
||
typename std::remove_all_extents<Ty>::type>::value, BinReadFile &
|
||
>::type operator >>(Ty (&arrStr)[N])
|
||
{
|
||
for(int64_t i=0; i<N; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
*this >>arrStr[i];
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ôpair½øÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty1, typename Ty2>
|
||
BinReadFile &operator >>(std::pair<Ty1, Ty2> &pr)
|
||
{
|
||
*this >>pr.first >>pr.second;
|
||
return *this;
|
||
}
|
||
//¶Ôtuple½øÐÐÎļþ¶ÁÈ¡
|
||
template<typename ...Tys>
|
||
BinReadFile &operator >>(std::tuple<Tys...> &tup)
|
||
{
|
||
TupleRead<sizeof...(Tys)-1>(tup);
|
||
return *this;
|
||
}
|
||
template<int index, typename ...Tys>
|
||
typename std::enable_if<(index>=0), void
|
||
>::type TupleRead(std::tuple<Tys...> &tup)
|
||
{
|
||
*this >>std::get<index>(tup);
|
||
TupleRead<index-1>(tup);
|
||
}
|
||
template<int index, typename Ty>
|
||
void TupleRead(Ty &tup)
|
||
{
|
||
}
|
||
//¶Ôstring½øÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty>
|
||
BinReadFile &operator >>(std::basic_string<Ty> &str)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
str.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast) {
|
||
if(bSave)
|
||
str.reserve((typename std::basic_string<Ty>::size_type)size);
|
||
str.resize((typename std::basic_string<Ty>::size_type)size);
|
||
ReadBuf(&str[0], (size_t)(size*sizeof(Ty)));
|
||
}
|
||
else {
|
||
constexpr int64_t perBufSize = bufSize/sizeof(Ty);
|
||
for(; size>0; size-=perBufSize) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
int64_t realSize = size<perBufSize? size:perBufSize;
|
||
auto nowSize = str.size();
|
||
str.resize((typename std::basic_string<Ty>::size_type)(nowSize+realSize));
|
||
ReadBuf(&str[0]+nowSize, (size_t)(realSize*sizeof(Ty)));
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
//¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
|
||
>::type operator >>(std::vector<Ty> &vec)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
constexpr int64_t perBufSize = bufSize/sizeof(Ty);
|
||
vec.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast) {
|
||
if(bSave)
|
||
vec.reserve((typename std::vector<Ty>::size_type)size);
|
||
vec.resize((typename std::vector<Ty>::size_type)size);
|
||
ReadBuf(vec.data(), size*sizeof(Ty));
|
||
}
|
||
else {
|
||
for(; size>0; size-=perBufSize) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
int64_t realSize = size<perBufSize? size:perBufSize;
|
||
auto nowSize = vec.size();
|
||
vec.resize((typename std::vector<Ty>::size_type)(nowSize+realSize));
|
||
ReadBuf(vec.data()+nowSize, realSize*sizeof(Ty));
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
|
||
template<typename Ty>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile &
|
||
>::type operator >>(std::vector<Ty> &vec)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
//¶ÁÊý¾Ý
|
||
vec.clear();
|
||
if(bFast) {
|
||
if(bSave)
|
||
vec.reserve((typename std::vector<Ty>::size_type)size);
|
||
vec.resize((typename std::vector<Ty>::size_type)size);
|
||
for(auto &r : vec) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
*this >>r;
|
||
}
|
||
}
|
||
else {
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
vec.emplace_back();
|
||
*this >>vec.back();
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
//¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty, size_t c_size>
|
||
typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
|
||
>::type operator >>(std::array<Ty, c_size> &arr)
|
||
{
|
||
//¶ÁÊý¾Ý
|
||
ReadBuf(arr.data(), c_size*sizeof(Ty));
|
||
return *this;
|
||
}
|
||
//¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
|
||
template<typename Ty, size_t c_size>
|
||
typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile &
|
||
>::type operator >>(std::array<Ty, c_size> &arr)
|
||
{
|
||
//¶ÁÊý¾Ý
|
||
for(auto &ele: arr) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
*this >>ele;
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ôdeque½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
|
||
template<typename Ty>
|
||
BinReadFile &operator >>(std::deque<Ty> &deq)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
deq.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
deq.emplace_back();
|
||
*this >>deq.back();
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ôlist½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
|
||
template<typename Ty>
|
||
BinReadFile &operator >>(std::list<Ty> &lis)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
lis.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
lis.emplace_back();
|
||
*this >>lis.back();
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty, typename TyComp>
|
||
BinReadFile &operator >>(std::set<Ty, TyComp> &bst)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
bst.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty data;
|
||
*this >>data;
|
||
bst.insert(bst.end(), std::move(data));
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty, typename TyComp>
|
||
BinReadFile &operator >>(std::multiset<Ty, TyComp> &bst)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
bst.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty data;
|
||
*this >>data;
|
||
bst.insert(bst.end(), std::move(data));
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty1, typename Ty2, typename TyComp>
|
||
BinReadFile &operator >>(std::map<Ty1, Ty2, TyComp> &bst)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
bst.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty1 data;
|
||
*this >>data;
|
||
if(ifs.fail())
|
||
return *this;
|
||
auto res = bst.emplace_hint(bst.end(), std::piecewise_construct,
|
||
std::forward_as_tuple(std::move(data)), std::make_tuple());
|
||
*this >>res->second;
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty1, typename Ty2, typename TyComp>
|
||
BinReadFile &operator >>(std::multimap<Ty1, Ty2, TyComp> &bst)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
bst.clear();
|
||
//¶ÁÊý¾Ý
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty1 data;
|
||
*this >>data;
|
||
if(ifs.fail())
|
||
return *this;
|
||
auto res = bst.emplace_hint(bst.end(), std::piecewise_construct,
|
||
std::forward_as_tuple(std::move(data)), std::make_tuple());
|
||
*this >>res->second;
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty, typename TyHash, typename TyComp>
|
||
BinReadFile &operator >>(std::unordered_set<Ty, TyHash, TyComp> &htb)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
htb.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast)
|
||
htb.reserve((typename std::unordered_set<Ty, TyHash, TyComp>::size_type)size);
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty data;
|
||
*this >>data;
|
||
htb.insert(std::move(data));
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty, typename TyHash, typename TyComp>
|
||
BinReadFile &operator >>(std::unordered_multiset<Ty, TyHash, TyComp> &htb)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
htb.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast)
|
||
htb.reserve((typename std::unordered_multiset<Ty, TyHash, TyComp>::size_type)size);
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty data;
|
||
*this >>data;
|
||
htb.insert(std::move(data));
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
|
||
BinReadFile &operator >>(std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
htb.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast)
|
||
htb.reserve((typename std::unordered_map<Ty1, Ty2, TyHash, TyComp>::size_type)size);
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty1 data;
|
||
*this >>data;
|
||
if(ifs.fail())
|
||
return *this;
|
||
auto res = htb.emplace(std::piecewise_construct,
|
||
std::forward_as_tuple(std::move(data)), std::make_tuple()).first;
|
||
*this >>res->second;
|
||
}
|
||
return *this;
|
||
}
|
||
//¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
|
||
template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
|
||
BinReadFile &operator >>(std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb)
|
||
{
|
||
//¶Á³ß´ç
|
||
int64_t size = -1;
|
||
operator >>(size);
|
||
if(ifs.fail())
|
||
return *this;
|
||
htb.clear();
|
||
//¶ÁÊý¾Ý
|
||
if(bFast)
|
||
htb.reserve((typename std::unordered_multimap<Ty1, Ty2, TyHash, TyComp>::size_type)size);
|
||
for(int64_t i=0; i<size; ++i) {
|
||
if(ifs.fail())
|
||
return *this;
|
||
Ty1 data;
|
||
*this >>data;
|
||
if(ifs.fail())
|
||
return *this;
|
||
auto res = htb.emplace(std::piecewise_construct,
|
||
std::forward_as_tuple(std::move(data)), std::make_tuple());
|
||
*this >>res->second;
|
||
}
|
||
return *this;
|
||
}
|
||
};
|
||
|
||
//¶ÁÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷
|
||
//ÊÇÊäÈëµü´úÆ÷£¬´æ´¢ÀàÐͱØÐë¿ÉĬÈϹ¹Ôì
|
||
template<typename Ty>
|
||
class BinReadFileIter:
|
||
public std::iterator<std::input_iterator_tag, Ty,
|
||
int64_t, Ty *, Ty &>
|
||
{
|
||
private://Êý¾Ý
|
||
BinReadFile *pBrf;//¹ØÁªÎļþ
|
||
int64_t size;//Ê£ÓàдÈë´óС£¬¸ºÊý±íʾÎÞÏÞдÈë
|
||
Ty data;//´æ´¢Êý¾Ý
|
||
|
||
public://»ù±¾º¯Êý
|
||
//ĬÈϹ¹Ô죬³ÉΪβºóµü´úÆ÷
|
||
BinReadFileIter():
|
||
pBrf(nullptr), size(0)
|
||
{
|
||
}
|
||
//¹ØÁª¹¹Ô죬³õʼ½øÐжÁÈ¡£¬¿ÉÑ¡ÔñµÄ¼ÓÈë¶ÁÈ¡ÊýÁ¿ÏÞÖÆ
|
||
BinReadFileIter(BinReadFile &brf, int64_t o_size= -1):
|
||
pBrf(&brf), size(o_size)
|
||
{
|
||
Read();
|
||
}
|
||
public://ÔËËã·ûÖØÔØ
|
||
//½âÒýÓòÙ×÷£¬·µ»ØÊý¾ÝÒýÓã¬Ö§³ÖÒÆ¶¯²Ù×÷
|
||
Ty &operator *() const
|
||
{
|
||
return data;
|
||
}
|
||
Ty *operator ->() const
|
||
{
|
||
return &operator *();
|
||
}
|
||
//µÝÔö²Ù×÷£¬Í¬Ê±½øÐжÁÈ¡
|
||
BinReadFileIter &operator ++()
|
||
{
|
||
Read();
|
||
return *this;
|
||
}
|
||
BinReadFileIter operator ++(int)
|
||
{
|
||
BinReadFileIter ret(*this);
|
||
operator ++();
|
||
return ret;
|
||
}
|
||
//±È½Ï²Ù×÷£¬Ö¸ÏòÏàͬµÄÎļþ¾ÍÈÏΪÏàͬ
|
||
bool operator ==(const BinReadFileIter &other) const
|
||
{
|
||
return pBrf==other.pBrf;
|
||
}
|
||
bool operator !=(const BinReadFileIter &other) const
|
||
{
|
||
return !operator ==(other);
|
||
}
|
||
private:
|
||
//¶ÁÈ¡Êý¾Ý£¬Ã¿´Î¶ÁÈ¡ÊÇÎö¹¹ÔÙĬÈϹ¹ÔìÒ»´ÎÊý¾Ý£¬ÒÔÖ§³ÖÒÆ¶¯²Ù×÷
|
||
void Read()
|
||
{
|
||
assert(pBrf!=nullptr);
|
||
//ÈôÊ£Óà0ÔòתΪβºó
|
||
if(size==0) {
|
||
pBrf = nullptr;
|
||
return;
|
||
}
|
||
//Çå³ý
|
||
CallDestruct(data);
|
||
new(&data) Ty();
|
||
//¶ÁÈ¡
|
||
*pBrf >>data;
|
||
//Èô¶Áȡʧ°ÜÔòתΪβºó
|
||
if(!*pBrf)
|
||
pBrf = nullptr;
|
||
//¼õÉÙÊ£Óà
|
||
if(size>0)
|
||
-- size;
|
||
}
|
||
};
|