libutils.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 691 行 · 第 1/2 页

C
691
字号
                 && (p[3] == '/' || p[3] == 0)){
          while (o != target && *--o != '/');
          if (o == target && *o == '/') {
            ++o;
          }
          p += 3;
        }
        else {
          *o++ = *p++;
        }
  }
  target[o-target] = 0;
  return (char *)target;
}

/**
 * Prints out debug messages.
 */
EXTERN void printDebug(int level, char *str, ...) {
  if (level < DEBUG_LEVEL) {
    char buf[512];
    va_list ptr;
    va_start(ptr,str);
    vsprintf(buf,str,ptr);
    printf("DEBUG : %s\n",  buf);
    va_end(ptr);
  }
}

/**
 * Prints out warning messages
 */
EXTERN void printWarning(int level, char *str, ...) {
  if (level < DEBUG_LEVEL) {
    char buf[512];
    va_list ptr;
    va_start(ptr,str);
    vsprintf(buf,str,ptr);
    printf("WARNING : %s\n",  buf);
    va_end(ptr);
  }
}

/**
 * Prints a dictionary's contents as ICLTerms.
 */
void print_dictionary(DICTIONARY *d) {
  int i, n;

  printf("Print dictionary of size %d\n", d->size);
  for(i=0, n=d->size; i<n; i++)
    printf("Key %s Value : %s\n",
           icl_NewStringFromTerm((ICLTerm*)d->key[i]),
           icl_NewStringFromTerm((ICLTerm*)d->value[i]));
}

/**
 * Initialize the hash_table to the size asked for.  Allocates space
 * for the correct number of pointers and sets them to NULL.  If it
 * can't allocate sufficient memory, signals error by setting the size
 * of the table to 0.
 */
hthash_table *htconstruct_table(hthash_table *table, size_t size)
{
  size_t i;
  htbucket **temp;

  table -> size  = size;
  table -> table = (htbucket * *)malloc(sizeof(htbucket *) * size);
  temp = table -> table;

  if ( temp == NULL )
  {
    table -> size = 0;
    return table;
  }

  for (i=0;i<size;i++)
    temp[i] = NULL;
  return table;
}


/*
 * Hashes a string to produce an unsigned short, which should be
 * sufficient for most purposes.
 */
static unsigned hthash(char *string)
{
  unsigned ret_val = 0;
  int i;

  while (*string)
  {
    i = (int)(*string);
    ret_val ^= i;
    ret_val <<= 1;
    string ++;
  }
  return ret_val;
}

/**
 * Insert <code>key</code> into hash table.
 * Returns pointer to old data associated with the key, if any, or
 * NULL if the key wasn't in the table previously.
 */
void *htinsert(char *key, void *data, hthash_table *table)
{
  unsigned val = hthash(key) % table->size;
  htbucket *ptr;

  /*
   * NULL means this bucket hasn't been used yet.  We'll simply
   * allocate space for our new bucket and put our data there, with
   * the table pointing at it.
   */

  if (NULL == (table->table)[val])
  {
    (table->table)[val] = (htbucket *)malloc(sizeof(htbucket));
    if (NULL==(table->table)[val])
      return NULL;

    (table->table)[val] -> key = strdup(key);
    (table->table)[val] -> next = NULL;
    (table->table)[val] -> data = data;
    return (table->table)[val] -> data;
  }

  /*
   * This spot in the table is already in use.  See if the current string
   * has already been inserted, and if so, increment its count.
   */

  for (ptr = (table->table)[val];NULL != ptr; ptr = ptr -> next)
    if (0 == strcmp(key, ptr->key))
    {
      void *old_data;

      old_data = ptr->data;
      ptr -> data = data;
      return old_data;
    }

  /*
   * This key must not be in the table yet.  We'll add it to the head of
   * the list at this spot in the hash table.  Speed would be
   * slightly improved if the list was kept sorted instead.  In this case,
   * this code would be moved into the loop above, and the insertion would
   * take place as soon as it was determined that the present key in the
   * list was larger than this one.
   */

  ptr = (htbucket *)malloc(sizeof(htbucket));
  if (NULL==ptr)
    return 0;
  ptr -> key = strdup(key);
  ptr -> data = data;
  ptr -> next = (table->table)[val];
  (table->table)[val] = ptr;
  return data;
}


/**
 * Look up a key and return the associated data.  Returns NULL if
 * the key is not in the table.
 */
void *htlookup(char *key, hthash_table *table)
{
  unsigned val = hthash(key) % table->size;
  htbucket *ptr;

  if (NULL == (table->table)[val])
    return NULL;

  for ( ptr = (table->table)[val];NULL != ptr; ptr = ptr->next )
  {
    if (0 == strcmp(key, ptr -> key ) ) {
      return ptr->data;
    }
  }
  return NULL;
}

/**
 * Delete a key from the hash table and return associated
 * data, or NULL if not present.
 */
void *htdel(char *key, hthash_table *table)
{
  unsigned val = hthash(key) % table->size;
  void *data;
  htbucket *ptr, *last = NULL;

  if (NULL == (table->table)[val])
    return NULL;

  /*
   * Traverse the list, keeping track of the previous node in the list.
   * When we find the node to delete, we set the previous node's next
   * pointer to point to the node after ourself instead.  We then delete
   * the key from the present node, and return a pointer to the data it
   * contains.
   */

  for (last = NULL, ptr = (table->table)[val];
       NULL != ptr;
       last = ptr, ptr = ptr->next)
  {
    if (0 == strcmp(key, ptr -> key))
    {
      if (last != NULL )
      {
	data = ptr -> data;
	last -> next = ptr -> next;
	free(ptr->key);
	free(ptr);
	return data;
      }

      /*
       * If 'last' still equals NULL, it means that we need to
       * delete the first node in the list. This simply consists
       * of putting our own 'next' pointer in the array holding
       * the head of the list.  We then dispose of the current
       * node as above.
       */

      else
      {
	data = ptr->data;
	(table->table)[val] = ptr->next;
	free(ptr->key);
	free(ptr);
	return data;
      }
    }
  }

  /*
   * If we get here, it means we didn't find the item in the table.
   * Signal this by returning NULL.
   */

  return NULL;
}

/**
 * Function htfree_table() iterates the table, calling this repeatedly to free
 * each individual node.  This, in turn, calls one or two other
 * functions - one to free the storage used for the key, the other
 * passes a pointer to the data back to a function defined by the user,
 * process the data as needed.
 */
void htfree_node(char *key, void *data, void *otherData)
{
  htfreeNodeData *oData;
  (void)data;
  oData = (htfreeNodeData *)otherData;

  if (oData->function) {
    void *toFree = htdel(key,oData->the_table);
    oData->function(toFree);
  }
  else {
    htdel(key,oData->the_table);
  }
}

/**
 * Frees a complete table by iterating over it and freeing each node.
 * the second parameter is the address of a function it will call with a
 * pointer to the data associated with each node.  This function is
 * responsible for freeing the data, or doing whatever is needed with
 * it.
 */
void htfree_table(hthash_table *table, void (*func)(void *))
{
  htfreeNodeData freeData;
  freeData.function = func;
  freeData.the_table = table;
  htenumerate( table, htfree_node, &freeData);
  free(table->table);
  table->table = NULL;
  table->size = 0;
}

/**
 * Simply invokes the function given as the second parameter for each
 * node in the table, passing it the key and the associated data.
 */
void htenumerate( hthash_table *table, void (*func)(char *, void *, void *), void *otherData)
{
  unsigned i;
  htbucket *temp;

  htbucket *nextPtr;
  for (i=0;i<table->size; i++)
  {
    if ((table->table)[i] != NULL)
    {
      nextPtr = (table->table)[i]->next;
      for (temp = (table->table)[i];
	   NULL != temp;
	   temp = nextPtr)
      {
	nextPtr = temp->next;
	func(temp -> key, temp->data, otherData);
      }
    }
  }
}

void printer(char *key, void *data, void *otherData)
{
  (void)otherData;
  printf("Key = [%s], data = %s\n", key, (char *)data);
}

void htprint(hthash_table *table)
{
  printf("Printing table\n");
  htenumerate(table, printer, NULL);
}

/**
 * @defgroup Utilities Utilities
 *
 * Some text about this module.
 *
 * @{
 */

/**
 * @file libutils.h
 */

/**
 * @file libutils.c
 */

/** @} */

⌨️ 快捷键说明

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