//hello.cpp
#include "html.h"
void
main(int argc, char *argv[]){
Pause::init(argc, argv);
cout << (Html() << "Hello, world!");
}
//html.h
#if !defined(HTML_DEFINED)
#define HTML_DEFINED
#include "strClass.h"
class
BlockOption : public String{
friend ostream& operator << ( ostream& out, BlockOption& option);
protected:
String name;
public:
BlockOption(BlockOption& b) :
String((String&) b), name(b.name){}
BlockOption(const char * const _name,
const char * const value):
name(_name), String(value){}
BlockOption(const char * const _name) : name(_name){}
CAST_INJECTORS(BlockOption)
};
CAST_IOMANIP(BlockOption)
ostream& operator << ( ostream& out, BlockOption& b);
class Block;
ostream& operator << ( ostream& out, Block& b);
class Block : public String {
friend ostream& operator << ( ostream& out, Block& b);
protected:
String tag;
BlockOption* option[10];
unsigned blockOptionCount;
public:
Block():tag(),blockOptionCount(0){}
Block(const char * const _tag):
tag(_tag),blockOptionCount(0){}
Block( Block& sourceBlock);
~Block();
Block& operator<<( BlockOption& opt );
Block& filter(const char * text);
CAST_INJECTORS(Block)
Block& operator<< ( Block& b ){
(ostrstream&)*this << b;
return *this;
}
};
CAST_IOMANIP(Block)
class Anchor : public Block{
public:
Anchor(const char * const ref) : Block("a"){
(Block&)*this << BlockOption( "HREF", ref);
}
CAST_INJECTORS(Anchor)
Anchor& filter(const char * text)
{ ((Block&)*this).filter(text); return *this;}
};
CAST_IOMANIP(Anchor)
class Html : public Block {
friend ostream& operator << ( ostream& out, Html &html);
protected:
String title;
int isIndex;
static int responseHeader;
public:
Html(const char * const _title, int _isIndex =0) :
Block("body"), title(_title), isIndex(_isIndex){};
Html() : Block("body"), title(), isIndex(0){};
static void noResponseHeader(){ responseHeader =0;}
CAST_INJECTORS(Html)
Html& operator << ( Block& b ) {
((ostrstream&)(Block&)(*this)) << b ;
return *this;
}
Html& filter(const char * text)
{ ((Block&)*this).filter(text); return *this;}
};
CAST_IOMANIP(Html)
ostream& operator << ( ostream& out, Html &html);
#endif
//html.cpp
#include "html.h"
void message( char* code, unsigned long line,
char* file, char* date){
cout << (
Html("Error")
<< (Block("H1") << "Error!")
<< (Block("DL")
<< "\n<DT>CODE<DD>" << code
<< "\n<DT>LINE<DD>" << line
<< "\n<DT>FILE<DD>" << file
<< "\n<DT>DATE<DD>" << date
<< "\n"
)
);
}
//********************* Block messages ************************
Block& Block :: operator<< ( BlockOption& opt ){
if(blockOptionCount < 10) // Deep copy the option
option[blockOptionCount++] = new BlockOption(opt);
return *this;
}
Block::Block( Block& b): String(b), tag(b.tag){
for(blockOptionCount =0;
blockOptionCount < b.blockOptionCount;
blockOptionCount++
)
option[blockOptionCount] =
new BlockOption(*b.option[b.blockOptionCount]);
}
Block::~Block(){
unsigned k =0;
while(k < blockOptionCount) delete option[k++];
}
Block& Block::filter(const char * text){
char *s =(char*)text, c;
while( (c =*s++) != 0 )
switch(c){
case '&': *this << "&"; break;
case '<': *this << "<"; break;
default: *this << c;
}
return *this;
}
ostream& operator<< ( ostream& out, Block& b){
out << "<" << b.tag;
unsigned k =0;
while(k < b.blockOptionCount)
out << b.option[k++];
out << ">" ;
return out << (String&)b << "</" << b.tag << ">\n";
}
//********************* BlockOption **************************
ostream& operator<< ( ostream& out, BlockOption& b){
out << " ";
out << b.name;
out << "=\"";
out << (String&)b;
out << "\"";
return out;
}
//******************** Html messages *************************
int Html::responseHeader =1;
ostream& operator<<( ostream& out, Html& body){
Block htmlBlock("html");
if( body.title.notNull() || body.isIndex ){
Block head("head");
if(body.title.notNull()){
Block title("title");
title << body.title;
head << title;
}
if( body.isIndex )
head << "<isIndex>";
htmlBlock << head;
}
htmlBlock << (Block&)body;
if(Html::responseHeader)
out << "Content-type: text/html\n\n";
else
out << "Suppress: Content-type: text/html\n\n";
return out << htmlBlock << endl;
}
//strClass.h
#if !defined(STRINGCLASS_DEFINED)
#define STRINGCLASS_DEFINED
#include <strstrea.h>
#include <string.h>
/************************ Pause *****************************
To force a pause() at exit, include:
Pause::init(argc, argv);
at the beginning of main(), and include "-pause"
as a command line arguement.
*/
class Pause{
static char *programName;
static int noPause;
friend ostream& operator<<(ostream& out, Pause& pause);
friend void pause();
public:
static void init(int argc, char *argv[]);
};
//************************ String *****************************
// ostream& operator <<(ostream& out, Pause& pause);
#define MESSAGE(s) message(#s,__LINE__,__FILE__,__DATE__)
#define ASSERT(s) if((s)==NULL){ \
MESSAGE(s); \
exit(1); \
}
extern void message( char* code, unsigned long line,
char* file, char* date);
#define CAST_INJECTORS(CLASS) \
CLASS& operator<< (char _c) { \
(ostrstream&)*this << _c; return *this; } \
CLASS& operator<< (signed char _c) { \
(ostrstream&)*this << _c; return *this; } \
. . .
//portions omitted to save space
//complete macro available on code disk -- mb
. . .
#include <iomanip.h>
#ifdef _MSC_VER // for Microsoft's parameterized io manipulators
#define CAST_IOMANIP(CLASS) \
inline CLASS& operator \
<<(CLASS& _s, const SMANIP(int)& _f) { \
(ostream&)_s << _f ; return _s; \
} \
inline CLASS& operator \
<<(CLASS& _s, const SMANIP(long)& _f) { \
(ostream&)_s << _f ; return _s; \
}
#else // for Borland's template class io manipulators
#define CAST_IOMANIP(CLASS) \
inline CLASS& operator \
<<(CLASS& _s, smanip<int>& _f) { \
(ostream&)_s << _f ; \
return _s; \
} \
inline CLASS& operator \
<<(CLASS& _s, smanip<long>& _f) { \
(ostream&)_s << _f ; \
return _s; \
}
#endif
class String : public ostrstream{
String& replace(const char * const str);
public:
CAST_INJECTORS(String)
String() : ostrstream(){}
String(const char * const s){(ostrstream&)*this << s;}
String(String& str){
if(str.notNull())
(ostrstream&)*this << (const char * const)str;
}
String& testType(){ return *this;}
String& setNull();
int notNull(){ return rdbuf()->out_waiting();}
int isNull(){ return !notNull();}
String& operator= (const char * const val) {
return replace(val);
}
int operator!= ( String& val) {
return (strcmp((char*)*this,(char*)val) != 0);
}
int operator== ( String& val) {
return !strcmp((char*)*this,(char*)val);
}
operator char* (void);
};
inline ostream& operator<<(ostream& out, String& s){
return (out << (char *)s);
}
CAST_IOMANIP(String)
#endif
//strClass.cpp
#include "strClass.h"
#include <stdlib.h>
void pause(){
cerr << Pause::programName
<< ": press [Enter] to continue...";
cin.unsetf(ios::skipws);
char x;
cin >> &x;
cin.clear();
cin.setf(ios::skipws);
}
//********************* Pause messages ************************
int Pause::noPause = -1;
char* Pause::programName ="";
void Pause::init(int argc, char *argv[]){
programName = *argv++;
if(noPause == -1){
noPause = 1;
while( --argc && noPause )
if( !strcmp( *argv++, "-pause") ){
noPause =0;
atexit(pause);
}
}
}
//******************** String messages *************************
String::operator char* (void){
streampos pos =tellp();
(ostrstream&)*this << ends; //append null byte to the buffer
char *s =str(); // get a pointer to the buffer
rdbuf()->freeze(0); // unfreeze the buffer
seekp(pos); //backup over the terminal null byte
ASSERT((ios&)*this); //test for inability to allocate buffer
return s;
}
String& String::setNull(){
seekp(0); // rewind the buffer
rdbuf()->freeze(0); // unfreeze the buffer
return *this;
}
String& String::replace(const char * const str){
return setNull() << str; // put the new string in the buffer
}
//End of File