10. cratewav

The cratewav procedure loads a wav file from a weewiki crate partial UUID into an ftable.

A partial UUID is provided as a string. The crate is provided as an open SQLite database handle. It is assumed that the procedure that the crate AND the SQLar tables are contained in this same database.

This procedure works first by extracting the filename from the UUID. The filename can then be used to load things from the blob in the SQLar table to an ftable via sqlar_loadwav (not included here).

The loader for this is load_cratewav.

<<sqlar_function_declarations>>=
int load_cratewav(runt_vm *vm, runt_ptr pw);
<<sqlar_functions>>=
<<rproc_cratewav>>
int load_cratewav(runt_vm *vm, runt_ptr pw)
{
    runt_cell *c;
    runt_keyword_define(vm, "cratewav", 8, rproc_cratewav, &c);
    runt_cell_data(vm, c, pw);
    return runt_is_alive(vm);
}

The procedure is in a C function called rproc_cratewav.

The word order for this is the database (crate) THEN the id. This is a bit counterintuitive from the usual small-to-large order that I usually respect. The reason for doing it this way has to do with some quirks that Runt has with strings. It's better to evaluate the UUID string last.

sqlar_loadwav_db, defined in another file, is forward-declared here.

Support for ergo-id now here! using some code lifted from weewiki.

<<static_sqlar_function_declarations>>=
static void ergo_to_hex(const char *ergo, int sz, char *hex);
<<sqlar_functions>>=
static const char *ergohex = "0??2a3?4d567??ef8b1?c?9";
static void ergo_to_hex(const char *ergo, int sz, char *hex)
{
    int i;
    for (i = 0; i < sz; i++) {
        if (ergo[i] >= 'a' && ergo[i] <= 'w') {
            int pos = ergo[i] - 'a';
            hex[i] = ergohex[pos];
        } else {
            hex[i] = ergo[i];
        }
    }
}
<<rproc_cratewav>>=
static int rproc_cratewav(runt_vm *vm, runt_ptr p)
{
    int rc;
    sqlite3 *db;
    const char *idstr;
    sp_ftbl *ft;
    runt_stacklet *s;
    sqlite3_stmt *stmt;
    const char *filename;
    gf_patch *pw;
    int count;
    char *ergo;

    rc = runt_ppop(vm, &s);
    RUNT_ERROR_CHECK(rc);
    idstr = runt_to_string(s->p);

    if (idstr == NULL) {
        runt_print(vm, "Bad string.\n");
        return RUNT_NOT_OK;
    }

    rc = rgf_get_sqlite(vm, &db);
    RUNT_ERROR_CHECK(rc);

    pw = runt_to_cptr(p);

    sqlite3_prepare_v2(db,
                       "SELECT value, COUNT(DISTINCT uuid) "
                       "from wikizet "
                       "WHERE uuid LIKE ?1 "
                       "AND value LIKE \"/%\";",
                       -1, &stmt, NULL);

    ergo = NULL;
    if (idstr[0] == 'g') {
        size_t sz;
        /* 'g' is truncated, so N - 1 */
        sz = strlen(idstr) - 1;
        ergo = malloc(sz + 1);
        ergo[sz] = '\0';
        ergo_to_hex(&idstr[1], sz, ergo);

        sqlite3_bind_text(stmt, 1, ergo, -1, NULL);
    } else {
        sqlite3_bind_text(stmt, 1, idstr, -1, NULL);
    }

    rc = sqlite3_step(stmt);

    if (rc != SQLITE_ROW) {
        runt_print(vm, "cratewav: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return RUNT_NOT_OK;
    }

    count = sqlite3_column_int(stmt, 1);

    if (count < 1) {
        runt_print(vm, "Could not resolve id %s\n", idstr);
        sqlite3_finalize(stmt);
        return RUNT_NOT_OK;
    } else if (count > 1) {
        runt_print(vm, "id pattern %s not unique.\n", idstr);
        sqlite3_finalize(stmt);
        return RUNT_NOT_OK;
    }

    filename = (const char *)sqlite3_column_text(stmt, 0);

    rc = sqlar_loadwav_db(db, &filename[1], &ft);

    rgf_append_ftable(pw, ft);

    if (rc != SP_OK) {
        runt_print(vm, "There were SQLar problems.\n");
        sqlite3_finalize(stmt);
        return RUNT_NOT_OK;
    }

    rc = runt_ppush(vm, &s);
    RUNT_ERROR_CHECK(rc);
    rgf_stacklet_ftable(vm, s, ft);

    sqlite3_finalize(stmt);

    if (ergo != NULL) free(ergo);
    return RUNT_OK;
}



prev | home | next