/* C++ code produced by gperf version 2.7.2 */
/* Command-line: /usr/bin/gperf -D --initializer-suffix=,0 --struct-type --enum --omit-struct-type --readonly-tables --language=C++ --class-name=function_hash drizzled/function_hash.gperf  */
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Copyright (C) 2008 Sun Microsystems
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */


/* This file includes all functions */

#include <drizzled/foreign_key.h>
#include <drizzled/sql_yacc.h>
#include <drizzled/lex_symbol.h>

using namespace drizzled;

/*
  Symbols are broken into separated arrays to allow field names with
  same name as functions.
  These are kept sorted for human lookup (the symbols are hashed).

  NOTE! The symbol tables should be the same regardless of what features
  are compiled into the server. Don't add ifdef'ed symbols to the
  lists
*/
/* maximum key range = 54, duplicates = 1 */

class function_hash
{
private:
  static inline unsigned int hash (const char *str, unsigned int len);
public:
  static const struct st_symbol *in_word_set (const char *str, unsigned int len);
};

inline unsigned int
function_hash::hash (register const char *str, register unsigned int len)
{
  static const unsigned char asso_values[] =
    {
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 15, 10, 10,  2,  0,
      59, 15, 59, 59, 59, 59, 59, 20, 20, 59,
      30, 59, 20,  0, 20, 59,  8, 10, 15, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
      59, 59, 59, 59, 59, 59
    };
  return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
}

const struct st_symbol *
function_hash::in_word_set (register const char *str, register unsigned int len)
{
  enum
    {
      TOTAL_KEYWORDS = 28,
      MIN_WORD_LENGTH = 3,
      MAX_WORD_LENGTH = 12,
      MIN_HASH_VALUE = 5,
      MAX_HASH_VALUE = 58
    };

  static const struct st_symbol wordlist[] =
    {
      {"STD",STD_SYM},
      {"SUBDATE",SUBDATE_SYM},
      {"SYSDATE",SYSDATE},
      {"DATE_ADD",DATE_ADD_INTERVAL},
      {"STDDEV",STD_SYM},
      {"VARIANCE",VARIANCE_SYM},
      {"CURDATE",CURDATE},
      {"DATE_SUB",DATE_SUB_INTERVAL},
      {"ADDDATE",ADDDATE_SYM},
      {"SUM",SUM_SYM},
      {"SUBSTRING",SUBSTRING},
      {"MID",SUBSTRING},
      {"SUBSTR",SUBSTRING},
      {"EXTRACT",EXTRACT_SYM},
      {"SYSTEM_USER",USER},
      {"SESSION_USER",USER},
      {"NOW",NOW_SYM},
      {"CAST",CAST_SYM},
      {"COUNT",COUNT_SYM},
      {"MAX",MAX_SYM},
      {"STDDEV_POP",STD_SYM},
      {"STDDEV_SAMP",STDDEV_SAMP_SYM},
      {"MIN",MIN_SYM},
      {"TRIM",TRIM},
      {"VAR_POP",VARIANCE_SYM},
      {"VAR_SAMP",VAR_SAMP_SYM},
      {"GROUP_CONCAT",GROUP_CONCAT_SYM},
      {"POSITION",POSITION_SYM}
    };

  static const signed char lookup[] =
    {
       -1,  -1,  -1,  -1,  -1,   0,  -1, -37, -27,  -2,
       -1,  -1,   3,  -1,   4,  -1,   5,   6,  -1,  -1,
        7,  -1,   8,   9,  10,  11,  12,  13,  -1,  -1,
       -1,  14,  15,  16,  17,  18,  -1,  -1,  19,  -1,
       20,  21,  -1,  22,  23,  24,  25,  26,  -1,  -1,
       -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  27
    };

  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
    {
      register int key = hash (str, len);

      if (key <= MAX_HASH_VALUE && key >= 0)
        {
          register int index = lookup[key];

          if (index >= 0)
            {
              register const char *s = wordlist[index].name;

              if (*str == *s && !strcmp (str + 1, s + 1))
                return &wordlist[index];
            }
          else if (index < -TOTAL_KEYWORDS)
            {
              register int offset = - 1 - TOTAL_KEYWORDS - index;
              register const struct st_symbol *wordptr = &wordlist[TOTAL_KEYWORDS + lookup[offset]];
              register const struct st_symbol *wordendptr = wordptr + -lookup[offset + 1];

              while (wordptr < wordendptr)
                {
                  register const char *s = wordptr->name;

                  if (*str == *s && !strcmp (str + 1, s + 1))
                    return wordptr;
                  wordptr++;
                }
            }
        }
    }
  return 0;
}
