// saved from url
// http://www-cs.canisius.edu/PL_TUTORIALS/C++/EXAMPLES/MRD/SRC/parseline.c -->

//---------------------------------- parseline.c -------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parseline.h"

Parseline::Parseline (char *line)
{
     numwords = 0;
     parse (line);
}

Parseline::Parseline ()
{
     numwords = 0;
}

void Parseline::set (char *line)
{
     freeup ();
     numwords = 0;
     parse (line);
}

Parseline::~Parseline()
{
     freeup();
}

void Parseline::freeup ()
{
     int i;
     for (i=0; i<numwords; i++) {
          delete [] (words[i]);
          words[i] = 0;
     }
}

int Parseline::parse (char *line)
{
     int i;
     char newword[MAXWORDLENGTH+1];
     char *string = line;

     numwords = 0;

     while (1) {

          /* Check to see if there is room for another word in our
             array.  If not, then we just as well quit and not waste our
             time looking for the next word. */

          if (numwords == MAXWORDS) return 1;

          /* Skip over leading blanks */

          while (string && *string == ' ') string++;
          if (*string == 0) return 0;

          /* At this point, we know we are sitting on the first character
             of our next word and are not at the end of the string.  
             So we collect the characters into newword until we find a 
             blank or a NULL.  If the first character is a double quote
             mark, then this is not really part of our word, and we do not
             stop at blanks, but continue on until we see the next double 
             quote.  Right now we can't handle embedded quote marks.
          */

          i = 0;
          if (*string == '\"') {
			  string++;
               while (i < MAXWORDLENGTH) {
                    if (*string == 0 || *string == '\"') break;
                    newword[i] = *string;
                    string++;
                    i++;
               }
               if (*string == '\"') string++;
          }

		  else {
               while (i < MAXWORDLENGTH) {
                    if (*string == 0 || *string == ' ' || *string == '|') break;
                    newword[i] = *string;
                    string++;
                    i++;
               }
          }

          newword[i] = 0;   /* ensure an ASCII null at end of newword. */

          /* install into array */
          words[numwords] = new char [strlen(newword)+5];
          strcpy (words[numwords], newword);  

          numwords++;

          /* If we were stopped by an ASCII NULL above, we exit the loop
             and immediately return to the calling routine. */
 
          if (*string == 0) break;

          /* Else we were stopped by the terminator character.  Skip
             over it. */

          if (*string == ' '|| *string == '|') string++;
		  
     }
     return 0;
}

void Parseline::addword (char *newvalue)
{
	 words[numwords]  = new char[strlen(newvalue)+5];
     strcpy (words[numwords], newvalue);
	 numwords++;
}

void Parseline::setword (int fieldnum, char *newvalue)
{
	 if (fieldnum < numwords) {
		 delete words[fieldnum];
		 words[fieldnum] = new char[strlen(newvalue)+5];
		 strcpy (words[fieldnum], newvalue);
	 }
}

// The following is used when you need to write out the fields
// with blanks in between.  
// The width of the field is determined by getting the field's width from
// the character string widths.  This consists of a number of integers,
// separated by blanks.  If the first character is a dollar sign, then
// there is just one width, which follows the number sign.
// The resulting line goes into "result."

void Parseline::makeline (char *result, char *widths)
{
     int use_default = 0, width;
     int wi=0;   // width index

     if (widths[0] == '$') {
          use_default = 1;
          width = atoi(&widths[1]);
     }

     strcpy (result, "");

     for (int i=0; i<numwords; i++) {
          char temp[1000];
          int embedded_blanks = 0;
          strcpy (temp, words[i]);
          for (int j=0; j<strlen(temp); j++)
               if (temp[j] == ' ') {
                    embedded_blanks = 1;
                    break;
               }
          if (embedded_blanks)
               strcat (result, "\"");
          strcat (result, words[i]);
          if (embedded_blanks)
               strcat (result, "\"");


          int used = strlen(temp);
          if (embedded_blanks) used += 2;

          if (i == numwords-1) continue;  // don't pad at end with blanks
          // get next number from widths
          char num[100];
          int k = 0;

          if (!use_default) {
               while (1) {
                    char ch = widths[wi];
                    if (ch == 0) break;
                    wi++;
                    if (ch == ' ') break;
                    num[k++] = ch;
               }
               num[k] = 0;
               width = atoi (num);
          }
          int leftover = width - used;
          if (leftover <= 0) leftover = 1;
          while (leftover) {
               leftover--;
               strcat (result, " ");
          }
     }
}

//  The following is used to make up a line with just one blank in between.

void Parseline::makeline (char *result)
{
     makeline (result, "$1");
}

