#include <string.h>

/*
     class CHARACTER
     ===============
     A minimal class used when passing string arguments from C++
     to FORTRAN 77 (received as FORTRAN 77 CHARACTER strings), and
     subsequently returned back to C++ as properly zero terminated
     strings.

     Method used for zero-termination:
     =================================
     When the CHARACTER destructor is activated the zero-termination
     of the c-string is automatically managed. Zero termination is
     also done each time a string array is subscripted using
     CHARACTER::operator()(size_t index)

     FORTRAN Assumptions:
     ====================
     (1) F77 truncates strings when CHARACTER variable is short
     (2) F77 pads variable with blanks when assigned string is short
     (3) F77 represents a string as a pointer followed by a length
     (4) A string array is stored in contiguous memory

     Author: Carsten A. Arnholm, 20-AUG-1995

     Updates:
         04-MAR-1996 Added features for handling arrays of strings
         16-MAR-1996 Tested array features, explicit padding included
         29-JUL-1996 Tested portability to SGI/Unix, moved decl. of destructor
         04-APR-1997 Using strncpy instead of strcpy in operator=(char* str);
   */

class CHARACTER {
  public:
   CHARACTER(char* cstring);
   CHARACTER(char* cstring, const size_t lstr);
   ~CHARACTER();
   CHARACTER operator()(size_t index);
   void  pad(size_t first,size_t howmany=1);
   void  operator=(char* str);
   operator char*();
  public:
   char*   rep;  // Actual string
   size_t  len;  // String length
};

inline CHARACTER::CHARACTER(char* cstring)
   : rep(cstring), len(strlen(cstring))
{};

inline CHARACTER::CHARACTER(char* cstring, const size_t lstr)
   : rep(cstring), len(lstr)
{
   // find position from where to start padding
   size_t slen   = strlen(rep);                // upper limit
   size_t actual = (slen < len)? slen : len;   // actual <= len.
   for(size_t i=actual;i<len;i++) rep[i]=' ';  // Do the padding.
}

inline CHARACTER::~CHARACTER() {
   if(rep[len] == '\0') return;     // catches string constants

   for(int i=len-1;i>=0;i--) {
      if(rep[i] == '\0') break;      // already zero terminated

      if(rep[i] != ' ') {            // non-blank discovered, so
	 rep[i+1] = '\0';            // zero-terminate and jump out
	 break;
      }
   }
}

inline CHARACTER CHARACTER::operator()(size_t index)
{
   // Construct a temporary CHARACTER object for the array element
   // identified by "index" in order to zero-terminate that element
   size_t pos = index*len;          // start pos of array element
   CHARACTER element(rep+pos,len);  // construct new CHARACTER.
   return element;                  // destructor called here.
}

inline void  CHARACTER::pad(size_t first,size_t howmany)
{

   size_t pos=0,i=0,stop=first+howmany-1;
   for(size_t index=first; index<=stop; index++) {
      pos = index*len;
      size_t slen   = strlen(rep+pos);             // upper limit
      size_t actual = (slen < len)? slen : len;
      for(i=pos+actual;i<pos+len;i++) rep[i]=' ';  // Do the padding.
   }
}

inline void CHARACTER::operator=(char* str)
{
   strncpy(rep,str,len);    // this will copy a zero if str < rep
   rep[len-1] = '\0';       // zero terminate in case strncpy did not
   size_t slen   = strlen(rep);                // upper limit
   size_t actual = (slen < len)? slen : len;   // actual <= len.
   for(size_t i=actual;i<len;i++) rep[i]=' ';  // Do the padding.
}

inline CHARACTER::operator char*()
{
   return rep;
}


syntax highlighted by Code2HTML, v. 0.9.1