Exemple #1
0
int
main (void)
{
  struct hash_table *ht = make_string_hash_table (0);
  char line[80];
  while ((fgets (line, sizeof (line), stdin)))
    {
      int len = strlen (line);
      if (len <= 1)
	continue;
      line[--len] = '\0';
      if (!hash_table_contains (ht, line))
	hash_table_put (ht, strdup (line), "here I am!");
#if 1
      if (len % 5 == 0)
	{
	  char *line_copy;
	  if (hash_table_get_pair (ht, line, &line_copy, NULL))
	    {
	      hash_table_remove (ht, line);
	      xfree (line_copy);
	    }
	}
#endif
    }
#if 0
  print_hash (ht);
#endif
#if 1
  printf ("%d %d\n", ht->count, ht->size);
#endif
  return 0;
}
Exemple #2
0
list* search_breadth_first(void* state,
                           void* state_world,
                           search_is_goal state_goal_func,
                           search_gen_successors state_gen_func,
                           search_link_parent state_link_func,
                           search_goal_backtrace state_back_func,
                           hash_func state_hash_alg,
                           generic_comp state_comp_func,
                           generic_cpy state_copy_func,
                           generic_op state_free_func) {
    int found;
    void* current_state, *successor_state;
    list* state_queue, *successor_list, *path;
    hash_table* state_closed_set;

    state_queue = list_create(NULL,
                              NULL,
                              state_free_func);

    state_closed_set = hash_table_create(89,
                                         .75,
                                         state_hash_alg,
                                         state_comp_func,
                                         state_copy_func,
                                         state_free_func);
    current_state = state;
    list_push_front(state_queue, current_state);
    hash_table_insert(state_closed_set, current_state, 0);
    path = NULL;
    found = 0;
    while(!list_is_empty(state_queue) && !found) {
        current_state = list_back(state_queue);
        list_deque(state_queue);
        if(state_goal_func(current_state, state_world)) {
            current_state = state_copy_func(current_state);
            path = state_back_func(current_state);
            found = 1;
        } else {
            successor_list = state_gen_func(current_state, state_world);
            while(!list_is_empty(successor_list)) {
                successor_state = list_front(successor_list);
                if(!hash_table_contains(state_closed_set, successor_state)) {
                    state_link_func(successor_state, current_state);
                    hash_table_insert(state_closed_set, successor_state, 0);
                    list_push_front(state_queue, successor_state);
                    list_pop(successor_list);
                } else {
                    list_remove_front(successor_list);
                }
            }
            list_kill(successor_list);
        }
    }
    hash_table_kill(state_closed_set);
    list_dissolve(state_queue);
    return path;
}
Exemple #3
0
void
register_redirection (const char *from, const char *to)
{
    char *file;

    ENSURE_TABLES_EXIST;

    file = hash_table_get (dl_url_file_map, to);
    assert (file != NULL);
    if (!hash_table_contains (dl_url_file_map, from))
        hash_table_put (dl_url_file_map, xstrdup (from), xstrdup (file));
}
void
register_html (const char *url, const char *file)
{
  if (!downloaded_html_set)
    downloaded_html_set = make_string_hash_table (0);
  else if (hash_table_contains (downloaded_html_set, file))
    return;

  /* The set and the list should use the same copy of FILE, but the
     slist interface insists on strduping the string it gets.  Oh
     well. */
  string_set_add (downloaded_html_set, file);
  downloaded_html_list = slist_prepend (downloaded_html_list, file);
}
Exemple #5
0
void
string_set_add (struct hash_table *ht, const char *s)
{
  /* First check whether the set element already exists.  If it does,
     do nothing so that we don't have to free() the old element and
     then strdup() a new one.  */
  if (hash_table_contains (ht, s))
    return;

  /* We use "1" as value.  It provides us a useful and clear arbitrary
     value, and it consumes no memory -- the pointers to the same
     string "1" will be shared by all the key-value pairs in all `set'
     hash tables.  */
  hash_table_put (ht, xstrdup (s), "1");
}
Exemple #6
0
static gboolean
is_read_only (const gchar *changed_element,
              const gchar *changed_attribute)
{
        static GHashTable *readonly_props = NULL;
        static gsize readonly_props_loaded = 0;

        if (g_once_init_enter (&readonly_props_loaded)) {
                readonly_props = g_hash_table_new (g_str_hash,
                                                   g_str_equal);

                hash_table_add (readonly_props, (gpointer)  "@id");
                hash_table_add (readonly_props, (gpointer)  "@parentID");
                hash_table_add (readonly_props, (gpointer)  "@refID");
                hash_table_add (readonly_props, (gpointer)  "@restricted");
                hash_table_add (readonly_props, (gpointer)  "@searchable");
                hash_table_add (readonly_props, (gpointer)  "@childCount");
                hash_table_add (readonly_props, (gpointer)  "searchClass");
                hash_table_add (readonly_props, (gpointer)  "searchClass@name");
                hash_table_add (readonly_props, (gpointer)  "searchClass@includeDerived");
                hash_table_add (readonly_props, (gpointer)  "createClass");
                hash_table_add (readonly_props, (gpointer)  "createClass@name");
                hash_table_add (readonly_props, (gpointer)  "createClass@includeDerived");
                hash_table_add (readonly_props, (gpointer)  "writeStatus");
                hash_table_add (readonly_props, (gpointer)  "res@importUri");
                hash_table_add (readonly_props, (gpointer)  "storageTotal");
                hash_table_add (readonly_props, (gpointer)  "storageUsed");
                hash_table_add (readonly_props, (gpointer)  "storageFree");
                hash_table_add (readonly_props, (gpointer)  "storageMaxPartition");
                hash_table_add (readonly_props, (gpointer)  "storageMedium");
                hash_table_add (readonly_props, (gpointer)  "playbackCount");
                hash_table_add (readonly_props, (gpointer)  "srsRecordScheduleID");
                hash_table_add (readonly_props, (gpointer)  "srsRecordTaskID");
                hash_table_add (readonly_props, (gpointer)  "price");
                hash_table_add (readonly_props, (gpointer)  "price@currency");
                hash_table_add (readonly_props, (gpointer)  "payPerView");
                hash_table_add (readonly_props, (gpointer)  "dateTimeRange");
                hash_table_add (readonly_props, (gpointer)
                                "dateTimeRange@daylightSaving");
                hash_table_add (readonly_props, (gpointer)  "signalStrength");
                hash_table_add (readonly_props, (gpointer)  "signalLocked");
                hash_table_add (readonly_props, (gpointer)  "tuned");
                hash_table_add (readonly_props, (gpointer)  "containerUpdateID");
                hash_table_add (readonly_props, (gpointer)  "objectUpdateID");
                hash_table_add (readonly_props, (gpointer)  "totalDeletedChildCount");
                hash_table_add (readonly_props, (gpointer)  "res@updateCount");
                g_once_init_leave (&readonly_props_loaded, 1);
        }
        if (changed_element != NULL) {
                if (changed_attribute != NULL) {
                        gchar *test_prop = g_strdup_printf ("%s@%s",
                                                            changed_element,
                                                            changed_attribute);
                        gboolean result = hash_table_contains (readonly_props,
                                                               test_prop);

                        g_free (test_prop);
                        if (result)
                                return TRUE;
                        test_prop = g_strdup_printf ("@%s", changed_attribute);
                        result = hash_table_contains (readonly_props,
                                                      test_prop);
                        g_free (test_prop);
                        if (result)
                                return TRUE;
                }

                return hash_table_contains (readonly_props, changed_element);
        }

        return FALSE;
}
Exemple #7
0
void
register_download (const char *url, const char *file)
{
    char *old_file, *old_url;

    ENSURE_TABLES_EXIST;

    /* With some forms of retrieval, it is possible, although not likely
       or particularly desirable.  If both are downloaded, the second
       download will override the first one.  When that happens,
       dissociate the old file name from the URL.  */

    if (hash_table_get_pair (dl_file_url_map, file, &old_file, &old_url))
    {
        if (0 == strcmp (url, old_url))
            /* We have somehow managed to download the same URL twice.
               Nothing to do.  */
            return;

        if (match_except_index (url, old_url)
                && !hash_table_contains (dl_url_file_map, url))
            /* The two URLs differ only in the "index.html" ending.  For
               example, one is "http://www.server.com/", and the other is
               "http://www.server.com/index.html".  Don't remove the old
               one, just add the new one as a non-canonical entry.  */
            goto url_only;

        hash_table_remove (dl_file_url_map, file);
        xfree (old_file);
        xfree (old_url);

        /* Remove all the URLs that point to this file.  Yes, there can
           be more than one such URL, because we store redirections as
           multiple entries in dl_url_file_map.  For example, if URL1
           redirects to URL2 which gets downloaded to FILE, we map both
           URL1 and URL2 to FILE in dl_url_file_map.  (dl_file_url_map
           only points to URL2.)  When another URL gets loaded to FILE,
           we want both URL1 and URL2 dissociated from it.

           This is a relatively expensive operation because it performs
           a linear search of the whole hash table, but it should be
           called very rarely, only when two URLs resolve to the same
           file name, *and* the "<file>.1" extensions are turned off.
           In other words, almost never.  */
        dissociate_urls_from_file (file);
    }

    hash_table_put (dl_file_url_map, xstrdup (file), xstrdup (url));

url_only:
    /* A URL->FILE mapping is not possible without a FILE->URL mapping.
       If the latter were present, it should have been removed by the
       above `if'.  So we could write:

           assert (!hash_table_contains (dl_url_file_map, url));

       The above is correct when running in recursive mode where the
       same URL always resolves to the same file.  But if you do
       something like:

           wget URL URL

       then the first URL will resolve to "FILE", and the other to
       "FILE.1".  In that case, FILE.1 will not be found in
       dl_file_url_map, but URL will still point to FILE in
       dl_url_file_map.  */
    if (hash_table_get_pair (dl_url_file_map, url, &old_url, &old_file))
    {
        hash_table_remove (dl_url_file_map, url);
        xfree (old_url);
        xfree (old_file);
    }

    hash_table_put (dl_url_file_map, xstrdup (url), xstrdup (file));
}
Exemple #8
0
int
string_set_contains (struct hash_table *ht, const char *s)
{
  return hash_table_contains (ht, s);
}
Exemple #9
0
bool
ssl_init (void)
{
  /* Becomes true if GnuTLS is initialized. */
  static bool ssl_initialized = false;
  const char *ca_directory;
  DIR *dir;
  int ncerts = -1;

  /* GnuTLS should be initialized only once. */
  if (ssl_initialized)
    return true;

  gnutls_global_init ();
  gnutls_certificate_allocate_credentials (&credentials);
  gnutls_certificate_set_verify_flags (credentials,
                                       GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

#if GNUTLS_VERSION_MAJOR >= 3
  if (!opt.ca_directory)
    ncerts = gnutls_certificate_set_x509_system_trust (credentials);
#endif

  /* If GnuTLS version is too old or CA loading failed, fallback to old behaviour.
   * Also use old behaviour if the CA directory is user-provided.  */
  if (ncerts <= 0)
    {
      ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
      if ((dir = opendir (ca_directory)) == NULL)
        {
          if (opt.ca_directory && *opt.ca_directory)
            logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
                       opt.ca_directory);
        }
      else
        {
          struct hash_table *inode_map = hash_table_new (196, NULL, NULL);
          struct dirent *dent;
          size_t dirlen = strlen(ca_directory);
          int rc;

          ncerts = 0;

          while ((dent = readdir (dir)) != NULL)
            {
              struct stat st;
              size_t ca_file_length = dirlen + strlen(dent->d_name) + 2;
              char *ca_file = alloca(ca_file_length);

              snprintf (ca_file, ca_file_length, "%s/%s", ca_directory, dent->d_name);
              if (stat (ca_file, &st) != 0)
                continue;

              if (! S_ISREG (st.st_mode))
                continue;

              /* avoid loading the same file twice by checking the inode.  */
              if (hash_table_contains (inode_map, (void *)(intptr_t) st.st_ino))
                continue;

              hash_table_put (inode_map, (void *)(intptr_t) st.st_ino, NULL);
              if ((rc = gnutls_certificate_set_x509_trust_file (credentials, ca_file,
                                                                GNUTLS_X509_FMT_PEM)) <= 0)
                DEBUGP (("WARNING: Failed to open cert %s: (%d).\n", ca_file, rc));
              else
                ncerts += rc;
            }

          hash_table_destroy (inode_map);
          closedir (dir);
        }
    }

  if (opt.ca_cert)
    {
      int rc;

      ncerts = 0;

      if ((rc = gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
                                                        GNUTLS_X509_FMT_PEM)) <= 0)
        logprintf (LOG_NOTQUIET, _ ("ERROR: Failed to open cert %s: (%d).\n"),
                   opt.ca_cert, rc);
      else
        {
          ncerts += rc;
          logprintf (LOG_NOTQUIET, _ ("Loaded CA certificate '%s'\n"), opt.ca_cert);
        }
    }

  if (opt.crl_file)
    {
      int rc;

      if ((rc = gnutls_certificate_set_x509_crl_file (credentials, opt.crl_file, GNUTLS_X509_FMT_PEM)) <= 0)
        {
          logprintf (LOG_NOTQUIET, _("ERROR: Failed to load CRL file '%s': (%d)\n"), opt.crl_file, rc);
          return false;
        }

      logprintf (LOG_NOTQUIET, _ ("Loaded CRL file '%s'\n"), opt.crl_file);
    }

  DEBUGP (("Certificates loaded: %d\n", ncerts));

  /* Use the private key from the cert file unless otherwise specified. */
  if (opt.cert_file && !opt.private_key)
    {
      opt.private_key = xstrdup (opt.cert_file);
      opt.private_key_type = opt.cert_type;
    }
  /* Use the cert from the private key file unless otherwise specified. */
  if (!opt.cert_file && opt.private_key)
    {
      opt.cert_file = xstrdup (opt.private_key);
      opt.cert_type = opt.private_key_type;
    }

  if (opt.cert_file && opt.private_key)
    {
      int type;
      if (opt.private_key_type != opt.cert_type)
        {
          /* GnuTLS can't handle this */
          logprintf (LOG_NOTQUIET, _("ERROR: GnuTLS requires the key and the \
cert to be of the same type.\n"));
        }
uerr_t
retrieve_tree (const char *start_url)
{
  uerr_t status = RETROK;

  /* The queue of URLs we need to load. */
  struct url_queue *queue;

  /* The URLs we do not wish to enqueue, because they are already in
     the queue, but haven't been downloaded yet.  */
  struct hash_table *blacklist;

  int up_error_code;
  struct url *start_url_parsed = url_parse (start_url, &up_error_code);

  if (!start_url_parsed)
    {
      logprintf (LOG_NOTQUIET, "%s: %s.\n", start_url,
		 url_error (up_error_code));
      return URLERROR;
    }

  queue = url_queue_new ();
  blacklist = make_string_hash_table (0);

  /* Enqueue the starting URL.  Use start_url_parsed->url rather than
     just URL so we enqueue the canonical form of the URL.  */
  url_enqueue (queue, xstrdup (start_url_parsed->url), NULL, 0, 1);
  string_set_add (blacklist, start_url_parsed->url);

  while (1)
    {
      int descend = 0;
      char *url, *referer, *file = NULL;
      int depth, html_allowed;
      boolean dash_p_leaf_HTML = FALSE;

      if (opt.quota && total_downloaded_bytes > opt.quota)
	break;
      if (status == FWRITEERR)
	break;

      /* Get the next URL from the queue... */

      if (!url_dequeue (queue,
			(const char **)&url, (const char **)&referer,
			&depth, &html_allowed))
	break;

      /* ...and download it.  Note that this download is in most cases
	 unconditional, as download_child_p already makes sure a file
	 doesn't get enqueued twice -- and yet this check is here, and
	 not in download_child_p.  This is so that if you run `wget -r
	 URL1 URL2', and a random URL is encountered once under URL1
	 and again under URL2, but at a different (possibly smaller)
	 depth, we want the URL's children to be taken into account
	 the second time.  */
      if (dl_url_file_map && hash_table_contains (dl_url_file_map, url))
	{
	  file = xstrdup (hash_table_get (dl_url_file_map, url));

	  DEBUGP (("Already downloaded \"%s\", reusing it from \"%s\".\n",
		   url, file));

	  if (html_allowed
	      && downloaded_html_set
	      && string_set_contains (downloaded_html_set, file))
	    descend = 1;
	}
      else
	{
	  int dt = 0;
	  char *redirected = NULL;
	  int oldrec = opt.recursive;

	  opt.recursive = 0;
	  status = retrieve_url (url, &file, &redirected, referer, &dt);
	  opt.recursive = oldrec;

	  if (html_allowed && file && status == RETROK
	      && (dt & RETROKF) && (dt & TEXTHTML))
	    descend = 1;

	  if (redirected)
	    {
	      /* We have been redirected, possibly to another host, or
		 different path, or wherever.  Check whether we really
		 want to follow it.  */
	      if (descend)
		{
		  if (!descend_redirect_p (redirected, url, depth,
					   start_url_parsed, blacklist))
		    descend = 0;
		  else
		    /* Make sure that the old pre-redirect form gets
		       blacklisted. */
		    string_set_add (blacklist, url);
		}

	      xfree (url);
	      url = redirected;
	    }
	}

      if (descend
	  && depth >= opt.reclevel && opt.reclevel != INFINITE_RECURSION)
	{
	  if (opt.page_requisites
	      && (depth == opt.reclevel || depth == opt.reclevel + 1))
	    {
	      /* When -p is specified, we are allowed to exceed the
		 maximum depth, but only for the "inline" links,
		 i.e. those that are needed to display the page.
		 Originally this could exceed the depth at most by
		 one, but we allow one more level so that the leaf
		 pages that contain frames can be loaded
		 correctly.  */
	      dash_p_leaf_HTML = TRUE;
	    }
	  else
	    {
	      /* Either -p wasn't specified or it was and we've
		 already spent the two extra (pseudo-)levels that it
		 affords us, so we need to bail out. */
	      DEBUGP (("Not descending further; at depth %d, max. %d.\n",
		       depth, opt.reclevel));
	      descend = 0;
	    }
	}

      /* If the downloaded document was HTML, parse it and enqueue the
	 links it contains. */

      if (descend)
	{
	  int meta_disallow_follow = 0;
	  struct urlpos *children
	    = get_urls_html (file, url, &meta_disallow_follow);

	  if (opt.use_robots && meta_disallow_follow)
	    {
	      free_urlpos (children);
	      children = NULL;
	    }

	  if (children)
	    {
	      struct urlpos *child = children;
	      struct url *url_parsed = url_parsed = url_parse (url, NULL);
	      assert (url_parsed != NULL);

	      for (; child; child = child->next)
		{
		  if (child->ignore_when_downloading)
		    continue;
		  if (dash_p_leaf_HTML && !child->link_inline_p)
		    continue;
		  if (download_child_p (child, url_parsed, depth, start_url_parsed,
					blacklist))
		    {
		      url_enqueue (queue, xstrdup (child->url->url),
				   xstrdup (url), depth + 1,
				   child->link_expect_html);
		      /* We blacklist the URL we have enqueued, because we
			 don't want to enqueue (and hence download) the
			 same URL twice.  */
		      string_set_add (blacklist, child->url->url);
		    }
		}

	      url_free (url_parsed);
	      free_urlpos (children);
	    }
	}

      if (opt.delete_after || (file && !acceptable (file)))
	{
	  /* Either --delete-after was specified, or we loaded this
	     otherwise rejected (e.g. by -R) HTML file just so we
	     could harvest its hyperlinks -- in either case, delete
	     the local file. */
	  DEBUGP (("Removing file due to %s in recursive_retrieve():\n",
		   opt.delete_after ? "--delete-after" :
		   "recursive rejection criteria"));
	  logprintf (LOG_VERBOSE,
		     (opt.delete_after
		      ? _("Removing %s.\n")
		      : _("Removing %s since it should be rejected.\n")),
		     file);
	  if (unlink (file))
	    logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
	  register_delete_file (file);
	}

      xfree (url);
      FREE_MAYBE (referer);
      FREE_MAYBE (file);
    }

  /* If anything is left of the queue due to a premature exit, free it
     now.  */
  {
    char *d1, *d2;
    int d3, d4;
    while (url_dequeue (queue,
			(const char **)&d1, (const char **)&d2, &d3, &d4))
      {
	xfree (d1);
	FREE_MAYBE (d2);
      }
  }
  url_queue_delete (queue);

  if (start_url_parsed)
    url_free (start_url_parsed);
  string_set_free (blacklist);

  if (opt.quota && total_downloaded_bytes > opt.quota)
    return QUOTEXC;
  else if (status == FWRITEERR)
    return FWRITEERR;
  else
    return RETROK;
}
Exemple #11
0
/* Returns the route to dest or NULL on failure.
 */
miniroute_t miniroute_discover_route(network_address_t dest) {
  char tmp;
  struct resend_arg arg;
  interrupt_level_t l;
  miniroute_t path;
  dcb_t control_block;
  struct routing_header hdr;

  //printf("entering miniroute_discover_route\n"); 
  l = set_interrupt_level(DISABLED);
  path = miniroute_cache_get(route_cache, dest);
  if (path != NULL) {
    //printf("got route from cache\n");
    set_interrupt_level(l);
    return path;
  }
  if (!hash_table_contains(dcb_table, dest)) {
    control_block = (dcb_t)malloc(sizeof(struct discover_control_block));
    if (!control_block) {
      set_interrupt_level(l);
      return NULL;
    }
    control_block->count = 0;
    control_block->mutex = semaphore_create();
    if (!control_block->mutex) {
      free(control_block);
      set_interrupt_level(l);
      return NULL;
    }
    control_block->route_ready = semaphore_create();
    if (!control_block->route_ready) {
      free(control_block);
      semaphore_destroy(control_block->mutex);
      set_interrupt_level(l);
      return NULL;
    }
    semaphore_initialize(control_block->mutex, 1);
    semaphore_initialize(control_block->route_ready, 0);
    control_block->resend_alarm = NULL;
    control_block->alarm_arg = NULL;
    hash_table_add(dcb_table, dest, control_block);
    //printf("made a NEW discover control block\n"); 
    }
  control_block = hash_table_get(dcb_table, dest);
  if (!control_block) {
    //printf("ERROR: could not find discover control block\n");
    set_interrupt_level(l);
    return NULL;
  }

  control_block->count++;
  set_interrupt_level(l);
  
  semaphore_P(control_block->mutex);
  path = miniroute_cache_get(route_cache, dest);
  if (path) {
    l = set_interrupt_level(DISABLED);
    control_block->count--;
    semaphore_V(control_block->mutex);
    set_interrupt_level(l);
    //printf("exiting miniroute_discover_route on SUCCESS\n"); 
    return path;
  }
  else {
    hdr.routing_packet_type = ROUTING_ROUTE_DISCOVERY;
    pack_address(hdr.destination, dest);
    l = set_interrupt_level(DISABLED);
    pack_unsigned_int(hdr.id, curr_discovery_pkt_id++);
    pack_unsigned_int(hdr.ttl, MAX_ROUTE_LENGTH);
    pack_unsigned_int(hdr.path_len, 1);
    pack_address(hdr.path[0], my_addr);
    //make arg
    arg.try_count = 0;
    arg.hdr = &hdr;
    arg.control_block = control_block;    
    control_block->alarm_arg = &arg; 

    //printf("sending first DISCOVERY pkt\n");
    if (network_bcast_pkt(sizeof(struct routing_header), (char*)(&hdr), 0, &tmp) == -1) {
      //error
      control_block->count--;
      semaphore_V(control_block->mutex);
      set_interrupt_level(l);
      return NULL;
    } 
    control_block->resend_alarm = set_alarm(120, miniroute_resend, 
        control_block->alarm_arg, minithread_time());  
    set_interrupt_level(l);
    semaphore_P(control_block->route_ready); 
    //got a reply pkt or timed out
    path = miniroute_cache_get(route_cache, dest);
    l = set_interrupt_level(DISABLED);
    control_block->count--;
    semaphore_V(control_block->mutex);
    set_interrupt_level(l);
    //printf("exiting miniroute_discover_route on SUCCESS\n"); 
    return path;
  }
}
Exemple #12
0
list* search_a_star(void* state,
                    void* state_world,
                    search_is_goal state_goal_func,
                    search_gen_successors state_gen_func,
                    search_link_parent state_link_func,
                    search_goal_backtrace state_back_func,
                    search_trans_cost state_trans_func,
                    search_heuristic state_heur_func,
                    search_set_f_cost state_f_cost_set_func,
                    hash_func state_hash_alg,
                    generic_comp state_comp_func,
                    generic_cpy state_copy_func,
                    generic_op state_free_func,
                    heap_comp state_heap_func) {
    int* g_cost_ptr, *f_cost_ptr, f_cost, tmp_f, g_cost, found;
    void* current_state, *successor_state, *heap_memory_location;
    list* states_overflow, *successor_list, *path;
    hash_table* states_closed_set, *states_open_set;
    hash_map* states_g_cost, *states_f_cost, *states_heap_index;
    heap* states_heap;

    states_overflow = list_create(NULL,
                                  NULL,
                                  state_free_func);

    states_closed_set = hash_table_create(89,
                                          .75,
                                          state_hash_alg,
                                          state_comp_func,
                                          state_copy_func,
                                          state_free_func);

    states_open_set = hash_table_create(89,
                                        .75,
                                        state_hash_alg,
                                        state_comp_func,
                                        state_copy_func,
                                        state_free_func);

    states_g_cost = hash_map_create(89,
                                    .75,
                                    state_hash_alg,
                                    state_comp_func,
                                    NULL,
                                    NULL,
                                    NULL,
                                    state_free_func,
                                    (generic_op)free);

    states_f_cost = hash_map_create(89,
                                    .75,
                                    state_hash_alg,
                                    state_comp_func,
                                    NULL,
                                    NULL,
                                    NULL,
                                    state_free_func,
                                    (generic_op)free);

    states_heap_index = hash_map_create(89,
                                        .75,
                                        state_hash_alg,
                                        state_comp_func,
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL);

    states_heap = heap_create(89,
                              state_heap_func,
                              state_comp_func,
                              state_copy_func,
                              state_free_func);
    current_state = state;
    f_cost = state_heur_func(current_state, NULL);
    state_f_cost_set_func(current_state, f_cost);
    g_cost = 0;
    g_cost_ptr = malloc(sizeof(int));
    *g_cost_ptr = g_cost;
    f_cost_ptr = malloc(sizeof(int));
    *f_cost_ptr = f_cost;
    hash_map_insert(states_g_cost, current_state, g_cost_ptr, 0);
    heap_memory_location = heap_add(states_heap, state_copy_func(current_state));
    hash_table_insert(states_open_set, state_copy_func(current_state), 0);
    hash_map_insert(states_f_cost, state_copy_func(current_state), f_cost_ptr, 0);
    hash_map_insert(states_heap_index, current_state, heap_memory_location, 1);
    path = NULL;
    found = 0;
    while(!heap_is_empty(states_heap) && !found) {
        current_state = state_copy_func(heap_peek(states_heap));
        heap_remove(states_heap);
        hash_table_remove(states_open_set, current_state);
        hash_map_remove(states_heap_index, current_state);
        if(state_goal_func(current_state, state_world)) {
            path = state_back_func(current_state);
            found = 1;
        } else {
            if(!hash_table_insert(states_closed_set, current_state, 0)) {
                list_push_front(states_overflow, current_state);
            }
            successor_list = state_gen_func(current_state, state_world);
            while(!list_is_empty(successor_list)) {
                successor_state = list_front(successor_list);
                g_cost = *(int*)hash_map_get(states_g_cost, current_state) +
                    state_trans_func(current_state, successor_state, state_world);
                f_cost = g_cost + state_heur_func(successor_state, state_world);
                tmp_f = hash_map_contains_key(states_f_cost, successor_state) ?
                    *(int*)hash_map_get(states_f_cost, successor_state) : UINT_MAX;
                if(hash_table_contains(states_closed_set, successor_state) && f_cost > tmp_f) {
                    list_remove_front(successor_list);
                    continue;
                }
                if(!hash_table_contains(states_open_set, successor_state) || f_cost < tmp_f) {
                    state_f_cost_set_func(successor_state, f_cost);
                    state_link_func(successor_state, current_state);
                    g_cost_ptr = malloc(sizeof(int));
                    f_cost_ptr = malloc(sizeof(int));
                    *g_cost_ptr = g_cost;
                    *f_cost_ptr = f_cost;
                    if(!hash_table_contains(states_open_set, successor_state)) {
                        hash_table_insert(states_open_set, successor_state, 0);
                        heap_memory_location = heap_add(states_heap, state_copy_func(successor_state));
                        hash_map_insert(states_heap_index, successor_state,  heap_memory_location, 1);
                    } else {
                        heap_memory_location = hash_map_get(states_heap_index, successor_state);
                        heap_up_mod_data(states_heap, heap_memory_location,  successor_state);
                    }
                    if(!hash_map_set(states_g_cost, successor_state, g_cost_ptr)) {
                        hash_map_insert(states_g_cost, state_copy_func(successor_state), g_cost_ptr, 0);
                    }
                    if(!hash_map_set(states_f_cost, successor_state, f_cost_ptr)) {
                        hash_map_insert(states_f_cost, state_copy_func(successor_state), f_cost_ptr, 0);
                    }
                    list_pop(successor_list);
                } else {
                    list_remove_front(successor_list);
                }
            }
            list_kill(successor_list);
        }
    }
    heap_kill(states_heap);
    list_kill(states_overflow);
    hash_map_kill(states_g_cost);
    hash_map_kill(states_f_cost);
    hash_table_kill(states_open_set);
    hash_table_kill(states_closed_set);
    hash_map_dissolve(states_heap_index);
    return path;
}
Exemple #13
0
int main(void) {
    hash_table_t ht;
    network_address_t addr1;
    network_address_t addr2;
    network_address_t addr3;
    network_address_t addr4;

    addr1[0] = 42;
    addr1[1] = 1;
    addr2[1] = 2;
    addr3[1] = 3;
    addr4[0] = 14;
    addr4[1] = 4;

    assert(network_compare_network_addresses(addr1, addr1));
    ht = hash_table_create();
    assert(hash_table_size(ht) == 0);
    assert(hash_table_capacity(ht) == 64);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr3, (void*)24);
    assert(hash_table_contains(ht, addr1));
    assert(!hash_table_contains(ht, addr4));
    assert((long)hash_table_get(ht, addr2) == 16);
    assert((long)hash_table_get(ht, addr3) == 24);
    assert(hash_table_size(ht) == 3);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert(!hash_table_contains(ht, addr1));
    assert(hash_table_capacity(ht) == 64);
    assert(hash_table_size(ht) == 2);
    assert(!hash_table_destroy(ht));

    ht = hash_table_create();
    assert(hash_table_size(ht) == 0);
    assert(!hash_table_add(ht, addr1, (void*)8));
    assert((long)hash_table_get(ht, addr2) == 0);
    assert(!hash_table_add(ht, addr2, (void*)16));
    assert((long)hash_table_get(ht, addr2) == 16);
    assert(!hash_table_destroy(ht));

    ht = hash_table_create();
    hash_table_add(ht, addr4, (void*)32);
    hash_table_add(ht, addr4, (void*)32);
    hash_table_add(ht, addr4, (void*)32);
    hash_table_add(ht, addr4, (void*)32);
    assert(hash_table_size(ht) == 4);
    assert(hash_table_contains(ht, addr4));
    assert((long)hash_table_remove(ht, addr4) == 32);
    assert((long)hash_table_remove(ht, addr1) == 0);
    assert(hash_table_contains(ht, addr4));
    assert(hash_table_size(ht) == 3);
    assert((long)hash_table_remove(ht, addr4) == 32);
    assert((long)hash_table_remove(ht, addr4) == 32);
    assert((long)hash_table_remove(ht, addr4) == 32);
    assert(!hash_table_contains(ht, addr4));
    assert(hash_table_size(ht) == 0);
    assert(!hash_table_destroy(ht));

    ht = hash_table_create();
    assert(hash_table_size(ht) == 0);
    assert(hash_table_capacity(ht) == 64);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    assert(hash_table_contains(ht, addr2));
    assert(!hash_table_contains(ht, addr4));
    assert(!hash_table_get(ht, addr4));
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    hash_table_add(ht, addr1, (void*)8);
    hash_table_add(ht, addr2, (void*)16);
    assert(hash_table_size(ht) == 50);
    assert(hash_table_capacity(ht) == 128);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert((long)hash_table_remove(ht, addr1) == 8);
    assert((long)hash_table_remove(ht, addr2) == 16);
    assert(hash_table_size(ht) == 30);
    assert(hash_table_capacity(ht) == 64);
    printf("all tests pass\n");

    return 0;
}