KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Майкл Джонсон - Разработка приложений в среде Linux. Второе издание

Майкл Джонсон - Разработка приложений в среде Linux. Второе издание

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Майкл Джонсон, "Разработка приложений в среде Linux. Второе издание" бесплатно, без регистрации.
Перейти на страницу:

Если последний параметр, dataSize, не будет равен NULL, то целое число, на которое он указывает, будет соответствовать количеству прочитанных байтов.

В случае сбоя эта функция возвращает NULL, а в случае успешного завершения она возвращает указатель на прочитанные данные. В случае сбоя dpcode сообщает о том, что стало причиной сбоя. В частности, если элемент не существует или имеет менее start байтов данных, dpcode будет присвоено DP_ENOITEM.

Когда функция dpget() возвращает данные, к ним добавляется байт 0, позволяя работать с ними как со строкой. Размещение указателя производится с помощью функции malloc(), и приложение отвечает за освобождение памяти после завершения своей работы. Если приложениям необходимо поместить данные в буфер, вместо того чтобы Depot размещала его с помощью функции malloc(), то они должны использовать функцию dpgetwb().

int dpgetwb(DEPOT * depot, const char * key, int keySize, int start,

int max, const char * data);

Функции dpgetwb() и dpget() отличаются друг от друга только двумя параметрами: max (который интерпретируется по-разному) и data (который заменяет параметр dataSize из функции dpgetwb()). Параметр data должен указывать на буфер из max байтов, в который функция dpgetwb() будет помещать данные, прочитанные из базы данных. В функции dpgetwb() параметр max не должен иметь значение -1, и буфер не будет иметь байт 0, автоматически добавляемый в него этой функцией. Функция dpgetwb() возвращает количество байтов, хранящихся в data, и -1, если запись не была найдена, если данных оказалось меньше start байтов или если возникла ошибка.

25.3.2. Последовательное чтение записей

С помощью функций dpiterinit() и dpiternext() приложения могут производить итерации по всем ключам в базе данных. Ключи не возвращаются в каком-то определенном порядке[180], а базу данных не нужно модифицировать во время итераций, производимых приложением.

int dpiterinit(DEPOT * depot);

char * dpiternext(DEPOT * depot, int * keySize);

В результате вызова функции dpiterinit() qdbm вернет первый ключ в базе данных во время следующего вызова функции dpiternext().

Функция dpiternext() возвращает указатель либо на первый ключ в базе данных (если только что была вызвана функция dpiterinit()), либо ключ в базе данных, который следует за ключом, возвращенным в последний раз. Если же в базе данных больше не окажется ключей, будет возвращено NULL. Если keySize не равен NULL, то целочисленное значение, на которое указывает этот параметр, будет задано в качестве размера возвращаемого ключа.

Функция dpiternext() буфера возвращает указатель на размещение, выполненное функцией malloc(); после того как приложение завершит работу с ключом, указатель необходимо освободить функцией free(). Буфер также завершается NULL, поэтому при необходимости его можно трактовать как строку.

25.4. Модификация базы данных

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

25.4.1. Добавление записей

Новые и обновленные записи заносятся в базу данных с использованием функции dpput().

int dpput(DEPOT * dfepot, const char * key, int keySize, const char * data,

 int dataSize, int dmode);

key представляет собой значение индекса, который впоследствии может использоваться для получения информации, на которую указывает data. Параметры keySize и dataSize могут иметь значение -1, при котором функция dpput() будет использовать функцию strlen() для получения размера данного поля. Проверка параметра dmode производится только в том случае, если параметр key в базе данных уже связан с элементом данных. Параметр dmode может иметь одно из перечисленных ниже значений.

DP_DCAT Новые данные добавляются в конец данных, которые уже находятся в базе данных. DP_DKEEP База данных не модифицируется; функция dpput() возвращает сбой, а параметру dpecode присваивается значение DP_EKEEP. DP_DOVER Вместо существующего значения записывается новое.

Функция dpput() возвращает нулевое значение в случае возникновения ошибки (или если ключ уже существует, и было определено значение DP_DKEEP), и ненулевое значение, если данные для ключа были успешно обновлены.

25.4.2. Удаление записей

Удаление записей из базы данных осуществляется путем вызова функции dpout() и передачи ей ключа, данные которого необходимо удалить.

int dpout(DEPOT * depot, const char * key, int keySize);

Заданный ключ и связанные с ним данные удаляются из базы, после чего возвращается ненулевое значение. Если для заданного ключа данные не существовали, возвращается нулевое значение. Как и для всех остальных функций, принимающих ключ, если параметр keySize равен -1, то функция dpout() использует strlen() для определения длины ключа.

25.5. Пример

Для закрепления материала этой главы ниже приводится пример приложения, в котором задействовано большинство функциональных возможностей qdbm. Подразумевается, что в результате выполнения этого приложения будет создана простая база данных телефонных номеров, хотя ее можно использовать и для хранения любых простых пар "имя-значение". Приложение хранит базу данных в домашнем каталоге пользователя как .phonedb.

Флаг -а добавляет запись в базу данных. Если будет указан флаг -f, то любой существующий элемент будет заменен новыми данными. Следующий параметр представляет собой значение ключа, которое необходимо использовать, а последний параметр — собственно данные (номер телефона).

Флаг -q запрашивает в базе данных определенный ключ, который должен быть представлен другим указанным параметром. Записи удаляются из базы данных с помощью флага -d, который принимает значение ключа для удаления в другом параметре.

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

Вот как выглядят пример использования phones.

$ ./phones -a Erik 374-5876

$ ./phones -a Michael 642-4235

$ ./phones -a Larry 527-7976

$ ./phones -a Barbara 227-2272

$ ./phones -q Larry

Larry 527-7976

$ ./phones -l

Larry 527-7976

Erik 374-5876

Michael 642-4235

Barbara 227-2272

$ ./phones -d Michael

$ ./phones -l

Larry 527-7976

Erik 374-5876

Barbara 227-2272

Эта программа выполняет определенные полезные действия, состоит менее чем из 200 строк исходного кода, и с успехом может применяться для работы с большим количеством пар "ключ-значение", четко раскрывая назначение библиотеки qdbm.

  1: /* phones.с */

  2:

  3: /* Программа реализует очень простую базу данных телефонных номеров.

  4: Всю необходимую информацию по ее использованию можно найти в тексте. */

  5:

  6: #include <alloca.h>

  7: #include <depot.h>

  8: #include <errno.h>

  9: #include <fcntl.h>

 10: #include <stdio.h>

 11: #include <stdlib.h>

 12: #include <string.h>

 13: #include <unistd.h>

 14:

 15: void usage(void) {

 16:  fprintf(stderr, "использование: phones -a [-f] <имя> <телефон>n");

 17:  fprintf(stderr, " -d <имя>n");

 18:  fprintf(stderr, " -q <имя>n");

 19:  fprintf(stderr, " -ln");

 20:  exit(1);

 21: }

 22:

 23: /* Открыть базу данных $НОМЕ/.phonedb. Если writeable имеет ненулевое

 24:    значение, база данных открывается для обновления. Если writeable

 25:    равен 0, база данных открывается только для чтения. */

 26: DEPOT * openDatabase(int writeable) {

 27:  DEPOT * dp;

 28:  char * filename;

 29:  int flags;

 30:

 31:  /* Установить режим открытия */

 32:  if (writeable) {

 33:   flags = DP_OWRITER | DP_OCREAT;

 34:  } else {

 35:   flags = DP_OREADER;

 36:  }

 37:

 38:  filename = alloca(strlen(getenv("HOME")) + 20);

 39:  strcpy(filename, getenv("HOME"));

 40:  strcat(filename, "/.phonedb");

 41:

 42:  dp = dpopen(filename, flags, 0);

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*