From 7c80d4e5db2f1a7d0ae5d219979f0bfe50697ac1 Mon Sep 17 00:00:00 2001
From: Justin Collins <justin@presidentbeef.com>
Date: Mon, 7 May 2012 20:58:54 -0700
Subject: [PATCH] Add documentation for SDBM

---
 ext/sdbm/init.c |  331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 330 insertions(+), 1 deletions(-)

diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index f138d24..69a185a 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -15,6 +15,56 @@
 #include <fcntl.h>
 #include <errno.h>
 
+/*
+ * Document-class: SDBM
+ *
+ * = Introduction
+ *
+ * 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
+ *
+ *     #Output:
+ *     #  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 +97,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 +117,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 +142,18 @@ 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 +195,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 +250,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 +291,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 +320,12 @@ fsdbm_key(VALUE obj, VALUE valstr)
     return Qnil;
 }
 
+/*
+ * call-seq:
+ *      sdbm.index(value) -> key
+ *
+ * This method is the same as SDBM#key and has been deprecated.
+ */
 static VALUE
 fsdbm_index(VALUE hash, VALUE value)
 {
@@ -204,6 +333,26 @@ fsdbm_index(VALUE hash, VALUE value)
     return fsdbm_key(hash, value);
 }
 
+/* call-seq:
+ *      sdbm.select { |key, value| block } -> 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 +377,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 +402,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 kay-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 +449,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 +479,14 @@ fsdbm_shift(VALUE obj)
     return rb_assoc_new(keystr, valstr);
 }
 
+/*
+ * call-seq:
+ *      sdbm.delete_if { |key, value| block } -> self
+ *      sdbm.reject! { |key, value| block } -> 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 +526,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 +552,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 +587,17 @@ fsdbm_invert(VALUE obj)
     return hash;
 }
 
+/*
+ * call-seq:
+ *      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 +644,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 +660,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 +677,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 +703,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 +732,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 +759,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 +785,15 @@ fsdbm_each_key(VALUE obj)
     return obj;
 }
 
+/*
+ * call-seq:
+ *      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 +816,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 +839,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 +863,12 @@ fsdbm_values(VALUE obj)
     return ary;
 }
 
+/*
+ * call-seq:
+ *      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 +886,12 @@ fsdbm_has_key(VALUE obj, VALUE keystr)
     return Qfalse;
 }
 
+/*
+ * call-seq:
+ *      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 +913,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 +948,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 +973,14 @@ fsdbm_to_hash(VALUE obj)
     return hash;
 }
 
+/*
+ * call-seq:
+ *      sdbm.reject { |key, value| block } -> 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 +992,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);
-- 
1.7.1

