// This may look like C code, but it is really -*- C++ -*-
 
//<copyright>
// 
// Copyright (c) 1995-1996
// Institute for Information Processing and Computer Supported New Media (IICM)
// Graz University of Technology, Austria.
// 
//</copyright>
 
//<file>
//
// Name:       nstr.h
//
// Purpose:    NString Class (RString Extension for Number Conversion)
//
// Created:    11 Oct 95    Georg Essl
//
// Modified:   26 Sep 96    Georg Essl
//
//
//
// Description:
//
// If a numbers are passed with in RStrings this numbers need to be converted
// into int, long, float etc. The NString class adds new method to the RString
// class to cope with this need.
//
//</file>

#ifndef hg_utils_nstr_h
#define hg_utils_nstr_h

// ***** INCLUDES *****

#include <math.h>
#include "fields.h"
#include "str.h"
#include <string.h>
// ***** OS Dependant Stuff ******

#ifndef trunc
// #define trunc(x) x >=0.0 ? floor(x) : ceil(x)
double trunc(double x);
#endif

//<class>
//
// Name:       NSCharField
//
// Purpose:    Format converting character field
// 
//
// Public Interface:
//
// - NSCharField()
//   Default constructor. Empty field, initial field size is zero.
//
// - NSCharField( int size )
//   Constructor. Empty field, initial field size is size.
//
// - NSCharField& write ( const NSCharField& )
//   Appends another NSCharField. Returns *this.
//
// - NSCharField& write ( const char* s, int len )
//   Appends a number of len characters from character array
//   s. Returns *this.
//
// - NSCharField& write ( const RString& )
//   Appends an RString . Returns *this.
//
// - NSCharField& write ( const char* )
//   Appends a 0-terminated character string. Returns *this.
//
// - NSCharField& write ( char )
//   Appends a character. Returns *this.
//
// - NSCharField& write ( int, const RString& format ="%d" )
//   Appends an integer. The integer is converted according to a
//   format string as known from printf except, that all format fields
//   will operate for an integer. Unknown or invalid conversion types
//   are treated as %d.  Returns *this.
//
// - NSCharField& write ( unsigned int, const RString& format ="%u" )
//   Appends an unsigned integer. The integer is converted according
//   to a format string as known from printf except that all format
//   fields will operate for an unsigned integer. Unknown or invalid
//   conversion types are treated as %u. Returns *this.
//
// - NSCharField& write ( long, const RString& format ="%ld" )
//   Appends a long integer. The integer is converted according to a
//   format string as known from printf except that all format fields
//   will operate for a long integer. Unknown or invalid conversion
//   types are treated as %l. Returns *this.
//
// - NSCharField& write ( unsigned long, const RString& format ="%lu" )
//   Appends an unsigned long integer. The integer is converted
//   according to a format string as known from printf except that all
//   format fields are treated as %lu. Returns *this.
//
// - NSCharField& write ( float, const RString& format ="%g" )
//   Appends a float. The float is converted according to a format
//   string as known from printf except that all format fields are
//   treated as %g.  Returns *this.
//
// - NSCharField& write ( double, const RString& format ="%g" )
//   Appends a double float. The float is converted according to a
//   format string as known from printf expect that all format fields
//   are treated as %g. Returns *this.
//
// - NSCharField& write_format ( char, const RString& format = "%c" )
//   Appends a character. The character is first embedded into a
//   format string as known from printf. Note, that all format fields
//   are treated as %c. Returns *this.
//
// - NSCharField& write_format ( const RString&, const RString& format = "%s" )
//   Appends an RString which is first embedded into a format string
//   as known frin printf, except that all format fields are treated
//   as %s.  Returns *this.
//
// -  RString getRString()
//    Creates an RString from *this. 
//
//</class>

Fieldsdeclare (NSCharFieldBase, char) ;

class NSCharField : public NSCharFieldBase
{
public:
    NSCharField() : NSCharFieldBase() {}
    NSCharField(int size) : NSCharFieldBase(size) {}
    
    NSCharField& write (const NSCharField&);
    NSCharField& write (const char*, int) ;
    NSCharField& write (const RString&) ;
    NSCharField& write (const char*) ;
    NSCharField& write (char) ;
    NSCharField& write (int, const RString& format ="%d") ;
    NSCharField& write (long, const RString& format ="%ld") ;
    NSCharField& write (unsigned int, const RString& format ="%u");
    NSCharField& write (unsigned long, const RString& format ="%lu");
    NSCharField& write (float, const RString& format ="%g") ;
    NSCharField& write (double, const RString& format ="%g") ;
    NSCharField& write_format (char, const RString& format = "%c");
    NSCharField& write_format (const RString&, const RString& format = "%s");

    RString getRString();
protected:
    void convertValue(void);                      // Converts value according to format.
    
    void padChar(int,long);                       // Left/Right aligned width padding.
    
    void clearFormat();                           // Clears current format.
    
    void digits2String(unsigned long, long, int); // Converts digits to string
    void digits2String(double, long, int); // Converts digits to string
    void long2String(long,int);                   // Converts long to string
    void float2String(double);                    // Converts double to string 
    
    void parseFormat(const RString&);             // Parses and converts format.
    
private:
    enum ConvTypes {INT, FLOAT, STRING, CHAR};    // Known Conversion Types
    ConvTypes convtype_;
    char argchar_;                                // Typed Arguments
    RString argstring_;
    long arglong_;
    double argdouble_;
    boolean forceleftalign_;                      // Prefix behavior '-'
    boolean forceshowsign_;                       // Prefix behavior '+'
    boolean forceprefixchars_;                    // Prefix behavior '#'
    boolean forceleadingzeros_;                   // Prefix behavior '0'
    boolean forcespacepad_;                       // Prefix behavior ' '
    int width_;                                   // Field width
    int precision_;                               // Conversion precision
    boolean ignoreshort_;                         // Ignored format characters 
    boolean ignorelong_;
    enum IntFormat {SIGNEDDECINT, UNSIGNEDDECINT, OCTALINT, HEXINT}; // Int Conversion Types
    IntFormat intformat_;
    enum FloatFormat {PLAINFLOAT, EXPONENTFLOAT}; // Float Conversion Types             
    FloatFormat floatformat_;
    boolean capitals_;                            // Capitalized alpha characters
    boolean adaptivefloat_;                       // %g for floats
    boolean ignorechar_;                          // Ignored known format types
    boolean ignorestring_;
} ;

inline RString NSCharField::getRString()
{
    return  RString(data(),count());
}
inline NSCharField& NSCharField :: write (const char* s, int len) {
    while (len--) 
        append (*s++) ;
    return *this ;
}
inline NSCharField& NSCharField :: write (const NSCharField& n)
{
    return write(n.data(), n.count());
}
inline NSCharField& NSCharField :: write (const RString& s) {
    return write (s.string(), s.length()) ;
}
inline NSCharField& NSCharField :: write (const char* s) {
    write (s, strlen(s)) ;
    return *this ;
}
inline NSCharField& NSCharField :: write (char c) {
    append (c) ;
    return *this ;
}

//<class>
//
// Name:      NString
//
// Purpose:   Convert RStrings to numbers.
//
//   This Class is a subclass of the RString class. See the respective header
//   file for the inhertited part of the public interface.
//
// Public Interface:
//
// - NString()
//   Default Constructor. An empty string.
//
// - NString(const RString&)
//   Constructs (Creates) an NString copying the RString.
//
// - NString(const char*)
//   Constructs (Creates) an NString copying char*.
//
// - NString(const char*,int len)
//   Constructs (Creates) an NString copying char* with len.

//
// - int toInt(int base =0)
//   Returns the Integer (int) value of the NString. If the base is
//   zero numbers with one or more leading zeros are treated as octal,
//   leading 0x or 0X are treated as hexadecimal all others are
//   decimal.  The behavior is the same as strtol. The base may be 0
//   to 36. Any other base makes the method assert.
//
// - long toLong(int base=0)
//   Returns the long integer value of the NString. If the base is
//   zero numbers with one or more leading zeros are treated as octal,
//   leading 0x or 0X are treated as hexadecimal all others are
//   decimal.  The behavior is the same as strtol. The base may be 0
//   to 36. Any other base makes the method assert.
//
// - unsigned long toUnsignedLong(int base=0)
//   Returns the unsigned long integer value of the NString. If the
//   base is zero numbers with one or more leading zeros are treated
//   as octal, leading 0x or 0X are treated as hexadecimal all others
//   are decimal.  The behavior is the same as strtol. The base may be
//   0 to 36. Any other base makes the method assert.
//
// - double toDouble()
//   Returns the double float value of the NString. The behavior is
//   the same as strtod.
//
// - NString& loadChar(const char, const RString& ="%c")
//   Loads (that is, overwrites current contents) with a character,
//   which is first embedded and converted using a printf format
//   string. Refer to NSCharField::write_format(char, const
//   RString&). Returns *this.
//
// - NString& loadString(const RString&, const RString& ="%s")
//   Loads (that is, overwrites current contents) with an RString,
//   which is first embedded and converted using a printf format
//   string. Refer to NSCharField::write_format(const RString&, const
//   RString&). Returns *this.
//
// - NString& loadLong(const long , const RString& = "%ld" )
//   Loads (that is, overwrites current contents) with a long integer,
//   which is first converted using a printf format string. Refer to
//   NSCharField::write(long, const RString&). Returns *this.
//
// - NString& loadDouble(const double, const RString& = "%g");
//   Loads (that is, overwrites current contents) with a double float,
//   which is first converted using a printf format string. Refer to
//   NSCharField::write(double, const RString&). Returns *this.

// - NString& appendChar(const char, const RString& ="%c")
//   Appends a character, which is first embedded and converted using
//   a printf format string. Refer to NSCharField::write_format(char,
//   const RString&). Returns *this.
//
// - NString& appendString(const RString&, const RString& ="%s")
//   Appends an RString, which is first embedded and converted using a
//   printf format string. Refer to NSCharField::write_format(const
//   RString&, const RString&). Returns *this.
//
// - NString& appendLong(const long , const RString& = "%ld" )
//   Appends a long integer, which is first converted using a printf
//   format string. Refer to NSCharField::write(long, const
//   RString&). Returns *this.
//
// - NString& appendDouble(const double, const RString& = "%g");
//   Appends a double float, which is first converted using a printf
//   format string. Refer to NSCharField::write(double, const
//   RString&). Returns *this.


//</class>

class NString : public RString 
{
public:
    NString() : RString() {}
    NString( const RString& str) : RString( str ) {}
    NString( const char* it) : RString(it) {}
    NString( const char* it, int len) : RString(it, len) {}

    int toInt( int base=0 );
    long toLong( int base=0 ); 
    unsigned long toUnsignedLong( int base=0 );
    double toDouble();
    
    NString& loadChar(const char, const RString& ="%c");
    NString& loadString(const RString&, const RString& ="%s");
    NString& loadLong(const long , const RString& = "%ld" );
    NString& loadDouble(const double, const RString& = "%g");
    
    NString& appendChar(const char, const RString& ="%c");
    NString& appendString(const RString&, const RString& ="%s");
    NString& appendLong(const long , const RString& = "%ld" );
    NString& appendDouble(const double, const RString& = "%g");
    
private:
    static NSCharField nscharfield_;
};

#endif /* hg_utils_nstr_h */
