Limited line width to 80 characters

This commit is contained in:
2017-09-14 13:43:40 -07:00
parent dad86bc0f2
commit 0a8611065b
2 changed files with 138 additions and 49 deletions

View File

@ -10,25 +10,32 @@ References used:
Overview: Overview:
This component is slightly based on util.py of XonStats, but the only functionality needed is coloring the player's names. Since C programming language does not have standard libraries for color model conversions and regex, some functionality had to be self written. The function of interest is: This component is slightly based on util.py of XonStats, but the only
functionality needed is coloring the player's names. Since C programming
language does not have standard libraries for color model conversions and
regex, some functionality had to be self written. The function of interest
is:
def html_colors(qstr='', limit=None): def html_colors(qstr='', limit=None):
This component uses purely C standard library. This component uses purely C standard library.
Advanced string manipulations such as replace and concatenation are avoided. Advanced string manipulations such as replace and concatenation are
Instead, strings are printed in parts across functions. avoided. Instead, strings are printed in parts across functions.
There is only one instance of dynamic memory allocation. There is only one instance of dynamic memory allocation.
void print_plname(const char *) void print_plname(const char *)
It both allocates, near the start, and frees memory at the end. It both allocates, near the start, and frees memory at the end.
darkplaces Player Names & Colors darkplaces Player Names & Colors
Players can add color themes to their names. They're expressed either decimal or hexidecimal. Players can add color themes to their names. They're expressed either
decimal or hexidecimal.
The decimal format follows The decimal format follows
A character '^' that is not displayed, followed by a single digit between 0 and 9. A character '^' that is not displayed, followed by a single digit
between 0 and 9.
The hexidecimal format follows The hexidecimal format follows
A string '^x' that is not displayed, followed by 3 digits between 0 - 0xF. A string '^x' that is not displayed, followed by 3 digits between
0 - 0xF.
Python Regex to C Translation Python Regex to C Translation
@ -55,61 +62,98 @@ Python Regex to C Translation
def html_colors(qstr='', limit=None): def html_colors(qstr='', limit=None):
... ...
html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))], qstr) html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))],
qstr)
html = _hex_colors.sub(hex_repl, html) html = _hex_colors.sub(hex_repl, html)
... ...
html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))], qstr) html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))], qstr)
The character following a '^' is treated as an index to the array '_dec_spans'. The corresponding element in '_dec_spans' replaces the character '^' and the following digit in the string 'qstr'. The character following a '^' is treated as an index to the array
'_dec_spans'. The corresponding element in '_dec_spans' replaces the
character '^' and the following digit in the string 'qstr'.
html = _hex_colors.sub(hex_repl, html) html = _hex_colors.sub(hex_repl, html)
The output of function 'hex_repl' replaces matching strings in html- '^x' followed by 3 hexadecimal digits. The function 'hex_repl' has more to do with the algorithms of color model conversions than it has to do with regex rules. The output of function 'hex_repl' replaces matching strings in html-
'^x' followed by 3 hexadecimal digits. The function 'hex_repl' has more
to do with the algorithms of color model conversions than it has to do
with regex rules.
The control flow to output similar results to the regex substitutions is in the function The control flow to output similar results to the regex substitutions is
in the function
static void b(char * const str); static void b(char * const str);
Unlike the python counterparts, it segments the player name into tokens and prints strings also other strings instead of the sequences not intended to be displayed. Unlike the python counterparts, it segments the player name into tokens and
prints strings also other strings instead of the sequences not intended to
be displayed.
Function Walkthrough Function Walkthrough
Sorted by caller to callee. Sorted by caller to callee.
void print_plname(const char *) void print_plname(const char *)
const char * parameter is the player's name. It is used as a basis for the variable 'copy'. 'copy' will always be the shorter character string. const char * parameter is the player's name. It is used as a basis for
the variable 'copy'. 'copy' will always be the shorter character string.
This is function is intended to be used by the client file. This is function is intended to be used by the client file.
This function unconditionally allocates memory (calloc) and frees it at the end. This function unconditionally allocates memory (calloc) and frees it at
the end.
By itself, it only removes extraneous instances of the character '^'. It then calls the function By itself, it only removes extraneous instances of the character '^'.
It then calls the function
static void b(char * const) static void b(char * const)
where actual output occurs. where actual output occurs.
static void b(char * const) static void b(char * const)
const char * parameter is the player's name. The data pointed at by the pointer is altered by function 'strtok', but the pointer itself is never changed. Abstractly, fragments of the player's name are treated as a command to print specific strings. const char * parameter is the player's name. The data pointed at by the
pointer is altered by function 'strtok', but the pointer itself is
never changed. Abstractly, fragments of the player's name are treated
as a command to print specific strings.
This function iterates once through the player's name. 'strtok' segments the player's name; sequences between and not including '^'s are treated as substrings. The first character of the substring is checked for a digit inclusively between 0 and 9 for a decimal color code. Exclusively or, checked for an 'x' and a numerical sequence afterwards for a hexidecimal color code. If the substring does not have either, it is printed like an ordinary string. This function iterates once through the player's name. 'strtok'
segments the player's name; sequences between and not including '^'s
are treated as substrings. The first character of the substring is
checked for a digit inclusively between 0 and 9 for a decimal color
code. Exclusively or, checked for an 'x' and a numerical sequence
afterwards for a hexidecimal color code. If the substring does not have
either, it is printed like an ordinary string.
This function may not be adequate when a player's name intentionally contains '^'. This function may not be adequate when a player's name intentionally
contains '^'.
static void hexspan(const char *) static void hexspan(const char *)
const char * parameter is ideally a sequence of 3 hexidecimal digits. Actually it is the entire substring from the callee. The first 3 elements are of interest as 3 separate single digit numerical values and are explicitly separated to prevent function 'strtol' from interpreting them as multidigit numbers. These 3 elements are rgb values from the game engine. const char * parameter is ideally a sequence of 3 hexidecimal digits.
Xonotic represents RGB values as a sequence of three digits 0 - 0xF. Before conversion is to be done, they must be multiplied by 0xF so the full range of values for RGB, 0 - 255 can be represented. Actually it is the entire substring from the callee. The first 3
elements are of interest as 3 separate single digit numerical values
and are explicitly separated to prevent function 'strtol' from
interpreting them as multidigit numbers. These 3 elements are rgb
values from the game engine.
Xonotic represents RGB values as a sequence of three digits 0 - 0xF.
Before conversion is to be done, they must be multiplied by 0xF so the
full range of values for RGB, 0 - 255 can be represented.
This function prints the an html span tag. This function prints the an html span tag.
This function will first convert rgb to hsl to check if the colors are too dark for the web page, and if so brighten up the colors then reconvert to rgb. This function will first convert rgb to hsl to check if the colors are
too dark for the web page, and if so brighten up the colors then
reconvert to rgb.
static void decspan(const int) static void decspan(const int)
const int parameter is a digit, the range being [0, 9]. const int parameter is a digit, the range being [0, 9].
This function is straightforward. It will print an html tag corresponding to the const int parameter. This function is straightforward. It will print an html tag
corresponding to the const int parameter.
void hsl2rgb(struct Rgb *, const struct Hls const *) void hsl2rgb(struct Rgb *, const struct Hls const *)
First parameter, 'struct Rgb *' is the result of the conversion. It does not need to be initialized. First parameter, 'struct Rgb *' is the result of the conversion. It
Second parameter, 'const struct Hls const *' is the values and color model to convert from and because, it must be initialized. does not need to be initialized.
Second parameter, 'const struct Hls const *' is the values and color
model to convert from and because, it must be initialized.
The math referenced from: The math referenced from:
http://www.rapidtables.com/convert/color/hsl-to-rgb.htm http://www.rapidtables.com/convert/color/hsl-to-rgb.htm
The implemenation deviates at the last 3 lines of code where the results are finalized and placed in the output. The webpage does not mention that rounding up is necessary. However it is, otherwise the nonzero rgb values for the following colors The implemenation deviates at the last 3 lines of code where the
results are finalized and placed in the output. The webpage does not
mention that rounding up is necessary. However it is, otherwise the
nonzero rgb values for the following colors
Silver (0°,0%,75%) Silver (0°,0%,75%)
Gray (0°,0%,50%) Gray (0°,0%,50%)
Maroon (0°,100%,25%) Maroon (0°,100%,25%)
@ -121,9 +165,12 @@ Sorted by caller to callee.
will be off by one. will be off by one.
void rgb2hsl(struct Hls *, const struct Rgb const *) void rgb2hsl(struct Hls *, const struct Rgb const *)
First parameter, 'struct Hls *' is the result of the conversion. It does not need to be initialized. First parameter, 'struct Hls *' is the result of the conversion. It
Second parameter, 'const struct Rgb const *' is the values and color model to convert from and because, it must be initialized. does not need to be initialized.
Second parameter, 'const struct Rgb const *' is the values and color
model to convert from and because, it must be initialized.
The math referenced from: The math referenced from:
http://www.rapidtables.com/convert/color/rgb-to-hsl.htm http://www.rapidtables.com/convert/color/rgb-to-hsl.htm
The implementation deviates when calculating hue, when Cmax is R'. Instead of modulo, there is a summation by 6 when G' is less than B'. The implementation deviates when calculating hue, when Cmax is R'.
Instead of modulo, there is a summation by 6 when G' is less than B'.

View File

@ -9,17 +9,25 @@ Overview
Every function that allocates memory also frees it. Every function that allocates memory also frees it.
Advanced string manipulation such as concatenation is avoided. Instead strings are printed in parts. Advanced string manipulation such as concatenation is avoided. Instead
strings are printed in parts.
Exo File Dependencies Exo File Dependencies
SQL commands are stored in an outside file (.sql) and executed. The functions in this file are largely adaptable until SQL commands are stored in an outside file (.sql) and executed. The
functions in this file are largely adaptable until
void qresult(void * const, const char *); void qresult(void * const, const char *);
which prints the results of the query. This is specific to the query. All functions in this file could be considered non-modular because the specialized functions like 'qresult' are eventually called by the more adaptable functions. This may later be solved by calling function pointers to display table data, but currently many of the tables are similar enough that one function to print all tables suffices. which prints the results of the query. This is specific to the query. All
functions in this file could be considered non-modular because the
specialized functions like 'qresult' are eventually called by the more
adaptable functions. This may later be solved by calling function pointers
to display table data, but currently many of the tables are similar enough
that one function to print all tables suffices.
Adding or Removing New Queries Adding or Removing New Queries
To add new queries the program may handle the following functions need to be adjusted. To add new queries the program may handle the following functions need to
be adjusted.
inline void print_tblheader(const char *); inline void print_tblheader(const char *);
@ -27,37 +35,58 @@ Adding or Removing New Queries
void qresult(void * const, const char *); void qresult(void * const, const char *);
The file name of the query file should be added to the switch statement of function 'get_filename'. The starting html tags and labels should also be added to the switch statement of function 'print_tblheader'. For both forementioned functions, the switch statement operates on a variable 'c' which represents the first character of the query string. Currently, the case is that the different queries, '?map=' and '?player=', begin with different letters. The file name of the query file should be added to the switch statement of
function 'get_filename'. The starting html tags and labels should also be
added to the switch statement of function 'print_tblheader'. For both
forementioned functions, the switch statement operates on a variable 'c'
which represents the first character of the query string. Currently, the
case is that the different queries, '?map=' and '?player=', begin with
different letters.
The function 'qresult'- extra formatting and corresponding conditions should be added to the series of if/else-if statements. 'qresult's most applicable conditionals are player names and formatted times- if a new query will involve those, the conditionals should be added. The function 'qresult'- extra formatting and corresponding conditions
should be added to the series of if/else-if statements. 'qresult's most
applicable conditionals are player names and formatted times- if a new
query will involve those, the conditionals should be added.
Function Walkthrough Function Walkthrough
Sorted by caller to callee. Sorted by caller to callee.
void getquery(char * const); void getquery(char * const);
Parameter 'char * const' is the query string retrieved from the environment. NULL is an acceptable parameter. Only the first character of the string pointed at by the pointer will be changed. Parameter 'char * const' is the query string retrieved from the
environment. NULL is an acceptable parameter. Only the first character
of the string pointed at by the pointer will be changed.
A file name is then retrieved from 'get_filename', depending on the first character of the query string. Then the contents of the query file is read in to be later to query the database. A file name is then retrieved from 'get_filename', depending on the
first character of the query string. Then the contents of the query
file is read in to be later to query the database.
Currently, this function determines the size of the file by using 'fseek' and 'ftell'. Often recommended against however: Currently, this function determines the size of the file by using
'fseek' and 'ftell'. Often recommended against however:
1. The files to open are restricted to a specific set. 1. The files to open are restricted to a specific set.
2. The files are plain text files. 2. The files are plain text files.
3. The file sizes, in bytes, are very unlikely to exceed the maximum value representable by integers. 3. The file sizes, in bytes, are very unlikely to exceed the
maximum value representable by integers.
'ftell' returns a long int. It can determine the file size of a ~2 GB file. 'ftell' returns a long int. It can determine the file size of a ~2 GB
file.
int executequery(const char *, const char *); int executequery(const char *, const char *);
Parameter #1 is the string containing the query for the database. NULL is not acceptable. If a null value is given, the program will output the following string to stderr: Parameter #1 is the string containing the query for the database. NULL
is not acceptable. If a null value is given, the program will output
the following string to stderr:
Could not prepare SQL statement: not an error Could not prepare SQL statement: not an error
(null) (null)
Parameter #2 is the query string. NULL is acceptable. Parameter #2 is the query string. NULL is acceptable.
This function opens and closes the connection to the database. Also prepares and finalizes the sql statement. However itself, it does not actually query the database. This function opens and closes the connection to the database. Also
prepares and finalizes the sql statement. However itself, it does not
actually query the database.
void qresult(void * const, const char *); void qresult(void * const, const char *);
Parameter #1 is the prepared sql statement. Parameter #1 is the prepared sql statement.
Parameter #2 is the first character of the query string- in use to identify the query. Parameter #2 is the first character of the query string- in use to
identify the query.
This function both executes the query and displays the data. This function both executes the query and displays the data.
The for loop iterates for each field of the row returned. The for loop iterates for each field of the row returned.
@ -78,31 +107,44 @@ Sorted by caller to callee.
select trank, alias, tvalue select trank, alias, tvalue
i = 0 1 2 i = 0 1 2
if ((*c == QMLEADERBOARD && i == 1) || (*c == QOVERVIEW && i == 3) || (*c == QRPLAYER && i == 0)) if ((*c == QMLEADERBOARD && i == 1)
If the field is for map leaderboards and column 1, or the overview and column 3, or player ranks and column 0, then it is a player name; which should have the in-game color codes translated to html. || (*c == QOVERVIEW && i == 3)
|| (*c == QRPLAYER && i == 0))
If the field is for map leaderboards and column 1, or the overview
and column 3, or player ranks and column 0, then it is a player
name; which should have the in-game color codes translated to html.
if ((i == 0 && *c == QOVERVIEW) || (i == 1 && *c == QRPLAYER)) if ((i == 0 && *c == QOVERVIEW) || (i == 1 && *c == QRPLAYER))
If the field is for overview and column 0 or is player ranks column 1, then it is a map name, and it should have html tags linking it to the map leaderboards. If the field is for overview and column 0 or is player ranks column
1, then it is a map name, and it should have html tags linking it
to the map leaderboards.
if (i == 2 && (*c == QMLEADERBOARD || *c == QOVERVIEW)) if (i == 2 && (*c == QMLEADERBOARD || *c == QOVERVIEW))
If the field is column 2 of either the overview or the map leaderboards, then it is a time which should be formatted as such. If the field is column 2 of either the overview or the map
leaderboards, then it is a time which should be formatted as such.
If none of the conditionals are met, then the field is printed as usual. If none of the conditionals are met, then the field is printed as usual.
void print_time(const unsigned char *); void print_time(const unsigned char *);
Parameter 'const unsigned char *' is the string that represents a number- quantity of centiseconds. Parameter 'const unsigned char *' is the string that represents a
number- quantity of centiseconds.
The time as a string is converted to a number by 'strtoul'. Thus, the maximum value that is returned by 'strtoul' given a string is 21,474,836.47 seconds. This is by far, more than enough for a game mode focused on the lowest possible times. The time as a string is converted to a number by 'strtoul'. Thus, the
maximum value that is returned by 'strtoul' given a string is
21,474,836.47 seconds. This is by far, more than enough for a game mode
focused on the lowest possible times.
This function performs the conversion and prints the value. This function performs the conversion and prints the value.
inline void print_tblheader(const char *); inline void print_tblheader(const char *);
Parameter 'const char *' is a pointer to a string. However, only the first character is of interest because C can not switch on strings. Parameter 'const char *' is a pointer to a string. However, only the
first character is of interest because C can not switch on strings.
This function prints the starting tag of the html table. This function prints the starting tag of the html table.
inline char *get_filename(const char *) ; inline char *get_filename(const char *) ;
Parameter 'const char *' is a pointer to a string. However, only the first character is of interest because C can not switch on strings. Parameter 'const char *' is a pointer to a string. However, only the
first character is of interest because C can not switch on strings.
This function returns the file name of a sql query file. This function returns the file name of a sql query file.