diff --git a/includes/dbquery.c b/includes/dbquery.c new file mode 100644 index 0000000..5518d36 --- /dev/null +++ b/includes/dbquery.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + +static inline char *get_filename(const char *c) { + char *qout = "queries/mranks.sql"; + if (c != NULL) { + switch(*c) { + case 'm': + qout = "queries/mleaderboard-ojoin.sql"; + break; + case 'p': + qout = "queries/rplayers.sql"; + break; + case 't': + qout = "queries/test.txt"; + break; + } + } + return qout; +} + +static inline void print_tblheader(const char *c) { + char *labels; + switch (*c) { + default: + labels = "\ + \ + \ + \ + \ + \ + \ + "; + break; + case 'm': + labels = "


Map List

NameRecordsBest TimeHeld By
\ + \ + \ + \ + \ + \ + "; + break; + case 'p': + labels = "


Leaderboard

RankNameTime
\ + \ + \ + \ + \ + \ + "; + break; + } + printf("%s", labels); +} + +// input is an integer as a string. +// the time is in centiseconds. +// this means the longest XDF run this can support is +// 21,474,836.47 seconds +// someone would need to idle in-game for 248 days +static void print_time(const unsigned char *strcs) { + const unsigned int num = strtoul((const char*)strcs, NULL, 10); + unsigned int s = num/100; + const unsigned int cs = num % 100; + const unsigned int min = s/60; + s = s % 60; + if (min > 0) { + printf("", min, s, cs); + } else { + printf("", s, cs); + } +} + +// display and format the results of the query. +static void qresult(sqlite3_stmt * const sp, const char *c) { + int e; + unsigned int i; + unsigned int cc = sqlite3_column_count(sp); + print_tblheader(c); + while ((e = sqlite3_step(sp)) == SQLITE_ROW) { + printf(""); + for (i = 0; i < cc; i++) { + if ((*c == 'm' && i == 1) || (*c == '\0' && i == 3) || (*c == 'p' && i == 0)) { + printf("", sqlite3_column_text(sp, i)); + } else if ((i == 0 && *c == '\0') || (i == 1 && *c == 'p') ) { + printf("", sqlite3_column_text(sp, i), sqlite3_column_text(sp, i)); + } else if (i == 2 && (*c == 'm' || *c == '\0')) { + print_time(sqlite3_column_text(sp, i)); + } else { + printf("", sqlite3_column_text(sp, i)); + } + } + printf(""); + } + printf("


Ranks

NameMapRank
%u:%.2u.%.2u%u.%.2u
%s%s%s
"); +} + +// const char 'sql' is never NULL. +// const char 'str' may be NULL, however it is only when +// the contents of mranks.sql is in const char 'sql'. +static bool executequery(const char *sql, const char *str) { + const char *p = (str != NULL) ? strchr(str, '=') + 1 : NULL; + const char qc = (str != NULL) ? str[0] : '\0'; + sqlite3 *db; + int con = sqlite3_open("db/cts.db", &db); + if (con != SQLITE_OK) { + fprintf(stderr, "Can not open database: %s\n", sqlite3_errmsg(db)); + return false; + } + sqlite3_stmt *s; + // prepare sql to s, reading until null character. + con = sqlite3_prepare_v2(db, sql, -1, &s, NULL); + if (con != SQLITE_OK) { + fprintf(stderr, "Could not prepare SQL statement: %s\n", sqlite3_errmsg(db)); + return false; + } + // bind parameter with a string length that is the # of bytes to null char. + con = sqlite3_bind_text(s, 1, p, -1, NULL); + qresult(s, &qc); + sqlite3_finalize(s); + sqlite3_close(db); + return true; +} + +// both allocates and frees memory used up by the string.. +// containing the data from query files. +void getquery(const char *qs) { + char *qf = NULL; + char *fname = get_filename(qs); + if (fname != NULL) { + FILE *f = fopen(fname, "r"); + if (f != NULL) { + // change from fseek/SEEK_END when sql queries are >2 GB in size. + fseek(f, 0, SEEK_END); // go to the end of file + unsigned int size = ftell(f); + qf = calloc(size, sizeof(char)); + if (qf != NULL) { + fseek(f, 0, SEEK_SET); // go to the start of file + fread(qf, sizeof(char), size, f); + } + } + fclose(f); + } + executequery(qf, qs); + free(qf); +} diff --git a/includes/dbquery.h b/includes/dbquery.h new file mode 100644 index 0000000..20b157b --- /dev/null +++ b/includes/dbquery.h @@ -0,0 +1,16 @@ +#ifndef DBQUERY_H +#define DBQUERY_H + +inline char *get_filename(const char *) ; + +inline void print_tblheader(const char *); + +void print_time(const unsigned char *); + +void qresult(void * const, const char *); + +int executequery(const char *, const char *); + +void getquery(const char *); + +#endif \ No newline at end of file diff --git a/main.c b/main.c index f836569..c2e98a8 100644 --- a/main.c +++ b/main.c @@ -1,153 +1,5 @@ +#include "dbquery.h" #include -#include -#include -#include -#include - -inline char *get_filename(const char *c) { - char *qout = "queries/mranks.sql"; - if (c != NULL) { - switch(*c) { - case 'm': - qout = "queries/mleaderboard-ojoin.sql"; - break; - case 'p': - qout = "queries/rplayers.sql"; - break; - case 't': - qout = "queries/test.txt"; - break; - } - } - return qout; -} - -inline void print_tblheader(const char *c) { - char *labels; - switch (*c) { - default: - labels = "\ - \ - \ - \ - \ - \ - \ - "; - break; - case 'm': - labels = "


Map List

NameRecordsBest TimeHeld By
\ - \ - \ - \ - \ - \ - "; - break; - case 'p': - labels = "


Leaderboard

RankNameTime
\ - \ - \ - \ - \ - \ - "; - break; - } - printf("%s", labels); -} - -// input is an integer as a string. -// the time is in centiseconds. -// this means the longest XDF run this can support is -// 21,474,836.47 seconds -// someone would need to idle in-game for 248 days -void print_time(const unsigned char *strcs) { - const unsigned int num = strtoul((const char*)strcs, NULL, 10); - unsigned int s = num/100; - const unsigned int cs = num % 100; - const unsigned int min = s/60; - s = s % 60; - if (min > 0) { - printf("", min, s, cs); - } else { - printf("", s, cs); - } -} - -// display and format the results of the query. -void qresult(sqlite3_stmt * const sp, const char *c) { - int e; - unsigned int i; - unsigned int cc = sqlite3_column_count(sp); - print_tblheader(c); - while ((e = sqlite3_step(sp)) == SQLITE_ROW) { - printf(""); - for (i = 0; i < cc; i++) { - if ((*c == 'm' && i == 1) || (*c == '\0' && i == 3) || (*c == 'p' && i == 0)) { - printf("", sqlite3_column_text(sp, i)); - } else if ((i == 0 && *c == '\0') || (i == 1 && *c == 'p') ) { - printf("", sqlite3_column_text(sp, i), sqlite3_column_text(sp, i)); - } else if (i == 2 && (*c == 'm' || *c == '\0')) { - print_time(sqlite3_column_text(sp, i)); - } else { - printf("", sqlite3_column_text(sp, i)); - } - } - printf(""); - } - printf("


Ranks

NameMapRank
%u:%.2u.%.2u%u.%.2u
%s%s%s
"); -} - -// const char 'sql' is never NULL. -// const char 'str' may be NULL, however it is only when -// the contents of mranks.sql is in const char 'sql'. -bool executequery(const char *sql, const char *str) { - const char *p = (str != NULL) ? strchr(str, '=') + 1 : NULL; - const char qc = (str != NULL) ? str[0] : '\0'; - sqlite3 *db; - int con = sqlite3_open("db/cts.db", &db); - if (con != SQLITE_OK) { - fprintf(stderr, "Can not open database: %s\n", sqlite3_errmsg(db)); - return false; - } - sqlite3_stmt *s; - // prepare sql to s, reading until null character. - con = sqlite3_prepare_v2(db, sql, -1, &s, NULL); - if (con != SQLITE_OK) { - fprintf(stderr, "Could not prepare SQL statement: %s\n", sqlite3_errmsg(db)); - return false; - } - // bind parameter with a string length that is the # of bytes to null char. - con = sqlite3_bind_text(s, 1, p, -1, NULL); - qresult(s, &qc); - sqlite3_finalize(s); - sqlite3_close(db); - return true; -} - -// both allocates and frees memory used up by the string.. -// containing the data from query files. -void getquery(const char *qs) { - char *qf = NULL; - char *fname = get_filename(qs); - if (fname != NULL) { - FILE *f = fopen(fname, "r"); - if (f != NULL) { - // change from fseek/SEEK_END when sql queries are >2 GB in size. - fseek(f, 0, SEEK_END); // go to the end of file - unsigned int size = ftell(f); - qf = calloc(size, sizeof(char)); - if (qf != NULL) { - fseek(f, 0, SEEK_SET); // go to the start of file - fread(qf, sizeof(char), size, f); - } - } - fclose(f); - } - executequery(qf, qs); - free(qf); -} void html(void) { const char *html_top = "Content-Type: text/html\n\n\