Re: Using cout with Fast CGI

George Feinberg (gmf@odi.com)
Mon, 25 Nov 1996 18:13:57 -0500 (EST)

From: George Feinberg <gmf@odi.com>
Message-Id: <199611252313.SAA14609@loon.odi.com>
Subject: Re: Using cout with Fast CGI
To: Vasile_Montan@teir.com (Vasile Montan/TEIR/Thomson)
Date: Mon, 25 Nov 1996 18:13:57 -0500 (EST)
In-Reply-To: <9611252255.AA0405@TEIR_Gateway1.teir.com> from "Vasile Montan/TEIR/Thomson" at Nov 25, 96 05:00:22 pm


> What is the status of converting C++ programs which use cout to FastCGI?  Is 
> there a quicker and easier solution than changing all cout's to fprintf's?

I wrote a quick iostream encapsulation of the FastCGI interfaces.  It
only works for fcgiapp.h (not fcgi_stdio).

I think you could just assign this stream to cout to get
the desired effect.

(DISCLAIMER -- the code works for me, but may not for you)
If anyone discovers problems, or has enhancements, just mail
them to the list.

Here it is (header followed by source)
Have fun...

George



#ifndef __FCCIO_H__
#define __FCCIO_H__

#include <iostream.h>
#include "fcgiapp.h"

// Definition of  FastCGI i/o buffer, derived from streambuf

class fcgio_buf : public streambuf {

  // construction
public:
  fcgio_buf( FCGX_Stream *str) 
    { fcgi_str = str; }
  ~fcgio_buf() {}

  // from streambuf
  virtual int           sync() 
    { return FCGX_FFlush(fcgi_str); }
  virtual int xsgetn(char*, int) 
    { return EOF; }
  virtual int           doallocate() 
    { return 0; }

  // Put these out of line
  virtual int xsputn(const char* s, int n);
  virtual int           overflow(int);
  virtual streambuf*    setbuf(char* s, int n);

private:
  FCGX_Stream * fcgi_str;
};

// Here's the ostream class definition.  All it has to do is 
// call ios::init() passing an instance of fcgio_buf

class fcgio_str : public ostream {
public:
  fcgio_str(FCGX_Stream *str);
  ~fcgio_str() {}

private:
  fcgio_buf buf;
};

#endif __FCCIO_H__



#include "fcgiapp.h"
#include "fcgio.h"

/*
 * This function is implemented using two classes, fcgio_buf,
 * derived from streambuf, and fcgio_str, derived from ostream.
 * Most of the implementation of these two classes is inline,
 * in the header file, fcgio.h.  The non-inline portions are
 * here.
 *
 */

/*---------------------------------------------------------------------*/

// Non-inline implementation of fcgio_buf

/*
 * This is called for things like:
 *  output << "hello world"
 *  output.write(string, n);
 */
int 
fcgio_buf::xsputn(const char* s, int n) { 
  return FCGX_PutStr(s, n, fcgi_str); 
}

/* 
 * overflow is called for "endl" and for stream.put().
 * Perhaps we should also call flush, but that's pretty high
 * cost, so let's not.
 */
int
fcgio_buf::overflow(int c) {
  if (c)
    return FCGX_PutChar(c, fcgi_str);
  else
    return EOF;
}

streambuf*
fcgio_buf::setbuf(char*, int) {
  setb(0,0,0);
  setg(0,0,0);
  setp(0,0);
  unbuffered(1);
  return this;
}

/*---------------------------------------------------------------------*/

/* 
 * Non inline implementation of fcgio_str -- the ctor.
 * The init() function call is ios::init(), which simply
 * takes your own notion of class streambuf*.  In our
 * case, it's an instance of fcgio_buf.
 */

fcgio_str::fcgio_str(FCGX_Stream *str) : buf(str) {
  // init is a protected member of ios
  init(&buf);
}