/*ident "@(#)cls4:lib/stream/intin.c 1.4" */
/*******************************************************************************
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) 1993 UNIX System Laboratories, Inc.
Copyright (c) 1991, 1992 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 <ctype.h>
#include <iostream.h>
/****************
*
* This file contains the extraction operations for integer input.
* It suffers from several flaws that ought to be fixed.
*
* All other versions depend on the extractor for longs to
* do the real work. This is OK when int==long but on a machine
* where int!=long there will be a large performance penalty.
*
* Overflow detection is limited to cases where the long is
* shortened and changes its value. This misses a lot of cases.
*
***************/
#define ISTREAM istream
static const int a10 = 'a'-10;
static const int A10 = 'A'-10;
istream& ISTREAM::operator>>(long& i)
{
// This code ignores overflows. This ought to be fixed
// in some future version.
if ( !ipfx() ) return *this ;
register int c;
register int base ;
switch ( flags()&(ios::dec|ios::hex|ios::oct) ) {
case ios::hex : base = 16 ; break ;
case ios::oct : base = 8 ; break ;
case ios::dec : base = 10 ; break ;
default : base = 0 ; break ;
}
register streambuf *nbp = bp; // put bp in a reg for efficiency
register int x = 0 ; // how many chars are processed
register int neg = 0; // set to '-' for negative number
switch (c = nbp->sgetc()) {
case '-':
neg = 1 ;
c = nbp->snextc(); ++x ;
break;
case '+':
c = nbp->snextc(); ++x ;
break;
case EOF:
setstate(failbit|eofbit) ;
break ;
}
if ( base==0 && c=='0' ) {
c = nbp->snextc() ; ++x ;
if ( c=='x' || c=='X' ) {
base = 16 ;
c = nbp->snextc() ; x = 0;
}
else {
base = 8 ;
}
} else if ( base==0 ) base = 10 ;
// for efficiency we have similar loops
// Note that when we reach this point c has already been set to
// the first char of the string to be converted.
if ( base==10 ) {
register long ii = 0;
for( ; isdigit(c) ; c=nbp->snextc(),++x ) {
/* accumulate as negative to avoid problems
* with biggest negative integer on
* 2's complement machines
*/
ii = ii*10-(c-'0');
}
i = neg ? ii : -ii;
} else if ( base < 10 ) {
register unsigned long ii = 0;
for( ; isdigit(c) ; c=nbp->snextc(),++x ) {
/* accumulate as unsigned */
register int diff = c-'0' ;
if ( diff >= base ) break ;
ii = ii*base+diff ;
}
i = neg ? -(long)ii : (long)ii;
} else if ( base>10 ) { /* hex like base */
register unsigned long ii = 0;
/* accumulate as unsigned */
for( ; isxdigit(c) ; c=nbp->snextc(),++x ) {
register int diff ;
if ( isdigit(c) ) diff = (c-'0');
else if ( isupper(c) ) diff = (c-A10);
else diff = (c-a10);
if ( diff >= base ) break ;
ii = ii*base+diff ;
}
i = neg ? -(long)ii : (long)ii;
}
if (x == 0 ) setstate(failbit) ;
// Correct treatment of this case
// (i.e. no correct digits)
// is unclear. Making it an error
// avoids certain infinite loops.
return *this;
}
istream& ISTREAM::operator>>(int& i)
{
long l;
if ( !ipfx() ) return *this ;
*this>>l ;
if ( good() ) {
i = (int)l ;
if ( i != l ) {
// overflow
setstate(failbit) ;
}
}
return *this;
}
istream& ISTREAM::operator>>(short& i)
{
long l;
if (!ipfx() ) return *this ;
*this>>l ;
if ( good() ) {
i = (short)l ;
if ( i != l ) {
// overflow
setstate(failbit) ;
}
}
return *this;
}
// The following routines deal with unsigned by reading a long and
// copying. This is certainly safe for "shorts", but is
// slightly problematic for ints and longs. It works on "common"
// machines.
istream& ISTREAM::operator>>(unsigned short& u)
{
long l ;
*this >> l ;
if ( good() ) {
u = (unsigned short)l ;
if ( u != l ) {
// overflow
setstate(failbit) ;
}
}
return *this ;
}
istream& ISTREAM::operator>>(unsigned int& u)
{
long l ;
*this >> l ;
if ( good() ) {
u = (unsigned int)l ;
if ( u != l ) {
// overflow
setstate(failbit) ;
}
}
return *this ;
}
istream& ISTREAM::operator>>(unsigned long& u)
{
long l ;
*this >> l ;
if ( good() ) {
u = (unsigned long)l ;
if ( u != l ) {
// overflow
setstate(failbit) ;
}
}
return *this ;
}
|