diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/sdbm/init.c | 340 |
1 files changed, 337 insertions, 3 deletions
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c index f138d24e23..65e2ded07b 100644 --- a/ext/sdbm/init.c +++ b/ext/sdbm/init.c @@ -15,6 +15,55 @@ #include <fcntl.h> #include <errno.h> +/* + * Document-class: SDBM + * + * SDBM provides a simple file-based key-value store, which can only store + * String keys and values. + * + * Note that Ruby comes with the source code for SDBM, while the DBM and GDBM + * standard libraries rely on external libraries and headers. + * + * === Examples + * + * Insert values: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db['apple'] = 'fruit' + * db['pear'] = 'fruit' + * db['carrot'] = 'vegetable' + * db['tomato'] = 'vegetable' + * end + * + * Bulk update: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db.update('peach' => 'fruit', 'tomato' => 'fruit') + * end + * + * Retrieve values: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db.each do |key, value| + * puts "Key: #{key}, Value: #{value}" + * end + * end + * + * Outputs: + * + * Key: apple, Value: fruit + * Key: pear, Value: fruit + * Key: carrot, Value: vegetable + * Key: peach, Value: fruit + * Key: tomato, Value: fruit + */ + static VALUE rb_cDBM, rb_eDBMError; struct dbmdata { @@ -47,6 +96,14 @@ free_sdbm(struct dbmdata *dbmp) ruby_xfree(dbmp); } +/* + * call-seq: + * sdbm.close -> nil + * + * Closes the database file. + * + * Raises SDBMError if the database is already closed. + */ static VALUE fsdbm_close(VALUE obj) { @@ -59,6 +116,12 @@ fsdbm_close(VALUE obj) return Qnil; } +/* +* call-seq: +* sdbm.closed? -> true or false +* +* Returns +true+ if the database is closed. +*/ static VALUE fsdbm_closed(VALUE obj) { @@ -78,7 +141,21 @@ fsdbm_alloc(VALUE klass) { return Data_Wrap_Struct(klass, 0, free_sdbm, 0); } - +/* +* call-seq: +* SDBM.new(filename, mode = 0666) +* +* Creates a new database handle by opening the given +filename+. SDBM actually +* uses two physical files, with extensions '.dir' and '.pag'. These extensions +* will automatically be appended to the +filename+. +* +* If the file does not exist, a new file will be created using the given +* +mode+, unless +mode+ is explicitly set to nil. In the latter case, no +* database will be created. +* +* If the file exists, it will be opened in read/write mode. If this fails, it +* will be opened in read-only mode. +*/ static VALUE fsdbm_initialize(int argc, VALUE *argv, VALUE obj) { @@ -120,6 +197,24 @@ fsdbm_initialize(int argc, VALUE *argv, VALUE obj) return obj; } +/* + * call-seq: + * SDBM.open(filename, mode = 0666) + * SDBM.open(filename, mode = 0666) { |sdbm| ... } + * + * If called without a block, this is the same as SDBM.new. + * + * If a block is given, the new database will be passed to the block and + * will be safely closed after the block has executed. + * + * Example: + * + * require 'sdbm' + * + * SDBM.open('my_database') do |db| + * db['hello'] = 'world' + * end + */ static VALUE fsdbm_s_open(int argc, VALUE *argv, VALUE klass) { @@ -157,12 +252,34 @@ fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) return rb_external_str_new(value.dptr, value.dsize); } +/* + * call-seq: + * sdbm[key] -> value or nil + * + * Returns the +value+ in the database associated with the given +key+ string. + * + * If no value is found, returns +nil+. + */ static VALUE fsdbm_aref(VALUE obj, VALUE keystr) { return fsdbm_fetch(obj, keystr, Qnil); } +/* + * call-seq: + * sdbm.fetch(key) -> value or nil + * sdbm.fetch(key) { |key| ... } + * + * Returns the +value+ in the database associated with the given +key+ string. + * + * If a block is provided, the block will be called when there is no + * +value+ associated with the given +key+. The +key+ will be passed in as an + * argument to the block. + * + * If no block is provided and no value is associated with the given +key+, + * then an IndexError will be raised. + */ static VALUE fsdbm_fetch_m(int argc, VALUE *argv, VALUE obj) { @@ -176,6 +293,14 @@ fsdbm_fetch_m(int argc, VALUE *argv, VALUE obj) return valstr; } +/* + * call-seq: + * sdbm.key(value) -> key + * + * Returns the +key+ associated with the given +value+. If more than one + * +key+ corresponds to the given +value+, then the first key to be found + * will be returned. If no keys are found, +nil+ will be returned. + */ static VALUE fsdbm_key(VALUE obj, VALUE valstr) { @@ -197,6 +322,9 @@ fsdbm_key(VALUE obj, VALUE valstr) return Qnil; } +/* + * :nodoc: + */ static VALUE fsdbm_index(VALUE hash, VALUE value) { @@ -204,6 +332,25 @@ fsdbm_index(VALUE hash, VALUE value) return fsdbm_key(hash, value); } +/* call-seq: + * sdbm.select { |key, value| ... } -> Array + * + * Returns a new Array of key-value pairs for which the block returns +true+. + * + * Example: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db['apple'] = 'fruit' + * db['pear'] = 'fruit' + * db['spinach'] = 'vegetable' + * + * veggies = db.select do |key, value| + * value == 'vegetable' + * end #=> [["apple", "fruit"], ["pear", "fruit"]] + * end + */ static VALUE fsdbm_select(VALUE obj) { @@ -228,6 +375,11 @@ fsdbm_select(VALUE obj) return new; } +/* call-seq: + * sdbm.values_at(key, ...) -> Array + * + * Returns an Array of values corresponding to the given keys. + */ static VALUE fsdbm_values_at(int argc, VALUE *argv, VALUE obj) { @@ -248,6 +400,18 @@ fdbm_modify(VALUE obj) if (OBJ_FROZEN(obj)) rb_error_frozen("SDBM"); } +/* + * call-seq: + * sdbm.delete(key) -> value or nil + * sdbm.delete(key) { |key, value| ... } + * + * Deletes the key-value pair corresponding to the given +key+. If the + * +key+ exists, the deleted value will be returned, otherwise +nil+. + * + * If a block is provided, the deleted +key+ and +value+ will be passed to + * the block as arguments. If the +key+ does not exist in the database, the + * value will be +nil+. + */ static VALUE fsdbm_delete(VALUE obj, VALUE keystr) { @@ -283,6 +447,13 @@ fsdbm_delete(VALUE obj, VALUE keystr) return valstr; } +/* + * call-seq: + * sdbm.shift -> Array or nil + * + * Removes a key-value pair from the database and returns them as an + * Array. If the database is empty, returns +nil+. + */ static VALUE fsdbm_shift(VALUE obj) { @@ -306,6 +477,14 @@ fsdbm_shift(VALUE obj) return rb_assoc_new(keystr, valstr); } +/* + * call-seq: + * sdbm.delete_if { |key, value| ... } -> self + * sdbm.reject! { |key, value| ... } -> self + * + * Iterates over the key-value pairs in the database, deleting those for + * which the block returns +true+. + */ static VALUE fsdbm_delete_if(VALUE obj) { @@ -345,6 +524,12 @@ fsdbm_delete_if(VALUE obj) return obj; } +/* + * call-seq: + * sdbm.clear -> self + * + * Deletes all data from the database. + */ static VALUE fsdbm_clear(VALUE obj) { @@ -365,6 +550,22 @@ fsdbm_clear(VALUE obj) return obj; } +/* + * call-seq: + * sdbm.invert -> Hash + * + * Returns a Hash in which the key-value pairs have been inverted. + * + * Example: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db.update('apple' => 'fruit', 'spinach' => 'vegetable') + * + * db.invert #=> {"fruit" => "apple", "vegetable" => "spinach"} + * end + */ static VALUE fsdbm_invert(VALUE obj) { @@ -384,6 +585,18 @@ fsdbm_invert(VALUE obj) return hash; } +/* + * call-seq: + * sdbm[key] = value -> value + * sdbm.store(key, value) -> value + * + * Stores a new +value+ in the database with the given +key+ as an index. + * + * If the +key+ already exists, this will update the +value+ associated with + * the +key+. + * + * Returns the given +value+. + */ static VALUE fsdbm_store(VALUE obj, VALUE keystr, VALUE valstr) { @@ -430,6 +643,15 @@ update_i(VALUE pair, VALUE dbm) return Qnil; } +/* + * call-seq: + * sdbm.update(pairs) -> self + * + * Insert or update key-value pairs. + * + * This method will work with any object which implements an each_pair + * method, such as a Hash. + */ static VALUE fsdbm_update(VALUE obj, VALUE other) { @@ -437,6 +659,15 @@ fsdbm_update(VALUE obj, VALUE other) return obj; } +/* + * call-seq: + * sdbm.replace(pairs) -> self + * + * Empties the database, then inserts the given key-value pairs. + * + * This method will work with any object which implements an each_pair + * method, such as a Hash. + */ static VALUE fsdbm_replace(VALUE obj, VALUE other) { @@ -445,6 +676,13 @@ fsdbm_replace(VALUE obj, VALUE other) return obj; } +/* + * call-seq: + * sdbm.length -> integer + * sdbm.size -> integer + * + * Returns the number of keys in the database. + */ static VALUE fsdbm_length(VALUE obj) { @@ -464,6 +702,12 @@ fsdbm_length(VALUE obj) return INT2FIX(i); } +/* + * call-seq: + * sdbm.empty? -> true or false + * + * Returns +true+ if the database is empty. + */ static VALUE fsdbm_empty_p(VALUE obj) { @@ -487,6 +731,15 @@ fsdbm_empty_p(VALUE obj) return Qfalse; } +/* + * call-seq: + * sdbm.each_value + * sdbm.each_value { |value| ... } + * + * Iterates over each +value+ in the database. + * + * If no block is given, returns an Enumerator. + */ static VALUE fsdbm_each_value(VALUE obj) { @@ -505,6 +758,15 @@ fsdbm_each_value(VALUE obj) return obj; } +/* + * call-seq: + * sdbm.each_key + * sdbm.each_key { |key| ... } + * + * Iterates over each +key+ in the database. + * + * If no block is given, returns an Enumerator. + */ static VALUE fsdbm_each_key(VALUE obj) { @@ -522,6 +784,17 @@ fsdbm_each_key(VALUE obj) return obj; } +/* + * call-seq: + * sdbm.each + * sdbm.each { |key, value| ... } + * sdbm.each_pair + * sdbm.each_pair { |key, value| ... } + * + * Iterates over each key-value pair in the database. + * + * If no block is given, returns an Enumerator. + */ static VALUE fsdbm_each_pair(VALUE obj) { @@ -544,6 +817,12 @@ fsdbm_each_pair(VALUE obj) return obj; } +/* + * call-seq: + * sdbm.keys -> Array + * + * Returns a new Array containing the keys in the database. + */ static VALUE fsdbm_keys(VALUE obj) { @@ -561,6 +840,12 @@ fsdbm_keys(VALUE obj) return ary; } +/* + * call-seq: + * sdbm.values -> Array + * + * Returns a new Array containing the values in the database. + */ static VALUE fsdbm_values(VALUE obj) { @@ -579,6 +864,15 @@ fsdbm_values(VALUE obj) return ary; } +/* + * call-seq: + * sdbm.include?(key) -> true or false + * sdbm.key?(key) -> true or false + * sdbm.member?(key) -> true or false + * sdbm.has_key?(key) -> true or false + * + * Returns +true+ if the database contains the given +key+. + */ static VALUE fsdbm_has_key(VALUE obj, VALUE keystr) { @@ -596,6 +890,13 @@ fsdbm_has_key(VALUE obj, VALUE keystr) return Qfalse; } +/* + * call-seq: + * sdbm.value?(key) -> true or false + * sdbm.has_value?(key) -> true or false + * + * Returns +true+ if the database contains the given +value+. + */ static VALUE fsdbm_has_value(VALUE obj, VALUE valstr) { @@ -617,6 +918,22 @@ fsdbm_has_value(VALUE obj, VALUE valstr) return Qfalse; } +/* + * call-seq: + * sdbm.to_a -> Array + * + * Returns a new Array containing each key-value pair in the database. + * + * Example: + * + * require 'sdbm' + * + * SDBM.open 'my_database' do |db| + * db.update('apple' => 'fruit', 'spinach' => 'vegetable') + * + * db.to_a #=> [["apple", "fruit"], ["spinach", "vegetable"]] + * end + */ static VALUE fsdbm_to_a(VALUE obj) { @@ -636,6 +953,12 @@ fsdbm_to_a(VALUE obj) return ary; } +/* + * call-seq: + * sdbm.to_hash -> Hash + * + * Returns a new Hash containing each key-value pair in the database. + */ static VALUE fsdbm_to_hash(VALUE obj) { @@ -655,6 +978,14 @@ fsdbm_to_hash(VALUE obj) return hash; } +/* + * call-seq: + * sdbm.reject { |key, value| ... } -> Hash + * + * Creates a new Hash using the key-value pairs from the database, then + * calls Hash#reject with the given block, which returns a Hash with + * only the key-value pairs for which the block returns +false+. + */ static VALUE fsdbm_reject(VALUE obj) { @@ -666,6 +997,9 @@ Init_sdbm() { rb_cDBM = rb_define_class("SDBM", rb_cObject); rb_eDBMError = rb_define_class("SDBMError", rb_eStandardError); + /* Document-class: SDBMError + * Exception class used to return errors from the sdbm library. + */ rb_include_module(rb_cDBM, rb_mEnumerable); rb_define_alloc_func(rb_cDBM, fsdbm_alloc); @@ -701,11 +1035,11 @@ Init_sdbm() rb_define_method(rb_cDBM,"update", fsdbm_update, 1); rb_define_method(rb_cDBM,"replace", fsdbm_replace, 1); - rb_define_method(rb_cDBM, "include?", fsdbm_has_key, 1); rb_define_method(rb_cDBM, "has_key?", fsdbm_has_key, 1); + rb_define_method(rb_cDBM, "include?", fsdbm_has_key, 1); + rb_define_method(rb_cDBM, "key?", fsdbm_has_key, 1); rb_define_method(rb_cDBM, "member?", fsdbm_has_key, 1); rb_define_method(rb_cDBM, "has_value?", fsdbm_has_value, 1); - rb_define_method(rb_cDBM, "key?", fsdbm_has_key, 1); rb_define_method(rb_cDBM, "value?", fsdbm_has_value, 1); rb_define_method(rb_cDBM, "to_a", fsdbm_to_a, 0); |