/*****************************************************
           File Name: STR_EDIT.C
         Description: Library of functions for editing
                      strings
Global Function List: str_center
                      str_delete
                      str_insert
                      str_ljust
                      str_ltrim
                      str_mrplc
                      str_ocat
                      str_repeat
                      str_rjust
                      str_rplc
                      str_rtrim
                      str_trim
                      str_vcat
         Portability: Standard C
******************************************************/

/* Standard C */
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

/* Own */
#include <str_edit.h>

/*****************************************************
         Name: str_center
   Parameters: Str - string to center
               Len - num of chars of centered string
       Return: Str
  Description: Centers a string in a desired length
               by removing tabs and adding spaces
               to both sides of string.
*****************************************************/
char *str_center( char *Str, size_t Len )
   {

   size_t LenOrg;

   /* Trim spaces and tabs off the string */ 
   str_trim( Str, " \t" );

   LenOrg = strlen( Str );
   if ( Len <= LenOrg )
      {
      /* The desired string length is shorter than
      ** the original so return */
      return ( Str );
      }

   /* Add the spaces to each side */
   str_rjust( Str, ( LenOrg + Len ) / 2 );
   str_ljust( Str, Len  );

   return ( Str );

   }   /* function str_center */


/*****************************************************
         Name: str_delete
   Parameters: Str - string to edit
               Pos - index to start deleting chars at
               Num - number of charcters to delete
       Return: Str
  Description: Modifies Str, by deleting Num chars
               beginning at Pos.
*****************************************************/
char *str_delete( char *Str, char *Pos, size_t Num )
   {

   size_t Len = strlen( Str );

   if ( ( Pos >= &Str[Len] ) || ( Num == 0 ) )
      {
      /* Outside string or no chars to delete */
      return ( Str );
      }

   Num = min( Num, strlen( Pos ) );
   if ( Num )
      {
      /* Delete characters by contactenating */
      memmove( Pos, &Pos[Num],
            strlen( &Pos[Num] ) + 1 );
      }

   return ( Str );

   }   /* function str_delete */


/*****************************************************
         Name: str_insert
   Parameters: Str - string to edit
               Pos - pointer to location withing Str
               Insrt - string to insert into Str
       Return: Str
  Description: Inserts a string Insrt into Str at Pos
*****************************************************/
char *str_insert( char *Str, char *Pos, char *Insrt )
   {

   size_t Len = strlen( Insrt );
   char *Tmp   = &Pos[Len];

   memmove( Tmp, Pos, strlen( Pos ) + 1 );
   memmove( Pos, Insrt, Len );

   return ( Str );

   }   /* function str_insert */


/*****************************************************
         Name: str_ljust
   Parameters: Str - string to left justify
               Len - length of string
       Return: Str
  Description: Pads right end of Str with spaces to
               left justify Str to a new length Len.
*****************************************************/
char *str_ljust( char *Str, size_t Len )
   {

   size_t LenOrg = strlen( Str );
   char *StrEnd = &Str[LenOrg];

   Len = max( Len, LenOrg ) - LenOrg;
   StrEnd[Len] = '\0';

   while ( Len )
      {
      Len--;
      StrEnd[Len] = ' ';
      }

   return ( Str );

   }   /* function str_ljust */


/*****************************************************
         Name: str_ltrim
   Parameters: Str - string to trim
               Trim - string containing chars to trim
       Return: Str
  Description: Delete characters from the left end of
               Str that are contained in Trim
*****************************************************/
char *str_ltrim( char *Str, char *Trim )
   {

   size_t Num = strspn( Str, Trim );

   str_delete( Str, Str, Num );

   return ( Str );

   }   /* function str_ltrim */


/*****************************************************
         Name: str_mrplc
Expanded Name: String Multiple Search and Replace
   Parameters: Str - string to edit
               Find - search string
               Rplc - replacement string
       Return: Str
  Description: Multiple search and replace.  All
               occurrences of Find within Str are
               replaced with Rplc.
*****************************************************/
char *str_mrplc( char *Str, char *Find, char *Rplc )
   {

   char *StrWork = Str;
   size_t LenRplc = strlen( Rplc );

   while ( ( StrWork =
         strstr( StrWork, Find ) ) != NULL )
      {
      str_delete( Str, StrWork, strlen( Find ) );
      str_insert( Str, StrWork, Rplc );
      StrWork += LenRplc;
      }

   return ( Str );

   }   /* function str_mrplc */


/*****************************************************
         Name: str_ocat
Expanded Name: Concatenate overlapped strings
   Parameters: Dest - destination string
               Str - string to concat
       Return: Dest
  Description: Behaves the same as strcat in string.h.
               This version will work for strings that
               overlap in memory.
*****************************************************/
char *str_ocat( char *Dest, char *Str )
   {

   return ( (char *)memmove(
         (void *)&Dest[strlen( Dest )],
         (void *)Str, strlen( Str ) + 1 ) );

   }   /* function str_ocat */


/*****************************************************
         Name: str_repeat
   Parameters: Str - string buffer to load
               Rpt - repition string
               Num - number of repitions
       Return: Str
  Description: Builds a string of length Num, by
               repeating a substring Rpt.
*****************************************************/
char *str_repeat( char *Str, char *Rpt, size_t Num )
   {

   size_t Len = strlen( Rpt );

   if ( Len == 1 )
      {
      /* The string is only one character */
      memset( Str, *Rpt, Num );
      }
   else
      {

      size_t i, j;

      /* Build Str with repitions of Rpt */
      for ( i = 0, j = 0; i < Num; i++ )
         {
         Str[i] = Rpt[j++];
         j %= Len;
         }   /* for i */

      }   /* else */

   Str[Num] = '\0';

   return ( Str );

   }   /* function str_repeat */


/*****************************************************
         Name: str_rplc
Expanded Name: String Search and Replace
   Parameters: Str - string to edit
               Find - search string
               Rplc - replacement string
       Return: Str
  Description: Search and replace.  First
               occurrences of Find within Str is
               replaced with Rplc.
*****************************************************/
char *str_rplc( char *Str, char *Find, char *Rplc )
   {

   char *StrWork = strstr( Str, Find );

   if ( StrWork )
      {
      str_delete( Str, StrWork, strlen( Find ) );
      str_insert( Str, StrWork, Rplc );
      }

   return ( Str );

   }   /* function str_rplc */


/*****************************************************
         Name: str_rjust
Expanded Name: String Right Justify
   Parameters: Str - string to edit
               Len - new length of string
       Return: Str
  Description: Pads the left end of string so that it
               is right justified to a total length of
               Len.
*****************************************************/
char *str_rjust( char *Str, size_t Len )
   {

   size_t LenOrg = strlen( Str );

   Len = max( LenOrg, Len ) - LenOrg;

   if ( Len )
      {
      memmove( &Str[Len], Str, LenOrg + 1 );
      while ( Len )
         {
         Len--;
         Str[Len] = ' ';
         }
      }

   return ( Str );

   }   /* function str_rjust */


/*****************************************************
         Name: str_rtrim
   Parameters: Str - string to trim
               Trim - string of characters to trim
       Return: Str
  Description: Delete characters from the right end
               of Str that are contained in Trim
*****************************************************/
char *str_rtrim( char *Str, char *Trim )
   {

   char *StrWork = &Str[strlen( Str ) - 1];

   /* Look for last character in string not being
   ** in trim string */
   while ( ( Str != StrWork ) &&
         ( strspn( StrWork, Trim ) != 0 ) )
      {
      *StrWork-- = '\0';
      }

   return ( Str );

   }   /* function str_rtrim */


/*****************************************************
         Name: str_trim
   Parameters: Str - string to trim
               Trim - string of characters to trim
       Return: Str
  Description: Delete characters from both ends of Str
*****************************************************/
char *str_trim( char *Str, char *Trim )
   {

   str_ltrim( Str, Trim );
   str_rtrim( Str, Trim );

   return ( Str );

   }   /* function str_trim */

/*****************************************************
         Name: str_vcat
   Parameters: Dest - destination string
               Str1 - required first string
       Return: Dest
  Description: Variable argument version of strcat.
               Concatenates a list of strings into
               a destination string.  The last
               argument must be a NULL pointer.
*****************************************************/
char *str_vcat( char *Dest, char *Str1, ... )
   {

   va_list VarArgList;
   char *Str;

   /* Initialize variable arguments */
   va_start( VarArgList, Dest );

   /* Get first var arg string */
   Str = va_arg( VarArgList, char * );

   strcat( Dest, Str1 );
   while ( Str != NULL )
      {

      /* Loop though all the arguments */
      strcat( Dest, Str );

      /* Get the next string */
      Str = va_arg( VarArgList, char * );

      }

   /* Clean up */
   va_end( VarArgList );

   return ( Dest );

   } /* function str_vcat */

/* End of File */

