Spec-Zone.ru › Perl 5.36

perldbmfilter

СОДЕРЖАНИЕ

  • ИМЯ
  • СИНТАКСИС
  • ОПИСАНИЕ
    • Фильтр
    • Пример: проблема нуль-терминации.
    • Ещё один пример: ключ — C-целое.
  • СМОТРИТЕ ТАКЖЕ
  • АВТОР

ИМЯ

perldbmfilter — Фильтры Perl DBM

СИНТАКСИС

$db = tie %hash, 'DBM', ...

$old_filter = $db->filter_store_key  ( sub { ... } );
$old_filter = $db->filter_store_value( sub { ... } );
$old_filter = $db->filter_fetch_key  ( sub { ... } );
$old_filter = $db->filter_fetch_value( sub { ... } );

ОПИСАНИЕ

Четыре filter_* метода показаны выше, доступны во всех модулях DBM, поставляемых с Perl, а именно DB_File, GDBM_File, NDBM_File, ODBM_File и SDBM_File.

Каждый из методов работает идентично и используется для установки (или удаления) одного фильтра DBM. Единственное различие между ними — место, где устанавливается фильтр.

Вкратце:

filter_store_key

Если фильтр установлен с помощью этого метода, он будет вызываться каждый раз, когда вы записываете ключ в базу данных DBM.

filter_store_value

Если фильтр установлен с помощью этого метода, он будет вызываться каждый раз, когда вы записываете значение в базу данных DBM.

filter_fetch_key

Если фильтр установлен с помощью этого метода, он будет вызываться каждый раз, когда вы читаете ключ из базы данных DBM.

filter_fetch_value

Если фильтр установлен с помощью этого метода, он будет вызываться каждый раз, когда вы читаете значение из базы данных DBM.

Вы можете использовать любую комбинацию методов от нуля до всех четырёх.

Все методы фильтров возвращают существующий фильтр, если он есть, или undef в противном случае.

Чтобы удалить фильтр, передайте undef в него.

Фильтр

Когда каждый фильтр вызывается Perl, локальная копия $_ будет содержать ключ или значение для фильтрации. Фильтрация достигается путём изменения содержимого $_. Код возврата фильтра игнорируется.

Пример: проблема нуль-терминации.

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

Например, рассмотрим следующую ситуацию. У вас есть база данных DBM, которую вам нужно поделиться с приложением на C от стороннего разработчика. Приложение на C предполагает, что все ключи и значения завершаются нулём. К сожалению, когда Perl записывает в базы данных DBM, он не использует нуль-терминацию, поэтому вашему приложению Perl придётся управлять нуль-терминацией самостоятельно. Когда вы записываете в базу данных, вам нужно будет использовать что-то вроде этого:

$hash{"$key\0"} = "$value\0";

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

Гораздо лучше было бы игнорировать проблему нуль-терминации в основном коде приложения и иметь механизм, который автоматически добавлял бы завершающий нуль ко всем ключам и значениям при записи в базу данных и удалял бы их при чтении из базы данных. Как я уверен, вы уже догадались, это проблема, которую фильтры DBM могут решить очень легко.

use v5.36;
use SDBM_File;
use Fcntl;

my %hash;
my $filename = "filt";
unlink $filename;

my $db = tie(%hash, 'SDBM_File', $filename, O_RDWR|O_CREAT, 0640)
  or die "Cannot open $filename: $!\n";

# Install DBM Filters
$db->filter_fetch_key  ( sub { s/\0$//    } );
$db->filter_store_key  ( sub { $_ .= "\0" } );
$db->filter_fetch_value( 
    sub { no warnings 'uninitialized'; s/\0$// } );
$db->filter_store_value( sub { $_ .= "\0" } );

$hash{"abc"} = "def";
my $a = $hash{"ABC"};
# ...
undef $db;
untie %hash;

В приведенном выше коде используется SDBM_File, но он будет работать с любыми модулями DBM.

Надеюсь, содержимое каждого из фильтров должно быть самоочевидным. Оба фильтра «fetch» удаляют завершающий нуль, а оба фильтра «store» добавляют завершающий нуль.

Ещё один пример: ключ — C-целое.

Вот ещё один пример из реальной жизни. По умолчанию, когда Perl записывает в базу данных DBM, он всегда записывает ключ и значение как строки. Итак, когда вы используете это:

$hash{12345} = "something";

ключ 12345 будет сохранён в базе данных DBM как строка из 5 байтов "12345". Если вы хотите, чтобы ключ хранился в базе данных DBM как C-целое число, вам нужно использовать pack при записи и unpack при чтении.

Вот фильтр DBM, который это делает:

use v5.36;
use DB_File;
my %hash;
my $filename = "filt";
unlink $filename;


my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666,
    $DB_HASH or die "Cannot open $filename: $!\n";

$db->filter_fetch_key  ( sub { $_ = unpack("i", $_) } );
$db->filter_store_key  ( sub { $_ = pack ("i", $_) } );
$hash{123} = "def";
# ...
undef $db;
untie %hash;

В приведенном выше коде используется DB_File, но снова он будет работать с любыми модулями DBM.

На этот раз использовалось только два фильтра; нам нужно было манипулировать только содержимым ключа, поэтому не было необходимости устанавливать какие-либо фильтры значений.

СМОТРИТЕ ТАКЖЕ

DB_File, GDBM_File, NDBM_File, ODBM_File и SDBM_File.

АВТОР

Пол Маркесс

© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.36.0/perldbmfilter

Spec-Zone.ru

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