Re: C++ support?

George Feinberg (gmf@odi.com)
Fri, 8 Aug 1997 10:01:59 -0400 (EDT)

From: George Feinberg <gmf@odi.com>
Message-Id: <199708081401.KAA01085@loon>
Subject: Re: C++ support?
To: t16@nikhef.nl (Kasper Peeters)
Date: Fri, 8 Aug 1997 10:01:59 -0400 (EDT)
In-Reply-To: <9708080726.JA05185@macbeth.nikhef.nl> from "Kasper Peeters" at Aug 8, 97 09:26:00 am


> > I sent code that wraps fcgi output in an ostream class to this group a
> > year or more ago. 
> 
> I couldn't find it. Could you mail it to me or to the list, or point
> us at a location where it can be found? Thanks.
> 
> > Input doesn't make as much sense in FCGI. 
> 
> Ehm, what about file uploads?

True, but I wasn't concerned with input, so I didn't do it.
It was the output that needed an ostream interface,
because of existing code.

The code is pretty simple, once you know what to do.
You could do the same trick for input.  It should be obvious how.
Code is below.

DISCLAIMER: This code is provided as-is. It works for me, it 
may not for you. You're on own if it doesn't.  I'm sending this as 
me, not my employer.

2 files, fcgio.h and fcgio.cpp.

/*--------------------------------------------------------------------
 |
 |  FILE NAME: fcgio.h
 |
 |  AUTHOR(S): George Feinberg
 |
 |
 |  NOTES:  encapsulates FCGI function in an ostream class
 |--------------------------------------------------------------------
 |
 ---------------------------------------------------------------------*/

#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__

/*--------------------------------------------------------------------
 |
 |  FILE NAME: fcgio.cpp
 |
 |  AUTHOR(S): George Feinberg
 |
 |  NOTES:  encapsulates FCGI function in an ostream
 |--------------------------------------------------------------------
 |
 ---------------------------------------------------------------------*/

#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);
}