⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key_list.cpp

📁 ACE源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    {
      list1->next = merge (list1->next, list2);
      return list1;
    }
}

// Applies the merge sort algorithm to recursively sort the key list
// by frequency of occurrence of elements in the key set.

List_Node *
Key_List::merge_sort (List_Node *a_head)
{
  if (!a_head || !a_head->next)
    return a_head;
  else
    {
      List_Node *middle = a_head;
      List_Node *temp = a_head->next->next;

      while (temp)
        {
          temp = temp->next;
          middle = middle->next;
          if (temp)
            temp = temp->next;
        }

      temp = middle->next;
      middle->next = 0;
      return merge (merge_sort (a_head), merge_sort (temp));
    }
}

// Returns the frequency of occurrence of elements in the key set.

inline int
Key_List::occurrence (List_Node *ptr)
{
  int value = 0;

  for (char *temp = ptr->keysig; *temp; temp++)
    value += Vectors::occurrences[(int) *temp];

  return value;
}

// Sets the index location for all keysig characters that are now
// determined.

inline void
Key_List::determined (List_Node *ptr)
{
  for (char *temp = ptr->keysig; *temp; temp++)
    Key_List::determined_[(int) *temp] = 1;
}

// Returns TRUE if PTR's key set is already completely determined.

inline int
Key_List::already_determined (List_Node *ptr)
{
  int is_determined = 1;

  for (char *temp = ptr->keysig; is_determined && *temp; temp++)
    is_determined = determined_[(int) *temp];

  return is_determined;
}

// Reorders the table by first sorting the list so that frequently
// occuring keys appear first, and then the list is reorded so that
// keys whose values are already determined will be placed towards the
// front of the list.  This helps prune the search time by handling
// inevitable collisions early in the search process.  See Cichelli's
// paper from Jan 1980 JACM for details....

void
Key_List::reorder (void)
{
  List_Node *ptr;

  for (ptr = head; ptr; ptr = ptr->next)
    ptr->occurrence = occurrence (ptr);

  // Switch to sorting by occurrence.
  hash_sort = 0;
  occurrence_sort = 1;

  for (ptr = head = merge_sort (head); ptr->next; ptr = ptr->next)
    {
      determined (ptr);

      if (already_determined (ptr->next))
        continue;
      else
        {
          List_Node *trail_ptr = ptr->next;
          List_Node *run_ptr = trail_ptr->next;

          for (; run_ptr; run_ptr = trail_ptr->next)
            {

              if (already_determined (run_ptr))
                {
                  trail_ptr->next = run_ptr->next;
                  run_ptr->next = ptr->next;
                  ptr = ptr->next = run_ptr;
                }
              else
                trail_ptr = run_ptr;
            }
        }
    }
}

// Outputs the maximum and minimum hash values.  Since the list is
// already sorted by hash value all we need to do is find the final
// item!

void
Key_List::output_min_max (void)
{
  List_Node *temp;
  for (temp = head; temp->next; temp = temp->next)
    continue;

  min_hash_value = head->hash_value;
  max_hash_value = temp->hash_value;

  if (!option[ENUM])
    ACE_OS::printf ("\n#define TOTAL_KEYWORDS %d\n#define MIN_WORD_LENGTH %d"
            "\n#define MAX_WORD_LENGTH %d\n#define MIN_HASH_VALUE %d"
            "\n#define MAX_HASH_VALUE %d\n#define HASH_VALUE_RANGE %d"
            "\n#define DUPLICATES %d\n#define WORDLIST_SIZE %d\n\n",
            total_keys, min_key_len, max_key_len, min_hash_value,
            max_hash_value, max_hash_value - min_hash_value + 1,
            total_duplicates ? total_duplicates + 1 : 0, total_keys + min_hash_value);
  else if (option[GLOBAL])
    ACE_OS::printf ("enum\n{\n"
            "  TOTAL_KEYWORDS = %d,\n"
            "  MIN_WORD_LENGTH = %d,\n"
            "  MAX_WORD_LENGTH = %d,\n"
            "  MIN_HASH_VALUE = %d,\n"
            "  MAX_HASH_VALUE = %d,\n"
            "  HASH_VALUE_RANGE = %d,\n"
            "  DUPLICATES = %d\n"
            "  WORDLIST_SIZE = %d};\n\n",
            total_keys, min_key_len, max_key_len, min_hash_value,
            max_hash_value, max_hash_value - min_hash_value + 1,
            total_duplicates ? total_duplicates + 1 : 0, total_keys + min_hash_value);
}

// Generates the output using a C switch.  This trades increased
// search time for decreased table space (potentially *much* less
// space for sparse tables). It the user has specified their own
// struct in the keyword file *and* they enable the POINTER option we
// have extra work to do.  The solution here is to maintain a local
// static array of user defined struct's, as with the
// Output_Lookup_Function.  Then we use for switch statements to
// perform either a strcmp or strncmp, returning 0 if the str fails to
// match, and otherwise returning a pointer to appropriate index
// location in the local static array.

void
Key_List::output_switch (int use_keyword_table)
{
  if (!option[GLOBAL] && use_keyword_table == 0)
    {
      if (option[LENTABLE] && option[DUP])
        output_keylength_table ();
      if (option[POINTER] && option[TYPE])
        output_keyword_table ();
    }

  char *comp_buffer;
  List_Node *curr = head;
  int pointer_and_type_enabled = option[POINTER] && option[TYPE];
  int total_switches = option.total_switches ();
  int switch_size = keyword_list_length () / total_switches;

  if (pointer_and_type_enabled)
    {
      // Keep track of the longest string we'll need!
      const char *s = "charmap[*str] == *resword->%s && !strncasecmp (str + 1, resword->%s + 1, len - 1)";
      comp_buffer =
        new char [ACE_OS::strlen (s) + 2 * ACE_OS::strlen (option.key_name ()) + 1];
      if (option[COMP])
        sprintf (comp_buffer, "%s == *resword->%s && !%s (str + 1, resword->%s + 1, len - 1)",
                 option[STRCASECMP] ? "charmap[*str]" : "*str", option.key_name (),
                 option[STRCASECMP] ? "strncasecmp" : "strncmp", option.key_name ());
      else
        sprintf (comp_buffer, "%s == *resword->%s && !%s (str + 1, resword->%s + 1)",
                 option[STRCASECMP] ? "charmap[*str]" : "*str", option.key_name (),
                 option[STRCASECMP] ? "strcasecmp" : "strcmp", option.key_name ());
    }
  else
    {
      if (option[COMP])
        comp_buffer = option[STRCASECMP]
          ? (char *) "charmap[*str] == *resword && !strncasecmp (str + 1, resword + 1, len - 1)"
          : (char *) "*str == *resword && !strncmp (str + 1, resword + 1, len - 1)";
      else
        comp_buffer = option[STRCASECMP]
          ? (char *) "charmap[*str] == *resword && !strncasecmp (str + 1, resword + 1, len - 1)"
          : (char *) "*str == *resword && !strcmp (str + 1, resword + 1)";
    }
  if (!option[OPTIMIZE])
    ACE_OS::printf ("  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n    {\n");
  ACE_OS::printf ("      unsigned int key = %s (str, len);\n\n", option.hash_name ());
  if (!option[OPTIMIZE])
    ACE_OS::printf ("      if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n");

  ACE_OS::printf ("        {\n");

  // Properly deal with user's who request multiple switch statements.

  while (curr)
    {
      List_Node *temp = curr;
      int lowest_case_value = curr->hash_value;
      int number_of_cases   = 0;

      // Figure out a good cut point to end this switch.

      for (; temp && ++number_of_cases < switch_size; temp = temp->next)
        if (temp->next && temp->hash_value == temp->next->hash_value)
          while (temp->next && temp->hash_value == temp->next->hash_value)
            temp = temp->next;

      if (temp && total_switches != 1)
        ACE_OS::printf ("          if (key <= %d)\n            {\n", temp->hash_value);
      else
        ACE_OS::printf ("            {\n");

      // Output each keyword as part of a switch statement indexed by
      // hash value.

      if (option[POINTER] || option[DUP] || use_keyword_table)
        {
          int i = 0;

          ACE_OS::printf ("              %s%s *resword; %s\n\n",
                  option[CONSTANT] || pointer_and_type_enabled == 0 ? "const " : "",
                  pointer_and_type_enabled ? struct_tag : "char",
                  option[LENTABLE] && !option[DUP] ? "unsigned int key_len;" : "");
          if (total_switches == 1)
            {
              ACE_OS::printf ("              switch (key)\n                {\n");
              lowest_case_value = 0;
            }
          else
            ACE_OS::printf ("              switch (key - %d)\n                {\n", lowest_case_value);

          for (temp = curr; temp && ++i <= number_of_cases; temp = temp->next)
            {
              ACE_OS::printf ("                case %*d:\n",
                      Key_List::field_width,
                      temp->hash_value - lowest_case_value);

              // Handle `static links,' i.e., those that occur during
              // the initial preprocessing.

              if (temp->link == 0)
                {
                  if (option[DEBUGGING])
                    ACE_OS::printf ("                  /* hash value = %4d, keyword = \"%s\" */\n",
                            temp->hash_value,
                            temp->key);
                }
              else
                {
                  List_Node *links;

                  for (links = temp; links; links = links->link)
                    {
                      if (option[DEBUGGING])
                        ACE_OS::printf ("                  /* hash value = %4d, keyword = \"%s\" */\n",
                                temp->hash_value,
                                links->key);
                      if (pointer_and_type_enabled)
                        ACE_OS::printf ("                  resword = &wordlist[%d];\n", links->slot);
                      else if (use_keyword_table)
                        ACE_OS::printf ("                  resword = wordlist[%d];\n", links->slot);
                      else
                        ACE_OS::printf ("                  resword = \"%s\";\n", links->key);
                      ACE_OS::printf ("                  if (%s) return resword;\n", comp_buffer);
                    }
                }

              // Handle unresolved duplicate hash values.  These are
              // guaranteed to be adjacent since we sorted the keyword
              // list by increasing hash values.
              if (temp->next && temp->hash_value == temp->next->hash_value)
                {

                  for ( ; temp->next && temp->hash_value == temp->next->hash_value;
                        temp = temp->next)
                    {
                      if (pointer_and_type_enabled)
                        ACE_OS::printf ("                  resword = &wordlist[%d];\n", temp->slot);
                      else if (use_keyword_table)
                        ACE_OS::printf ("                  resword = wordlist[%d];", temp->slot);
                      else
                        ACE_OS::printf ("                  resword = \"%s\";\n", temp->key);
                      ACE_OS::printf ("                  if (%s) return resword;\n", comp_buffer);
                    }
                  if (pointer_and_type_enabled)
                    ACE_OS::printf ("                  resword = &wordlist[%d];\n", temp->slot);
                  else if (use_keyword_table)
                    ACE_OS::printf ("                  resword = wordlist[%d];", temp->slot);
                  else
                    ACE_OS::printf ("                  resword = \"%s\";\n", temp->key);
                  ACE_OS::printf ("                  return %s ? resword : 0;\n", comp_buffer);
                }
              else if (temp->link)
                ACE_OS::printf ("                  return 0;\n");
              else
                {
                  if (pointer_and_type_enabled)
                    ACE_OS::printf ("                  resword = &wordlist[%d];", temp->slot);
                  else if (use_keyword_table)
                    ACE_OS::printf ("                  resword = wordlist[%d];", temp->slot);
                  else
                    ACE_OS::printf ("                  resword = \"%s\";", temp->key);
                  if (option[LENTABLE] && !option[DUP])
                    ACE_OS::printf (" key_len = %d;", temp->length);
                  ACE_OS::printf (" break;\n");
                }
            }
          ACE_OS::printf ("                default: return 0;\n                }\n");
          if (option[OPTIMIZE])
            ACE_OS::printf ("                return resword;\n");
          else
            {
              ACE_OS::printf (option[LENTABLE] && !option[DUP]
                      ? "              if (len == key_len && %s)\n                return resword;\n"
                      : "              if (%s)\n                return resword;\n", comp_buffer);
              ACE_OS::printf ("              return 0;\n");
            }
          ACE_OS::printf ("            }\n");
          curr = temp;
        }
      else // Nothing special required here.
        {
          int i = 0;
          ACE_OS::printf ("              char *s;\n\n              switch (key - %d)\n                {\n",
                  lowest_case_value);

          for (temp = curr; temp && ++i <= number_of_cases; temp = temp->next)
            if (option[LENTABLE])
              ACE_OS::printf ("                case %*d: if (len == %d) s = \"%s\"; else return 0; break;\n",
                      Key_List::field_width,
                      temp->hash_value - lowest_case_value,
                      temp->length,
                      temp->key);
            else
              ACE_OS::printf ("                case %*d: s = \"%s\"; break;\n",
                      Key_List::field_width,
                      temp->hash_value - lowest_case_value,
                      temp->key);

          ACE_OS::printf ("                default: return 0;\n                }\n              ");
          if (option[COMP])
            ACE_OS::printf ("return %s == *s && !%s;\n            }\n",
                    option[STRCASECMP] ? "charmap[*str]" : "*str",
                    option[STRCASECMP] ? "strncasecmp (s + 1, str + 1, len - 1)" : "strcmp (s + 1, str + 1)");
          else
            ACE_OS::printf ("return %s == *s && !%s;\n            }\n",
                    option[STRCASECMP] ? "charmap[*str]" : "*str",
                    option[STRCASECMP] ? "strcasecmp (s + 1, str + 1, len - 1)" : "strcmp (s + 1, str + 1)");
          curr = temp;
        }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -