Spec-Zone.ru › Ruby 2.5

класс DBM

Родитель:
Объект
Включенные модули:
Enumerable

Введение

Класс DBM предоставляет оболочку для библиотеки управления базами данных Unix-стиля dbm.

Базы данных dbm не имеют таблиц или столбцов; они представляют собой простые хранилища данных ключ-значение, подобные Ruby Hash, но не хранящиеся в оперативной памяти. Ключи и значения должны быть строками.

Точная используемая библиотека зависит от того, как был скомпилирован Ruby. Она может быть любой из следующих:

  • Оригинальная библиотека ndbm выпущена в 4.3BSD. Она основана на библиотеке dbm в Unix Версии 7, но имеет другой API для поддержки нескольких баз данных в одном процессе.

  • Berkeley DB версии с 1 по 5, также известные как BDB и Sleepycat DB, сейчас принадлежащие корпорации Oracle.

  • Berkeley DB 1.x, всё ещё встречается в производных 4.4BSD (FreeBSD, OpenBSD и т. д.).

  • gdbm, GNU реализация dbm.

  • qdbm, другая открытая реализация dbm.

Все эти реализации dbm имеют свои Ruby интерфейсы, которые предоставляют более богатый (но различающийся) API.

Предостережения

Прежде чем вы решите использовать DBM, стоит рассмотреть некоторые проблемы:

  • Каждая реализация dbm имеет свой собственный формат файла. Как правило, библиотеки dbm не будут читать файлы друг друга. Это делает файлы dbm плохим выбором для обмена данными.

  • Даже при использовании той же операционной системы и той же реализации dbm, формат файла базы данных может зависеть от архитектуры процессора. Например, файлы могут быть не переносимы между PowerPC и 386, или между 32 и 64-битными Linux.

  • Разные версии Berkeley DB используют разные форматы файлов. Изменение операционной системы может поэтому нарушить доступ DBM к существующим файлам.

  • Размер данных ограничений различаются между реализациями. Первоначальный Berkeley DB был ограничен 2 ГБ данных. Библиотеки dbm также иногда ограничивают общий размер пары ключ/значение и общий размер всех ключей, хеширующихся в одно и то же значение. Эти ограничения могут быть всего 512 байтами. Однако, gdbm и последние версии Berkeley DB лишены этих ограничений.

Учитывая вышеизложенные предостережения, DBM не является хорошим выбором для долгосрочного хранения важных данных. Возможно, его лучше использовать в качестве быстрого и простого альтернативного варианта Hash для обработки больших объёмов данных.

Пример

require 'dbm'
db = DBM.open('rfcs', 0666, DBM::WRCREAT)
db['822'] = 'Standard for the Format of ARPA Internet Text Messages'
db['1123'] = 'Requirements for Internet Hosts - Application and Support'
db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers'
puts db['822']

Константы

NEWDB

Указывает, что dbm_open() должен открыть базу данных в режиме чтения/записи, создать её, если она не существует, и удалить всё содержимое, если оно уже существует.

READER

Указывает, что dbm_open() должен открыть базу данных в режиме только для чтения

VERSION

Идентифицирует версию библиотеки ndbm.

Примеры:

  • “ndbm (4.3BSD)”

  • “Berkeley DB 4.8.30: (9 апреля 2010 г.)”

  • “Berkeley DB (неизвестно)” (возможно, 4.4BSD)

  • “GDBM version 1.8.3. 15/10/2002 (built 1 июля 2011 12:32:45)”

  • “QDBM 1.8.78”

WRCREAT

Указывает, что dbm_open() должен открыть базу данных в режиме чтения/записи и создать её, если она не существует

WRITER

Указывает, что dbm_open() должен открыть базу данных в режиме чтения/записи

Общественные методы класса

new(filename[, mode[, flags]]) → dbm Показать исходный код
static VALUE
fdbm_initialize(int argc, VALUE *argv, VALUE obj)
{
    VALUE file, vmode, vflags;
    DBM *dbm;
    struct dbmdata *dbmp;
    int mode, flags = 0;

    TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp);
    if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
        mode = 0666;           /* default value */
    }
    else if (NIL_P(vmode)) {
        mode = -1;             /* return nil if DB not exist */
    }
    else {
        mode = NUM2INT(vmode);
    }

    if (!NIL_P(vflags))
        flags = NUM2INT(vflags);

    FilePathValue(file);

    /*
     * Note:
     * gdbm 1.10 works with O_CLOEXEC.  gdbm 1.9.1 silently ignore it.
     */
#ifndef O_CLOEXEC
#   define O_CLOEXEC 0
#endif

    if (flags & RUBY_DBM_RW_BIT) {
        flags &= ~RUBY_DBM_RW_BIT;
        dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode);
    }
    else {
        dbm = 0;
        if (mode >= 0) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode);
        }
        if (!dbm) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0);
        }
        if (!dbm) {
            dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0);
        }
    }

    if (dbm) {
        /*
         * History of dbm_pagfno() and dbm_dirfno() in ndbm and its compatibles.
         * (dbm_pagfno() and dbm_dirfno() is not standardized.)
         *
         * 1986: 4.3BSD provides ndbm.
         *       It provides dbm_pagfno() and dbm_dirfno() as macros.
         * 1991: gdbm-1.5 provides them as functions.
         *       They returns a same descriptor.
         *       (Earlier releases may have the functions too.)
         * 1991: Net/2 provides Berkeley DB.
         *       It doesn't provide dbm_pagfno() and dbm_dirfno().
         * 1992: 4.4BSD Alpha provides Berkeley DB with dbm_dirfno() as a function.
         *       dbm_pagfno() is a macro as DBM_PAGFNO_NOT_AVAILABLE.
         * 1997: Berkeley DB 2.0 is released by Sleepycat Software, Inc.
         *       It defines dbm_pagfno() and dbm_dirfno() as macros.
         * 2011: gdbm-1.9 creates a separate dir file.
         *       dbm_pagfno() and dbm_dirfno() returns different descriptors.
         */
#if defined(HAVE_DBM_PAGFNO)
        rb_fd_fix_cloexec(dbm_pagfno(dbm));
#endif
#if defined(HAVE_DBM_DIRFNO)
        rb_fd_fix_cloexec(dbm_dirfno(dbm));
#endif

#if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC)
        /* Disable Berkeley DB error messages such as:
         * DB->put: attempt to modify a read-only database */
        ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL);
#endif
    }

    if (!dbm) {
        if (mode == -1) return Qnil;
        rb_sys_fail_str(file);
    }

    if (dbmp->di_dbm)
        dbm_close(dbmp->di_dbm);
    dbmp->di_dbm = dbm;
    dbmp->di_size = -1;

    return obj;
}

Открывает базу данных dbm с указанным именем, которое может включать путь к каталогу. Любые необходимые расширения файлов будут автоматически добавлены библиотекой dbm. Например, Berkeley DB добавляет '.db', а GNU gdbm использует два физических файла с расширениями '.dir' и '.pag'.

Режим должен быть целым числом, как в Unix chmod.

Флаги должны быть одним из READER, WRITER, WRCREAT или NEWDB.

open(filename[, mode[, flags]]) → dbm Показать исходный код
open(filename[, mode[, flags]]) {|dbm| block}
static VALUE
fdbm_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE obj = fdbm_alloc(klass);

    if (NIL_P(fdbm_initialize(argc, argv, obj))) {
        return Qnil;
    }

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, obj, fdbm_close, obj);
    }

    return obj;
}

Открывает базу данных dbm и возвращает её, если задан блок. См. также DBM.new.

Публичные методы экземпляра

dbm[key] → string value or nil Show source
static VALUE
fdbm_aref(VALUE obj, VALUE keystr)
{
    return fdbm_fetch(obj, keystr, Qnil);
}

Возвращает значение из базы данных по указанной строке ключа. Если ключ не найден, возвращает nil.

dbm[key] = value Show source
static VALUE
fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;

    fdbm_modify(obj);
    keystr = rb_obj_as_string(keystr);
    valstr = rb_obj_as_string(valstr);

    key.dptr = RSTRING_PTR(keystr);
    key.dsize = RSTRING_DSIZE(keystr);

    val.dptr = RSTRING_PTR(valstr);
    val.dsize = RSTRING_DSIZE(valstr);

    GetDBM2(obj, dbmp, dbm);
    dbmp->di_size = -1;
    if (dbm_store(dbm, key, val, DBM_REPLACE)) {
        dbm_clearerr(dbm);
        if (errno == EPERM) rb_sys_fail(0);
        rb_raise(rb_eDBMError, "dbm_store failed");
    }

    return valstr;
}

Сохраняет указанное строковое значение в базе данных с индексом по указанной строке ключа.

clear Show source
static VALUE
fdbm_clear(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;

    fdbm_modify(obj);
    GetDBM2(obj, dbmp, dbm);
    dbmp->di_size = -1;
    while (key = dbm_firstkey(dbm), key.dptr) {
        if (dbm_delete(dbm, key)) {
            rb_raise(rb_eDBMError, "dbm_delete failed");
        }
    }
    dbmp->di_size = 0;

    return obj;
}

Удаляет все данные из базы данных.

close Show source
static VALUE
fdbm_close(VALUE obj)
{
    struct dbmdata *dbmp;

    GetDBM(obj, dbmp);
    dbm_close(dbmp->di_dbm);
    dbmp->di_dbm = 0;

    return Qnil;
}

Закрывает базу данных.

closed? → true or false Show source
static VALUE
fdbm_closed(VALUE obj)
{
    struct dbmdata *dbmp;

    TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp);
    if (dbmp->di_dbm == 0)
        return Qtrue;

    return Qfalse;
}

Возвращает true, если база данных закрыта, false в противном случае.

delete(key) Show source
static VALUE
fdbm_delete(VALUE obj, VALUE keystr)
{
    datum key, value;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE valstr;
    long len;

    fdbm_modify(obj);
    ExportStringValue(keystr);
    len = RSTRING_LEN(keystr);
    if (TOO_LONG(len)) goto not_found;
    key.dptr = RSTRING_PTR(keystr);
    key.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);

    value = dbm_fetch(dbm, key);
    if (value.dptr == 0) {
      not_found:
        if (rb_block_given_p()) return rb_yield(keystr);
        return Qnil;
    }

    /* need to save value before dbm_delete() */
    valstr = rb_tainted_str_new(value.dptr, value.dsize);

    if (dbm_delete(dbm, key)) {
        dbmp->di_size = -1;
        rb_raise(rb_eDBMError, "dbm_delete failed");
    }
    else if (dbmp->di_size >= 0) {
        dbmp->di_size--;
    }
    return valstr;
}

Удаляет запись из базы данных.

delete_if {|key, value| block} → self Show source
static VALUE
fdbm_delete_if(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE keystr, valstr;
    VALUE ret, ary = rb_ary_tmp_new(0);
    int status = 0;
    long i, n;

    fdbm_modify(obj);
    GetDBM2(obj, dbmp, dbm);
    n = dbmp->di_size;
    dbmp->di_size = -1;

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        keystr = rb_tainted_str_new(key.dptr, key.dsize);
        OBJ_FREEZE(keystr);
        valstr = rb_tainted_str_new(val.dptr, val.dsize);
        ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
        if (status != 0) break;
        if (RTEST(ret)) rb_ary_push(ary, keystr);
        GetDBM2(obj, dbmp, dbm);
    }

    for (i = 0; i < RARRAY_LEN(ary); i++) {
        keystr = RARRAY_AREF(ary, i);
        key.dptr = RSTRING_PTR(keystr);
        key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
        if (dbm_delete(dbm, key)) {
            rb_raise(rb_eDBMError, "dbm_delete failed");
        }
    }
    if (status) rb_jump_tag(status);
    if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
    rb_ary_clear(ary);

    return obj;
}

Удаляет все записи, для которых блок кода возвращает true. Возвращает self.

each_pair {|key,value| block} → self Show source
static VALUE
fdbm_each_pair(VALUE obj)
{
    datum key, val;
    DBM *dbm;
    struct dbmdata *dbmp;
    VALUE keystr, valstr;

    RETURN_ENUMERATOR(obj, 0, 0);

    GetDBM2(obj, dbmp, dbm);

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        keystr = rb_tainted_str_new(key.dptr, key.dsize);
        valstr = rb_tainted_str_new(val.dptr, val.dsize);
        rb_yield(rb_assoc_new(keystr, valstr));
        GetDBM2(obj, dbmp, dbm);
    }

    return obj;
}

Вызывает блок один раз для каждой пары [ключ, значение] в базе данных. Возвращает self.

each_key {|key| block} → self Show source
static VALUE
fdbm_each_key(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;

    RETURN_ENUMERATOR(obj, 0, 0);

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
        GetDBM2(obj, dbmp, dbm);
    }
    return obj;
}

Вызывает блок один раз для каждой строки ключа в базе данных. Возвращает self.

each_pair {|key,value| block} → self Show source
static VALUE
fdbm_each_pair(VALUE obj)
{
    datum key, val;
    DBM *dbm;
    struct dbmdata *dbmp;
    VALUE keystr, valstr;

    RETURN_ENUMERATOR(obj, 0, 0);

    GetDBM2(obj, dbmp, dbm);

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        keystr = rb_tainted_str_new(key.dptr, key.dsize);
        valstr = rb_tainted_str_new(val.dptr, val.dsize);
        rb_yield(rb_assoc_new(keystr, valstr));
        GetDBM2(obj, dbmp, dbm);
    }

    return obj;
}

Вызывает блок один раз для каждой пары [ключ, значение] в базе данных. Возвращает self.

each_value {|value| block} → self Show source
static VALUE
fdbm_each_value(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;

    RETURN_ENUMERATOR(obj, 0, 0);

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
        GetDBM2(obj, dbmp, dbm);
    }
    return obj;
}

Вызывает блок один раз для каждой строки значения в базе данных. Возвращает self.

empty? Show source
static VALUE
fdbm_empty_p(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;

    GetDBM2(obj, dbmp, dbm);
    if (dbmp->di_size < 0) {
        dbm = dbmp->di_dbm;

        for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
            return Qfalse;
        }
    }
    else {
        if (dbmp->di_size)
            return Qfalse;
    }
    return Qtrue;
}

Возвращает true, если база данных пуста, false в противном случае.

fetch(key[, ifnone]) → value Show source
static VALUE
fdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
{
    VALUE keystr, valstr, ifnone;

    rb_scan_args(argc, argv, "11", &keystr, &ifnone);
    valstr = fdbm_fetch(obj, keystr, ifnone);
    if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
        rb_raise(rb_eIndexError, "key not found");

    return valstr;
}

Возвращает значение из базы данных по указанной строке ключа. Если ключ не найден, возвращает ifnone. Если ifnone не задан, вызывает IndexError.

has_key?(key) → boolean Show source
static VALUE
fdbm_has_key(VALUE obj, VALUE keystr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(keystr);
    len = RSTRING_LEN(keystr);
    if (TOO_LONG(len)) return Qfalse;
    key.dptr = RSTRING_PTR(keystr);
    key.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    val = dbm_fetch(dbm, key);
    if (val.dptr) return Qtrue;
    return Qfalse;
}

Возвращает true, если база данных содержит указанный ключ, false в противном случае.

has_value?(value) → boolean Show source
static VALUE
fdbm_has_value(VALUE obj, VALUE valstr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(valstr);
    len = RSTRING_LEN(valstr);
    if (TOO_LONG(len)) return Qfalse;
    val.dptr = RSTRING_PTR(valstr);
    val.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
            memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
            return Qtrue;
    }
    return Qfalse;
}

Возвращает true, если база данных содержит указанное строковое значение, false в противном случае.

include?(key) → boolean Show source
static VALUE
fdbm_has_key(VALUE obj, VALUE keystr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(keystr);
    len = RSTRING_LEN(keystr);
    if (TOO_LONG(len)) return Qfalse;
    key.dptr = RSTRING_PTR(keystr);
    key.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    val = dbm_fetch(dbm, key);
    if (val.dptr) return Qtrue;
    return Qfalse;
}

Возвращает true, если база данных содержит указанный ключ, false в противном случае.

invert → hash Show source
static VALUE
fdbm_invert(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE keystr, valstr;
    VALUE hash = rb_hash_new();

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        keystr = rb_tainted_str_new(key.dptr, key.dsize);
        valstr = rb_tainted_str_new(val.dptr, val.dsize);
        rb_hash_aset(hash, valstr, keystr);
    }
    return hash;
}

Возвращает Hash (не базу данных DBM), созданную с использованием каждого значения в базе данных в качестве ключа, а соответствующего ключа — в качестве его значения.

key(value) → string Show source
static VALUE
fdbm_key(VALUE obj, VALUE valstr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(valstr);
    len = RSTRING_LEN(valstr);
    if (TOO_LONG(len)) return Qnil;

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        if ((long)val.dsize == RSTRING_LEN(valstr) &&
            memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) {
            return rb_tainted_str_new(key.dptr, key.dsize);
        }
    }
    return Qnil;
}

Возвращает ключ для указанного значения.

key?(key) → boolean Show source
static VALUE
fdbm_has_key(VALUE obj, VALUE keystr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(keystr);
    len = RSTRING_LEN(keystr);
    if (TOO_LONG(len)) return Qfalse;
    key.dptr = RSTRING_PTR(keystr);
    key.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    val = dbm_fetch(dbm, key);
    if (val.dptr) return Qtrue;
    return Qfalse;
}

Возвращает true, если база данных содержит указанный ключ, false в противном случае.

keys → array Show source
static VALUE
fdbm_keys(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE ary;

    GetDBM2(obj, dbmp, dbm);

    ary = rb_ary_new();
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
    }

    return ary;
}

Возвращает массив всех строковых ключей в базе данных.

length → integer Show source
static VALUE
fdbm_length(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;
    int i = 0;

    GetDBM2(obj, dbmp, dbm);
    if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        i++;
    }
    dbmp->di_size = i;

    return INT2FIX(i);
}

Возвращает количество записей в базе данных.

member?(key) → boolean Show source
static VALUE
fdbm_has_key(VALUE obj, VALUE keystr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(keystr);
    len = RSTRING_LEN(keystr);
    if (TOO_LONG(len)) return Qfalse;
    key.dptr = RSTRING_PTR(keystr);
    key.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    val = dbm_fetch(dbm, key);
    if (val.dptr) return Qtrue;
    return Qfalse;
}

Возвращает true, если база данных содержит указанный ключ, false в противном случае.

reject {|key,value| block} → Hash Show source
static VALUE
fdbm_reject(VALUE obj)
{
    return rb_hash_delete_if(fdbm_to_hash(obj));
}

Преобразует содержимое базы данных в находящийся в памяти Hash, затем вызывает Hash#reject с указанным блоком кода, возвращая новый Hash.

reject! {|key, value| block} → self Show source
static VALUE
fdbm_delete_if(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE keystr, valstr;
    VALUE ret, ary = rb_ary_tmp_new(0);
    int status = 0;
    long i, n;

    fdbm_modify(obj);
    GetDBM2(obj, dbmp, dbm);
    n = dbmp->di_size;
    dbmp->di_size = -1;

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        keystr = rb_tainted_str_new(key.dptr, key.dsize);
        OBJ_FREEZE(keystr);
        valstr = rb_tainted_str_new(val.dptr, val.dsize);
        ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
        if (status != 0) break;
        if (RTEST(ret)) rb_ary_push(ary, keystr);
        GetDBM2(obj, dbmp, dbm);
    }

    for (i = 0; i < RARRAY_LEN(ary); i++) {
        keystr = RARRAY_AREF(ary, i);
        key.dptr = RSTRING_PTR(keystr);
        key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
        if (dbm_delete(dbm, key)) {
            rb_raise(rb_eDBMError, "dbm_delete failed");
        }
    }
    if (status) rb_jump_tag(status);
    if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
    rb_ary_clear(ary);

    return obj;
}

Удаляет все записи, для которых блок кода возвращает true. Возвращает self.

replace(obj) Show source
static VALUE
fdbm_replace(VALUE obj, VALUE other)
{
    fdbm_clear(obj);
    rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
    return obj;
}

Заменяет содержимое базы данных содержимым указанного объекта. Принимает любой объект, который реализует метод #each_pair, включая объекты Hash и DBM.

select {|key, value| block} → array Show source
static VALUE
fdbm_select(VALUE obj)
{
    VALUE new = rb_ary_new();
    datum key, val;
    DBM *dbm;
    struct dbmdata *dbmp;

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        VALUE assoc, v;
        val = dbm_fetch(dbm, key);
        assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
                             rb_tainted_str_new(val.dptr, val.dsize));
        v = rb_yield(assoc);
        if (RTEST(v)) {
            rb_ary_push(new, assoc);
        }
        GetDBM2(obj, dbmp, dbm);
    }

    return new;
}

Возвращает новый массив, состоящий из пар [ключ, значение], для которых блок кода возвращает true.

shift() → [key, value] Show source
static VALUE
fdbm_shift(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE keystr, valstr;

    fdbm_modify(obj);
    GetDBM2(obj, dbmp, dbm);
    dbmp->di_size = -1;

    key = dbm_firstkey(dbm);
    if (!key.dptr) return Qnil;
    val = dbm_fetch(dbm, key);
    keystr = rb_tainted_str_new(key.dptr, key.dsize);
    valstr = rb_tainted_str_new(val.dptr, val.dsize);
    dbm_delete(dbm, key);

    return rb_assoc_new(keystr, valstr);
}

Удаляет пару [ключ, значение] из базы данных и возвращает её. Если база данных пуста, возвращает nil. Порядок, в котором удаляются/возвращаются значения, не гарантируется.

size → integer Показать исходный код
static VALUE
fdbm_length(VALUE obj)
{
    datum key;
    struct dbmdata *dbmp;
    DBM *dbm;
    int i = 0;

    GetDBM2(obj, dbmp, dbm);
    if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);

    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        i++;
    }
    dbmp->di_size = i;

    return INT2FIX(i);
}

Возвращает количество записей в базе данных.

store(key, value) → value Показать исходный код
static VALUE
fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;

    fdbm_modify(obj);
    keystr = rb_obj_as_string(keystr);
    valstr = rb_obj_as_string(valstr);

    key.dptr = RSTRING_PTR(keystr);
    key.dsize = RSTRING_DSIZE(keystr);

    val.dptr = RSTRING_PTR(valstr);
    val.dsize = RSTRING_DSIZE(valstr);

    GetDBM2(obj, dbmp, dbm);
    dbmp->di_size = -1;
    if (dbm_store(dbm, key, val, DBM_REPLACE)) {
        dbm_clearerr(dbm);
        if (errno == EPERM) rb_sys_fail(0);
        rb_raise(rb_eDBMError, "dbm_store failed");
    }

    return valstr;
}

Сохраняет указанное строковое значение в базе данных, индексируя его с помощью предоставленного строкового ключа.

to_a → array Показать исходный код
static VALUE
fdbm_to_a(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE ary;

    GetDBM2(obj, dbmp, dbm);
    ary = rb_ary_new();
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
                                      rb_tainted_str_new(val.dptr, val.dsize)));
    }

    return ary;
}

Преобразует содержимое базы данных в массив массивов [ключ, значение] и возвращает его.

to_hash → hash Показать исходный код
static VALUE
fdbm_to_hash(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE hash;

    GetDBM2(obj, dbmp, dbm);
    hash = rb_hash_new();
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
                           rb_tainted_str_new(val.dptr, val.dsize));
    }

    return hash;
}

Преобразует содержимое базы данных в объект Hash в оперативной памяти и возвращает его.

update(obj) Показать исходный код
static VALUE
fdbm_update(VALUE obj, VALUE other)
{
    rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
    return obj;
}

Обновляет базу данных с помощью нескольких значений из указанного объекта. Принимает любой объект, реализующий метод #each_pair, включая объекты Hash и DBM.

value?(value) → boolean Показать исходный код
static VALUE
fdbm_has_value(VALUE obj, VALUE valstr)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    long len;

    ExportStringValue(valstr);
    len = RSTRING_LEN(valstr);
    if (TOO_LONG(len)) return Qfalse;
    val.dptr = RSTRING_PTR(valstr);
    val.dsize = (DSIZE_TYPE)len;

    GetDBM2(obj, dbmp, dbm);
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
            memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
            return Qtrue;
    }
    return Qfalse;
}

Возвращает true, если база данных содержит указанное строковое значение, и false в противном случае.

values → array Показать исходный код
static VALUE
fdbm_values(VALUE obj)
{
    datum key, val;
    struct dbmdata *dbmp;
    DBM *dbm;
    VALUE ary;

    GetDBM2(obj, dbmp, dbm);
    ary = rb_ary_new();
    for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
        val = dbm_fetch(dbm, key);
        rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
    }

    return ary;
}

Возвращает массив всех строковых значений в базе данных.

values_at(key, ...) → Array Показать исходный код
static VALUE
fdbm_values_at(int argc, VALUE *argv, VALUE obj)
{
    VALUE new = rb_ary_new2(argc);
    int i;

    for (i=0; i<argc; i++) {
        rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
    }

    return new;
}

Возвращает массив, содержащий значения, связанные с заданными ключами.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API