// ============================================================ // // io.cpp // // Copyright 2002, Dennis Meilicke and Rene Peralta // // ============================================================ // // Description: // // Input/Output functions. // // ============================================================ #include // // These were basically copied from LrgNum. // They need to be re-implemented. Specificaly, // they need to be updated to the ANSI version // of the streams library. // #include #include // // AIX: for isspace( ) // #include // // AIX: for exit( ) // #include // // This should be in a header, somewhere... // ? why not base.h ? // I put the definition in digit.h, see log 20050203,Rene. // // #define maxDigitsBase10 1000 // #define maxDigitsBase10 (digitSizeInBits*100*LN3_DIGIT_ARRAY_SIZE)/333 // log base 2 of 10 is about 3.3219280948 // ============================================================ void Read( Base *A, istream &stream ) // // 1. Change this to use the lookahead mechanism to determine // if the number contains a sign. // 2. This method should have a 'base' parameter, just like // Print(). // 3. Add support for other bases. // 4. If no digits can be read, then the stream should be // made invalid. Consider: // int x; // cin >> x; // if the user enters 'abc', then the stream will close. // { char _str[ maxDigitsBase10 + 3 ]; // +EOL, sign, and fudge char *str = _str; char ch; // // Gobble up whitespace // // Note: we treat an EOF character as whitespace, so that the // steam will be invalidated at End-Of-File. // do { ch = stream.get(); } while( stream && (isspace(ch) || ch==EOF) ); // // If the stream is invalid, there is no number on the input // stream. Hence we do not modify A. // if( !stream ) { return; } // // Check for an explicit sign. Note the (neat) fall-through hack // in the switch() statement. // switch( ch ) { case '-': *(str++) = '-'; case '+': ch=stream.get(); break; } for( size_t i=0 ; isize == 0 ) { stream << "0"; return; } if( X->sign == negative ) { stream << "-"; } //for( long i=NumBits()-1 ; i>=0 ; i-- ) // stream << Bit(i); } // ---------------------------------------------------------------------- // static void PrintDecimal( const Base* const X, ostream &stream ) { static size_t digitWidth = ( sizeof( digit_t) == 4 ) ? 4 : 9; static size_t digitMod = ( sizeof( digit_t) == 4 ) ? 10000 : 1000000000; if( X->size == 0 ) { stream << "0"; return; } Base x( *X ); Base y; x.sign = positive; long i; static sdigit_t digit[1000 + 1]; // s/b/ size of array plus some... for( i=0 ; x.size!=0 ; i++ ) { Divide( &x, digitMod, &y, &digit[i] ); x = y; } // // Save the state of the stream... // char fillChar = stream.fill(); short base = (stream.flags() & ios::oct) ? 8 : (stream.flags() & ios::hex) ? 16 : 10; // // The first 'digit' is a special case... do not set fill // or width. // i--; if( i > 0 ) { long width = stream.width(); long w = width - ( i * digitWidth ); if( w > 0 ) stream << setw(w); } if( X->sign == negative ) digit[i] = -digit[i]; stream << dec << digit[i]; ios::fmtflags showpos = stream.setf( ios::fmtflags(0), ios::showpos ); for( i-- ; i>=0 ; i-- ) { stream << setfill('0') << setw(digitWidth) << digit[i]; } // // Reset the state of the stream... // //stream << setfill( fillChar ); // doesn't work under MS w/STL stream.fill( fillChar ); stream.setf( showpos, ios::showpos ); switch( base ) { case 8: stream << oct; break; case 10: stream << dec; break; case 16: stream << hex; break; } } // ---------------------------------------------------------------------- // static void PrintHex( const Base* const X, ostream &stream ) // // Doesn't properly handle setw() by caller. // Doesn't properly handle showpos. // { if( X->size == 0 ) { stream << "0"; return; } if( X->sign == negative ) { stream << "-"; } const digit_t *x = X->digit + ( X->size - 1 ); ios::fmtflags base = stream.setf( ios::hex, ios::basefield ); stream << *(x--); for( ; x >= X->digit ; x-- ) stream << setw(8) << setfill('0') << *x; stream.setf( base, ios::basefield ); return; } // ---------------------------------------------------------------------- // static void PrintIB( const Base* const X, ostream &stream ) { if( X->size == 0 ) { stream << "0"; return; } if( X->sign == negative ) { stream << "-"; } for( const digit_t *x=X->digit + ( X->size - 1 ) ; x>X->digit ; x-- ) stream << *x << ","; stream << *(X->digit); return; } // ============================================================ void Print( const Base* const X, ostream &stream, short base ) // // Remember: fill and base are "sticky" (showpos) // width only works for the next integer. // { // // If no base has been specified, use the base currently // set in the stream. // if( base == -1 ) // use whatever base is set for the stream. { base = ( stream.flags( ) & ios::oct ) ? 8 : ( stream.flags( ) & ios::hex ) ? 16 : 10; } switch( base ) { case 0: // 'internal' base. PrintIB( X, stream ); break; case 2: PrintBinary( X, stream ); break; case 8: // Not yet implemented. break; case 10: PrintDecimal( X, stream ); break; case 16: PrintHex( X, stream ); break; default: // This should really toss an exception cerr << "Invalid base in Print( )" << endl; exit(1); } }