Роббинс Арнольд
Шрифт:
7 * более высокого уровня.
8 * if (AWKBUFSIZE == "exact")
9 * return the file size
10 * else if (AWKBUFSIZE == число)
11 * всегда возвращать это число
12 * else
13 * if размер < default_blocksize
14 * return размер
15 * else
16 * return default_blocksize
17 * end if
18 * end if
19 *
20 * Приходится повозиться, чтобы иметь дело с AWKBUFSIZE лишь
21 * однажды, при первом вызове этой процедуры, а не при каждом
22 * ее вызове. Производительность, знаете ли.
23 */
24
25 size_t
26 optimal_bufsize(fd, stb)
27 int fd;
28 struct stat *stb;
29 {
30 char *val;
31 static size_t env_val = 0;
32 static short first = TRUE;
33 static short exact = FALSE;
34
35 /* обнулить все члены, на случай, если ОС их не использует. */
36 memset(stb, '\0', sizeof(struct stat));
37
38 /* всегда использовать stat на случай, если stb используется кодом более высокого уровня */
39 if (fstat(fd, stb) == -1)
40 fatal("can't stat fd %d (%s)", fd, strerror(errno));
41
42 if (first) {
43 first = FALSE;
44
45 if ((val = getenv("AWKBUFSIZE")) != NULL) {
46 if (strcmp(val, "exact") == 0)
47 exact = TRUE;
48 else if (ISDIGIT(*val)) {
49 for (; *val && ISDIGIT(*val); val++)
50 env_val = (env_val * 10) + *val - '0';
51
52 return env_val;
53 }
54 }
55 } else if (!exact && env_val > 0)
56 return env_val;
57 /* else
58 обрабатывать дальше */
59
60 /*
61 * System V.n, n < 4, не имеет в структуре stat размера системного
62 * блока файла. Поэтому нам нужно осуществить разумную догадку.
63 * Мы используем BUFSIZ из stdio, поскольку именно это имелось
64 * в виду прежде всего.
65 */
66 #ifdef HAVE_ST_BLKSIZE
67 #define DEFBLKSIZE (stb->st_blksize > 0 ? stb->st_blksize : BUFSIZ)
68 #else
69 #define DEFBLKSIZE BUFSIZ
70 #endif
71
72 if (S_ISREG(stb->st_mode) /* обычный файл */
73 && 0 < stb->st_size /* ненулевой размер */
74 && (stb->st_size < DEFBLKSIZE /* маленький файл */
75 || exact)) /* или отладка */
76 return stb->st_size; /* использовать размер файла*/
77
78 return DEFBLKSIZE;
79 }
Комментарий в строках 3–23 объясняет алгоритм. Поскольку поиск переменных окружения может быть затратным и его нужно осуществить лишь однажды, функция использует для сбора соответствующих сведений в первый раз несколько статических переменных.
Строки 42–54 выполняются лишь при первом вызове функции. Строка 43 обеспечивает это условие, устанавливая в
first
значение false
. Строки 45–54 обрабатывают переменную окружения, разыскивая либо строку "exact"
, либо число. В последнем случае оно преобразуется из строкового значения в десятичное, сохраняясь в env_val
. (Возможно, нам следовало бы использовать здесь strtoul
; в свое время это не пришло нам на ум.) Строка 55 выполняется каждый раз, кроме первого. Если было представлено числовое значение, условие будет истинным, и возвращается это значение (строка 56). В противном случае, исполнение переходит к оставшейся части функции.