home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / prstreams / prstrms.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.7 KB  |  528 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * Robin J. Maxwell 11-22-96
  21.  */
  22.  
  23. #include "prstrms.h"
  24. #ifdef SVR4
  25. #include <string.h> // memmove
  26. #endif
  27.  
  28. //
  29. // Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
  30. //
  31. // _PRSTR_BP is the protected member of class ios that is returned
  32. // by the public method rdbuf().
  33. //
  34. // _PRSTR_DELBUF is the method or data member of class ios, if available,
  35. // with which we can ensure that the ios destructor does not delete
  36. // the associated streambuf.  If such a method or data member does not
  37. // exist, define _PRSTR_DELBUF to be empty.
  38. //
  39. // _PRSTR_DELBUF_C is just _PRSTR_DELBUF qualified by a base class.
  40. //
  41.  
  42. #if defined(__GNUC__)
  43. #define _PRSTR_BP _strbuf
  44. #define _PRSTR_DELBUF(x)    /* as nothing */
  45. #define _PRSTR_DELBUF_C(c, x)  /* as nothing */
  46. #elif defined(WIN32)
  47. #define _PRSTR_BP bp
  48. #define _PRSTR_DELBUF(x)    delbuf(x)
  49. #define _PRSTR_DELBUF_C(c, x)    c::_PRSTR_DELBUF(x)
  50. #elif defined(OSF1)
  51. #define _PRSTR_BP m_psb
  52. #define _PRSTR_DELBUF(x) /* as nothing */
  53. #define _PRSTR_DELBUF_C(c, x)    /* as nothing */
  54. #else
  55. #define _PRSTR_BP bp
  56. // Unix compilers don't believe in encapsulation
  57. // At least on Solaris this is also ignored
  58. #define _PRSTR_DELBUF(x)    delbuf = x
  59. #define _PRSTR_DELBUF_C(c, x)    c::_PRSTR_DELBUF(x)
  60. #endif
  61.  
  62. const PRIntn STRM_BUFSIZ = 8192;
  63.  
  64. #if !defined (PRFSTREAMS_BROKEN)   
  65.  
  66. PRfilebuf::PRfilebuf():
  67. _fd(0),
  68. _opened(PR_FALSE),
  69. _allocated(PR_FALSE)
  70. {
  71. }
  72.  
  73. PRfilebuf::PRfilebuf(PRFileDesc *fd):
  74. streambuf(),
  75. _fd(fd),
  76. _opened(PR_FALSE),
  77. _allocated(PR_FALSE)
  78. {
  79. }
  80.  
  81. PRfilebuf::PRfilebuf(PRFileDesc *fd, char * buffptr, int bufflen):
  82. _fd(fd),
  83. _opened(PR_FALSE),
  84. _allocated(PR_FALSE)
  85. {
  86.     PRfilebuf::setbuf(buffptr, bufflen);
  87. }
  88.  
  89. PRfilebuf::~PRfilebuf()
  90. {
  91.     if (_opened){
  92.         close();
  93.     }else
  94.         sync();
  95.     if (_allocated)
  96.         delete base();
  97. }
  98.  
  99. PRfilebuf*    
  100. PRfilebuf::open(const char *name, int mode, int flags)
  101. {
  102.      if (_fd != 0)
  103.         return 0;    // error if already open
  104.      PRIntn PRmode = 0;
  105.     // translate mode argument
  106.     if (!(mode & ios::nocreate))
  107.         PRmode |= PR_CREATE_FILE;
  108.     //if (mode & ios::noreplace)
  109.     //    PRmode |= O_EXCL;
  110.     if (mode & ios::app){
  111.         mode |= ios::out;
  112.         PRmode |= PR_APPEND;
  113.     }
  114.     if (mode & ios::trunc){
  115.         mode |= ios::out;  // IMPLIED
  116.         PRmode |= PR_TRUNCATE;
  117.     }
  118.     if (mode & ios::out){
  119.         if (mode & ios::in)
  120.             PRmode |= PR_RDWR;
  121.         else
  122.             PRmode |= PR_WRONLY;
  123.         if (!(mode & (ios::in|ios::app|ios::ate|ios::noreplace))){
  124.             mode |= ios::trunc; // IMPLIED
  125.             PRmode |= PR_TRUNCATE;
  126.         }
  127.     }else if (mode & ios::in)
  128.         PRmode |= PR_RDONLY;
  129.     else
  130.         return 0;    // error if not ios:in or ios::out
  131.  
  132.  
  133.     //
  134.     // The usual portable across unix crap...
  135.     // NT gets a hokey piece of junk layer that prevents
  136.     // access to the API.
  137. #ifdef WIN32
  138.     _fd = PR_Open(name, PRmode, PRmode);
  139. #else
  140.     _fd = PR_Open(name, PRmode, flags);
  141. #endif
  142.     if (_fd == 0)
  143.         return 0;
  144.     _opened = PR_TRUE;
  145.     if ((!unbuffered()) && (!ebuf())){
  146.         char * sbuf = new char[STRM_BUFSIZ];
  147.         if (!sbuf)
  148.             unbuffered(1);
  149.         else{
  150.             _allocated = PR_TRUE;
  151.             streambuf::setb(sbuf,sbuf+STRM_BUFSIZ,0);
  152.         }
  153.     }
  154.     if (mode & ios::ate){
  155.         if (seekoff(0,ios::end,mode)==EOF){
  156.             close();
  157.             return 0;
  158.         }
  159.     }
  160.     return this;
  161. }
  162.  
  163. PRfilebuf*    
  164. PRfilebuf::attach(PRFileDesc *fd)
  165. {
  166.     _opened = PR_FALSE;
  167.     _fd = fd;
  168.     return this;
  169. }
  170.  
  171. int    
  172. PRfilebuf::overflow(int c)
  173. {
  174.     if (allocate()==EOF)        // make sure there is a reserve area
  175.         return EOF;
  176.     if (PRfilebuf::sync()==EOF) // sync before new buffer created below
  177.         return EOF;
  178.  
  179.     if (!unbuffered())
  180.         setp(base(),ebuf());
  181.  
  182.     if (c!=EOF){
  183.         if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
  184.             sputc(c);
  185.         else{
  186.             if (PR_Write(_fd, &c, 1)!=1)
  187.                 return(EOF);
  188.         }
  189.     }
  190.     return(1);  // return something other than EOF if successful
  191. }
  192.  
  193. int    
  194. PRfilebuf::underflow()
  195. {
  196.     int count;
  197.     unsigned char tbuf;
  198.  
  199.     if (in_avail())
  200.         return (int)(unsigned char) *gptr();
  201.  
  202.     if (allocate()==EOF)        // make sure there is a reserve area
  203.         return EOF;
  204.     if (PRfilebuf::sync()==EOF)
  205.         return EOF;
  206.  
  207.     if (unbuffered())
  208.         {
  209.         if (PR_Read(_fd,(void *)&tbuf,1)<=0)
  210.             return EOF;
  211.         return (int)tbuf;
  212.         }
  213.  
  214.     if ((count=PR_Read(_fd,(void *)base(),blen())) <= 0)
  215.         return EOF;     // reached EOF
  216.     setg(base(),base(),base()+count);
  217.     return (int)(unsigned char) *gptr();
  218. }
  219.  
  220. streambuf*    
  221. PRfilebuf::setbuf(char *buffptr, int bufflen)
  222. {
  223.     if (is_open() && (ebuf()))
  224.         return 0;
  225.     if ((!buffptr) || (bufflen <= 0))
  226.         unbuffered(1);
  227.     else
  228.         setb(buffptr, buffptr+bufflen, 0);
  229.     return this;
  230. }
  231.  
  232. streampos    
  233. PRfilebuf::seekoff(streamoff offset, ios::seek_dir dir, int /* mode */)
  234. {
  235.     if (PR_GetDescType(_fd) == PR_DESC_FILE){
  236.         PRSeekWhence fdir;
  237.         PRInt32 retpos;
  238.         switch (dir) {
  239.             case ios::beg :
  240.                 fdir = PR_SEEK_SET;
  241.                 break;
  242.             case ios::cur :
  243.                 fdir = PR_SEEK_CUR;
  244.                 break;
  245.             case ios::end :
  246.                 fdir = PR_SEEK_END;
  247.                 break;
  248.             default:
  249.             // error
  250.                 return(EOF);
  251.             }
  252.  
  253.         if (PRfilebuf::sync()==EOF)
  254.             return EOF;
  255.         if ((retpos=PR_Seek(_fd, offset, fdir))==-1L)
  256.             return (EOF);
  257.         return((streampos)retpos);
  258.     }else
  259.         return (EOF);
  260. }
  261.  
  262.  
  263. int 
  264. PRfilebuf::sync()
  265. {
  266.     PRInt32 count; 
  267.  
  268.     if (_fd==0)
  269.         return(EOF);
  270.  
  271.     if (!unbuffered()){
  272.         // Sync write area
  273.         if ((count=out_waiting())!=0){
  274.             PRInt32 nout;
  275.             if ((nout =PR_Write(_fd,
  276.                                (void *) pbase(),
  277.                                (unsigned int)count)) != count){
  278.                 if (nout > 0) {
  279.                     // should set _pptr -= nout
  280.                     pbump(-(int)nout);
  281.                     memmove(pbase(), pbase()+nout, (int)(count-nout));
  282.                 }
  283.                 return(EOF);
  284.             }
  285.         }
  286.         setp(0,0); // empty put area
  287.  
  288.         if (PR_GetDescType(_fd) == PR_DESC_FILE){
  289.             // Sockets can't seek; don't need this
  290.             if ((count=in_avail()) > 0){
  291.                 if (PR_Seek(_fd, -count, PR_SEEK_CUR)!=-1L)
  292.                 {
  293.                     return (EOF);
  294.                 }
  295.             }
  296.         }
  297.         setg(0,0,0); // empty get area
  298.     }
  299.     return(0);
  300. }
  301.  
  302. PRfilebuf * 
  303. PRfilebuf::close()
  304. {
  305.     int retval;
  306.     if (_fd==0)
  307.         return 0;
  308.  
  309.     retval = sync();
  310.  
  311.     if ((PR_Close(_fd)==0) || (retval==EOF))
  312.         return 0;
  313.     _fd = 0;
  314.     return this;
  315. }
  316.  
  317. PRifstream::PRifstream():
  318. istream(new PRfilebuf)
  319. {
  320.     _PRSTR_DELBUF(0);
  321. }
  322.  
  323. PRifstream::PRifstream(PRFileDesc *fd):
  324. istream(new PRfilebuf(fd))
  325. {
  326.     _PRSTR_DELBUF(0);
  327. }
  328.  
  329. PRifstream::PRifstream(PRFileDesc *fd, char *buff, int bufflen):
  330. istream(new PRfilebuf(fd, buff, bufflen))
  331. {
  332.     _PRSTR_DELBUF(0);
  333. }
  334.  
  335. PRifstream::PRifstream(const char * name, int mode, int flags):
  336. istream(new PRfilebuf)
  337. {
  338.     _PRSTR_DELBUF(0);
  339.     if (!rdbuf()->open(name, (mode|ios::in), flags))
  340.         clear(rdstate() | ios::failbit);
  341. }
  342.  
  343. PRifstream::~PRifstream()
  344. {
  345.     sync();
  346.  
  347.     delete rdbuf();
  348. #ifdef _PRSTR_BP
  349.     _PRSTR_BP = 0;
  350. #endif
  351. }
  352.  
  353. streambuf * 
  354. PRifstream::setbuf(char * ptr, int len)
  355. {
  356.     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
  357.         clear(rdstate() | ios::failbit);
  358.         return 0;
  359.     }
  360.     return rdbuf();
  361. }
  362.  
  363. void 
  364. PRifstream::attach(PRFileDesc *fd)
  365. {
  366.     if (!(rdbuf()->attach(fd)))
  367.         clear(rdstate() | ios::failbit);
  368. }
  369.  
  370. void 
  371. PRifstream::open(const char * name, int mode, int flags)
  372. {
  373.     if (is_open() || !(rdbuf()->open(name, (mode|ios::in), flags)))
  374.         clear(rdstate() | ios::failbit);
  375. }
  376.  
  377. void 
  378. PRifstream::close()
  379. {
  380.     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
  381. }
  382.  
  383. PRofstream::PRofstream():
  384. ostream(new PRfilebuf)
  385. {
  386.     _PRSTR_DELBUF(0);
  387. }
  388.  
  389. PRofstream::PRofstream(PRFileDesc *fd):
  390. ostream(new PRfilebuf(fd))
  391. {
  392.     _PRSTR_DELBUF(0);
  393. }
  394.  
  395. PRofstream::PRofstream(PRFileDesc *fd, char *buff, int bufflen):
  396. ostream(new PRfilebuf(fd, buff, bufflen))
  397. {
  398.     _PRSTR_DELBUF(0);
  399. }
  400.  
  401. PRofstream::PRofstream(const char *name, int mode, int flags):
  402. ostream(new PRfilebuf)
  403. {
  404.     _PRSTR_DELBUF(0);
  405.     if (!rdbuf()->open(name, (mode|ios::out), flags))
  406.         clear(rdstate() | ios::failbit);
  407. }
  408.  
  409. PRofstream::~PRofstream()
  410. {
  411.     flush();
  412.  
  413.     delete rdbuf();
  414. #ifdef _PRSTR_BP
  415.     _PRSTR_BP = 0;
  416. #endif
  417. }
  418.  
  419. streambuf * 
  420. PRofstream::setbuf(char * ptr, int len)
  421. {
  422.     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
  423.         clear(rdstate() | ios::failbit);
  424.         return 0;
  425.     }
  426.     return rdbuf();
  427. }
  428.  
  429. void 
  430. PRofstream::attach(PRFileDesc *fd)
  431. {
  432.     if (!(rdbuf()->attach(fd)))
  433.         clear(rdstate() | ios::failbit);
  434. }
  435.  
  436. void 
  437. PRofstream::open(const char * name, int mode, int flags)
  438. {
  439.     if (is_open() || !(rdbuf()->open(name, (mode|ios::out), flags)))
  440.         clear(rdstate() | ios::failbit);
  441. }
  442.  
  443. void 
  444. PRofstream::close()
  445. {
  446.     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
  447. }
  448.  
  449. PRfstream::PRfstream():
  450. iostream(new PRfilebuf)
  451. {
  452.     _PRSTR_DELBUF_C(istream, 0);
  453.     _PRSTR_DELBUF_C(ostream, 0);
  454. }
  455.  
  456. PRfstream::PRfstream(PRFileDesc *fd):
  457. iostream(new PRfilebuf(fd))
  458. {
  459.     _PRSTR_DELBUF_C(istream, 0);
  460.     _PRSTR_DELBUF_C(ostream, 0);
  461. }
  462.  
  463. PRfstream::PRfstream(PRFileDesc *fd, char *buff, int bufflen):
  464. iostream(new PRfilebuf(fd, buff, bufflen))
  465. {
  466.     _PRSTR_DELBUF_C(istream, 0);
  467.     _PRSTR_DELBUF_C(ostream, 0);
  468. }
  469.  
  470. PRfstream::PRfstream(const char *name, int mode, int flags):
  471. iostream(new PRfilebuf)
  472. {
  473.     _PRSTR_DELBUF_C(istream, 0);
  474.     _PRSTR_DELBUF_C(ostream, 0);
  475.     if (!rdbuf()->open(name, (mode|(ios::in|ios::out)), flags))
  476.         clear(rdstate() | ios::failbit);
  477. }
  478.  
  479. PRfstream::~PRfstream()
  480. {
  481.     sync();
  482.     flush();
  483.  
  484.     delete rdbuf();
  485. #ifdef _PRSTR_BP
  486.     istream::_PRSTR_BP = 0;
  487.     ostream::_PRSTR_BP = 0;
  488. #endif
  489. }
  490.  
  491. streambuf * 
  492. PRfstream::setbuf(char * ptr, int len)
  493. {
  494.     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
  495.         clear(rdstate() | ios::failbit);
  496.         return 0;
  497.     }
  498.     return rdbuf();
  499. }
  500.  
  501. void 
  502. PRfstream::attach(PRFileDesc *fd)
  503. {
  504.     if (!(rdbuf()->attach(fd)))
  505.         clear(rdstate() | ios::failbit);
  506. }
  507.  
  508. void 
  509. PRfstream::open(const char * name, int mode, int flags)
  510. {
  511.     if (is_open() || !(rdbuf()->open(name, (mode|(ios::in|ios::out)), flags)))
  512.         clear(rdstate() | ios::failbit);
  513. }
  514.  
  515. void 
  516. PRfstream::close()
  517. {
  518.     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
  519. }
  520.  
  521. #else
  522.  
  523. // fix it sometime
  524.  
  525. int fix_prfstreams ()    {    return 0; }
  526.  
  527. #endif
  528.