/*
 * dspitems.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *  (c) 2007-2008 Jörg Wendel
 *
 * Date: 09.11.08
 */


//***************************************************************************
// Includes
//***************************************************************************

#include <stdlib.h>
#include <string.h>

#include <common.h>

//***************************************************************************
// Token Scanner
//***************************************************************************

class Scan
{
   public:

      Scan(const char* buf)       { asprintf(&buffer, "%s", buf); reset(); }
      ~Scan()                     { free(buffer); }

      void reset()                { p = buffer; isStr = no; }
      const char* all()           { return buffer; }
      const char* lastString()    { return _last; }
      const char* lastIdent()     { return _last; }
      int lastInt()               { return atoi(_last); }

      int isEmpty()               { return _last[0] == 0; }
      int isString()              { return isStr; }
      int isIdent()               { return !isStr && isIdent(*_last); }
      int isNum()                 { return !isStr && isNum(*_last); }
      int isLogical()             { return !isStr && isLogical(*_last); }
      int isOperator()            { return !isStr && isOperator(*_last); }
      int hasValue(const char* v) { return strcmp(Str::notNull(v), Str::notNull(_last)) == 0; }

      const char* next()          { return p; }

      int eat()
      { 
         int i = 0;

         _last[0] = 0;
         isStr = no;

         skipWs();

         while (p && *p && i < 1000)
         {
            if (*p == '"')
            {
               if (isStr)
               {
                  p++;
                  break;
               }

               isStr = yes;
               p++;

               continue;
            }

            if (!isStr && isDelimiter(*p))
               break;

            if (isStr && *p == '"')
               break;

            if (i)
            {
               if (isOperator(*_last) && !isOperator(*p) && !isStr)
               {
                  if (!isNum(*p))
                     break;
                  if (!isNumPrefix(*_last))
                     break;
               }

               if (!isOperator(*_last) && isOperator(*p) && !isStr)
                  break;

               if (isNum(*_last) && !isNum(*p) && !isStr)
                  break;
            }

            if (*p != '"')
               _last[i++] = *p;

            p++;
         }

         _last[i] = 0;

         return i == 0 ? fail : success;
      }

   private:

      void skipWs()            { while (*p && isWhiteSpace(*p)) p++; }

      int isDelimiter(char c)  { return strchr(delimiters, c) != 0; }
      int isWhiteSpace(char c) { return strchr(whitespace, c) != 0; }
      int isIdent(char c)      { return isalpha(c); }
      int isNum(char c)        { return isdigit(c) || c == '-'; }
      int isOperator(char c)   { return strchr(operators, c) != 0; }
      int isLogical(char c)    { return strchr(logicalOps, c) != 0; }
      int isNumPrefix(char c)  { return strchr(numprefix, c) != 0; }

      // data

      int isStr;
      const char* p;
      char* buffer;
      char _last[1000+TB];

      static const char* delimiters;
      static const char* operators;
      static const char* logicalOps;
      static const char* whitespace;
      static const char* numprefix;
};
