Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source demo stream lengthdemo.C
Document Actions

lengthdemo.C

by Michael L Powell last modified 2007-01-26 03:20

Click here to get the file

Size 5.9 kB - File type text/plain

File contents

/*ident	"@(#)cls4:demo/stream/lengthdemo.C	1.1" */
/*******************************************************************************
 
C++ source for the C++ Language System, Release 3.0.  This product
is a new release of the original cfront developed in the computer
science research center of AT&T Bell Laboratories.

Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.

THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
Laboratories, Inc.  The copyright notice above does not evidence
any actual or intended publication of such source code.

*******************************************************************************/
#include "lengthdemo.h"

int xunit ;

static const int max_unit_name_len = 32 ; 
	// Used to size an array for extracting units.

const Unit Unit::tbl[] = {	// Standard Unit is first element

	// Warning: max_unit_name_len must as great as maximum length
	// of string used as a unit.

	{ "in", 1. },		// inches
	{ "feet", 12.},		// feet
	{ "mi", 5280. * 12. },	// miles
	{ "m", 39.37079 },	// meters
} ;

Length::Length(float v,const Unit* u)
	: standard( u ? v * u->scale : v )
{	} 

Length::Length() { }

float Length::value(const Unit* u)
{
	return u ? standard / u->scale : standard ;
	}

const Unit* Unit::lookup(char* u)
{
	// Looks up u, returns a pointer to the Unit designated by
	// u or 0 if u does not designate a Unit.

	if ( !u ) return tbl ;
	for ( int x = 0 ; x < sizeof(tbl)/sizeof(*tbl) ; ++x ) {
		if ( strcmp(tbl[x].name,u) == 0 ) return &tbl[x] ;
		}
	return 0 ;
	}

ostream& operator<<(ostream& out, Length len)
{
	// Inserts the Length len, using the streams default unit.

	const Unit* u = (const Unit*)out.pword(xunit) ;
	out << (double)len.value(u) ;
	if ( u ) out << u->name ;
	return out ;
	}

istream& operator>>(istream& in, Length& len)
{
	float v ;			// Floating number in istream
	char str[max_unit_name_len] ;	// Unit in istream

	const Unit* u = (const Unit*)in.pword(xunit) ;
					// Default unit
	in>>v ;

	if ( in && !isspace(in.peek()) ) {
		// The next character is not whitespace, so it should
		// be a unit.

		// Note use of setw to avoid overflow of str in case
		// input is bad.

		in >> setw(sizeof(str)) >> str ;

		u = Unit::lookup(str) ;

		// If Unit wasn't legal (u==0), we consider it a formating
		// failure.  We use "clear" to set the error state of "in".
		// "in.rdstate()" is the current value.  We or in
		// "ios::failbit".  The previous state might have been
		// set non-zero when we read str. 

		if ( !u ) in.clear(ios::failbit|in.rdstate()) ;
		}

	len = Length(v,u) ;
	return in ;
	}

static ios& setufct(ios& s, const Unit* u) {
	// function to set the default unit of s.
	s.pword(xunit) = (void*)u ;
	return s ;
	}

SMANIP(pcUnit) setu(const Unit* u) {
	// Convert the function to a "manipulator".  setufct can
	// be used directly, but a manipulator is often more convenient.
	return SMANIP(pcUnit)(setufct,u) ;
	}

static Iostream_init* iosi ;
	// The iostream library uses the initialization technique
	// implemented by Length_init.  Namely, construction of
	// an Iostream_init causes it to be initialized.

int Length_init::count = 0 ;

Length_init::Length_init() 
{
	if ( count++ > 0 ) return ;
	// do these things only the first time this constructor is
	// called.

	iosi = new Iostream_init ;	// initialize iostream library
	xunit = ios::xalloc() ;	
		// get a unique index for the default unit. Using
		// ios::xalloc() to get an index instead of picking
		// one arbitrarily allows the Length library to coexist
		// with other libraries with user defined state variables.

	// Make sure state variable is initialized in predefined streams
	cin.pword(xunit) = 0 ;
	cout.pword(xunit) = 0 ;
	cerr.pword(xunit) = 0 ;
	clog.pword(xunit) = 0 ;
	} 

Length_init::~Length_init()
{
	if ( --count > 0 ) return ;
	
	// If we assume that a the Length_init destructor is called
	// for every Length_init that is ever constructed then we
	// reach here exactly once.  Namely when every Length_init
	// that is constructed has been unconstructed.  This should be
	// after any possible use of the library. 

	delete iosi ;
		// don't forget to unconstruct the Iostream_init.
		// The predefined streams are closed by the last
		// call to the Iostream_init destructor, so we have
		// to make sure they balance.
	} 


/**************
 *
 * What follows is a sample program.  It takes Lengths from its
 * command arguments or from cin. It prints each length on its
 * cout.
 *
 **************/

const Unit* feet = Unit::lookup("feet") ;
const Unit* meter = Unit::lookup("m") ;

void outlen(Length len)
{
	// Print len in various units.

	cout	<< setu(0);
	cout	<< len; 
	cout << " = "; 
	cout << setu(feet);
	cout << len;
	cout << " = ";
	cout << setu(meter);
	cout << len;
	cout << endl;

	// endl both inserts new line and flushes cout.  
	}

int main(int argc, char** argv )
{
	// This main is just a sample of how the above might be
	// used.  If it has arguments, it prints them.  If it
	// doesn't, then it reads Lengths from standard input and
	// prints them.
	
	Length len ;

	cout.precision(4) ;
		// Output with low precision to avoid machine dependencies.

	for ( int arg = 1 ; arg < argc ; ++arg ) {
		// We will use an "in core string stream" to do
		// the conversion

		istrstream a(argv[arg]) ;
		a >> len ;
		if ( !a ) {
			cerr << "cannot interpret " << argv[arg] << endl ;
			return 1 ;
			}
		outlen(len) ;
		} ;

	if ( argc <= 1 ) {
		// No arguments, so read from cin.

		while ( cin >> len ) outlen(len) ;

		// Normally we stop at end of file with both ios::eofbit
		// and ios::badbit set in the error state of cin.
		// The former because we reached eof, the latter because
		// the last call to the extractor didn't store a good
		// value into len.

		if ( cin.fail() && !cin.eof() ) {
			cerr << "badly formatted input" << endl ;
			return 1 ;
			}
		}
	
	if ( !cout ) {
		cerr << "output error" << endl ;
		return 1 ;
		}

	return 0 ;
	}

« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: