#ifndef TOKENIZER
#define TOKENIZER

#include <iostream>
#include <string>

/***************************************************************
 * CLASS:  Tokenizer
 * AUTHOR: Johnny Weber
 * DATE:   Mon May 13 12:15:56 EDT 2002
 * DESCRIPTION:
 *         The Tokenizer class accepts a string "text" and a 
 *         delimeter  "delim" as arguments to its constructor, 
 *         and separates text into tokens using delim as a 
 *         delimeter.
 * SAMPLE USAGE:
 *         int main(void) {
 *             Tokenizer t("0:LName:S",':');
 *             while(t.hasMoreTokens()) {
 *                string token = t.getToken();
 *                cout << "token = " << token << endl;
 *                t++;
 *             }
 *         }
 * EXCEPTIONS:
 *         TokenizerException - If constructor can not find
 *                              any occurences of delim in text
 *         TokenizerException - If Tokenizer++ is called when 
 *                              there are no more tokens.
 ***************************************************************/
class TokenizerException
{
public:
  TokenizerException(string msg) {
    cout << "TokenizerException: " << msg << endl;
  }
};

class Tokenizer
{
private:
  int     current;
  int     numTokens;
  string* tokens;
public:
  Tokenizer(string text, char delim = ' ') : 
    current(0),numTokens(0){
    // ---------------------------------------------------------
    // If we do not find the delimeter, then only one token.
    // ---------------------------------------------------------    
    if( text.find(delim) == -1 ) { 
      numTokens = 1;
      tokens = new string[1];
      tokens[0] = text;
      return;
    }
    
    int slength = text.length();
    
    // ---------------------------------------------------------
    // Calculate the number of tokens in text
    // (1) Count the number of times we find the delimeter.
    // (2) If we count x delimeters, then there are x+1 tokens
    //     so the total number of tokens is equal to number of
    //     delimeters plus 1.
    // ---------------------------------------------------------    
    /*(1)*/for(int i=0; i<slength; i++) if(text[i] == delim) numTokens++;
    /*(2)*/numTokens++;
    
    // ---------------------------------------------------------
    // Parse text
    // (1) Create an array for the tokens
    // (2) Extract tokens
    // ---------------------------------------------------------
    /*(1)*/tokens = new string[numTokens];
    /*(2)
     * We extract the tokens by finding the first occurence of 
     * of the delimeter, extracting the substring prior to this 
     * occurence, throwing this substring in the array and 
     * removing it from the text, and then repeating the process
     * until we are at the second from the last token.  The 
     * last token is whatever is left in the text string.
     */
    int i;
    int delims = numTokens - 1;
    for(i=0; i<delims; i++) {
      int delimpos = text.find(delim);
      tokens[i] = text.substr(0,delimpos);
      text = text.substr(delimpos+1, slength);
    }
    tokens[i] = text.substr(0,slength);
  }
  ~Tokenizer() { delete [] tokens; }

  bool hasMoreTokens() { return (current < numTokens); }

  int getNumTokens() { return numTokens; }
  string getToken() { return tokens[current]; }
  string getToken(int index) {
    if( index >= numTokens ) 
      throw TokenizerException("No such token");
    current = index;
    return tokens[current];
  }
  
  bool operator ++ (int sentinel) {
    if( hasMoreTokens() ) {
      current++;
      return true;
    } else {
      throw TokenizerException("Can not increment, no More Tokens!");
    }
  }
};

#endif
