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
10 KiB

  1. /***
  2. *strstream.cpp - definitions for strstreambuf, strstream
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * This file defines the functions used by strstream and strstrembuf
  8. * classes.
  9. *
  10. *Revision History:
  11. * 08-14-91 KRS Initial version.
  12. * 08-23-91 KRS Initial version completed.
  13. * 09-03-91 KRS Fix typo in strstreambuf::seekoff(,ios::in,)
  14. * 09-04-91 KRS Added virtual sync() to fix flush(). Fix underflow().
  15. * 09-05-91 KRS Change str() and freeze() to match spec.
  16. * 09-19-91 KRS Add calls to delbuf(1) in constructors.
  17. * 10-24-91 KRS Avoid virtual calls from virtual functions.
  18. * 01-12-95 CFW Debug CRT allocs, add debug support for freeze();
  19. * 03-17-95 CFW Change debug delete scheme.
  20. * 03-21-95 CFW Remove _delete_crt.
  21. * 05-08-95 CFW Grow buffer by x_bufmin rather than 1.
  22. * 06-14-95 CFW Comment cleanup.
  23. * 08-08-95 GJF Made calls to _CrtSetDbgBlockType conditional on
  24. * x_static.
  25. * 09-05-96 RDK Add strstreambuf initializer with unsigned arguments.
  26. * 03-04-98 RKP Restricted size to 2GB with 64 bits.
  27. * 01-05-99 GJF Changes for 64-bit size_t.
  28. *
  29. *******************************************************************************/
  30. #include <cruntime.h>
  31. #include <internal.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <strstrea.h>
  35. #include <dbgint.h>
  36. #pragma hdrstop
  37. /***
  38. *strstreambuf::strstreambuf() - default constructor for strstreambuf
  39. *
  40. *Purpose:
  41. * Default constructor for class strstreambuf.
  42. *
  43. *Entry:
  44. *
  45. *Exit:
  46. *
  47. *Exceptions:
  48. *
  49. *******************************************************************************/
  50. strstreambuf::strstreambuf()
  51. : streambuf()
  52. {
  53. x_bufmin = x_dynamic = 1;
  54. x_static = 0;
  55. x_alloc = (0);
  56. x_free = (0);
  57. }
  58. /***
  59. *strstreambuf::strstreambuf(int n) - constructor for strstreambuf
  60. *
  61. *Purpose:
  62. * Constructor for class strstreambuf. Created in dynamic mode.
  63. *
  64. *Entry:
  65. * n = minimum size for initial allocation.
  66. *
  67. *Exit:
  68. *
  69. *Exceptions:
  70. *
  71. *******************************************************************************/
  72. strstreambuf::strstreambuf(int n)
  73. : streambuf()
  74. {
  75. x_dynamic = 1;
  76. x_static = 0;
  77. x_alloc = (0);
  78. x_free = (0);
  79. setbuf(0,n);
  80. }
  81. /***
  82. *strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*)) - constructor for strstreambuf
  83. *
  84. *Purpose:
  85. * Construct a strstreambuf in dynamic mode. Use specified allocator
  86. * and deallocator instead of new and delete.
  87. *
  88. *Entry:
  89. * *_a = allocator: void * (*_a)(long)
  90. * *_f = deallocator: void (*_f)(void *)
  91. *
  92. *Exit:
  93. *
  94. *Exceptions:
  95. *
  96. *******************************************************************************/
  97. strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*))
  98. : streambuf()
  99. {
  100. x_dynamic = x_bufmin = 1;
  101. x_static = 0;
  102. x_alloc = _a;
  103. x_free = _f;
  104. }
  105. /***
  106. *strstreambuf::strstreambuf(unsigned char * ptr, int size, unsigned char * pstart = 0)
  107. *strstreambuf::strstreambuf(char * ptr, int size, char * pstart = 0) -
  108. *
  109. *Purpose:
  110. * Construct a strstreambuf in static mode. Buffer used is of 'size'
  111. * bytes. If 'size' is 0, uses a null-terminated string as buffer.
  112. * If negative, size is considered infinite. Get starts at ptr.
  113. * If pstart!=0, put buffer starts at pstart. Otherwise, no output.
  114. *
  115. *Entry:
  116. * [unsigned] char * ptr; pointer to buffer base()
  117. * int size; size of buffer, or 0= use strlen to calculate size
  118. * or if negative size is 'infinite'.
  119. * [unsigned] char * pstart; pointer to put buffer of NULL if none.
  120. *
  121. *Exit:
  122. *
  123. *Exceptions:
  124. *
  125. *******************************************************************************/
  126. strstreambuf::strstreambuf(unsigned char * ptr, int size, unsigned char * pstart)
  127. : streambuf()
  128. {
  129. strstreambuf((char *)ptr, size, (char *)pstart);
  130. }
  131. strstreambuf::strstreambuf(char * ptr, int size, char * pstart)
  132. : streambuf()
  133. {
  134. x_static = 1;
  135. x_dynamic = 0;
  136. char * pend;
  137. if (!size)
  138. pend = ptr + strlen(ptr);
  139. else if (size < 0)
  140. {
  141. pend = (char*)-1L;
  142. }
  143. else
  144. pend = ptr + size;
  145. setb(ptr, pend,0);
  146. if (pstart)
  147. {
  148. setg(ptr,ptr,pstart);
  149. setp(pstart, pend);
  150. }
  151. else
  152. {
  153. setg(ptr,ptr,pend);
  154. setp(0, 0);
  155. }
  156. }
  157. strstreambuf::~strstreambuf()
  158. {
  159. if ((x_dynamic) && (base()))
  160. {
  161. if (x_free)
  162. {
  163. (*x_free)(base());
  164. }
  165. else
  166. {
  167. delete base();
  168. }
  169. }
  170. }
  171. void strstreambuf::freeze(int n)
  172. {
  173. if (!x_static)
  174. {
  175. x_dynamic = (!n);
  176. #ifdef _DEBUG
  177. if (n)
  178. _CrtSetDbgBlockType(base(), _NORMAL_BLOCK);
  179. else
  180. _CrtSetDbgBlockType(base(), _CRT_BLOCK);
  181. #endif
  182. }
  183. }
  184. char * strstreambuf::str()
  185. {
  186. x_dynamic = 0; // freeze();
  187. #ifdef _DEBUG
  188. if (!x_static)
  189. _CrtSetDbgBlockType(base(), _NORMAL_BLOCK);
  190. #endif
  191. return base();
  192. }
  193. int strstreambuf::doallocate()
  194. {
  195. char * bptr;
  196. int size;
  197. size = __max(x_bufmin,blen() + __max(x_bufmin,1));
  198. long offset = 0;
  199. if (x_alloc)
  200. {
  201. bptr = (char*)(*x_alloc)(size);
  202. }
  203. else
  204. {
  205. bptr = _new_crt char[size];
  206. }
  207. if (!bptr)
  208. return EOF;
  209. if (blen())
  210. {
  211. memcpy(bptr, base(), blen());
  212. offset = (long)(bptr - base()); // amount to adjust pointers by
  213. }
  214. if (x_free)
  215. {
  216. (*x_free)(base());
  217. }
  218. else
  219. {
  220. delete base();
  221. }
  222. setb(bptr,bptr+size,0); // we handle deallocation
  223. // adjust get/put pointers too, if necessary
  224. if (offset)
  225. if (egptr())
  226. {
  227. setg(eback()+offset,gptr()+offset,egptr()+offset);
  228. }
  229. if (epptr())
  230. {
  231. size = (int)(pptr() - pbase());
  232. setp(pbase()+offset,epptr()+offset);
  233. pbump(size);
  234. }
  235. return(1);
  236. }
  237. streambuf * strstreambuf::setbuf( char *, int l)
  238. {
  239. if (l)
  240. x_bufmin = l;
  241. return this;
  242. }
  243. int strstreambuf::overflow(int c)
  244. {
  245. /*
  246. - if no room and not dynamic, give error
  247. - if no room and dynamic, allocate (1 more or min) and store
  248. - if and when the buffer has room, store c if not EOF
  249. */
  250. int temp;
  251. if (pptr() >= epptr())
  252. {
  253. if (!x_dynamic)
  254. return EOF;
  255. if (strstreambuf::doallocate()==EOF)
  256. return EOF;
  257. if (!epptr()) // init if first time through
  258. {
  259. setp(base() + (egptr() - eback()),ebuf());
  260. }
  261. else
  262. {
  263. temp = (int)(pptr()-pbase());
  264. setp(pbase(),ebuf());
  265. pbump(temp);
  266. }
  267. }
  268. if (c!=EOF)
  269. {
  270. *pptr() = (char)c;
  271. pbump(1);
  272. }
  273. return(1);
  274. }
  275. int strstreambuf::underflow()
  276. {
  277. char * tptr;
  278. if (gptr() >= egptr())
  279. {
  280. // try to grow get area if we can...
  281. if (egptr()<pptr())
  282. {
  283. tptr = base() + (gptr()-eback());
  284. setg(base(),tptr,pptr());
  285. }
  286. if (gptr() >= egptr())
  287. return EOF;
  288. }
  289. return (int)(unsigned char) *gptr();
  290. }
  291. int strstreambuf::sync()
  292. {
  293. // a strstreambuf is always in sync, by definition!
  294. return 0;
  295. }
  296. streampos strstreambuf::seekoff(streamoff off, ios::seek_dir dir, int mode)
  297. {
  298. char * tptr;
  299. long offset = EOF; // default return value
  300. if (mode & ios::in)
  301. {
  302. strstreambuf::underflow(); // makes sure entire buffer available
  303. switch (dir) {
  304. case ios::beg :
  305. tptr = eback();
  306. break;
  307. case ios::cur :
  308. tptr = gptr();
  309. break;
  310. case ios::end :
  311. tptr = egptr();
  312. break;
  313. default:
  314. return EOF;
  315. }
  316. tptr += off;
  317. offset = (long)(tptr - eback());
  318. if ((tptr < eback()) || (tptr > egptr()))
  319. {
  320. return EOF;
  321. }
  322. gbump((int)(tptr-gptr()));
  323. }
  324. if (mode & ios::out)
  325. {
  326. if (!epptr())
  327. {
  328. if (strstreambuf::overflow(EOF)==EOF) // make sure there's a put buffer
  329. return EOF;
  330. }
  331. switch (dir) {
  332. case ios::beg :
  333. tptr = pbase();
  334. break;
  335. case ios::cur :
  336. tptr = pptr();
  337. break;
  338. case ios::end :
  339. tptr = epptr();
  340. break;
  341. default:
  342. return EOF;
  343. }
  344. tptr += off;
  345. offset = (long)(tptr - pbase());
  346. if (tptr < pbase())
  347. return EOF;
  348. if (tptr > epptr())
  349. {
  350. if (x_dynamic)
  351. {
  352. x_bufmin = __max(x_bufmin, (int)(tptr-pbase()));
  353. if (strstreambuf::doallocate()==EOF)
  354. return EOF;
  355. }
  356. else
  357. return EOF;
  358. }
  359. pbump((int)(tptr-pptr()));
  360. }
  361. return offset; // note: if both in and out set, returns out offset
  362. }
  363. istrstream::istrstream(char * pszStr)
  364. : istream(_new_crt strstreambuf(pszStr,0))
  365. {
  366. delbuf(1);
  367. }
  368. istrstream::istrstream(char * pStr, int len)
  369. : istream(_new_crt strstreambuf(pStr,len))
  370. {
  371. delbuf(1);
  372. }
  373. istrstream::~istrstream()
  374. {
  375. }
  376. ostrstream::ostrstream()
  377. : ostream(_new_crt strstreambuf)
  378. {
  379. delbuf(1);
  380. }
  381. ostrstream::ostrstream(char * str, int size, int mode)
  382. : ostream(_new_crt strstreambuf(str,size,str))
  383. {
  384. delbuf(1);
  385. if (mode & (ios::app|ios::ate))
  386. seekp((long)strlen(str),ios::beg);
  387. }
  388. ostrstream::~ostrstream()
  389. {
  390. }
  391. strstream::strstream()
  392. : iostream(_new_crt strstreambuf)
  393. {
  394. istream::delbuf(1);
  395. ostream::delbuf(1);
  396. }
  397. strstream::strstream(char * str, int size, int mode)
  398. : iostream(_new_crt strstreambuf(str,size,str))
  399. {
  400. istream::delbuf(1);
  401. ostream::delbuf(1);
  402. if ((mode & ostream::out) && (mode & (ostream::app|ostream::ate)))
  403. seekp((long)strlen(str),ostream::beg);
  404. // rdbuf()->setg(rdbuf()->base(),rdbuf()->base(),rdbuf()->ebuf());
  405. }
  406. strstream::~strstream()
  407. {
  408. }