perldbmfilter
СОДЕРЖАНИЕ
ИМЯ
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 strict;
use warnings;
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.
Надеюсь, содержимое каждого из фильтров должно быть самоочевидным. Оба фильтра «считывания» удаляют завершающий нуль, а оба фильтра «записи» добавляют завершающий нуль.
Другой пример: ключ — целое число C.
Вот еще один пример из реальной жизни. По умолчанию, когда Perl записывает в базу данных DBM, он всегда записывает ключ и значение как строки. Итак, когда вы используете это:
$hash{12345} = "something"; ключ 12345 будет сохранен в базе данных DBM как строка длиной 5 байт «12345». Если вы хотите, чтобы ключ хранился в базе данных DBM как целое число C, вам необходимо использовать pack при записи и unpack при чтении.
Вот фильтр DBM, который это делает:
use strict;
use warnings;
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.34.0/perldbmfilter