èšäºã®æ¬æã§ã¯ããã¹ããªãŒã ããšããèšèãããåºãŠããŸããããã¯ãå ¥åºåã¹ããªãŒã ïŒïŒi / oïŒã¹ããªãŒã ïŒãæå³ããŸãããå®è¡ã¹ã¬ããïŒã¹ã¬ããïŒã§ã¯ãããŸããã èšäºå ã®ã¹ã¬ããã¯èæ ®ãããŸããã
ã¯ããã«
æšæºã©ã€ãã©ãªã®ã¹ããªãŒã ã¯åŒ·åãªããŒã«ã§ãã é¢æ°ãžã®åŒæ°ãšããŠã¹ããªãŒã ãæå®ã§ããŸããããã«ãããæ±çšæ§ã確ä¿ãããŸããé©åãªã©ã€ãã©ãªãèŠã€ãã£ãå Žåãæšæºãã¡ã€ã«ïŒfstreamïŒãšã³ã³ãœãŒã«ïŒcin / coutïŒãããã³ãœã±ãããšCOMããŒãã®äž¡æ¹ã§æ©èœããŸãã
ãã ããé©åãªæ©èœãæ¢ã«å®è£ ãããŠããæ¢è£œã®ã©ã€ãã©ãªãåžžã«èŠã€ããããšãã§ãããšã¯éããŸãããã¯ã©ã¹ã䜿çšããŠç¬èªã®ã©ã€ãã©ãªãéçºããŠããå ŽåããããŸãã 次ã«ã瀟å ã§ã¹ã¬ããã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããéã«åé¡ãçºçããŸãã
䜿çšç°å¢
ãã¹ãã±ãŒã¹ã®èšäºãæžããšãã¯ãg ++ã³ã³ãã€ã©ïŒUbuntu 5.4.0-6ubuntu1ã16.04.4ïŒãšc ++ 11æšæºã䜿çšãããŸããã ãããããããããããåºæ¬ã¯ã©ã¹ã®ãªãŒããŒã©ã€ãå¯èœãªã¡ãœãããããŒã¯ããããã«ãªãŒããŒã©ã€ãããŒã¯ãŒãã䜿çšããŸãããããããåé€ããïŒããã³nullptrãNULLã«çœ®ãæããïŒå Žåã¯ãå€ãæšæºã§ã³ã³ãã€ã«ããå¿ èŠããããŸãã
ãã¹ãŠã®äŸã¯ãgithubïŒ streambuf_examplesã§ãå ¥æã§ããŸãã
å 容
- ã¹ã¬ããã¯ã©ã®ããã«é 眮ãããŸããïŒ
- åçŽãªã±ãŒã¹-ãããã¡ãªã³ã°ãªã
- ãããã¡ãŒã䜿çšããŸã
- é«åºŠãªæ©èœ
- ãããã«
- åç §è³æ
ã¹ã¬ããã¯ã©ã®ããã«é 眮ãããŸããïŒ
ã¹ããªãŒãã³ã°I / OããµããŒãããåã¯ã©ã¹ã¯ã std :: istream ïŒå ¥åïŒã std :: ostream ïŒåºåïŒããŸãã¯std :: iostream ïŒå ¥åããã³åºåïŒã¯ã©ã¹ãç¶æ¿ããŸãã ãããã¯ããªãŒããŒããŒããããæŒç®åã<<ãããã³ã>>ãã®äœ¿çšãåºåã®ãã©ãŒããããæ°å€ã®æååãžã®å€æãããã³ãã®éãªã©ã®æ©èœãæäŸããŸãã
ãã ããããŒã¿ã®çŽæ¥èªã¿åããŸãã¯æžã蟌ã¿ã¯ããŒã¿å ã§ã¯ãªãã std :: streambufãç¶æ¿ããã¯ã©ã¹å ã§çºçããŸãã Streambufèªäœã¯ãåŸç¶ã¯ã©ã¹ã§åå®çŸ©ããå¿ èŠãããäžé£ã®ä»®æ³é¢æ°ãåããã€ã³ã¿ãŒãã§ã€ã¹ã§ãããæ¢ã«ããŒã¿ã®èªã¿åã/æžã蟌ã¿ãè¡ãç¬èªã®ããžãã¯ãæã£ãŠããŸãïŒããã¯ãfstreamããã³stringstreamã®std :: filebufããã³std :: stringbufã¯ã©ã¹ã§è¡ããããã®ã§ãããããïŒã
ããã«ãstreambufã¯ãããã¡ããžãã¯ã®äžéšãå®è£ ããŸãã ããã°ã©ãã¯ããããã¡ã®éå§ãšçµäºã®ã¿ãèšå®ãããªãŒããŒãããŒãæ¯æžãåæãªã©ã®ã€ãã³ããã³ãã©ãå®è£ ã§ããŸãã
ç¬èªã®ã¹ããªãŒã ãéçºããå Žåãæãé£ããéšåã¯std :: streambuf descendantã®å®è£ ã§ãã åçŽãªã±ãŒã¹ã§ã¯ãistreamãostreamããŸãã¯iostreamãã掟çããã¯ã©ã¹ã¯å®å šã«ååšããªãå ŽåããããŸãã
åçŽãªã±ãŒã¹-ãããã¡ãªã³ã°ãªã
åçŽãªå ŽåããŸãã¯ããã©ãŒãã³ã¹ãéèŠã§ã¯ãªãå Žåããããã¡ã¯äžèŠã§ãã ãã®åŸã3ã€ã®ä»®æ³é¢æ°ã®ã¿ãåå®çŸ©ããã ãã§ååã§ãã
- int overflowïŒint cïŒ -ãããã¡ãŒããªãŒããŒãããŒãããšãã«åŒã³åºãããŸãã åŒæ°ã¯ããããã¡ã«ãå
¥ã£ãŠããªããæåã§ãã
æ»ãå€ïŒæåããå Žåãèšé²ãããã·ã³ãã«ã®ã³ãŒããintã«ãã£ã¹ãããã以å€ã®å Žåã¯EOFã
ããã©ã«ãã®åäœïŒåžžã«EOFãè¿ããŸãã
- int underflowïŒïŒ -次ã«ç§»åããã«çŸåšã®æåãååŸããããã«åŒã³åºãããŸãã
æ»ãå€ïŒæåããå Žåãèªã¿åãããæåã®ã³ãŒããintã«ãã£ã¹ãããã以å€ã®å Žåã¯EOFã
ããã©ã«ãã®åäœïŒãããã¡ãå©çšå¯èœã§ãæªèªæåãããå Žåããããã¡å ã®çŸåšäœçœ®ã®æåãè¿ããŸãããã以å€ã®å Žåã¯EOFãè¿ããŸãã
- int uflowïŒïŒã¯ã¢ã³ããŒãããŒãšåãã§ãããæåãããšããããã¡ãŒãã€ã³ã¿ãŒã次ã®æåã«ã·ããããŸãã
æ»ãå€ïŒã¢ã³ããŒãããŒã®å Žåã
ããã©ã«ãã®åäœïŒã¢ã³ããŒãããŒãåŒã³åºããŸãã çµæãæåããå Žåããããã¡ãã€ã³ã¿ã次ã®æåã«ã·ããããã¢ã³ããŒãããŒåŒã³åºãã®çµæãè¿ããŸã;倱æããå ŽåãEOFãè¿ããŸãã æªå®çŸ©ã®ãããã¡ã®ãã€ã³ã¿ãã·ããããããšãããšãã»ã°ã¡ã³ããŒã·ã§ã³ãšã©ãŒãçºçããŸãããããã¡ã䜿çšããŠããªãå Žåã¯ããã®åäœããªãŒããŒã©ã€ãããããšãå¿ããªãã§ãã ããïŒ
以äžãé¢æ°ã®èª¬æã¯cppreference.comããåãããŸãã
äŸ1-æ°åã®ãã£ã«ã¿ãªã³ã°
ãããããååãªããã¹ãããããŸããã äŸãšããŠããã£ã«ã¿ãªã³ã°ã¹ããªãŒã ãèŠãŠã¿ãŸããããããã«ãããæ°åãšã¹ããŒã¹ã®ã¿ãééã§ããããã«ãªããŸãïŒãã®ãããæ°åãäºãã«åé¢ããããšãã§ããŸãïŒãå¥ã®ã¹ããªãŒã ããããŒã¿ãååŸããŸãã
ã³ãŒã
#include <iostream> #include <sstream> #include <string> using namespace std; class numfilterbuf : public streambuf { private: istream *in; ostream *out; int cur; // , underflow() protected: /* : */ virtual int overflow(int c) override { if (c == traits_type::eof()){ return traits_type::eof(); } char_type ch = static_cast<char_type>(c); if (ch == ' ' || (ch >= '0' && ch <= '9')){ // out->put(ch); // - , EOF return out->good() ? ch : traits_type::eof(); } return ch; } /* : */ // - segmentation fault virtual int uflow() override { int c = underflow(); cur = traits_type::eof(); // underflow() return c; } virtual int underflow() override { if (cur != traits_type::eof()){ return cur; } // , while (in->good()){ cur = in->get(); if (cur == traits_type::eof()){ return traits_type::eof(); } char_type ch = static_cast<char_type>(cur); if (ch == ' ' || (ch >= '0' && ch <= '9')){ // return ch; } } return traits_type::eof(); } public: numfilterbuf(istream &_in, ostream &_out) : in(&_in), out(&_out), cur(traits_type::eof()) {} }; int main(int argc, char **argv){ const char str1[] = "In 4 bytes contains 32 bits"; const char str2[] = "Unix time starts from Jan 1, 1970"; istringstream str(str1); numfilterbuf buf(str, cout); // stringstream, iostream numfilter(&buf); // iostream string val; getline(numfilter, val); numfilter.clear(); // EOF stringstream cout << "Original: '" << str1 << "'" << endl; cout << "Read from numfilter: '" << val << "'" << endl; cout << "Original: '" << str2 << "'" << endl; cout << "Written to numfilter: '"; numfilter << str2; cout << "'" << endl; return 0; }
ããã°ã©ã ã®çµæïŒ
Original: 'In 4 bytes contains 32 bits' Read from numfilter: ' 4 32 ' Original: 'Unix time starts from Jan 1, 1970' Written to numfilter: ' 1 1970'
ã³ãŒãã®äž»èŠãªãã€ã³ãã¯ãã§ã«ã³ã¡ã³ããããŠããŸãããã¢ã³ããŒãããŒã¯uflowã®åã« ãããã«ã¯æ°åé£ç¶ããŠåŒã³åºãããšãã§ãããããèªã¿åãã«ã¯uflowãšunderflowã®äž¡æ¹ã®é¢æ°ãå®è£ ããããšãéèŠã§ãã ãããã®é¢æ°ã®å é ã«ãããã°åºåãè¿œå ãããšãããšãã°ã¹ããªãŒã ããæŽæ°å€æ°ã«èªã¿èŸŒããšãã«ããããæ確ã«èŠãããšãã§ããŸãã
ãŸããã³ãŒãã§ã¯ã
char_type
ã¿ã€ãã®äœ¿çšã«æ°ä»ããããããŸããã ããã¯streambufã¯ã©ã¹ã§å®çŸ©ãããŠããããã®å Žåã¯
char
åã®ãšã€ãªã¢ã¹ã§ãã ã·ã³ã°ã«ãã€ãæåã 詳现ã«ã€ããŠã¯ãèšäºã®æåŸã§èª¬æããŸãã
ãããã¡ãŒã䜿çšããŸã
å ã»ã©èšã£ãããã«ãstreambufã¯ãã§ã«ãããã¡ãŒãæäœããããžãã¯ã®äžéšãå®è£ ããŠããã6ã€ã®ãã€ã³ã¿ãŒãå ¥åãããã¡ãŒãšåºåãããã¡ãŒãžã®3ã€ã®ãã€ã³ã¿ãŒãžã®ã¢ã¯ã»ã¹ãæäŸããŸãã ãã ããstreambufã¯ãããã¡ã®ã¡ã¢ãªå²ãåœãŠãå®è£ ããŸããã ãã®ã¿ã¹ã¯ã¯ããããã¡ãã€ã³ã¿ã®åæåãšãšãã«ããã°ã©ãã«å²ãåœãŠãããŸãã
å ¥åãããã¡ã®å Žåããã€ã³ã¿ã¯æ¬¡ã®ãšããã§ãã
- ebackïŒïŒ ïŒend back pointerïŒ -ãããã¡ãŒã®æåã®èŠçŽ ãžã®ãã€ã³ã¿ãŒ
- gptrïŒïŒ ïŒãã€ã³ã¿ã®ååŸïŒ -次ã«èªã¿èŸŒãŸãããããã¡èŠçŽ ãžã®ãã€ã³ã¿
- egptrïŒïŒ ïŒãã€ã³ã¿ã®ååŸãçµäºïŒ -ãããã¡ã®æåŸã®èŠçŽ ã«ç¶ãèŠçŽ ãžã®ãã€ã³ã¿ã
gptr
ãå°éãããšããããã¡ãŒã䜿ãæããããŠãããå床æºããå¿ èŠãããããšãæå³ããŸã
mr-edd.co.ukã®ããžã¥ã¢ã«ã€ã©ã¹ã
次ã®é¢æ°ã¯ãå ¥åãããã¡ãã€ã³ã¿ã®å¶åŸ¡ã«ã䜿çšãããŸãã
- setgïŒebackãgptrãegptrïŒ -察å¿ãããã€ã³ã¿ãŒã®å€ãèšå®ããŸã
- gbumpïŒoffsetïŒ
gptr
ãã€ã³ã¿ãŒãoffset
äœçœ®ã«ç§»åããŸãã å®éãgptr
é¢æ°ãå®è¡ãããåŸãå€ã¯gptr + offset
åºåãããã¡ãŒãã€ã³ã¿ãŒã«ã¯ãåæ§ã®ååãšç®çããããŸãã
- pbaseïŒïŒ ïŒput base pointerïŒ -ãããã¡ãŒã®æåã®èŠçŽ ãžã®ãã€ã³ã¿ãŒ
- pptrïŒïŒ ïŒputãã€ã³ã¿ãŒïŒ -ãããã¡ãŒèŠçŽ ãžã®ãã€ã³ã¿ãŒã次ã«æžã蟌ãŸããŸã
- epptrïŒïŒ ïŒããããã€ã³ã¿ã®çµäºïŒ -ãããã¡ã®æåŸã®èŠçŽ ã«ç¶ãèŠçŽ ãžã®ãã€ã³ã¿ã
ãµã€ãmr-edd.co.ukã®å¥ã®ã°ã©ãã£ãã¯ã€ã©ã¹ã
åºåãããã¡ã®å¶åŸ¡æ©èœãåæ§ã§ãã
- setpïŒpbaseãepptrïŒ -察å¿ãããã€ã³ã¿ãŒã®å€ãèšå®ããŸãã
setp
ç°ãªãã2ã€ã®åŒæ°ããsetp
ãŸãsetg
ãpptr
åºåãããã¡ãŒpptr
åæåãããšããpptr
èªåçã«åçåãããŸãïŒã€ãŸãããããã¡ãŒã®å é ã«èšå®ãããŸãïŒ - pbumpïŒãªãã»ããïŒ
pptr
ãã€ã³ã¿ãŒãoffset
äœçœ®ã«ç§»åããŸãã å®éãpptr
é¢æ°ãpptr
åŸãå€ã¯pptr + offset
ããã§çè«ã¯çµãããç§ãã¡ã¯å®è·µã«ç§»ããŸãã
äŸ2-ãããã¯åºå
ãããããžã§ã¯ãã§ã¯ãã¹ããªãŒã ãééçã«å°ããªéšåã«åå²ããå¿ èŠããããŸãããåéšåã«ã¯ãåºåã«ç¹å®ã®èŠåºããä»ããŠããŸããã æ°ãã
streambuf
ç¶æ¿è ã䜿çšããŠãããå®è£ ããŸããã ãã®ã¯ã©ã¹ã¯ãåºåãããã¡ã䜿çšããåçŽãªæäœãéåžžã«åçŽãã€æ確ã«ç€ºããŠããããã«æããŸããã ãããã£ãŠã次ã®äŸã§ã¯ãåºåãè€æ°ã®éšåã«åå²ãããããã
<start>
ããã³
<end>
ã¿ã°ã§ãã¬ãŒã åããŸãã
ã³ãŒã
#include <iostream> #include <sstream> #include <string> #include <vector> using namespace std; class blockoutputbuf : public streambuf { private: ostream *out; vector<char_type> buffer; string startb, endb; protected: virtual int overflow(int c) override { if (out->good() && c != traits_type::eof()){ *pptr() = c; // 1 "" , pbump(1); // return sync() == 0 ? c : traits_type::eof(); } return traits_type::eof(); } virtual int sync() override { if (pptr() == pbase()) // , return 0; ptrdiff_t sz = pptr() - pbase(); //, // *out << startb; out->write(pbase(), sz); *out << endb; if (out->good()){ pbump(-sz); // return 0; } return -1; } public: blockoutputbuf(ostream &_out, size_t _bufsize, string _startb, string _endb) : out(&_out), buffer(_bufsize), startb(_startb), endb(_endb) { char_type *buf = buffer.data(); setp(buf, buf + (buffer.size() - 1)); // -1 , overflow() } }; int main(int argc, char **argv){ const char str1[] = "In 4 bytes contains 32 bits"; const char str2[] = "Unix time starts from Jan 1, 1970"; blockoutputbuf buf(cout, 10, "<start>", "<end>\n"); ostream blockoutput(&buf); cout << "Original: '" << str1 << "'" << endl; cout << "Written to blockoutputbuf: '"; blockoutput << str1; blockoutput.flush(); //"" , str1 cout << "'" << endl; cout << "Original: '" << str2 << "'" << endl; cout << "Written to blockoutputbuf: '"; blockoutput << str2; blockoutput.flush(); cout << "'" << endl; return 0; }
æ°é ãã®ããèªè ã¯é·ãéèããŠããã¯ãã§ãïŒãããã¡ãŒã¯ãããã¡ãŒã§ããããªãŒããŒãããŒæã ãã§ãªããããã°ã©ããŒã®èŠæ±æã«ãäœããã®æ¹æ³ã§ãã©ãã·ã¥ããå¿ èŠããããŸãïŒãã¡ã€ã«ãžã®æžã蟌ã¿æãšåæ§ïŒã
ããã¯å¥ã®ä»®æ³é¢æ°int syncïŒïŒã§ãã éåžžãããã°ã©ããŒã®ãªã¯ãšã¹ãã§åŒã³åºãããŸãããäžèšã®äŸã§ã¯ããããã¡ãŒããªãŒããŒãããŒãããšãã«èªåã§åŒã³åºããŸãã è¿ãããå€ã¯ãåæã®æåïŒ0ïŒãŸãã¯å€±æïŒ-1ïŒã瀺ãã倱æããå Žåãã¹ã¬ããã¯ç¡å¹ãªç¶æ ãååŸããŸãã ããã©ã«ãã®å®è£ ã¯äœããããåã«0ïŒæåïŒãè¿ããŸãã
ãããã¡ãªãŒããŒãããŒãšããã°ã äŸã§ã¯ã
overflow()
å®è£ ãç°¡çŽ åããããã«ãå°ããªããªãã¯ãé©çšãããŸãããå®éã®ãããã¡ãŒãµã€ãºã¯ãstreambufã®ãèããããåžžã«1èŠçŽ 倧ãããªããŸãã ããã«ããã
overflow
é¢æ°ã«æž¡ããããé©åããªããæåããããã¡ãŒã«å ¥ããŠãç¹å®ã®åŠçã§ã³ãŒããè€éã«ããããšããªããªããŸãã
10æåã®ãããã¯ã®ããã°ã©ã åºåã¯æ¬¡ã®ãšããã§ãã
ãããã«
ãªãªãžãã«ïŒã4ãã€ãã«ã¯32ããããå«ãŸããŠããŸãã blockoutputbufã«èšè¿°ïŒ '<start> In 4 bytes <end> <start>ã«ã¯<end>ãå«ãŸããŸã <éå§> 32ããã<çµäº> '' ãªãªãžãã«ïŒã1970幎1æ1æ¥ããéå§ããUNIXæéã blockoutputbufã«èšè¿°ïŒ '<éå§> Unixæé<çµäº> <start>ã¯<end>ããéå§ããŸã <éå§> m 1æ1æ¥1 <çµäº> <éå§> 970 <çµäº> ''
äŸ3-ãã¡ã€ã«ããã®ãããã¡ãªã³ã°ãããå ¥å
èªæžã¯ããå°ãè€éãªã®ã§ãç°¡åãªãã®ããå§ããŸãããã 以äžã®äŸã§ã¯ãã¹ããªãŒã ã䜿çšããŠãåçŽãªé 次ãã¡ã€ã«èªã¿åããå®è£ ãããŠããŸãã ãã¡ã€ã«ããããŒã¿ãååŸããã«ã¯ãæšæºCã©ã€ãã©ãªã®æ段ã䜿çšããŸãã
ã³ãŒã
#include <iostream> #include <string> #include <vector> #include <cstdio> #include <cstdlib> using namespace std; class cfilebuf : public streambuf { private: vector<char_type> buffer; FILE *file; protected: virtual int underflow() override { if (!file) return traits_type::eof(); if (gptr() < egptr()) // , return *gptr(); char_type *start = eback(); // , size_t rd = fread(start, sizeof(char_type), buffer.size(), file); // , setg(start, start, start + rd); return rd > 0 ? *gptr() : traits_type::eof(); } public: cfilebuf(size_t _bufsize) : buffer(_bufsize), file(nullptr) { char_type *start = buffer.data(); char_type *end = start + buffer.size(); setg(start, end, end); // eback = start, gptr = end, egptr = end //.. gptr == egptr, } ~cfilebuf(){ close(); } bool open(string fn){ close(); file = fopen(fn.c_str(), "r"); return file != nullptr; } void close(){ if (file){ fclose(file); file = nullptr; } } }; int main(int argc, char **argv){ cfilebuf buf(10); istream in(&buf); string line; buf.open("file.txt"); while (getline(in, line)){ cout << line << endl; } return 0; }
ãã®äŸã¯åçŽã§ãããããå€ãã®æ¬ ç¹ããããŸããããã®äž»ãªãã®ã«ã€ããŠããã«åæããŸãã
é«åºŠãªæ©èœ
åã®ã»ã¯ã·ã§ã³ã§ååŸããã¹ããªãŒã ã¯ãã§ã«äœ¿çšã§ãããšããäºå®ã«ããããããããããã®å®è£ ã¯äžå®å šã§ãã å®éã«ã¯ãè¿œå ã®æ©èœãå¿ èŠãšããããè€éãªç¶æ³ãçºçããå ŽåããããŸãããããã«ã€ããŠã¯åŸã§èª¬æããŸãã
ãã¡ã€ã«ãããã²ãŒãããã·ãŒã¯ãªããšã·ãŒã¯ãã¹
ãã¡ã€ã«ãæäœããå Žåããã¡ã€ã«å ã®äœçœ®ãä»»æã®å Žæã«ç§»åããå¿ èŠãããå ŽåããããŸãã ãæ³åã®ãšãããäžèšã®äŸã§ã¯ããã¯å®è£ ãããŠããŸããããã¡ã€ã«ã¯äžæ¹åã«ã®ã¿èªã¿åãããæ»ãããšã¯ã§ããããã¡ã€ã«ãåæ€åºããã ãã§ãã ãã®é倧ãªæ¬ é¥ãä¿®æ£ããã«ã¯ã
streambuf
ã¯ã©ã¹ã®æ¬¡ã®ã¡ãœããããªãŒããŒã©ã€ãããå¿ èŠããããŸãã
- streampos seekposïŒstreampos spãopenmode whichïŒ -絶察å€ã§æå®ãããäœçœ®ã«ç§»åããããšãããšãã«åŒã³åºãããŸãã ã·ãŒã±ã³ã¹ã®å
é ããã®äœçœ®ã
æ»ãå€ïŒæåããå Žåãæ°ãã確ç«ãããäœçœ®ãããã§ãªãå Žåã¯-1
ããã©ã«ãã®åäœïŒäœãããã-1ãè¿ããŸãã
- streampos seekoffïŒstreamoff offãseekdir wayãopenmode whichïŒ-wayåŒæ°ã§æå®ãããåºæºç¹ã«å¯ŸããŠæå®ãããäœçœ®ã«ç§»åããããšãããšãã«åŒã³åºãããŸãã
æ»ãå€ïŒæåããå Žåãæ°ãã絶察äœçœ®ãèšå®ããããã§ãªããã°-1
ããã©ã«ãã®åäœïŒäœãããã-1ãè¿ããŸãã
é¢æ°ã§ã¯ãæåã®åŒæ°ïŒäœçœ®ãŸãã¯ãªãã»ããïŒã«å ããŠãããã«2ã€ãããŸãã
- openmodeã¯ã移åãããã€ã³ã¿ãŒã®ã¿ã€ãã§ãïŒ
ios_base::in
ïŒèªã¿åãäœçœ®ïŒããã³ios_base::out
ïŒæžã蟌ã¿äœçœ®ïŒã åŒæ°ã¯ããããã¹ã¯ã§ããããšã«æ³šæããŠãã ããïŒããªãã¡ å€ã®ããããããŸãã¯äž¡æ¹ãäžåºŠã«å«ããããšãã§ããŸãã
- seekdir-çžå¯Ÿã·ããã«äœ¿çšããããã€ã³ã¿ãŒã移åããããã®åç
§ãã€ã³ãã瀺ããŸãã
ios_base::beg
ïŒã¹ããªãŒã ã®å é ããïŒãios_base::cur
ïŒçŸåšã®äœçœ®ããïŒããŸãã¯ios_base::end
ïŒã¹ããªãŒã ã®æ«å°ŸããïŒã®3ã€ã®å€ã®ãããããåãããšãã§ããŸãã
ããã§ããã®ç¥èã身ã«ä»ããŠãäŸ3ã®ãã¡ã€ã«å ã移åããå®è£ ãã©ã®ããã«ãªããæ³åããŠãã ããã
virtual streampos seekpos(streampos sp, ios_base::openmode which) override { if (!(which & ios_base::in)) return streampos(-1); return fill_buffer_from(sp); } virtual streampos seekoff(streamoff off, ios_base::seekdir way, ios_base::openmode which) override { if (!(which & ios_base::in)) return streampos(-1); switch (way){ default: case ios_base::beg: return fill_buffer_from(off, SEEK_SET); case ios_base::cur: return fill_buffer_from(pos_base + gptr() - eback() + off, SEEK_SET); // case ios_base::end: return fill_buffer_from(off, SEEK_END); } }
説æïŒ
pos_base
ãã£ãŒã«ãã«ã¯ãããŒã¿ããããã¡ãŒã«ããŒãããããã¡ã€ã«ã®ãªãã»ãããæ ŒçŽãããŸãã
ãšãŠãã·ã³ãã«ã«èŠããŸãããå®éã«ã¯
fill_buffer_from
é¢æ°ããã¹ãŠã®è€éããåŠçããŸãã ãã®å®è£ ã¯æ¬¡ã®ãšããã§ãã
streampos fill_buffer_from(streampos newpos, int dir = SEEK_SET){ if (!file || fseek(file, newpos, dir) == -1) return -1; long pos = ftell(file); if (pos < 0) return -1; pos_base = pos; char_type *start = eback(); size_t rd = fread(start, sizeof(char_type), buffer.size(), file); setg(start, start, start + rd); return rd > 0 && pos_base >= 0 ? pos_base : streampos(-1); }
ãã®é¢æ°ã¯ããã¡ã€ã«å ã®ãã€ã³ã¿ãŒãæå®ãããäœçœ®ã«ç§»åãããããã¡ãŒå šäœãæåããæåŸãŸã§åããããšããŸãã ãã¡ã€ã«ãããããã¡ãè£å ããæäœã¯ããŸãçç£çã§ã¯ãããŸãããããã®äŸã§ã¯å®è£ ãç°¡çŽ åããããã«è¡ãããŸãã ç¬èªã®streambufã®åå«ãå®è£ ããå Žåãæãå¹ççãªãã€ã³ã¿ãŒããžã·ã§ãã³ã°é¢æ°ãäœæããããã«ãããŒã¿ãæäœããè€éããç¥ã£ãŠããã§ãããã
ããŠãããã«å ã«é²ã¿ãŸãã
pbackfail-èªã¿åã£ãæåãè¿ããŸã
ã¹ããªãŒã å ã®ä»»æã®å Žæãžã®èªç±ãªç§»åãå¿ èŠãšããªãã¢ã«ãŽãªãºã ããããŸãããèªã¿åãããã³åŠçäžã«ãããã€ãã®æåïŒéåžž1ã3ïŒãã¹ããªãŒã ã«æ»ãããã«æ±ããããå ŽåããããŸãã ãã®ããã
istream
ã¯
unget()
ããã³
putback(character)
ã¡ãœããããããŸãã
streambuf
ã¯ã©ã¹
streambuf
ã¯ãã¹ããªãŒã ã«è¿ãããæåããããã¡å ã®åã®æåãšäžèŽããå Žåãè¿œå ã®åŒã³åºãã¯çºçããŸããã ãã ããæåãäžèŽããªãã£ãå ŽåããŸãã¯ãããã¡ãã€ã³ã¿ãæåã«ãã£ãå Žåããã®ç¶æ³ãåŠçã§ããé¢æ°ãåŒã³åºãããŸãã
- int pbackfailïŒint cïŒ -ã¹ããªãŒã ã«è¿ãããæå
c
ããããã¡ãŒã®åã®äœçœ®ã«ããæåãšäžèŽããªãïŒãŸãã¯ååšããªãïŒãšãã«åŒã³åºãããŸãã
æ»ãå€ïŒå€±æããå Žåã«intã«ãã£ã¹ããããã¹ããªãŒã ã«è¿ãããæåã®ã³ãŒã-EOFã
ããã©ã«ãã®åäœïŒäœããããEOFãè¿ããŸãã
次ã«ã
pbackfail
ãå®è£ ããŸãã
virtual int pbackfail(int c) override { // if (pos_base <= 0 || gptr() > eback()) return traits_type::eof(); // , if (fill_buffer_from(pos_base - 1L) == -1) return traits_type::eof(); if (*gptr() != c){ gbump(1); return traits_type::eof(); } return *gptr(); }
å ã»ã©èšã£ãããã«ããã®äŸã§ã¯ãããã©ãŒãã³ã¹ã¯ã²ã©ããªããŸãã ã»ãŒãã¹ãŠã®
pbackfail
åŒã³åºã
pbackfail
ããŒã¿ã¯1æåã ãïŒåã®æåïŒã®ããã«ãã¡ã€ã«ãããããã¡ãŒã«åèªã¿åããããŸãã ãã ãããã®èšäºã®ç®çã¯ãå®è£ ã®ããã©ãŒãã³ã¹ã競ãã®ã§ã¯ãªãããã®ä»çµã¿ãç解ããããšã§ãã
äŸ4-æåãé 眮ããŠè¿ããã¡ã€ã«ãèªã¿åã
ããã§ã¯ãåã®ã»ã¯ã·ã§ã³ã§å®è£ ãããç·šéãè¿œå ãããã³ãŒããšããã®æ©èœã®äœ¿çšäŸã説æãšãšãã«è¿œå ãããŠããŸãã
ã³ãŒã
#include <iostream> #include <string> #include <vector> #include <cstdio> #include <cstdlib> using namespace std; class cfilebuf : public streambuf { private: vector<char_type> buffer; FILE *file; streampos pos_base; // eback streampos fill_buffer_from(streampos newpos, int dir = SEEK_SET) { if (!file || fseek(file, newpos, dir) == -1) return -1; // eback long pos = ftell(file); if (pos < 0) return -1; pos_base = pos; char_type *start = eback(); // , size_t rd = fread(start, sizeof(char_type), buffer.size(), file); // , setg(start, start, start + rd); return rd > 0 && pos_base >= 0 ? pos_base : streampos(-1); } protected: virtual int underflow() override { if (!file) return traits_type::eof(); if (gptr() < egptr()) // , return *gptr(); streampos pos; if (pos_base < 0) { // , pos = fill_buffer_from(0); } else { // pos = fill_buffer_from(pos_base + egptr() - eback()); } return pos != streampos(-1) ? *gptr() : traits_type::eof(); } // ios_base::in // ios_base::out ( ) virtual streampos seekpos(streampos sp, ios_base::openmode which) override { if (!(which & ios_base::in)) return streampos(-1); return fill_buffer_from(sp); } // : , virtual streampos seekoff(streamoff off, ios_base::seekdir way, ios_base::openmode which) override { if (!(which & ios_base::in)) return streampos(-1); switch (way) { default: case ios_base::beg: return fill_buffer_from(off, SEEK_SET); case ios_base::cur: return fill_buffer_from(pos_base + gptr() - eback() + off); // case ios_base::end: return fill_buffer_from(off, SEEK_END); } } virtual int pbackfail(int c) override { // gptr > eback, , // , if (pos_base <= 0 || gptr() > eback()) return traits_type::eof(); // , if (fill_buffer_from(pos_base - streampos(1L)) == streampos(-1)) return traits_type::eof(); if (*gptr() != c) { gbump(1); // , return traits_type::eof(); } return *gptr(); } public: cfilebuf(size_t _bufsize) : buffer(_bufsize), file(nullptr), pos_base(-1) { char_type *start = buffer.data(); char_type *end = start + buffer.size(); setg(start, end, end); // eback = start, gptr = end, egptr = end } ~cfilebuf() { close(); } bool open(string fn) { close(); file = fopen(fn.c_str(), "r"); return file != nullptr; } void close() { if (file) { fclose(file); file = nullptr; } } }; void read_to_end(istream &in) { string line; while (getline(in, line)) { cout << line << endl; } } int main(int argc, char **argv) { cfilebuf buf(10); istream in(&buf); buf.open("file.txt"); read_to_end(in); in.clear(); // cout << endl << endl << "Read last 6 symbols:" << endl; in.seekg(-5, ios_base::end); // , 5 in.seekg(-1, ios_base::cur); // 6, :) read_to_end(in); in.clear(); cout << endl << endl << "Read all again:" << endl; in.seekg(0); read_to_end(in); in.clear(); in.seekg(2); // 3- ( 2-) in.get(); in.putback('b'); in.putback('a'); // pbackfail() in.putback('H'); string word; in >> word; cout << endl << endl << "Read word after putback(): " << word << endl; return 0; }
ãã®ä»ã®æ©èœ
ãã®èšäºã§èª¬æããæ©èœã«å ããŠãä»ã«ãæ©èœããããŸãã å®è£ ãéåžžã«ç°¡åãªãã®ãããã°ãç¹å®ã®å Žåã«ã®ã¿å¿ èŠãªãã®ãããããã詳现ã«ã¯èæ ®ãããŠããŸããã 以äžã¯ããã®ãããªé¢æ°ã®ãªã¹ããšãããããå¿ èŠãªçç±ã®ç°¡åãªèª¬æã§ãã ãããã®ãã詳现ãªèª¬æã¯ãå ¬åŒããã¥ã¡ã³ãã«ãããŸãïŒãªã³ã¯ã¯èšäºã®æåŸã«ãããŸãïŒã
ä»ã®å©çšå¯èœãªãªãŒããŒã©ã€ãæ¹æ³ïŒ
- imbueïŒïŒ -ãã®é¢æ°ããªãŒããŒã©ã€ããããšãããŸããŸãªãã±ãŒã«ãæäœããŠãèªã¿åãå¯èœããã³æžã蟌ã¿å¯èœãªæåãå€æã§ããŸãã
- setbufïŒïŒ -çµã¿èŸŒã¿ã®ãããã¡ã®ä»£ããã«ã«ã¹ã¿ã ãããã¡ã䜿çšã§ããŸãã ããã©ã«ãã§ã¯ããã®é¢æ°ã¯äœãè¡ããŸãããããã®æ©èœãå®è£
ã«è¿œå ã§ããŸãã
- showmanycïŒïŒ -ãããã¯ããåã«ã¹ããªãŒã ãããŸã èªã¿åããæåæ°ã䜿çšããŠé¢æ°ã«äŒããããšãã§ããŸãã ããã©ã«ãã§ã¯0ãè¿ããŸãïŒã€ãŸããæåæ°ã«é¢ããæ
å ±ã¯ãããŸããïŒã
- xsgetnïŒïŒããã³xsputnïŒïŒã¯ãæ©èœã®ç¹ã§
fread
ããã³fwrite
䌌ããããŒã¿ã®åºäœãããã¯ãèªã¿æžãããããã®ã¡ãœããã®ãã¢ã§ãã çªç¶ãããã¯ã®èªã¿åããŸãã¯æžã蟌ã¿ãè¡ãå Žåãæåããšã®åŠçãããå¹ççãªã¢ã«ãŽãªãºã ãå®è£ ã§ããå Žåã¯ããããã®æ¹æ³ãé©ããŠããŸãã
ãŸãããããžã§ã¯ãã§ã¯ã1æåã®ãµã€ãºã1ãã€ããè¶ ããå Žåã«ç¶æ³ãçºçããå ŽåããããŸãã ãã®å Žåããã³ãã¬ãŒãã¯ã©ã¹
basic_streambuf
ããç¶æ¿ããå¿ èŠãªæåã¿ã€ãã䜿çšããå¿ èŠããããŸãã
char_type
ã
int_type
ã
pos_type
ãªã©ã®ã¿ã€ãã®ãšã€ãªã¢ã¹ã¯ãå®è£ ã«åœ¹ç«ã¡ãŸãã
streambuf
ã©ã€ãã©ãªå®è£ ã
streambuf
ããã¿ã€ãã«åžžã«å¯Ÿå¿ããããããããã䜿çšããããšãã
streambuf
ã
ãããã«
æšæºã©ã€ãã©ãªã¯ãç¬èªã®ã¹ã¬ãããæè»ãã€çç£çã«å®è£ ããããã®å¹ åºãæ©èœãæäŸããŸãã ãã ããå®éã®ããã©ãŒãã³ã¹ã¯ããªãŒããŒã©ã€ããããã¡ãœããã®ç¹å®ã®å®è£ ã«åžžã«äŸåããããšã«æ³šæããŠãã ããã
åç §è³æ
- https://github.com/iassasin/streambuf_examples-githubã®èšäºã®ãã¹ãŠã®äŸ;
- http://www.cplusplus.com/reference/streambuf/streambuf/-streambufã«é¢ããå ¬åŒããã¥ã¡ã³ãã
- http://www.mr-edd.co.uk/blog/beginners_guide_streambuf-ããã€ãã®äŸã®ã€ã©ã¹ããã¢ã€ãã¢ãåçšãããè±èªã®èšäºã