Commit 267f0c4e authored by jkvis's avatar jkvis

Included run-time versioning and restructed some testing/debug utilities

parent 5b0c6da1
......@@ -35,6 +35,12 @@ typedef struct
} GESA; // GESA
// Returns the version of the GESA library for run-time identification
void GESA_version(size_t* const major,
size_t* const minor,
size_t* const patch,
int* const is_release);
// Creates a GESA from a single string that *must* be '\0' terminated
// On success it returns 0
int GESA_create(GESA* const gesa,
......@@ -70,14 +76,8 @@ GESA_index_t GESA_lcs(GESA_index_t* document,
GESA_index_t* index,
GESA const* const gesa);
// Prints a GESA for debug purposes
void GESA_print(GESA const* const gesa,
FILE* stream);
// For now, implemented in utils.c
// Calculates the Longest Common Prefix (LCP) array of suffix array
// Kasai's Algorithm
// On success it return 0
int GESA_calculate_lcp(GESA_char_t const* const string,
size_t const length,
......
......@@ -5,6 +5,27 @@
#include "../lib/sais-lite-lcp/include/sais.h"
static size_t const MAJOR = 0;
static size_t const MINOR = 1;
static size_t const PATCH = 0;
void GESA_version(size_t* const major,
size_t* const minor,
size_t* const patch,
int* const is_release)
{
*major = MAJOR;
*minor = MINOR;
*patch = PATCH;
#if defined(NDEBUG)
*is_release = 1;
#else
*is_release = 0;
#endif
} // GESA_version
int GESA_create(GESA* const gesa,
GESA_char_t const* const string,
size_t const length)
......@@ -319,52 +340,146 @@ GESA_index_t GESA_lcs(GESA_index_t* document,
} // GESA_GESA
#if !defined(NDEBUG)
static size_t print_truncated(GESA_char_t const* const string,
size_t const start,
size_t const end,
size_t const length,
FILE* stream)
int GESA_calculate_lcp(GESA_char_t const* const string,
size_t const length,
GESA_index_t const* const sa,
GESA_index_t* const lcp)
{
if (end - start < length + 2 || length < 4)
GESA_index_t* const rank = malloc(length * sizeof(*rank));
if (rank == NULL)
{
return fwrite(string + start, sizeof(*string), end - start, stream);
return 1; // memory allocation failed
} // if
return fwrite(string + start, sizeof(*string), length / 2 - 1, stream) +
fputs("..", stream) +
fwrite(string + end - (length / 2), sizeof(*string), length / 2 - 1, stream);
} // print_trunctaced
#endif
// fprintf return values are ignored as this is for debugging only
void GESA_print(GESA const* const gesa,
FILE* stream)
for (size_t i = 0; i < length; ++i)
{
rank[sa[i]] = i;
} // for
GESA_index_t h = 0;
for (size_t i = 0; i < length; ++i)
{
if (rank[i] > 0)
{
GESA_index_t const j = sa[rank[i] - 1];
while ((size_t) i + h < length &&
(size_t) j + h < length &&
string[i + h] == string[j + h])
{
h += 1;
} // while
lcp[rank[i]] = h;
if (h > 0)
{
h -= 1;
} // if
} // if
} // for
free(rank);
return 0;
} // GESA_calculate_lcp
#define GESA_STACK_SIZE 2048
typedef struct
{
(void) gesa;
(void) stream;
#if !defined(NDEBUG)
fprintf(stream,
"GESA for %ld string(s):\n i length string\n",
gesa->n);
for (size_t i = 0; i < gesa->n; ++i)
GESA_index_t data[GESA_STACK_SIZE];
size_t size;
} GESA_STACK;
static void GESA_STACK_init(GESA_STACK* const stack)
{
stack->size = 0;
} // GESA_STACK_init
static GESA_index_t GESA_STACK_top(GESA_STACK const* const stack)
{
if (stack->size == 0)
{
fprintf(stderr, "Error: GESA_STACK_top()\n");
return -1;
} // if
return stack->data[stack->size - 1];
} // GESA_STACK_top
static void GESA_STACK_push(GESA_STACK* const stack, GESA_index_t data)
{
if (stack->size >= GESA_STACK_SIZE)
{
fprintf(stderr, "Error: GESA_STACK_push()\n");
return;
} // if
stack->data[stack->size] = data;
stack->size += 1;
} // GESA_STACK_push
static void GESA_STACK_pop(GESA_STACK* const stack)
{
if (stack->size == 0)
{
fprintf(stderr, "Error: GESA_STACK_pop()\n");
return;
} // if
stack->size -= 1;
} // GESA_STACK_pop
#undef GESA_STACK_SIZE
void GESA_calculate_childtab(GESA const* const gesa,
GESA_index_t* const childtab)
{
GESA_STACK stack;
GESA_STACK_init(&stack);
GESA_index_t last_index = -1;
GESA_STACK_push(&stack, 0);
for (size_t i = 1; i < gesa->total; ++i)
{
fprintf(stream, "%5ld %5ld ", i, gesa->length[i]);
print_truncated(gesa->string[i], 0, gesa->length[i], 40, stream);
fprintf(stream, "\n");
while (gesa->lcp[i] < gesa->lcp[GESA_STACK_top(&stack)])
{
last_index = GESA_STACK_top(&stack);
GESA_STACK_pop(&stack);
if (gesa->lcp[i] <= gesa->lcp[GESA_STACK_top(&stack)] &&
gesa->lcp[GESA_STACK_top(&stack)] != gesa->lcp[last_index])
{
childtab[GESA_STACK_top(&stack)] = last_index;
} // if
} // while
if (last_index != -1)
{
childtab[i - 1] = last_index;
last_index = -1;
} // if
GESA_STACK_push(&stack, i);
} // for
fprintf(stream, "total: %5ld\n\n", gesa->total);
fprintf(stream, " i da sa lcp suffix\n");
for (size_t i = 0; i < gesa->total; ++i)
GESA_STACK_init(&stack);
GESA_STACK_push(&stack, 0);
for (size_t i = 1; i < gesa->total; ++i)
{
fprintf(stream,
"%5ld %5d %5d %5d ",
i,
gesa->da[i],
gesa->sa[i],
gesa->lcp[i]);
print_truncated(gesa->string[gesa->da[i]], gesa->sa[i], gesa->length[gesa->da[i]], 40, stream);
fprintf(stream, "\n");
while (gesa->lcp[i] < gesa->lcp[GESA_STACK_top(&stack)])
{
GESA_STACK_pop(&stack);
} // while
if (gesa->lcp[i] == gesa->lcp[GESA_STACK_top(&stack)])
{
childtab[GESA_STACK_top(&stack)] = i;
GESA_STACK_pop(&stack);
} // if
GESA_STACK_push(&stack, i);
} // for
fprintf(stream, "\n");
#endif
} // GESA_print
} // GESA_calculate_childtab
#include <stdio.h>
#include <stdlib.h>
#include "../include/gesa.h"
int GESA_calculate_lcp(GESA_char_t const* const string,
size_t const length,
GESA_index_t const* const sa,
GESA_index_t* const lcp)
{
GESA_index_t* const rank = malloc(length * sizeof(*rank));
if (rank == NULL)
{
return 1; // memory allocation failed
} // if
for (size_t i = 0; i < length; ++i)
{
rank[sa[i]] = i;
} // for
GESA_index_t h = 0;
for (size_t i = 0; i < length; ++i)
{
if (rank[i] > 0)
{
GESA_index_t const j = sa[rank[i] - 1];
while ((size_t) i + h < length &&
(size_t) j + h < length &&
string[i + h] == string[j + h])
{
h += 1;
} // while
lcp[rank[i]] = h;
if (h > 0)
{
h -= 1;
} // if
} // if
} // for
free(rank);
return 0;
} // GESA_calculate_lcp
#define GESA_STACK_SIZE 2048
typedef struct
{
GESA_index_t data[GESA_STACK_SIZE];
size_t size;
} GESA_STACK;
static void GESA_STACK_init(GESA_STACK* const stack)
{
stack->size = 0;
} // GESA_STACK_init
static GESA_index_t GESA_STACK_top(GESA_STACK const* const stack)
{
if (stack->size == 0)
{
fprintf(stderr, "Error: GESA_STACK_top()\n");
return -1;
} // if
return stack->data[stack->size - 1];
} // GESA_STACK_top
static void GESA_STACK_push(GESA_STACK* const stack, GESA_index_t data)
{
if (stack->size >= GESA_STACK_SIZE)
{
fprintf(stderr, "Error: GESA_STACK_push()\n");
return;
} // if
stack->data[stack->size] = data;
stack->size += 1;
} // GESA_STACK_push
static void GESA_STACK_pop(GESA_STACK* const stack)
{
if (stack->size == 0)
{
fprintf(stderr, "Error: GESA_STACK_pop()\n");
return;
} // if
stack->size -= 1;
} // GESA_STACK_pop
#undef GESA_STACK_SIZE
void GESA_calculate_childtab(GESA const* const gesa,
GESA_index_t* const childtab)
{
GESA_STACK stack;
GESA_STACK_init(&stack);
GESA_index_t last_index = -1;
GESA_STACK_push(&stack, 0);
for (size_t i = 1; i < gesa->total; ++i)
{
while (gesa->lcp[i] < gesa->lcp[GESA_STACK_top(&stack)])
{
last_index = GESA_STACK_top(&stack);
GESA_STACK_pop(&stack);
if (gesa->lcp[i] <= gesa->lcp[GESA_STACK_top(&stack)] &&
gesa->lcp[GESA_STACK_top(&stack)] != gesa->lcp[last_index])
{
childtab[GESA_STACK_top(&stack)] = last_index;
} // if
} // while
if (last_index != -1)
{
childtab[i - 1] = last_index;
last_index = -1;
} // if
GESA_STACK_push(&stack, i);
} // for
GESA_STACK_init(&stack);
GESA_STACK_push(&stack, 0);
for (size_t i = 1; i < gesa->total; ++i)
{
while (gesa->lcp[i] < gesa->lcp[GESA_STACK_top(&stack)])
{
GESA_STACK_pop(&stack);
} // while
if (gesa->lcp[i] == gesa->lcp[GESA_STACK_top(&stack)])
{
childtab[GESA_STACK_top(&stack)] = i;
GESA_STACK_pop(&stack);
} // if
GESA_STACK_push(&stack, i);
} // for
} // GESA_calculate_childtab
......@@ -9,12 +9,7 @@
int main(int argc, char* argv[])
{
(void) argc;
(void) argv;
printf("version: %s\n", version());
printf("test 1\n");
print_test_prolog(argc, argv);
GESA gesa;
......@@ -41,5 +36,6 @@ int main(int argc, char* argv[])
free(childtab);
GESA_destroy(&gesa, GESA_KEEP_STRINGS);
print_test_epilog(EXIT_SUCCESS);
return EXIT_SUCCESS;
} // main
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "../include/gesa.h"
#include "utils.h"
int main(int argc, char* argv[])
{
(void) argc;
(void) argv;
printf("version: %s\n", version());
printf("test 2\n");
return EXIT_SUCCESS;
} // main
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#include "../include/gesa.h"
void print_test_prolog(int argc, char* argv[])
{
size_t major;
size_t minor;
size_t patch;
int is_release;
GESA_version(&major, &minor, &patch, &is_release);
printf("**** GESA library test suite\n");
printf("**** libgesa-%ld.%ld.%ld%s\n",
major,
minor,
patch,
is_release != 0 ? "" : "-dev");
printf("**** command: %s\n", argv[0]);
for (int i = 1; i < argc; ++i)
{
printf("**** args: %s\n", argv[i]);
} // for
printf("**** Start of test\n\n");
} // print_test_prolog
void print_test_epilog(int exit)
{
printf("\n**** End of test\n");
printf("**** exit: %d\n", exit);
} // print_test_epilog
static size_t print_truncated(GESA_char_t const* const string,
size_t const start,
size_t const end,
size_t const length,
FILE* stream)
{
if (end - start < length + 2 || length < 4)
{
return fwrite(string + start, sizeof(*string), end - start, stream);
} // if
return fwrite(string + start, sizeof(*string), length / 2 - 1, stream) +
fputs("..", stream) +
fwrite(string + end - (length / 2), sizeof(*string), length / 2 - 1, stream);
} // print_trunctaced
char const* version(void)
void GESA_print(GESA const* const gesa,
FILE* stream)
{
return "v0.0.1";
} // version
fprintf(stream,
"GESA for %ld string(s):\n i length string\n",
gesa->n);
for (size_t i = 0; i < gesa->n; ++i)
{
fprintf(stream, "%5ld %5ld ", i, gesa->length[i]);
print_truncated(gesa->string[i], 0, gesa->length[i], 40, stream);
fprintf(stream, "\n");
} // for
fprintf(stream, "total: %5ld\n\n", gesa->total);
fprintf(stream, " i da sa lcp suffix\n");
for (size_t i = 0; i < gesa->total; ++i)
{
fprintf(stream,
"%5ld %5d %5d %5d ",
i,
gesa->da[i],
gesa->sa[i],
gesa->lcp[i]);
print_truncated(gesa->string[gesa->da[i]], gesa->sa[i], gesa->length[gesa->da[i]], 40, stream);
fprintf(stream, "\n");
} // for
fprintf(stream, "\n");
} // GESA_print
#if !defined(__utils_h__)
#define __utils_h__
char const* version(void);
#include <stdio.h>
// fprintf return values are ignored as this is for testing only
#include "../include/gesa.h"
void print_test_prolog(int argc, char* argv[]);
void print_test_epilog(int exit);
void GESA_print(GESA const* const gesa,
FILE* stream);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment