Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
9.8 KiB

  1. // streambuf standard header
  2. #pragma once
  3. #ifndef _STREAMBUF_
  4. #define _STREAMBUF_
  5. #include <xiosbase>
  6. #pragma pack(push,8)
  7. #pragma warning(push,3)
  8. _STD_BEGIN
  9. // TEMPLATE CLASS basic_streambuf
  10. template<class _Elem, class _Traits>
  11. class basic_streambuf
  12. { // control read/write buffers
  13. basic_streambuf(const basic_streambuf<_Elem, _Traits>&); // not defined
  14. basic_streambuf<_Elem, _Traits>&
  15. operator=(const basic_streambuf<_Elem, _Traits>&); // not defined
  16. protected:
  17. basic_streambuf()
  18. : _Plocale(_NEW_CRT locale)
  19. { // construct with no buffers
  20. _Init();
  21. }
  22. basic_streambuf(_Uninitialized)
  23. { // construct uninitialized
  24. }
  25. public:
  26. typedef basic_streambuf<_Elem, _Traits> _Myt;
  27. typedef _Elem char_type;
  28. typedef _Traits traits_type;
  29. virtual ~basic_streambuf()
  30. { // destroy the object
  31. _DELETE_CRT(_Plocale);
  32. }
  33. typedef typename _Traits::int_type int_type;
  34. typedef typename _Traits::pos_type pos_type;
  35. typedef typename _Traits::off_type off_type;
  36. pos_type pubseekoff(off_type _Off, ios_base::seekdir _Way,
  37. ios_base::openmode _Mode = ios_base::in | ios_base::out)
  38. { // change position by _Off, according to _Way, _Mode
  39. return (seekoff(_Off, _Way, _Mode));
  40. }
  41. pos_type pubseekoff(off_type _Off, ios_base::seek_dir _Way,
  42. ios_base::open_mode _Mode)
  43. { // change position by _Off, according to _Way, _Mode (old style)
  44. return (pubseekoff(_Off, (ios_base::seekdir)_Way,
  45. (ios_base::openmode)_Mode));
  46. }
  47. pos_type pubseekpos(pos_type _Pos,
  48. ios_base::openmode _Mode = ios_base::in | ios_base::out)
  49. { // change position to _Pos, according to _Mode
  50. return (seekpos(_Pos, _Mode));
  51. }
  52. pos_type pubseekpos(pos_type _Pos, ios_base::open_mode _Mode)
  53. { // change position to _Pos, according to _Mode (old style)
  54. return (seekpos(_Pos, (ios_base::openmode)_Mode));
  55. }
  56. _Myt *pubsetbuf(_Elem *_Buffer, streamsize _Count)
  57. { // offer _Buffer to external agent
  58. return (setbuf(_Buffer, _Count));
  59. }
  60. locale pubimbue(const locale &_Newlocale)
  61. { // set locale to argument
  62. locale _Oldlocale = *_Plocale;
  63. imbue(_Newlocale);
  64. *_Plocale = _Newlocale;
  65. return (_Oldlocale);
  66. }
  67. locale getloc() const
  68. { // get locale
  69. return (*_Plocale);
  70. }
  71. streamsize in_avail()
  72. { // return count of buffered input characters
  73. return (gptr() != 0 && gptr() < egptr()
  74. ? (streamsize)(egptr() - gptr()) : showmanyc());
  75. }
  76. int pubsync()
  77. { // synchronize with external agent
  78. return (sync());
  79. }
  80. int_type sbumpc()
  81. { // get a character and point past it
  82. return (gptr() != 0 && gptr() < egptr()
  83. ? _Traits::to_int_type(*_Gninc()) : uflow());
  84. }
  85. int_type sgetc()
  86. { // get a character and don't point past it
  87. return (gptr() != 0 && gptr() < egptr()
  88. ? _Traits::to_int_type(*gptr()) : underflow());
  89. }
  90. streamsize sgetn(_Elem *_Ptr, streamsize _Count)
  91. { // get up to _Count characters into array beginning at _Ptr
  92. return (xsgetn(_Ptr, _Count));
  93. }
  94. int_type snextc()
  95. { // point to next character and return it
  96. return (_Traits::eq_int_type(_Traits::eof(), sbumpc())
  97. ? _Traits::eof() : sgetc());
  98. }
  99. int_type sputbackc(_Elem _Ch)
  100. { // put back _Ch
  101. return (gptr() != 0 && eback() < gptr()
  102. && _Traits::eq(_Ch, gptr()[-1])
  103. ? _Traits::to_int_type(*_Gndec())
  104. : pbackfail(_Traits::to_int_type(_Ch)));
  105. }
  106. void stossc()
  107. { // point past a character
  108. if (gptr() != 0 && gptr() < egptr())
  109. _Gninc();
  110. else
  111. uflow();
  112. }
  113. int_type sungetc()
  114. { // back up one position
  115. return (gptr() != 0 && eback() < gptr()
  116. ? _Traits::to_int_type(*_Gndec()) : pbackfail());
  117. }
  118. int_type sputc(_Elem _Ch)
  119. { // put a character
  120. return (pptr() != 0 && pptr() < epptr()
  121. ? _Traits::to_int_type(*_Pninc() = _Ch)
  122. : overflow(_Traits::to_int_type(_Ch)));
  123. }
  124. streamsize sputn(const _Elem *_Ptr, streamsize _Count)
  125. { // put _Count characters from array beginning at _Ptr
  126. return (xsputn(_Ptr, _Count));
  127. }
  128. void _Lock()
  129. { // set the thread lock
  130. _Mylock._Lock();
  131. }
  132. void _Unlock()
  133. { // clear the thread lock
  134. _Mylock._Unlock();
  135. }
  136. protected:
  137. _Elem *eback() const
  138. { // return beginning of read buffer
  139. return (*_IGfirst);
  140. }
  141. _Elem *gptr() const
  142. { // return current position in read buffer
  143. return (*_IGnext);
  144. }
  145. _Elem *pbase() const
  146. { // return beginning of write buffer
  147. return (*_IPfirst);
  148. }
  149. _Elem *pptr() const
  150. { // return current position in write buffer
  151. return (*_IPnext);
  152. }
  153. _Elem *egptr() const
  154. { // return end of read buffer
  155. return (*_IGnext + *_IGcount);
  156. }
  157. void gbump(int _Off)
  158. { // alter current position in read buffer by _Off
  159. *_IGcount -= _Off;
  160. *_IGnext += _Off;
  161. }
  162. void setg(_Elem *_First, _Elem *_Next, _Elem *_Last)
  163. { // set pointers for read buffer
  164. *_IGfirst = _First;
  165. *_IGnext = _Next;
  166. *_IGcount = (int)(_Last - _Next);
  167. }
  168. _Elem *epptr() const
  169. { // return end of write buffer
  170. return (*_IPnext + *_IPcount);
  171. }
  172. _Elem *_Gndec()
  173. { // decrement current position in read buffer
  174. ++*_IGcount;
  175. return (--*_IGnext);
  176. }
  177. _Elem *_Gninc()
  178. { // increment current position in read buffer
  179. --*_IGcount;
  180. return ((*_IGnext)++);
  181. }
  182. void pbump(int _Off)
  183. { // alter current position in write buffer by _Off
  184. *_IPcount -= _Off;
  185. *_IPnext += _Off;
  186. }
  187. void setp(_Elem *_First, _Elem *_Last)
  188. { // set pointers for write buffer
  189. *_IPfirst = _First;
  190. *_IPnext = _First;
  191. *_IPcount = (int)(_Last - _First);
  192. }
  193. void setp(_Elem *_First, _Elem *_Next, _Elem *_Last)
  194. { // set pointers for write buffer, extended version
  195. *_IPfirst = _First;
  196. *_IPnext = _Next;
  197. *_IPcount = (int)(_Last - _Next);
  198. }
  199. _Elem *_Pninc()
  200. { // decrement current position in write buffer
  201. --*_IPcount;
  202. return ((*_IPnext)++);
  203. }
  204. void _Init()
  205. { // initialize buffer parameters for no buffers
  206. _IGfirst = &_Gfirst, _IPfirst = &_Pfirst;
  207. _IGnext = &_Gnext, _IPnext = &_Pnext;
  208. _IGcount = &_Gcount, _IPcount = &_Pcount;
  209. setp(0, 0), setg(0, 0, 0);
  210. }
  211. void _Init(_Elem **_Gf, _Elem **_Gn, int *_Gc,
  212. _Elem **_Pf, _Elem **_Pn, int *_Pc)
  213. { // initialize buffer parameters as specified
  214. _IGfirst = _Gf, _IPfirst = _Pf;
  215. _IGnext = _Gn, _IPnext = _Pn;
  216. _IGcount = _Gc, _IPcount = _Pc;
  217. }
  218. virtual int_type overflow(int_type = _Traits::eof())
  219. { // put a character to stream (always fail)
  220. return (_Traits::eof());
  221. }
  222. virtual int_type pbackfail(int_type = _Traits::eof())
  223. { // put a character back to stream (always fail)
  224. return (_Traits::eof());
  225. }
  226. virtual streamsize showmanyc()
  227. { // return count of input characters
  228. return (0);
  229. }
  230. virtual int_type underflow()
  231. { // get a character from stream, but don't point past it
  232. return (_Traits::eof());
  233. }
  234. virtual int_type uflow()
  235. { // get a character from stream, point past it
  236. return (_Traits::eq_int_type(_Traits::eof(), underflow())
  237. ? _Traits::eof() : _Traits::to_int_type(*_Gninc()));
  238. }
  239. virtual streamsize xsgetn(_Elem * _Ptr, streamsize _Count)
  240. { // get _Count characters from stream
  241. int_type _Meta;
  242. streamsize _Size, _Copied;
  243. for (_Copied = 0; 0 < _Count; )
  244. if (gptr() != 0 && 0 < (_Size = (streamsize)(egptr() - gptr())))
  245. { // copy from read buffer
  246. if (_Count < _Size)
  247. _Size = _Count;
  248. _Traits::copy(_Ptr, gptr(), _Size);
  249. _Ptr += _Size;
  250. _Copied += _Size;
  251. _Count -= _Size;
  252. gbump((int)_Size);
  253. }
  254. else if (_Traits::eq_int_type(_Traits::eof(), _Meta = uflow()))
  255. break; // end of file, quit
  256. else
  257. { // get a single character
  258. *_Ptr++ = _Traits::to_char_type(_Meta);
  259. ++_Copied;
  260. --_Count;
  261. }
  262. return (_Copied);
  263. }
  264. virtual streamsize xsputn(const _Elem *_Ptr, streamsize _Count)
  265. { // put _Count characters to stream
  266. streamsize _Size, _Copied;
  267. for (_Copied = 0; 0 < _Count; )
  268. if (pptr() != 0 && 0 < (_Size = (streamsize)(epptr() - pptr())))
  269. { // copy to write buffer
  270. if (_Count < _Size)
  271. _Size = _Count;
  272. _Traits::copy(pptr(), _Ptr, _Size);
  273. _Ptr += _Size;
  274. _Copied += _Size;
  275. _Count -= _Size;
  276. pbump((int)_Size);
  277. }
  278. else if (_Traits::eq_int_type(_Traits::eof(),
  279. overflow(_Traits::to_int_type(*_Ptr))))
  280. break; // single character put failed, quit
  281. else
  282. { // count character successfully put
  283. ++_Ptr;
  284. ++_Copied;
  285. --_Count;
  286. }
  287. return (_Copied);
  288. }
  289. virtual pos_type seekoff(off_type, ios_base::seekdir,
  290. ios_base::openmode = ios_base::in | ios_base::out)
  291. { // change position by offset, according to way and mode
  292. return (streampos(_BADOFF));
  293. }
  294. virtual pos_type seekpos(pos_type,
  295. ios_base::openmode = ios_base::in | ios_base::out)
  296. { // change to specified position, according to mode
  297. return (streampos(_BADOFF));
  298. }
  299. virtual _Myt *setbuf(_Elem *, streamsize)
  300. { // offer buffer to external agent (do nothing)
  301. return (this);
  302. }
  303. virtual int sync()
  304. { // synchronize with external agent (do nothing)
  305. return (0);
  306. }
  307. virtual void imbue(const locale&)
  308. { // set locale to argument (do nothing)
  309. }
  310. private:
  311. _Mutex _Mylock; // thread lock
  312. _Elem *_Gfirst; // beginning of read buffer
  313. _Elem *_Pfirst; // beginning of write buffer
  314. _Elem **_IGfirst; // pointer to beginning of read buffer
  315. _Elem **_IPfirst; // pointer to beginning of write buffer
  316. _Elem *_Gnext; // current position in read buffer
  317. _Elem *_Pnext; // current position in write buffer
  318. _Elem **_IGnext; // pointer to current position in read buffer
  319. _Elem **_IPnext; // pointer to current position in write buffer
  320. int _Gcount; // length of read buffer
  321. int _Pcount; // length of write buffer
  322. int *_IGcount; // pointer to length of read buffer
  323. int *_IPcount; // pointer to length of write buffer
  324. locale *_Plocale; // pointer to imbued locale object
  325. };
  326. #ifdef _DLL_CPPLIB
  327. template class _CRTIMP2 basic_streambuf<char, char_traits<char> >;
  328. template class _CRTIMP2 basic_streambuf<wchar_t, char_traits<wchar_t> >;
  329. #endif // _DLL_CPPLIB
  330. _STD_END
  331. #pragma warning(pop)
  332. #pragma pack(pop)
  333. #endif /* _STREAMBUF_ */
  334. /*
  335. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  336. * Consult your license regarding permissions and restrictions.
  337. V3.10:0009 */