home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / _strstre.cpp < prev    next >
C/C++ Source or Header  |  1998-06-17  |  10KB  |  426 lines

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