#pragma once //IO²Ù×÷¿â //20191212-1034X #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //¿â¹ØÁªÐèÇóÎļþ #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 inline Ty2 StreamReadPredefInit(std::istream &is, Ty1 &table, Ty2 itFieldSt, Ty2 itFieldEd, bool bReplace= true, bool bCheckNull= true) { //½«¹Ø¼ü×Ö¶ÎдÈë Ty2 itField; std::set 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 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 &(*func)(std::basic_ostream &)) { bool res = (bool)is; if(func==&std::flush>) is.ignore(std::numeric_limits::max(), '\n'); else if(func==&std::ends>) is.clear(); else if(func==&std::endl>) { is.clear(); is.ignore(std::numeric_limits::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 class OstreamHold { OstreamHold() = delete; }; //Êä³öÁ÷±£³ÖÀà×óÖµÒýÓÃÌØ»¯ template class OstreamHold { 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 &) = delete; OstreamHold &operator =(const OstreamHold &) = delete; //ĬÈÏÒÆ¶¯ OstreamHold(OstreamHold &&) = default; OstreamHold &operator =(OstreamHold &&) = default; //Á÷ÒýÓà std::ostream &operator()() const { return os; } //ÒýÓúͳÉÔ±ÒýÓà Ty &operator *() const { return ref; } Ty *operator ->() const { return &ref; } //ת»»³£ÀàÐͰ汾 operator OstreamHold() const { return OstreamHold(os, ref); } }; //Êä³öÁ÷±£³ÖÀàÓÒÖµÒýÓÃÌØ»¯ template class OstreamHold { 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 &) = delete; OstreamHold &operator =(const OstreamHold &) = delete; //ĬÈÏÒÆ¶¯ OstreamHold(OstreamHold &&) = default; OstreamHold &operator =(OstreamHold &&) = default; //ת»»×óÖµÁ÷ OstreamHold operator()() const { return OstreamHold(os, data); } OstreamHold operator()() { return OstreamHold(os, data); } //ÒýÓúͳÉÔ±ÒýÓà Ty &operator *() const { return data; } Ty *operator ->() const { return &data; } }; //Êä³öÁ÷¼¯ºÏÎÞËø±êÖ¾£¬×÷ΪÁ÷Êä³ö±íʾÎÞËø class OstreamSetNoLock { }; //Êä³öÁ÷¼¯ºÏÀà //ÓÃÓÚ¶à¸öÊä³öÁ÷ͬʱÊä³ö£¬Ö§³Ö·ÇÁ÷ÒýÓ÷µ»ØÖµµÄ´«µÝÁ÷²Ù×÷ //¸½¼Ó»¥³âËø¹¦Äܽӿڣ¬ÒªÇó²ÎÊý¿ÉËøÀàÐÍ£¬Í¬Ê±´ËÀàÒ²Âú×ã¿ÉËø //ÈôÓÐËøÔòÁ÷²Ù×÷×Ô¶¯£¬³ý·Ç´«µÝ·ÇËø±êÖ¾£¬ÔÚÒ»´®Á÷²Ù×÷¿ªÊ¼½áÊøÊ±½øÐÐËø¶¨½âËø template class OstreamSet { public: //Êä³ö¼¯ºÏ´«µÝÀàÐÍ template class Hold; public: std::vector vecPOs;//Êä³öÁ÷£¬¸ü¸Ä·ÇḬ̈߳²È« std::vector 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 intlOs, std::initializer_list intlMtx = {} ): vecPOs(intlOs), vecPMtx(intlMtx) { } //µü´úÆ÷¹¹Ôì template 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 explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd): OstreamSet(itOsSt, itOsEd, (TyMtx *)nullptr, (TyMtx *)nullptr) { } public: //ת·¢Á÷²Ù×÷£¬Ḭ̈߳²È«£¬°´Ë³Ðòµ÷ÓÃËø£¬Ðè±£Ö¤²»ËÀËø template auto operator <<(Ty &&arg) const-> Hold(arg))> { //Á÷½á¹ûÀàÐÍÊý×é using TyRes = decltype(*vecPOs.front()<(arg)); std::vector> vecRes; vecRes.reserve(vecPOs.size()); //µ÷ÓÃËø¶¨ Lock(); //Êä³ö²¢´æ´¢ for(auto pOs : vecPOs) { vecRes.emplace_back(*pOs <(arg)); } //Éú³É½á¹ûµÄHoldÀàÐÍ return Hold(std::move(vecRes), vecPMtx.empty()? nullptr:this); } //¶Ô²Ù×÷·û½øÐÐת·¢ template auto operator <<(std::ios_base &(*func)(std::ios_base &)) const-> decltype(this->operator << (func)) { return operator << (func); } template auto operator <<(std::basic_ios &(*func)(std::basic_ios &)) const-> decltype(this->operator << (func)) { return operator << (func); } template auto operator <<( std::basic_ostream &(*func)(std::basic_ostream &)) const-> decltype(this->operator << (func)) { return operator << (func); } //¶Ô²»Ëø±êÖ¾½øÐÐÁ÷²Ù×÷£¬Á÷Êä³ö½«²»½øÐÐËø¶¨ºÍ½âËø Hold operator <<(OstreamSetNoLock) const { //Á÷½á¹ûÀàÐÍÊý×é using TyRes = std::ostream &; std::vector> vecRes; vecRes.reserve(vecPOs.size()); //´æ´¢ÀàÐÍ for(auto pOs : vecPOs) { vecRes.emplace_back(*pOs); } //Éú³É½á¹ûµÄHoldÀàÐÍ return Hold(std::move(vecRes), nullptr); } //µ÷ÓÃostreamµÄ³ÉÔ±º¯Êý£¬½øÐÐËø¶¨£¬ºöÂÔ·µ»ØÖµ template void operator()(const Ty &pmf, Tys &&...args) const { //µ÷ÓÃËø¶¨ Lock(); //µ÷ÓóÉÔ±º¯Êý for(auto pOs : vecPOs) { (pOs->*pmf)(std::forward(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; itry_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 template class OstreamSet::Hold { friend class OstreamSet; private: std::vector> vecRes;//Êä³öÁ÷µÄ½á¹ûÊý×é const OstreamSet *pSet;//Êä³öÁ÷¼¯ºÏÖ¸Õ룬Îö¹¹½âËø±êÖ¾ private: //¹¹Ô죬Êä³ö¼¯ºÏÒýÓóõʼ»¯ explicit Hold(std::vector> &&o_vecRes, const OstreamSet *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 auto operator <<(Ty &&arg)-> Hold(arg))> { //´Ë¶ÔÏó²»ÐèÎö¹¹½âËø auto ptr = pSet; pSet = nullptr; //еÄÁ÷²Ù×÷½á¹ûÀàÐÍ using TyResTmp = decltype(vecRes.front().hold<(arg)); std::vector> vecResTmp; vecResTmp.reserve(vecRes.size()); //Á÷Êä³ö²¢´æ´¢ for(auto &refRes : vecRes) { vecResTmp.emplace_back(refRes.hold <(arg)); } //¹¹ÔìеÄHoldÀàÐÍ£¬×ªÒåÎö¹¹½âËø±êÖ¾ return Hold(std::move(vecResTmp), ptr); } //¶Ô²Ù×÷·û½øÐÐת·¢ template auto operator <<(std::ios_base &(*func)(std::ios_base &))-> decltype(this->operator << (func)) { return operator << (func); } template auto operator <<(std::basic_ios &(*func)(std::basic_ios &))-> decltype(this->operator << (func)) { return operator << (func); } template auto operator <<( std::basic_ostream &(*func)(std::basic_ostream &))-> decltype(this->operator << (func)) { return operator << (func); } }; //¶ÏÑÔ²Ù×÷ÀàÊä³öÑ¡Ïî enum class AssertOption { thrw_log,//Å׳öÒì³£²¢Êä³öÈÕÖ¾ thrw,//Å׳öÒì³£ asst_log,//µ÷ÊÔ¶ÏÑÔ²¢Êä³öÈÕÖ¾ asst,//µ÷ÊÔ¶ÏÑÔ log,//Êä³öÈÕÖ¾ none,//ÎÞ²Ù×÷ }; //¶ÏÑÔ²Ù×÷Àà template 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 <(buf), size); if(ofs.bad()) throw std::runtime_error("Can't Write File"); return *this; } //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ template typename std::enable_if::value, BinWriteFile & >::Type WriteArray(const Ty *pt, size_t count) { WriteBuf(pt, sizeof(Ty)*count); return *this; } //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ template typename std::enable_if::value, BinWriteFile & >::Type WriteArray(const Ty *pt, size_t count) { for(; count!=0; --count, ++pt) *this <<*pt; return *this; } public: //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþдÈ룬°üÀ¨ÄÚÖÃÀàÐÍÊý×é template typename std::enable_if::type>::value, BinWriteFile & >::type operator <<(const Ty &r) { WriteBuf(&r, sizeof(r)); return *this; } //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþдÈë template typename std::enable_if::type>::value, BinWriteFile & >::type operator <<(const Ty (&arrStr)[N]) { for(int64_t i=0; i BinWriteFile &operator <<(const std::pair &pr) { *this < BinWriteFile &operator <<(const std::tuple &tup) { TupleWrite(tup); return *this; } template typename std::enable_if<(index>=0), void >::type TupleWrite(const std::tuple &tup) { *this <(tup); TupleWrite(tup); } template void TupleWrite(const Ty &tup) { } //¶Ôstring½øÐÐÎļþдÈë template BinWriteFile &operator <<(const std::basic_string &str) { //д³ß´ç int64_t size = str.size(); operator <<(size); //дÊý¾Ý WriteBuf(&str[0], (size_t)(size*sizeof(Ty))); return *this; } //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþдÈë template typename std::enable_if::value, BinWriteFile & >::type operator <<(const std::vector &vec) { //д³ß´ç int64_t size = vec.size(); operator <<(size); //дÊý¾Ý WriteBuf(vec.data(), size*sizeof(Ty)); return *this; } //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë template typename std::enable_if::value, BinWriteFile & >::type operator <<(const std::vector &vec) { //д³ß´ç int64_t size = vec.size(); operator <<(size); //дÊý¾Ý for(auto &r : vec) *this < typename std::enable_if::value, BinWriteFile & >::type operator <<(const std::array &arr) { //дÊý¾Ý WriteBuf(arr.data(), c_size*sizeof(Ty)); return *this; } //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë template typename std::enable_if::value, BinWriteFile & >::type operator <<(const std::array &arr) { //дÊý¾Ý for(auto &r : arr) *this < BinWriteFile &operator <<(const std::deque &deq) { //д³ß´ç int64_t size = deq.size(); operator <<(size); //дÊý¾Ý for(auto &r : deq) *this < BinWriteFile &operator <<(const std::list &lis) { //д³ß´ç int64_t size = lis.size(); operator <<(size); //дÊý¾Ý for(auto &r : lis) *this < BinWriteFile &operator <<(const std::set &bst) { //д³ß´ç int64_t size = bst.size(); operator <<(size); //дÊý¾Ý for(auto &r : bst) *this < BinWriteFile &operator <<(const std::multiset &bst) { //д³ß´ç int64_t size = bst.size(); operator <<(size); //дÊý¾Ý for(auto &r : bst) *this < BinWriteFile &operator <<(const std::map &bst) { //д³ß´ç int64_t size = bst.size(); operator <<(size); //дÊý¾Ý for(auto &r : bst) *this < BinWriteFile &operator <<(const std::multimap &bst) { //д³ß´ç int64_t size = bst.size(); operator <<(size); //дÊý¾Ý for(auto &r : bst) *this < BinWriteFile &operator <<(const std::unordered_set &htb) { //д³ß´ç int64_t size = htb.size(); operator <<(size); //дÊý¾Ý for(auto &r : htb) *this < BinWriteFile &operator <<(const std::unordered_multiset &htb) { //д³ß´ç int64_t size = htb.size(); operator <<(size); //дÊý¾Ý for(auto &r : htb) *this < BinWriteFile &operator <<(const std::unordered_map &htb) { //д³ß´ç int64_t size = htb.size(); operator <<(size); //дÊý¾Ý for(auto &r : htb) *this < BinWriteFile &operator <<(const std::unordered_multimap &htb) { //д³ß´ç int64_t size = htb.size(); operator <<(size); //дÊý¾Ý for(auto &r : htb) *this < class BinWriteFileIter: public std::iterator { 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 < 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::value>::type > explicit BinReadFile(Ty &&name, bool o_bFast= false, bool o_bSave= false): bFast(o_bFast), bSave(o_bSave) { Open(std::forward(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(buf), size); if(ifs.bad()) throw std::runtime_error("Read File Bad Error"); return *this; } //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ template typename std::enable_if::value, BinReadFile & >::Type ReadArray(Ty *pt, size_t count) { ReadBuf(pt, sizeof(Ty)*count); return *this; } //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ template typename std::enable_if::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 std::enable_if::type>::value, BinReadFile & >::type operator >>(Ty &r) { ReadBuf(&r, sizeof(r)); return *this; } //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþ¶ÁÈ¡ template typename std::enable_if::type>::value, BinReadFile & >::type operator >>(Ty (&arrStr)[N]) { for(int64_t i=0; i>arrStr[i]; } return *this; } //¶Ôpair½øÐÐÎļþ¶ÁÈ¡ template BinReadFile &operator >>(std::pair &pr) { *this >>pr.first >>pr.second; return *this; } //¶Ôtuple½øÐÐÎļþ¶ÁÈ¡ template BinReadFile &operator >>(std::tuple &tup) { TupleRead(tup); return *this; } template typename std::enable_if<(index>=0), void >::type TupleRead(std::tuple &tup) { *this >>std::get(tup); TupleRead(tup); } template void TupleRead(Ty &tup) { } //¶Ôstring½øÐÐÎļþ¶ÁÈ¡ template BinReadFile &operator >>(std::basic_string &str) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; str.clear(); //¶ÁÊý¾Ý if(bFast) { if(bSave) str.reserve((typename std::basic_string::size_type)size); str.resize((typename std::basic_string::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::size_type)(nowSize+realSize)); ReadBuf(&str[0]+nowSize, (size_t)(realSize*sizeof(Ty))); } } return *this; } //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ template typename std::enable_if::value, BinReadFile & >::type operator >>(std::vector &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::size_type)size); vec.resize((typename std::vector::size_type)size); ReadBuf(vec.data(), size*sizeof(Ty)); } else { for(; size>0; size-=perBufSize) { if(ifs.fail()) return *this; int64_t realSize = size::size_type)(nowSize+realSize)); ReadBuf(vec.data()+nowSize, realSize*sizeof(Ty)); } } return *this; } //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý template typename std::enable_if::value, BinReadFile & >::type operator >>(std::vector &vec) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; //¶ÁÊý¾Ý vec.clear(); if(bFast) { if(bSave) vec.reserve((typename std::vector::size_type)size); vec.resize((typename std::vector::size_type)size); for(auto &r : vec) { if(ifs.fail()) return *this; *this >>r; } } else { for(int64_t i=0; i>vec.back(); } } return *this; } //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ template typename std::enable_if::value, BinReadFile & >::type operator >>(std::array &arr) { //¶ÁÊý¾Ý ReadBuf(arr.data(), c_size*sizeof(Ty)); return *this; } //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ template typename std::enable_if::value, BinReadFile & >::type operator >>(std::array &arr) { //¶ÁÊý¾Ý for(auto &ele: arr) { if(ifs.fail()) return *this; *this >>ele; } return *this; } //¶Ôdeque½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý template BinReadFile &operator >>(std::deque &deq) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; deq.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>deq.back(); } return *this; } //¶Ôlist½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý template BinReadFile &operator >>(std::list &lis) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; lis.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>lis.back(); } return *this; } //¶Ô¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ template BinReadFile &operator >>(std::set &bst) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; bst.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>data; bst.insert(bst.end(), std::move(data)); } return *this; } //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ template BinReadFile &operator >>(std::multiset &bst) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; bst.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>data; bst.insert(bst.end(), std::move(data)); } return *this; } //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ template BinReadFile &operator >>(std::map &bst) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; bst.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>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 BinReadFile &operator >>(std::multimap &bst) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; bst.clear(); //¶ÁÊý¾Ý for(int64_t i=0; i>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 BinReadFile &operator >>(std::unordered_set &htb) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; htb.clear(); //¶ÁÊý¾Ý if(bFast) htb.reserve((typename std::unordered_set::size_type)size); for(int64_t i=0; i>data; htb.insert(std::move(data)); } return *this; } //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ template BinReadFile &operator >>(std::unordered_multiset &htb) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; htb.clear(); //¶ÁÊý¾Ý if(bFast) htb.reserve((typename std::unordered_multiset::size_type)size); for(int64_t i=0; i>data; htb.insert(std::move(data)); } return *this; } //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ template BinReadFile &operator >>(std::unordered_map &htb) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; htb.clear(); //¶ÁÊý¾Ý if(bFast) htb.reserve((typename std::unordered_map::size_type)size); for(int64_t i=0; i>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 BinReadFile &operator >>(std::unordered_multimap &htb) { //¶Á³ß´ç int64_t size = -1; operator >>(size); if(ifs.fail()) return *this; htb.clear(); //¶ÁÊý¾Ý if(bFast) htb.reserve((typename std::unordered_multimap::size_type)size); for(int64_t i=0; i>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 class BinReadFileIter: public std::iterator { 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; } };