Rules: mmap() rules file instead of using getc()

Good for a small performance win on my system.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
master
Daniel Stone 2012-08-03 05:13:46 +02:00
parent 3199ea7383
commit d5f725f69a
1 changed files with 43 additions and 21 deletions

View File

@ -26,28 +26,33 @@
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "rules.h"
#include "path.h"
static bool
input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
static const char *
input_line_get(struct xkb_context *ctx, const char *buf, const char *end,
darray_char *line)
{
int ch;
bool end_of_file = false;
bool space_pending;
bool slash_pending;
bool in_comment;
while (!end_of_file && darray_empty(*line)) {
while (buf < end && darray_empty(*line)) {
space_pending = slash_pending = in_comment = false;
while ((ch = getc(file)) != '\n' && ch != EOF) {
while (buf < end && (ch = *buf++) != '\n') {
if (ch == '\\') {
ch = getc(file);
if (ch == EOF)
buf++;
if (buf >= end)
break;
ch = *buf;
if (ch == '\n') {
in_comment = false;
@ -81,16 +86,16 @@ input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
}
if (isspace(ch)) {
while (isspace(ch) && ch != '\n' && ch != EOF)
ch = getc(file);
while (buf < end && isspace(ch) && ch != '\n')
ch = *buf++;
if (ch == EOF)
if (buf >= end)
break;
if (ch != '\n' && !darray_empty(*line))
space_pending = true;
ungetc(ch, file);
buf--;
}
else {
if (space_pending) {
@ -111,16 +116,13 @@ input_line_get(struct xkb_context *ctx, FILE *file, darray_char *line)
darray_append(*line, ch);
}
}
if (ch == EOF)
end_of_file = true;
}
if (darray_empty(*line) && end_of_file)
return false;
if (darray_empty(*line) && buf >= end)
return NULL;
darray_append(*line, '\0');
return true;
return buf;
}
/***====================================================================***/
@ -986,6 +988,22 @@ load_rules(struct xkb_context *ctx, FILE *file)
struct rule trule;
struct group tgroup;
struct rules *rules;
struct stat stat_buf;
const char *buf, *end;
char *orig;
int fd = fileno(file);
if (fstat(fd, &stat_buf) != 0) {
log_err(ctx, "couldn't stat rules file\n");
return NULL;
}
orig = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (!orig) {
log_err(ctx, "couldn't mmap rules file (%zu bytes)\n",
stat_buf.st_size);
return NULL;
}
rules = calloc(1, sizeof(*rules));
if (!rules)
@ -998,7 +1016,9 @@ load_rules(struct xkb_context *ctx, FILE *file)
darray_init(line);
darray_growalloc(line, 128);
while (input_line_get(ctx, file, &line)) {
buf = orig;
end = orig + stat_buf.st_size;
while ((buf = input_line_get(ctx, buf, end, &line))) {
if (match_line(ctx, &line, &mapping, &trule, &tgroup)) {
if (tgroup.number) {
darray_append(rules->groups, tgroup);
@ -1013,6 +1033,8 @@ load_rules(struct xkb_context *ctx, FILE *file)
darray_resize(line, 0);
}
munmap(orig, stat_buf.st_size);
darray_free(line);
return rules;
}
@ -1051,11 +1073,11 @@ struct xkb_component_names *
xkb_components_from_rules(struct xkb_context *ctx,
const struct xkb_rule_names *rmlvo)
{
struct rules *rules;
struct xkb_component_names *kccgst = NULL;
FILE *file;
char *path;
char **include;
struct rules *rules;
struct xkb_component_names *kccgst = NULL;
file = XkbFindFileInPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
if (!file) {