Split files into header and implementation
This commit is contained in:
parent
cb2f43b7c2
commit
82efb034ad
150
includes/dbquery.c
Normal file
150
includes/dbquery.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
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 = "<TABLE class='center'>\
|
||||||
|
<TH class='tablename' COLSPAN='4'> <H3><BR>Map List</H3> </TH>\
|
||||||
|
<TR>\
|
||||||
|
<TH class='columnname'>Name</TH>\
|
||||||
|
<TH class='columnname'>Records</TH>\
|
||||||
|
<TH class='columnname'>Best Time</TH>\
|
||||||
|
<TH class='columnname'>Held By</TH>\
|
||||||
|
</TR>";
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
labels = "<TABLE class='center'>\
|
||||||
|
<TH class='tablename' COLSPAN='3'><H3><BR>Leaderboard</H3></TH>\
|
||||||
|
<TR>\
|
||||||
|
<TH class='columnname'>Rank</TH>\
|
||||||
|
<TH class='columnname'>Name</TH>\
|
||||||
|
<TH class='columnname'>Time</TH>\
|
||||||
|
</TR>";
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
labels = "<TABLE class='center'>\
|
||||||
|
<TH class='tablename' COLSPAN='3'> <H3><BR>Ranks</H3> </TH>\
|
||||||
|
<TR>\
|
||||||
|
<TH class='columnname'>Name</TH>\
|
||||||
|
<TH class='columnname'>Map</TH>\
|
||||||
|
<TH class='columnname'>Rank</TH>\
|
||||||
|
</TR>";
|
||||||
|
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("<TD>%u:%.2u.%.2u</TD>", min, s, cs);
|
||||||
|
} else {
|
||||||
|
printf("<TD>%u.%.2u</TD>", 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("<TR>");
|
||||||
|
for (i = 0; i < cc; i++) {
|
||||||
|
if ((*c == 'm' && i == 1) || (*c == '\0' && i == 3) || (*c == 'p' && i == 0)) {
|
||||||
|
printf("<TD>%s</TD>", sqlite3_column_text(sp, i));
|
||||||
|
} else if ((i == 0 && *c == '\0') || (i == 1 && *c == 'p') ) {
|
||||||
|
printf("<TD><a href='/cgi/cts.py?map=%s'>%s</a></TD>", 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("<TD>%s</TD>", sqlite3_column_text(sp, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("</TR>");
|
||||||
|
}
|
||||||
|
printf("</TABLE>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
16
includes/dbquery.h
Normal file
16
includes/dbquery.h
Normal file
@ -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
|
150
main.c
150
main.c
@ -1,153 +1,5 @@
|
|||||||
|
#include "dbquery.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sqlite3.h>
|
|
||||||
|
|
||||||
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 = "<TABLE class='center'>\
|
|
||||||
<TH class='tablename' COLSPAN='4'> <H3><BR>Map List</H3> </TH>\
|
|
||||||
<TR>\
|
|
||||||
<TH class='columnname'>Name</TH>\
|
|
||||||
<TH class='columnname'>Records</TH>\
|
|
||||||
<TH class='columnname'>Best Time</TH>\
|
|
||||||
<TH class='columnname'>Held By</TH>\
|
|
||||||
</TR>";
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
labels = "<TABLE class='center'>\
|
|
||||||
<TH class='tablename' COLSPAN='3'><H3><BR>Leaderboard</H3></TH>\
|
|
||||||
<TR>\
|
|
||||||
<TH class='columnname'>Rank</TH>\
|
|
||||||
<TH class='columnname'>Name</TH>\
|
|
||||||
<TH class='columnname'>Time</TH>\
|
|
||||||
</TR>";
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
labels = "<TABLE class='center'>\
|
|
||||||
<TH class='tablename' COLSPAN='3'> <H3><BR>Ranks</H3> </TH>\
|
|
||||||
<TR>\
|
|
||||||
<TH class='columnname'>Name</TH>\
|
|
||||||
<TH class='columnname'>Map</TH>\
|
|
||||||
<TH class='columnname'>Rank</TH>\
|
|
||||||
</TR>";
|
|
||||||
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("<TD>%u:%.2u.%.2u</TD>", min, s, cs);
|
|
||||||
} else {
|
|
||||||
printf("<TD>%u.%.2u</TD>", 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("<TR>");
|
|
||||||
for (i = 0; i < cc; i++) {
|
|
||||||
if ((*c == 'm' && i == 1) || (*c == '\0' && i == 3) || (*c == 'p' && i == 0)) {
|
|
||||||
printf("<TD>%s</TD>", sqlite3_column_text(sp, i));
|
|
||||||
} else if ((i == 0 && *c == '\0') || (i == 1 && *c == 'p') ) {
|
|
||||||
printf("<TD><a href='/cgi/cts.py?map=%s'>%s</a></TD>", 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("<TD>%s</TD>", sqlite3_column_text(sp, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("</TR>");
|
|
||||||
}
|
|
||||||
printf("</TABLE>");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
void html(void) {
|
||||||
const char *html_top = "Content-Type: text/html\n\n\
|
const char *html_top = "Content-Type: text/html\n\n\
|
||||||
|
Loading…
Reference in New Issue
Block a user