Skip to content

Commit

Permalink
Better integration with table resolving functionality
Browse files Browse the repository at this point in the history
Instead of a comma separated list of directories, lou_indexTables now
accepts an array of table names which are resolved to files.

If lou_indexTables has not been called before lou_findTable,
LOUIS_TABLEPATH will be indexed instead of simply failing.
  • Loading branch information
bertfrees committed May 22, 2015
1 parent 111e702 commit 17a7ad1
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 63 deletions.
47 changes: 29 additions & 18 deletions liblouis/compileTranslationTable.c
Expand Up @@ -4584,6 +4584,30 @@ resolveSubtable (const char *table, const char *base, const char *searchPath)
return NULL;
}

char *
getTablePath()
{
char searchPath[MAXSTRING];
char *path;
char *cp;
cp = searchPath;
path = getenv ("LOUIS_TABLEPATH");
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s", path);
path = lou_getDataPath ();
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s%c%s%c%s", path, DIR_SEP, "liblouis", DIR_SEP,
"tables");
#ifdef _WIN32
path = lou_getProgramPath ();
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s%s", path, "\\share\\liblouis\\tables");
#else
cp += sprintf (cp, ",%s", TABLESDIR);
#endif
return strdup(searchPath);
}

/**
* The default table resolver
*
Expand All @@ -4601,31 +4625,16 @@ resolveSubtable (const char *table, const char *base, const char *searchPath)
static char **
defaultTableResolver (const char *tableList, const char *base)
{
char searchPath[MAXSTRING];
char * searchPath;
char **tableFiles;
char *subTable;
char *tableList_copy;
char *cp;
char *path;
int last;
int k;

/* Set up search path */
cp = searchPath;
path = getenv ("LOUIS_TABLEPATH");
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s", path);
path = lou_getDataPath ();
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s%c%s%c%s", path, DIR_SEP, "liblouis", DIR_SEP,
"tables");
#ifdef _WIN32
path = lou_getProgramPath ();
if (path != NULL && path[0] != '\0')
cp += sprintf (cp, ",%s%s", path, "\\share\\liblouis\\tables");
#else
cp += sprintf (cp, ",%s", TABLESDIR);
#endif
searchPath = getTablePath();

/* Count number of subtables in table list */
k = 0;
Expand All @@ -4645,6 +4654,7 @@ defaultTableResolver (const char *tableList, const char *base)
if (!(tableFiles[k++] = resolveSubtable (subTable, base, searchPath)))
{
logMessage (LOG_ERROR, "Cannot resolve table '%s'", subTable);
free(searchPath);
free(tableList_copy);
free (tableFiles);
return NULL;
Expand All @@ -4654,6 +4664,7 @@ defaultTableResolver (const char *tableList, const char *base)
if (last)
break;
}
free(searchPath);
free(tableList_copy);
tableFiles[k] = NULL;
return tableFiles;
Expand Down Expand Up @@ -4681,7 +4692,7 @@ copyStringArray(const char ** array)
return copy;
}

static char **
char **
resolveTable (const char *tableList, const char *base)
{
return copyStringArray((*tableResolver) (tableList, base));
Expand Down
151 changes: 112 additions & 39 deletions liblouis/findTable.c
Expand Up @@ -130,6 +130,36 @@ list_sort(List * list, int (* cmp)(void *, void *))
return newList;
}

/*
* Get the size of a list.
*/
static int
list_size(List * list)
{
int len = 0;
List * l;
for (l = list; l; l = l->tail)
len++;
return len;
}

/*
* Convert a list into a NULL terminated array.
*/
static void **
list_toArray(List * list, void * (* dup)(void *))
{
void ** array;
List * l;
int i;
array = malloc((1 + list_size(list)) * sizeof(void *));
i = 0;
for (l = list; l; l = l->tail)
array[i++] = dup ? dup(l->head) : l->head;
array[i] = NULL;
return array;
}

/* ============================== FEATURE ================================= */

typedef struct
Expand Down Expand Up @@ -378,18 +408,37 @@ widestrToStr(const widechar * str, size_t n)
}

/*
* Extract a list of features from a file.
* Extract a list of features from a table.
*/
static List *
analyzeTable(const char * fileName)
analyzeTable(const char * table)
{
static char fileName[MAXSTRING];
char ** resolved;
List * features = NULL;
FileInfo info;
int k;
resolved = resolveTable(table, NULL);
if (resolved == NULL)
{
logMessage(LOG_ERROR, "Cannot resolve table '%s'", table);
return NULL;
}
sprintf(fileName, "%s", *resolved);
k = 0;
for (k = 0; resolved[k]; k++)
free(resolved[k]);
free(resolved);
if (k > 1)
{
logMessage(LOG_ERROR, "Table '%s' resolves to more than one file", table);
return NULL;
}
info.fileName = fileName;
info.encoding = noEncoding;
info.status = 0;
info.lineNumber = 0;
if ((info.in = fopen(fileName, "rb")))
if ((info.in = fopen(info.fileName, "rb")))
{
while (getALine(&info))
{
Expand Down Expand Up @@ -457,7 +506,7 @@ analyzeTable(const char * fileName)
fclose(info.in);
}
else
logMessage (LOG_ERROR, "Cannot open table '%s'", fileName);
logMessage (LOG_ERROR, "Cannot open table '%s'", info.fileName);
return list_sort(features, (int (*)(void *, void *))cmpKeys);
compile_error:
if (info.linepos < info.linelen)
Expand All @@ -473,24 +522,47 @@ analyzeTable(const char * fileName)

static List * tableIndex = NULL;

void EXPORT_CALL
lou_indexTables(const char ** tables)
{
const char ** table;
list_free(tableIndex);
tableIndex = NULL;
for (table = tables; *table; table++)
{
logMessage(LOG_DEBUG, "Analyzing table %s", *table);
List * features = analyzeTable(*table);
if (features)
{
TableMeta m = { strdup(*table), features };
tableIndex = list_conj(tableIndex, memcpy(malloc(sizeof(m)), &m, sizeof(m)), NULL, NULL, free);
}
}
if (!tableIndex)
logMessage(LOG_WARN, "No tables were indexed");
}

#ifdef _WIN32
#define DIR_SEP '\\'
#else
#define DIR_SEP '/'
#endif

void EXPORT_CALL
lou_indexTables(const char * searchPath)
/*
* Returns the list of files found on searchPath, where searchPath is a
* comma-separated list of directories.
*/
static List *
listFiles(char * searchPath)
{
List * list;
char * dirName;
DIR * dir;
struct dirent * file;
static char fileName[MAXSTRING];
struct stat info;
int pos = 0;
int n;
list_free(tableIndex);
tableIndex = NULL;
while (1)
{
for (n = 0; searchPath[pos + n] != '\0' && searchPath[pos + n] != ','; n++);
Expand All @@ -502,13 +574,7 @@ lou_indexTables(const char * searchPath)
sprintf(fileName, "%s%c%s", dirName, DIR_SEP, file->d_name);
if (stat(fileName, &info) == 0 && !(info.st_mode & S_IFDIR))
{
logMessage(LOG_DEBUG, "Analyzing table %s", fileName);
List * features = analyzeTable(fileName);
if (features)
{
TableMeta m = { strdup(fileName), features };
tableIndex = list_conj(tableIndex, memcpy(malloc(sizeof(m)), &m, sizeof(m)), NULL, NULL, free);
}
list = list_conj(list, strdup(fileName), NULL, NULL, free);
}
}
closedir(dir);
Expand All @@ -524,41 +590,48 @@ lou_indexTables(const char * searchPath)
else
pos++;
}
if (!tableIndex)
logMessage(LOG_WARN, "No tables were indexed");
return list;
}

char * EXPORT_CALL
lou_findTable(const char * query)
{
if (tableIndex)
if (!tableIndex)
{
List * queryFeatures = parseQuery(query);
int bestQuotient = 0;
char * bestMatch = NULL;
List * l;
for (l = tableIndex; l; l = l->tail)
{
TableMeta * table = l->head;
int q = matchFeatureLists(queryFeatures, table->features, 0);
if (q > bestQuotient)
{
bestQuotient = q;
bestMatch = strdup(table->name);
}
}
logMessage(LOG_INFO, "Best match: %s (%d)", bestMatch, bestQuotient);
if (bestMatch)
return bestMatch;
else
char * searchPath;
List * tables;
const char ** tablesArray;
logMessage(LOG_WARN, "Tables have not been indexed yet. Indexing LOUIS_TABLEPATH.");
searchPath = getTablePath();
tables = listFiles(searchPath);
tablesArray = list_toArray(tables, NULL);
lou_indexTables(tablesArray);
free(searchPath);
list_free(tables);
free(tablesArray);
}
List * queryFeatures = parseQuery(query);
int bestQuotient = 0;
char * bestMatch = NULL;
List * l;
for (l = tableIndex; l; l = l->tail)
{
TableMeta * table = l->head;
int q = matchFeatureLists(queryFeatures, table->features, 0);
if (q > bestQuotient)
{
logMessage(LOG_INFO, "No table could be found for query '%s'", query);
return NULL;
bestQuotient = q;
bestMatch = strdup(table->name);
}
}
if (bestMatch)
{
logMessage(LOG_INFO, "Best match: %s (%d)", bestMatch, bestQuotient);
return bestMatch;
}
else
{
logMessage(LOG_ERROR, "Tables have not been indexed yet. Call lou_indexTables first.");
logMessage(LOG_INFO, "No table could be found for query '%s'", query);
return NULL;
}
}
9 changes: 4 additions & 5 deletions liblouis/liblouis.h.in
Expand Up @@ -173,11 +173,10 @@ typedef void (*logcallback)(int level, const char *message);
void EXPORT_CALL lou_setLogLevel(logLevels level);
/* Set the level for logging callback to be called at */

void EXPORT_CALL lou_indexTables(const char * searchPath);
/* Parses, analyzes and indexes table on searchPath. searchPath is a
* colon-separated list of directories to search for tables. This function
* must be called prior to lou_findTable(). An error message is given when a
* table contains invalid or duplicate metadata fields.
void EXPORT_CALL lou_indexTables(const char ** tables);
/* Parses, analyzes and indexes tables. This function must be called prior to
* lou_findTable(). An error message is given when a table contains invalid or
* duplicate metadata fields.
*/
char * EXPORT_CALL lou_findTable(const char * query);
/* Finds the best match for a query. Returns a string with the table
Expand Down
6 changes: 6 additions & 0 deletions liblouis/louis.h
Expand Up @@ -499,6 +499,12 @@ extern "C"
int getALine (FileInfo * info);
/* Read a line of widechar's from an input file */

char * getTablePath();
/* Comma separated list of directories to search for tables. */

char ** resolveTable(const char *tableList, const char *base);
/* Resolve tableList against base. */

widechar getDotsForChar (widechar c);
/* Returns the single-cell dot pattern corresponding to a character. */

Expand Down
3 changes: 2 additions & 1 deletion tests/findTable.c
Expand Up @@ -9,8 +9,9 @@ main(int argc, char **argv)
{
int success = 0;
char * match;
const char * tables[] = {"tablesWithMetadata/foo","tablesWithMetadata/bar",NULL};
lou_setLogLevel(LOG_DEBUG);
lou_indexTables("tablesWithMetadata");
lou_indexTables(tables);
match = lou_findTable("id:foo");
success |= (!match || strcmp(match, "tablesWithMetadata/foo"));
match = lou_findTable("language:en");
Expand Down

0 comments on commit 17a7ad1

Please sign in to comment.