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.

444 lines
8.6 KiB

  1. /***
  2. *streamb.cpp - fuctions for streambuf class.
  3. *
  4. * Copyright (c) 1990-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Functions for streambuf class.
  8. *
  9. *Revision History:
  10. * 09-10-90 WAJ Initial version.
  11. * 07-02-91 KRS Initial version completed.
  12. * 08-20-91 KRS Treat chars as unsigned; fix sgetn() function.
  13. * 09-06-91 KRS Do a sync() in ~streambuf before destroying buffer.
  14. * 11-18-91 KRS Split off stream1.cxx for input-specific code.
  15. * 12-09-91 KRS Fix up xsputn/xsgetn usage.
  16. * 03-03-92 KRS Added mthread lock init calls to constructors.
  17. * 06-02-92 KRS CAV #1745: Don't confuse 0xFF with EOF in xsputn()
  18. * call to overflow().
  19. * 04-06-93 JWM Changed constructors to enable locking by default.
  20. * 10-28-93 SKS Add call to _mttermlock() in streamb::~streamb to clean
  21. * up o.s. resources associated with a Critical Section.
  22. * 09-06-94 CFW Replace MTHREAD with _MT.
  23. * 01-12-95 CFW Debug CRT allocs.
  24. * 03-17-95 CFW Change debug delete scheme.
  25. * 03-21-95 CFW Remove _delete_crt.
  26. * 06-14-95 CFW Comment cleanup.
  27. * 03-04-98 RKP Restrict size to 2GB on 64 bit systems.
  28. *
  29. *******************************************************************************/
  30. #include <cruntime.h>
  31. #include <internal.h>
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #include <iostream.h>
  35. #include <dbgint.h>
  36. #pragma hdrstop
  37. #ifndef BUFSIZ
  38. #define BUFSIZ 512
  39. #endif
  40. /***
  41. *streambuf::streambuf() -
  42. *
  43. *Purpose:
  44. * Default constructor.
  45. *
  46. *Entry:
  47. *
  48. *Exit:
  49. *
  50. *Exceptions:
  51. *
  52. *******************************************************************************/
  53. streambuf::streambuf()
  54. {
  55. _fAlloc = 0;
  56. _fUnbuf = 0;
  57. x_lastc = EOF;
  58. _base = NULL;
  59. _ebuf = NULL;
  60. _pbase = NULL;
  61. _pptr = NULL;
  62. _epptr = NULL;
  63. _eback = NULL;
  64. _gptr = NULL;
  65. _egptr = NULL;
  66. #ifdef _MT
  67. LockFlg = -1; // default is now : locking
  68. _mtlockinit(lockptr());
  69. #endif /* _MT */
  70. }
  71. /***
  72. *streambuf::streambuf(char* pBuf, int cbBuf) -
  73. *
  74. *Purpose:
  75. * Constructor which specifies a buffer area.
  76. *
  77. *Entry:
  78. *
  79. *Exit:
  80. *
  81. *Exceptions:
  82. *
  83. *******************************************************************************/
  84. streambuf::streambuf( char* pBuf, int cbBuf )
  85. {
  86. _fAlloc = 0;
  87. _fUnbuf = 0;
  88. x_lastc = EOF;
  89. _base = pBuf;
  90. _ebuf = pBuf + (unsigned)cbBuf;
  91. _pbase = NULL;
  92. _pptr = NULL;
  93. _epptr = NULL;
  94. _eback = NULL;
  95. _gptr = NULL;
  96. _egptr = NULL;
  97. if( pBuf == NULL || cbBuf == 0 ){
  98. _fUnbuf = 1;
  99. _base = NULL;
  100. _ebuf = NULL;
  101. }
  102. #ifdef _MT
  103. LockFlg = -1; // default is now : locking
  104. _mtlockinit(lockptr());
  105. #endif /* _MT */
  106. }
  107. /***
  108. *virtual streambuf::~streambuf() -
  109. *
  110. *Purpose:
  111. * Destructor.
  112. *
  113. *Entry:
  114. *
  115. *Exit:
  116. *
  117. *Exceptions:
  118. *
  119. *******************************************************************************/
  120. streambuf::~streambuf()
  121. {
  122. #ifdef _MT
  123. _mtlockterm(lockptr());
  124. #endif /* _MT */
  125. sync(); // make sure buffer empty before possibly destroying it
  126. if( (_fAlloc) && (_base) )
  127. delete _base;
  128. }
  129. /***
  130. * virtual streambuf * streambuf::setbuf(char * p, int len) -
  131. *
  132. *Purpose:
  133. * Offers the array at p with len bytes to be used as a reserve area.
  134. *
  135. *Entry:
  136. *
  137. *Exit:
  138. *
  139. *Exceptions:
  140. *
  141. *******************************************************************************/
  142. streambuf * streambuf::setbuf(char * p, int len)
  143. {
  144. if (!_base)
  145. {
  146. if ((!p) || (!len))
  147. _fUnbuf = 1; // mark as unbuffered
  148. else
  149. {
  150. _base = p;
  151. _ebuf = p + (unsigned)len;
  152. _fUnbuf = 0;
  153. }
  154. return (this);
  155. }
  156. return((streambuf *)NULL);
  157. }
  158. /***
  159. *virtual int streambuf::xsputn( char* pBuf, int cbBuf ) -
  160. *
  161. *Purpose:
  162. * Tries to output cbBuf characters. Returns number of characters
  163. * that were outputted.
  164. *
  165. *Entry:
  166. *
  167. *Exit:
  168. *
  169. *Exceptions:
  170. *
  171. *******************************************************************************/
  172. int streambuf::xsputn( const char* pBuf, int cbBuf )
  173. {
  174. int cbOut;
  175. for (cbOut = 0; cbBuf--; cbOut++)
  176. {
  177. if ((_fUnbuf) || (_pptr >= _epptr))
  178. {
  179. if (overflow((unsigned char)*pBuf)==EOF) // 0-extend 0xFF !=EOF
  180. break;
  181. }
  182. else
  183. {
  184. *(_pptr++) = *pBuf;
  185. }
  186. pBuf++;
  187. }
  188. return cbOut;
  189. }
  190. /***
  191. *virtual int streambuf::xsgetn( char* pBuf, int cbBuf ) -
  192. *
  193. *Purpose:
  194. * Tries to input cbBuf characters. Returns number of characters
  195. * that were read from streambuf.
  196. *
  197. *Entry:
  198. *
  199. *Exit:
  200. *
  201. *Exceptions:
  202. *
  203. *******************************************************************************/
  204. // #pragma intrinsic(memcpy,__min)
  205. int streambuf::xsgetn( char * pBuf, int cbBuf)
  206. {
  207. int count;
  208. int cbIn = 0;
  209. if (_fUnbuf)
  210. {
  211. if (x_lastc==EOF)
  212. x_lastc=underflow();
  213. while (cbBuf--)
  214. {
  215. if (x_lastc==EOF)
  216. break;
  217. *(pBuf++) = (char)x_lastc;
  218. cbIn++;
  219. x_lastc=underflow();
  220. }
  221. }
  222. else
  223. {
  224. while (cbBuf)
  225. {
  226. if (underflow()==EOF) // make sure something to read
  227. break;
  228. count = __min((int)(egptr() - gptr()),cbBuf);
  229. if (count>0)
  230. {
  231. memcpy(pBuf,gptr(),count);
  232. pBuf += count;
  233. _gptr += count;
  234. cbIn += count;
  235. cbBuf -= count;
  236. }
  237. }
  238. }
  239. return cbIn;
  240. }
  241. /***
  242. *virtual int streambuf::sync() -
  243. *
  244. *Purpose:
  245. * Tries to flush all data in put area and give back any data in the
  246. * get area (if possible), leaving both areas empty on exit.
  247. * Default behavior is to fail unless buffers empty.
  248. *
  249. *Entry:
  250. *
  251. *Exit:
  252. *
  253. *Exceptions:
  254. *
  255. *******************************************************************************/
  256. int streambuf::sync()
  257. {
  258. if ((gptr() <_egptr) || (_pptr > _pbase))
  259. {
  260. return EOF;
  261. }
  262. return 0;
  263. }
  264. /***
  265. *int streambuf::allocate() -
  266. *
  267. *Purpose:
  268. * Tries to set up a Reserve Area. If one already exists, or if
  269. * unbuffered, just returns 0.
  270. *
  271. *Entry:
  272. *
  273. *Exit:
  274. *
  275. *Exceptions:
  276. *
  277. *******************************************************************************/
  278. int streambuf::allocate()
  279. {
  280. if ((_fUnbuf) || (_base))
  281. return 0;
  282. if (doallocate()==EOF) return EOF;
  283. return(1);
  284. }
  285. /***
  286. *virtual int streambuf::doallocate() -
  287. *
  288. *Purpose:
  289. * Tries to set up a Reserve Area. Returns EOF if unsuccessful.
  290. *
  291. *Entry:
  292. *
  293. *Exit:
  294. *
  295. *Exceptions:
  296. *
  297. *******************************************************************************/
  298. int streambuf::doallocate()
  299. {
  300. char * tptr;
  301. if (!( tptr = _new_crt char[BUFSIZ]))
  302. return(EOF);
  303. setb(tptr, tptr + BUFSIZ, 1);
  304. return(1);
  305. }
  306. /***
  307. *void streambuf::setb(char * b, char * eb, int a = 0) -
  308. *
  309. *Purpose:
  310. * Sets up reserve area.
  311. *
  312. *Entry:
  313. *
  314. *Exit:
  315. *
  316. *Exceptions:
  317. *
  318. *******************************************************************************/
  319. void streambuf::setb(char * b, char * eb, int a )
  320. {
  321. if ((_fAlloc) && (_base))
  322. delete _base;
  323. _base = b;
  324. _fAlloc = a;
  325. _ebuf = eb;
  326. }
  327. /***
  328. *virtual streampos streambuf::seekoff(streamoff off, ios::seekdir dir, int mode)
  329. *
  330. *Purpose:
  331. * seekoff member function. seek forward or backward in the stream.
  332. * Default behavior: returns EOF.
  333. *
  334. *Entry:
  335. * off = offset (+ or -) to seek by
  336. * dir = one of ios::beg, ios::end, or ios::cur.
  337. * mode = ios::in or ios::out.
  338. *
  339. *Exit:
  340. * Returns new file position or EOF if error or seeking not supported.
  341. *
  342. *Exceptions:
  343. * Returns EOF if error.
  344. *
  345. *******************************************************************************/
  346. streampos streambuf::seekoff(streamoff,ios::seek_dir,int)
  347. {
  348. return EOF;
  349. }
  350. /***
  351. *virtual streampos streambuf::seekpos(streampos pos, int mode) -
  352. *
  353. *Purpose:
  354. * seekoff member function. seek to absolute file position.
  355. * Default behavior: returns seekoff(streamoff(pos), ios::beg, mode).
  356. *
  357. *Entry:
  358. * pos = absolute offset to seek to
  359. * mode = ios::in or ios::out.
  360. *
  361. *Exit:
  362. * Returns new file position or EOF if error or seeking not supported.
  363. *
  364. *Exceptions:
  365. * Returns EOF if error.
  366. *
  367. *******************************************************************************/
  368. streampos streambuf::seekpos(streampos pos,int mode)
  369. {
  370. return seekoff(streamoff(pos), ios::beg, mode);
  371. }
  372. /***
  373. *virtual int streambuf::pbackfail(int c) - handle failure of putback
  374. *
  375. *Purpose:
  376. * pbackfail member function. Handle exception of pback function.
  377. * Default behavior: returns EOF. See spec. for details.
  378. *
  379. * Note: the following implementation gives default behavior, thanks
  380. * to the default seekoff, but also supports derived classes properly:
  381. *
  382. *Entry:
  383. * c = character to put back
  384. *
  385. *Exit:
  386. * Returns c if successful or EOF on error.
  387. *
  388. *Exceptions:
  389. * Returns EOF if error. Behavior is undefined if c was not the
  390. * previous character in the stream.
  391. *
  392. *******************************************************************************/
  393. int streambuf::pbackfail(int c)
  394. {
  395. if (eback()<gptr()) return sputbackc((char)c);
  396. if (seekoff( -1, ios::cur, ios::in)==EOF) // always EOF for streambufs
  397. return EOF;
  398. if (!unbuffered() && egptr())
  399. {
  400. memmove((gptr()+1),gptr(),(int)(egptr()-(gptr()+1)));
  401. *gptr()=(char)c;
  402. }
  403. return(c);
  404. }