This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangshuo1-domain-classific…/IoOperator.h

1607 lines
40 KiB
C
Raw Normal View History

#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;
}
};