pike.git / src / builtin.cmod

version» Context lines:

pike.git/src/builtin.cmod:2136:    pop_stack();   }      /*! @decl array random(mapping m)    *! Returns a random index-value pair from the mapping.    */      PMOD_EXPORT   PIKEFUN array random(mapping m)   { -  struct mapping_data *md=m->data; -  size_t bucket, count; +     struct keypair *k; -  +  int e, count;       if(!m_sizeof(m))    SIMPLE_BAD_ARG_ERROR("random", 1, "mapping with elements in it");    -  /* Find a random, nonempty bucket */ -  bucket=my_rand(md->hashsize); -  while(! md->hash[bucket] ) -  if(++bucket > (size_t)md->hashsize) -  bucket=0; +  count = my_rand( m_sizeof(m) );    -  /* Count entries in bucket */ -  count=0; -  for(k=md->hash[bucket];k;k=k->next) count++; +  /* We could optimize this by not iterating over hash buckets we will +  not pick a member from. */    -  /* Select a random entry in this bucket */ -  count = my_rand(count); -  k=md->hash[bucket]; -  while(count-- > 0) k=k->next; -  -  /* Push result and return */ +  NEW_MAPPING_LOOP(m->data) +  { +  if(count-- < 1) +  {    push_svalue(&k->ind);    push_svalue(&k->val);    f_aggregate(2);    stack_swap();    pop_stack(); -  +  return;    } -  +  } + }      #if defined(HAVE_SETENV) && defined(HAVE_UNSETENV)   #define USE_SETENV   #else   /* Used to hold refs to the strings that we feed to putenv. Indexed on    * variable names, values are the "name=value" strings.    *    * This is not needed when using {,un}setenv(), since they maintain    * their own corresponding table. */   static struct mapping *env_allocs = NULL;