* hash.c (rb_hash_assoc): new method.

* hash.c (rb_hash_rassoc): ditto.

* hash.c (rb_hash_flatten): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2007-06-22 16:26:07 +00:00
Родитель 115410ecde
Коммит fdf213b71a
3 изменённых файлов: 154 добавлений и 5 удалений

Просмотреть файл

@ -1,3 +1,11 @@
Sat Jun 23 01:25:40 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* hash.c (rb_hash_assoc): new method.
* hash.c (rb_hash_rassoc): ditto.
* hash.c (rb_hash_flatten): ditto.
Fri Jun 22 23:55:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (rb_str_upto): add optional argument to specify

Просмотреть файл

@ -2342,10 +2342,10 @@ rb_ary_assoc(VALUE ary, VALUE key)
/*
* call-seq:
* array.rassoc(key) -> an_array or nil
* array.rassoc(obj) -> an_array or nil
*
* Searches through the array whose elements are also arrays. Compares
* <em>key</em> with the second element of each contained array using
* _obj_ with the second element of each contained array using
* <code>==</code>. Returns the first contained array that matches. See
* also <code>Array#assoc</code>.
*

147
hash.c
Просмотреть файл

@ -1517,6 +1517,103 @@ rb_hash_merge(VALUE hash1, VALUE hash2)
return rb_hash_update(rb_obj_dup(hash1), hash2);
}
static int
assoc_i(VALUE key, VALUE val, VALUE *args)
{
if (key == Qundef) return ST_CONTINUE;
if (RTEST(rb_equal(args[0], key))) {
args[1] = rb_assoc_new(key, val);
return ST_STOP;
}
return ST_CONTINUE;
}
/*
* call-seq:
* hash.assoc(obj) -> an_array or nil
*
* Searches through the hash comparing _obj_ with the key using <code>==</code>.
* Returns the key-value pair (two elements array) or +nil+
* if no match is found. See <code>Array#assoc</code>.
*
* h = {"colors" => ["red", "blue", "green"],
* "letters" => ["a", "b", "c" ]}
* h.assoc("letters") #=> ["letters", ["a", "b", "c"]]
* h.assoc("foo") #=> nil
*/
VALUE
rb_hash_assoc(VALUE hash, VALUE obj)
{
VALUE args[2];
args[0] = obj;
args[1] = Qnil;
rb_hash_foreach(hash, assoc_i, (st_data_t)args);
return args[1];
}
static int
rassoc_i(VALUE key, VALUE val, VALUE *args)
{
if (key == Qundef) return ST_CONTINUE;
if (RTEST(rb_equal(args[0], val))) {
args[1] = rb_assoc_new(key, val);
return ST_STOP;
}
return ST_CONTINUE;
}
/*
* call-seq:
* hash.rassoc(key) -> an_array or nil
*
* Searches through the hash comparing _obj_ with the value using <code>==</code>.
* Returns the first key-value pair (two elements array) that matches. See
* also <code>Array#rassoc</code>.
*
* a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
* a.rassoc("two") #=> [2, "two"]
* a.rassoc("four") #=> nil
*/
VALUE
rb_hash_rassoc(VALUE hash, VALUE obj)
{
VALUE args[2];
args[0] = obj;
args[1] = Qnil;
rb_hash_foreach(hash, rassoc_i, (st_data_t)args);
return args[1];
}
/*
* call-seq:
* hash.flatten -> an_array
* hash.flatten(level) -> an_array
*
* Returns a new array that is a one-dimensional flattening of this
* hash. That is, for every key or value that is an array, extract
* its elements into the new array. Unlike Array#flatten, this
* method does not flatten recursively by default. If the optional
* <i>level</i> argument determins the level of recursion to flatten.
*
* a = {1=> "one", 2 => [2,"two"], 3 => "three"}
* a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
* a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
*/
static VALUE
rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
{
VALUE ary, lv;
ary = rb_hash_to_a(hash);
rb_funcall2(ary, rb_intern("flatten!"), argc, argv);
return ary;
}
static struct st_hash_type identhash = {
st_numcmp,
st_numhash,
@ -2176,18 +2273,33 @@ env_has_key(VALUE env, VALUE key)
}
static VALUE
env_has_value(VALUE dmy, VALUE value)
env_assoc(VALUE env, VALUE key)
{
char *s, *e;
rb_secure(4);
s = StringValuePtr(key);
if (strlen(s) != RSTRING_LEN(key))
rb_raise(rb_eArgError, "bad environment variable name");
e = getenv(s);
if (e) return rb_assoc_new(key, rb_tainted_str_new2(e));
return Qnil;
}
static VALUE
env_has_value(VALUE dmy, VALUE obj)
{
char **env;
rb_secure(4);
if (TYPE(value) != T_STRING) return Qfalse;
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
if (s++) {
long len = strlen(s);
if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
FREE_ENVIRON(environ);
return Qtrue;
}
@ -2198,6 +2310,30 @@ env_has_value(VALUE dmy, VALUE value)
return Qfalse;
}
static VALUE
env_rassoc(VALUE dmy, VALUE obj)
{
char **env;
rb_secure(4);
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
if (s++) {
long len = strlen(s);
if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
FREE_ENVIRON(environ);
return rb_assoc_new(rb_tainted_str_new(*env, s-*env-1), obj);
}
}
env++;
}
FREE_ENVIRON(environ);
return Qnil;
}
static VALUE
env_key(VALUE dmy, VALUE value)
{
@ -2407,6 +2543,9 @@ Init_Hash(void)
rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
rb_define_method(rb_cHash,"merge", rb_hash_merge, 1);
rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
@ -2460,6 +2599,8 @@ Init_Hash(void)
rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
rb_define_singleton_method(envtbl,"assoc", env_assoc, 1);
rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
rb_define_global_const("ENV", envtbl);
#else /* __MACOS__ */