home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / STRSTREA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  8.0 KB  |  360 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - strstrea.cpp
  3.  * Class strstrea member functions
  4.  *-----------------------------------------------------------------------*/
  5.  
  6. /*[]------------------------------------------------------------[]*/
  7. /*|                                                              |*/
  8. /*|     Turbo C++ Run Time Library - Version 1.0                 |*/
  9. /*|                                                              |*/
  10. /*|                                                              |*/
  11. /*|     Copyright (c) 1990 by Borland International              |*/
  12. /*|     All Rights Reserved.                                     |*/
  13. /*|                                                              |*/
  14. /*[]------------------------------------------------------------[]*/
  15.  
  16. #include <strstrea.h>
  17. #include <string.h>
  18. #include <limits.h>
  19.  
  20.  
  21.  
  22. // minimum string size
  23. const int min_str_alloc = 16;
  24.  
  25. // minimum string increment when extending
  26. const int min_str_incr = 4;
  27.  
  28. // to improve legibility
  29. #define expandable ((ssbflags&(dynamic|frozen))==dynamic)
  30.  
  31.  
  32. strstreambuf::strstreambuf()
  33. {
  34.     allocf = 0;
  35.     freef = 0;
  36.     ssbflags = dynamic;
  37. }
  38.  
  39.  
  40. strstreambuf::strstreambuf(void* (*a)(long), void (*f)(void*))
  41. {
  42.     allocf = a;
  43.     freef = f;
  44.     ssbflags = dynamic;
  45. }
  46.  
  47.  
  48. strstreambuf::strstreambuf(int n)
  49. {
  50.     if( n < min_str_alloc )
  51.     n = min_str_alloc;
  52.     char *p = new char[n];
  53.     setb(p, p+n, 0);
  54.     *p = 0;
  55.     allocf = 0;
  56.     freef = 0;
  57.     ssbflags = dynamic;
  58. }
  59.  
  60.  
  61. /*
  62.     If n is negative, the provided buffer is supposed to be unlimited.
  63.     As a practical way to handle this, the buffer is arbitrarily defined
  64.     to be size INT_MAX.  (It really should be the max value supported by
  65.     type size_t, but AT&T defined all sizes to be int.)
  66. */
  67. void strstreambuf::init(signed char* ptr, int n, signed char* pstart)
  68. {
  69.     ssbflags = 0;
  70.     if( n == 0 ) n = strlen((char*)ptr);
  71.     else if( n < 0 ) {
  72.     n = INT_MAX;
  73.     ssbflags |= unlimited;    // distinguish it from merely large
  74.     }
  75.     setb((char*)ptr, (char*)ptr+n, 0);
  76.     if( pstart ) {
  77.     setp((char*)pstart, ebuf());
  78.     setg((char*)ptr, (char*)ptr, (char*)pstart);
  79.     }
  80.     else
  81.     setg((char*)ptr, (char*)ptr, (char*)ebuf());
  82.  
  83.     allocf = 0;
  84.     freef = 0;
  85. }
  86.  
  87.  
  88. strstreambuf::strstreambuf(signed char* ptr, int n, signed char* pstart)
  89. {
  90.     init(ptr, n, pstart);
  91. }
  92.  
  93.  
  94. strstreambuf::strstreambuf(unsigned char* ptr, int n, unsigned char* pstart)
  95. {
  96.     init((signed char*)ptr, n, (signed char*)pstart);
  97. }
  98.  
  99.  
  100. strstreambuf::~strstreambuf()
  101. {
  102.     if( expandable )
  103.     if( freef )
  104.         (*freef)((void*)base());
  105.     else
  106.         delete base();
  107. }
  108.  
  109.  
  110. void strstreambuf::freeze(int n)
  111. {
  112.     if( ssbflags & dynamic )
  113.     if( n )
  114.         ssbflags |= frozen;
  115.     else
  116.         ssbflags &= ~frozen;
  117. }
  118.  
  119.  
  120. char* strstreambuf::str()
  121. {
  122.     freeze(1);
  123.     return base();
  124. }
  125.  
  126.  
  127. int strstreambuf::doallocate()
  128. {
  129.     int size = next_alloc ? next_alloc : min_str_alloc;
  130.     char *p;
  131.     if( allocf )
  132.     p = (char*)(*allocf)((long)size);
  133.     else
  134.     p = new char[size];
  135.     if( ! p )
  136.     return EOF;
  137.  
  138.     next_alloc = 0;    // assume next_alloc increment is one time only
  139.     setb(p, p + size, 0);
  140.     *p = 0;
  141.     return 1;
  142. }
  143.  
  144.  
  145. int strstreambuf::overflow(int c)
  146. {
  147.     if( expandable ) {
  148.     // allocate put area as needed
  149.     if( ! base() )
  150.         doallocate();
  151.     if( ! pbase() )
  152.         setp(base(), ebuf());
  153.     }
  154.     if( pbase() ) {
  155.     if( (pptr() >= epptr()) && expandable ) {
  156.         // expand the reserve area
  157.         char *oldp = base();    // old buf
  158.         int len = blen();        // length of old buf
  159.         char *p = new char[len + min_str_incr];    // new buf
  160.         if( ! p )
  161.         return EOF;        // out of memory
  162.  
  163.         memcpy(p, oldp, len);    // copy data to new buf
  164.         // get relative pointer data 
  165.         int ebloc, gloc, egloc;    // get area pointer data
  166.         int ploc = (int)(pptr() - oldp);    // put area pointer data
  167.         int get_area = (gptr() != 0);
  168.         if( get_area ) {
  169.         ebloc = (int)(eback() - oldp);    // eback location
  170.         gloc = (int)(gptr() - oldp);    // gptr location
  171.         egloc = (int)(egptr() - oldp);    // egptr location
  172.         }
  173.         // set up new pointers
  174.         setb(p, p + len + min_str_incr, 0);
  175.         setp(p, ebuf());    // the put area goes to end of buf
  176.         pbump(ploc);
  177.         if( get_area )
  178.         setg(p + ebloc, p + gloc, p + egloc);
  179.     }
  180.     if( pptr() < epptr() )
  181.         return sputc(c);        // now there is room in the put area
  182.     }
  183.  
  184.     return EOF;        // could not make more space
  185. }
  186.  
  187.  
  188. int strstreambuf::underflow()
  189. {
  190.     if( egptr() > gptr() )
  191.     return (unsigned char) *gptr();
  192.  
  193.     if( base()  &&  ! unbuffered()  &&  pptr() > pbase() ) {
  194.     if( ! gptr()  ||  gptr() < pbase() ) {
  195.         // initialize get area to current put area
  196.         setg(base(), pbase(), pptr());
  197.         return (unsigned char) *gptr();
  198.     }
  199.     if( gptr() < pptr() ) {
  200.         // extend get area to match put area
  201.         setg(eback(), gptr(), pptr());
  202.         return (unsigned char) *gptr();
  203.     }
  204.     // else no more chars
  205.     }
  206.  
  207.     return EOF;
  208. }
  209.  
  210.  
  211. streambuf* strstreambuf::setbuf(char* p, int n)
  212. {
  213.     if( p )
  214.     return 0;    // can't honor this kind of request
  215.  
  216.     if( n > min_str_incr )
  217.     next_alloc = n;    // next alloc will be this many
  218.     return this;
  219. }
  220.  
  221.  
  222. // we assume streampos and streamoff are type int or long
  223. streampos strstreambuf::seekoff(streamoff off, seek_dir dir, int omode)
  224. {
  225.     streamoff pos = EOF;    // result
  226.  
  227.     // find position if from beginning or end
  228.     if( dir == ios::end ) {
  229.     if( (ssbflags & unlimited) || off > 0 )
  230.         pos = -1;    // can't do it
  231.     else
  232.         pos = blen() + off;
  233.     }
  234.     else if( dir == ios::beg )
  235.     pos = off;
  236.  
  237.     if( omode & ios::in ) {
  238.     // set up get area
  239.     if( dir == ios::cur ) {
  240.         // find a reasonable value for current position
  241.         if( gptr() ) pos = streamoff(gptr() - base()) + off;
  242.         else if( pptr() ) pos = streamoff(pptr() - base()) + off;
  243.         else pos = off;
  244.     }
  245.     if( pos < 0  ||  blen() < pos )
  246.         pos = EOF;    // illegal request
  247.     else {
  248. #pragma warn -sig
  249.         char* g = base() + pos;
  250. #pragma warn .sig
  251.         char* eb = (eback() && eback() < g) ? eback() : g;
  252.         char* eg = (egptr() && g < egptr()) ? egptr() : g;
  253.         setg(eb, g, eg);
  254.     }
  255.     }
  256.     if( omode & ios::out ) {
  257.     // set up put area
  258.     if( dir == ios::cur ) {
  259.         // find a reasonable value for current position
  260.         if( pptr() ) pos = streamoff(pptr() - base()) + off;
  261.         else if( gptr() ) pos = streamoff(gptr() - base()) + off;
  262.         else pos = off;
  263.     }
  264.     if( pos < 0  ||  blen() < pos )
  265.         pos = EOF;    // illegal request
  266.     else {
  267. #pragma warn -sig
  268.         char* p = base() + pos;
  269. #pragma warn .sig
  270.         char* ep = (epptr() && p < epptr()) ? epptr() : ebuf();
  271.         setp(p, ep);
  272.     }
  273.     }
  274.     return streampos(pos);
  275. }
  276.  
  277.  
  278.  
  279. strstreambase::strstreambase(char* ptr, int n, char* pstart) :
  280.         buf(ptr, n, pstart)
  281. {
  282.     ios::init(&this->buf);
  283. }
  284.  
  285.  
  286. strstreambase::strstreambase() :
  287.         buf()
  288. {
  289.     ios::init(&this->buf);
  290. }
  291.  
  292.  
  293. strstreambase::~strstreambase()
  294. {
  295. }
  296.  
  297.  
  298.  
  299. istrstream::istrstream(char* str) :
  300.         strstreambase(str, 0, 0),
  301.         istream(strstreambase::rdbuf())
  302. {
  303. }
  304.  
  305.  
  306. istrstream::istrstream(char* str, int len) :
  307.         strstreambase(str, len, 0),
  308.         istream(strstreambase::rdbuf())
  309. {
  310. }
  311.  
  312.  
  313. istrstream::~istrstream()
  314. {
  315. }
  316.  
  317.  
  318.  
  319. ostrstream::ostrstream(char* str, int len, int omode) :
  320.         strstreambase(str, len, str),
  321.         ostream(strstreambase::rdbuf())
  322. {
  323.     if( omode & (ios::ate | ios::app) )
  324.     strstreambase::rdbuf()->seekoff(strlen(str), ios::beg, ios::out);
  325. }
  326.  
  327.  
  328. ostrstream::ostrstream() :
  329.         strstreambase(),
  330.         ostream(strstreambase::rdbuf())
  331. {
  332. }
  333.  
  334.  
  335. ostrstream::~ostrstream()
  336. {
  337. }
  338.  
  339.  
  340.  
  341. strstream::strstream() :
  342.         strstreambase(),
  343.         iostream(strstreambase::rdbuf())
  344. {
  345. }
  346.  
  347.  
  348. strstream::strstream(char* str, int size, int omode) :
  349.         strstreambase(str, size, str),
  350.         iostream(strstreambase::rdbuf())
  351. {
  352.     if( omode & (ios::ate | ios::app) )
  353.     strstreambase::rdbuf()->seekoff(strlen(str), ios::beg, ios::out);
  354. }
  355.  
  356.  
  357. strstream::~strstream()
  358. {
  359. }
  360.