DBM_Filter
СОДЕРЖАНИЕ
- ИМЯ
- СИНОПСИС
- ОПИСАНИЕ
- Что такое фильтр DBM?
- МЕТОДЫ
- Написание фильтра
- Включенные фильтры
- ЗАМЕЧАНИЯ
- ПРИМЕР
- СМОТРИ ТАКЖЕ
- АВТОР
ИМЯ
DBM_Filter -- Фильтрация ключей/значений DBM
СИНОПСИС
use DBM_Filter ;
use SDBM_File; # or DB_File, GDBM_File, NDBM_File, or ODBM_File
$db = tie %hash, ...
$db->Filter_Push(Fetch => sub {...},
Store => sub {...});
$db->Filter_Push('my_filter1');
$db->Filter_Push('my_filter2', params...);
$db->Filter_Key_Push(...) ;
$db->Filter_Value_Push(...) ;
$db->Filter_Pop();
$db->Filtered();
package DBM_Filter::my_filter1;
sub Store { ... }
sub Fetch { ... }
1;
package DBM_Filter::my_filter2;
sub Filter
{
my @opts = @_;
...
return (
sub Store { ... },
sub Fetch { ... } );
}
1; ОПИСАНИЕ
Этот модуль предоставляет интерфейс, который позволяет применять фильтры к связанным хешам, ассоциированным с файлами DBM. Он основан на обработчиках фильтров DBM, присутствующих во всех модулях *DB*_File, включённых в стандартную дистрибуцию Perl с версии 5.6.1 и выше. В дополнение к модулям *DB*_File, распространяемым с Perl, модуль BerkeleyDB, доступный на CPAN, поддерживает обработчики фильтров DBM. Для получения дополнительной информации об обработчиках фильтров DBM см. perldbmfilter.
Что такое фильтр DBM?
Фильтр DBM позволяет изменять ключи и/или значения в связанном хеше с помощью некоторого пользовательского кода непосредственно перед записью в файл DBM и непосредственно после чтения из файла DBM. Например, этот фрагмент кода
$some_hash{"abc"} = 42; может потенциально запустить два фильтра, один для записи ключа "abc" и другой для записи значения 42. Аналогично, этот фрагмент
my ($key, $value) = each %some_hash запустит два фильтра, один для чтения ключа и один для чтения значения.
Как и существующая функциональность фильтров DBM, этот модуль обеспечивает заполнение переменной $_ ключом или значением, которые будет проверять фильтр. Обычно это означает, что большинство фильтров DBM имеют очень короткий код.
Что нового?
Основные улучшения по сравнению со стандартными обработчиками фильтров DBM:
-
Более чистый интерфейс.
-
Возможность легко применять несколько фильтров к одному файлу DBM.
-
Возможность создавать "готовые" фильтры. Это позволяет упаковывать часто используемые фильтры в отдельный модуль.
МЕТОДЫ
Этот модуль организует доступ к следующим методам через объект, возвращаемый вызовом tie.
$db->Filter_Push() / $db->Filter_Key_Push() / $db->Filter_Value_Push()
Добавляет фильтр в стек фильтров базы данных, $db. Различия в трёх форматах заключаются только в том, относятся ли они к ключу DBM, значению DBM или к обоим.
- Filter_Push
-
Фильтр применяется к оба ключу и значению.
- Filter_Key_Push
-
Фильтр применяется только к ключу.
- Filter_Value_Push
-
Фильтр применяется только к значению.
$db->Filter_Pop()
Удаляет последний применённый фильтр к файлу DBM, связанному с $db, если он присутствует.
$db->Filtered()
Возвращает TRUE, если к DBM, связанному с $db, применены какие-либо фильтры. В противном случае возвращает FALSE.
Написание фильтра
Фильтры можно создать двумя основными способами.
Немедленные фильтры
Немедленный фильтр позволяет указать код фильтра, который будет использоваться в момент применения фильтра к dbm. В этом режиме методы Filter_*_Push ожидают получения ровно двух параметров.
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Push( Store => sub { },
Fetch => sub { }); Ссылка на код, связанная с Store, будет вызвана перед записью любого ключа/значения в базу данных, а ссылка на код, связанная с Fetch, будет вызвана после чтения любого ключа/значения из базы данных.
Например, вот пример фильтра, который добавляет завершающий символ NULL ко всем строкам перед записью в файл DBM и удаляет завершающий NULL при чтении из файла DBM.
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Push( Store => sub { $_ .= "\x00" ; },
Fetch => sub { s/\x00$// ; }); Примечания:
-
Оба фильтра Store и Fetch обрабатывают
$_.
Готовые фильтры
Немедленные фильтры удобны для разовых случаев. Для более общих задач полезно упаковать фильтр в собственный модуль.
Использование готового фильтра:
$db->Filter_Push("name", params) где
- "name"
-
имя загружаемого модуля. Если указанная строка не содержит символов разделителя пакета "::", предполагается, что она относится к полному имени модуля "DBM_Filter::name". Это означает, что полные имена готовых фильтров, "null" и "utf8", включённых в этот модуль, следующие:
DBM_Filter::null DBM_Filter::utf8 - params
-
любые необязательные параметры, которые необходимо передать фильтру. См. фильтр encode для примера модуля, использующего параметры.
Модуль, реализующий готовый фильтр, может иметь одну из двух форм. Вот шаблон для первой:
package DBM_Filter::null ;
use strict;
use warnings;
sub Store
{
# store code here
}
sub Fetch
{
# fetch code here
}
1; Примечания:
-
Имя пакета использует префикс
DBM_Filter::. -
Модуль обязательно должен иметь методы Store и Fetch. Если присутствует только один метод, или ни один из них, будет выброшено сообщение об ошибке.
Вторая форма позволяет фильтру хранить информацию состояния с помощью замыкания, таким образом:
package DBM_Filter::encoding ;
use strict;
use warnings;
sub Filter
{
my @params = @_ ;
...
return {
Store => sub { $_ = $encoding->encode($_) },
Fetch => sub { $_ = $encoding->decode($_) }
} ;
}
1; В этом случае методы "Store" и "Fetch" инкапсулированы в метод "Filter".
Включенные фильтры
В этом модуле предоставляется ряд готовых фильтров. Они охватывают ряд основных областей, в которых необходимы фильтры при взаимодействии с файлами DBM. Они также служат шаблонами для ваших собственных фильтров.
Включённые фильтры:
-
utf8
Этот модуль гарантирует, что все данные, записываемые в DBM, будут закодированы в UTF-8.
Этому модулю необходим модуль Encode.
-
encode
Позволяет выбрать кодировку символов, которая будет храниться в файле DBM.
-
compress
Этот фильтр сжимает все данные перед записью в базу данных и распаковывает их при чтении.
Этому модулю необходим Compress::Zlib.
-
int32
Этот модуль используется при взаимодействии с приложением C/C++, которое использует C int в качестве ключа и/или значения в файле DBM.
-
null
Этот модуль гарантирует, что все данные, записываемые в файл DBM, завершаются символом NULL. Это полезно, когда у вас есть скрипт Perl, которому необходимо взаимодействовать с файлом DBM, которым также пользуется программа C. Довольно распространённая проблема заключается в том, что приложение C включает завершающий NULL в строке при записи в файл DBM. Этот фильтр гарантирует, что все данные, записанные в файл DBM, могут быть прочитаны приложением C.
ЗАМЕЧАНИЯ
Поддержание целостности цикла чтения-записи
При написании фильтра DBM крайне важно обеспечить возможность извлечения всех данных, которые вы записали, когда фильтр DBM включён. На практике это означает, что любая трансформация, применяемая к данным в методе Store, должна быть точной обратной операцией в методе Fetch.
Если вы не предоставите точную обратную трансформацию, вы обнаружите, что такой код не будет работать так, как вы ожидаете.
while (my ($k, $v) = each %hash)
{
...
} В зависимости от преобразования вы обнаружите, что произойдёт одно или несколько из следующих действий:
-
Цикл никогда не завершится.
-
Будет получено слишком мало записей.
-
Будет получено слишком много записей.
-
Цикл будет работать правильно некоторое время, но неожиданно завершится неудачей.
Не смешивайте отфильтрованные и неотфильтрованные данные в одном файле базы данных.
Это просто повторное изложение предыдущего раздела. По крайней мере, пока вы не уверены, что знаете, что делаете, избегайте смешивания отфильтрованных и неотфильтрованных данных.
ПРИМЕР
Предположим, вам нужно взаимодействовать с устаревшей программой C, которая хранит ключи как целые числа C, а значения — как строки UTF-8, завершающиеся нулём. Вот как вы это настроите
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Key_Push('int32') ;
$db->Filter_Value_Push('utf8');
$db->Filter_Value_Push('null'); СМОТРИ ТАКЖЕ
<DB_File>, GDBM_File, NDBM_File, ODBM_File, SDBM_File, perldbmfilter
АВТОР
Paul Marquess <pmqs@cpan.org>
© 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/DBM_Filter