Compare commits
18 commits
Author | SHA1 | Date | |
---|---|---|---|
8e58873ea9 | |||
2d485a3824 | |||
3fc301cde5 | |||
82693bfa3e | |||
e6e9fc16af | |||
fddc43f36b | |||
10bf88ec3e | |||
20f413c8d9 | |||
5e2ae5f87b | |||
d46a323b15 | |||
e9de2682f6 | |||
12a1edc897 | |||
63a5eca63c | |||
ba1c692e2f | |||
8da223461d | |||
d9d286c53f | |||
08769d026e | |||
2c82b82b06 |
14 changed files with 1610 additions and 211 deletions
44
Changelog.md
44
Changelog.md
|
@ -2,6 +2,50 @@
|
||||||
|
|
||||||
## Upcoming Changes
|
## Upcoming Changes
|
||||||
|
|
||||||
|
## Version 1.4
|
||||||
|
|
||||||
|
Implemented "IF", "ELSEIF", "ELSE", "ENDIF", and "INDEX" for templates.
|
||||||
|
|
||||||
|
IF is used like: `{{{!IF Variable==SomeString}}}`.
|
||||||
|
Not equals can also be used: `{{{!IF Variable!=OtherString}}}`.
|
||||||
|
ELSEIF is used like: `{{{!ELSEIF Variable==AnotherString}}}`.
|
||||||
|
Not equals can also be used: `{{{!ELSEIF Variable!=AnotherOtherString}}}`.
|
||||||
|
ELSE is used like: `{{{!ELSE}}}`.
|
||||||
|
ENDIF is used like: `{{{!ENDIF}}}`.
|
||||||
|
INDEX is used like: `{{{!INDEX ArrayVar[2]}}}`.
|
||||||
|
|
||||||
|
Implemented "FOREACH" and "ENDFOREACH" for templates.
|
||||||
|
|
||||||
|
FOREACH is used like:
|
||||||
|
|
||||||
|
PATH=/
|
||||||
|
HTML='''
|
||||||
|
{{{!FOREACH ArrayVar}}}
|
||||||
|
{{{ArrayVar}}}
|
||||||
|
{{{!ENDFOREACH}}}'''
|
||||||
|
ArrayVar=FirstValue
|
||||||
|
ArrayVar=SecondValue
|
||||||
|
ArrayVar=ThirdValue
|
||||||
|
|
||||||
|
For multiple variables to expand in FOREACH:
|
||||||
|
|
||||||
|
PATH=/
|
||||||
|
HTML='''
|
||||||
|
{{{!FOREACH ArrayVar!ArrayVarSecond!ArrayVarThird}}}
|
||||||
|
{{{ArrayVar}}}
|
||||||
|
{{{ArrayVarSecond}}}
|
||||||
|
{{{ArrayVarThird}}}
|
||||||
|
{{{!ENDFOREACH}}}'''
|
||||||
|
ArrayVar=FirstVarOnce
|
||||||
|
ArrayVar=FirstVarTwice
|
||||||
|
ArrayVarSecond=SecondVarOnce
|
||||||
|
ArrayVarSecond=SecondVarTwice
|
||||||
|
ArrayVarThird=ThirdVarOnce
|
||||||
|
ArrayVarThird=ThirdVarTwice
|
||||||
|
|
||||||
|
Implemented nestable "IF" and "FOREACH" expressions in templates. In other
|
||||||
|
words, there can be `{{{!IF}}}` inside other IF/FOREACH blocks, and vice versa.
|
||||||
|
|
||||||
## Version 1.3
|
## Version 1.3
|
||||||
|
|
||||||
Fix internal erronous buffer declaration.
|
Fix internal erronous buffer declaration.
|
||||||
|
|
1
example_config/each_file_one.html
Normal file
1
example_config/each_file_one.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<b>Each File ONE</b><br>
|
1
example_config/each_file_two.html
Normal file
1
example_config/each_file_two.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<b>Each File TWO</b><br>
|
1
example_config/each_file_zero.html
Normal file
1
example_config/each_file_zero.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<b>Each File ZERO</b><br>
|
|
@ -1,6 +1,6 @@
|
||||||
PATH=/
|
PATH=/
|
||||||
HTML='''
|
HTML='''
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -24,14 +24,131 @@ HTML='''
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Test HTML</h1><br>
|
<h2>Test IF/FOREACH Expr</h2>
|
||||||
<h2>{{{Var}}}</h2>
|
|
||||||
<h3><a href="/inner">To inner.</a></h3>
|
Outer IF<br>
|
||||||
</body>
|
<pre>
|
||||||
|
{{{!IF ThisValue==true}}}
|
||||||
|
ThisValue is <b>true</b>.<br>
|
||||||
|
{{{!FOREACH ArrayValue}}}
|
||||||
|
{{{!IF ThisOtherValue==true}}}
|
||||||
|
{{{ArrayValue}}}<br>
|
||||||
|
ThisOtherValue is <b>true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ELSE}}}
|
||||||
|
{{{ArrayValue}}}<br>
|
||||||
|
ThisOtherValue is <b>NOT true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ELSE}}}
|
||||||
|
ThisValue is <b>NOT true</b>.<br>
|
||||||
|
{{{!FOREACH ArrayValueSecond}}}
|
||||||
|
{{{!IF ThisOtherValue==true}}}
|
||||||
|
{{{ArrayValueSecond}}}<br>
|
||||||
|
ThisOtherValue is <b>true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ELSE}}}
|
||||||
|
{{{ArrayValueSecond}}}<br>
|
||||||
|
ThisOtherValue is <b>NOT true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
</pre><br>
|
||||||
|
|
||||||
|
Outer FOREACH<br>
|
||||||
|
<pre>
|
||||||
|
{{{!FOREACH ArrayValue}}}
|
||||||
|
{{{ArrayValue}}}<br>
|
||||||
|
{{{!IF ThisValue==true}}}
|
||||||
|
ThisValue is <b>true</b>.<br>
|
||||||
|
{{{!FOREACH ArrayValueSecond}}}
|
||||||
|
{{{ArrayValueSecond}}}<br>
|
||||||
|
{{{!IF ThisOtherValue==true}}}
|
||||||
|
ThisOtherValue is <b>true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ELSE}}}
|
||||||
|
ThisOtherValue is <b>NOT true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ELSE}}}
|
||||||
|
ThisValue is <b>NOT true</b>.<br>
|
||||||
|
{{{!FOREACH ArrayValueSecond}}}
|
||||||
|
{{{ArrayValueSecond}}}<br>
|
||||||
|
{{{!IF ThisOtherValue==true}}}
|
||||||
|
ThisOtherValue is <b>true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ELSE}}}
|
||||||
|
ThisOtherValue is <b>NOT true</b>.<br>
|
||||||
|
{{{Var}}}<br>
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDIF}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
</pre><br>
|
||||||
|
|
||||||
|
Nested FOREACH:<br>
|
||||||
|
<pre>
|
||||||
|
{{{!FOREACH ArrayValue}}}
|
||||||
|
{{{ArrayValue}}}
|
||||||
|
{{{!FOREACH ArrayValueSecond}}}
|
||||||
|
{{{ArrayValueSecond}}}
|
||||||
|
{{{!FOREACH ArrayValueThird}}}
|
||||||
|
{{{ArrayValueThird}}}
|
||||||
|
{{{!FOREACH ArrayValueFourth}}}
|
||||||
|
{{{ArrayValueFourth}}}
|
||||||
|
{{{!FOREACH Each_FILE}}}
|
||||||
|
{{{Each_FILE}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
{{{!ENDFOREACH}}}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<br><h2><a href="/inner">inner</a></h2>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Var='''Test var value'''
|
Var='''Test var value'''
|
||||||
|
ThisValue=true
|
||||||
|
ThisOtherValue=true
|
||||||
|
|
||||||
|
ArrayValue=1_IDX_Zero
|
||||||
|
ArrayValue=1_IDX_One
|
||||||
|
ArrayValue=1_IDX_Two
|
||||||
|
|
||||||
|
ArrayValueSecond=2_IDX_Zero
|
||||||
|
ArrayValueSecond=2_IDX_One
|
||||||
|
ArrayValueSecond=2_IDX_Two
|
||||||
|
|
||||||
|
ArrayValueThird=3_IDX_Zero
|
||||||
|
ArrayValueThird=3_IDX_One
|
||||||
|
ArrayValueThird=3_IDX_Two
|
||||||
|
|
||||||
|
ArrayValueFourth=4_IDX_Zero
|
||||||
|
ArrayValueFourth=4_IDX_One
|
||||||
|
ArrayValueFourth=4_IDX_Two
|
||||||
|
|
||||||
|
EachTestHead='''First Entry Head'''
|
||||||
|
EachTestMid='''First Entry Mid'''
|
||||||
|
EachTestTail='''First Entry Tail'''
|
||||||
|
|
||||||
|
EachTestHead='''Second Entry Head'''
|
||||||
|
EachTestMid='''Second Entry Mid'''
|
||||||
|
EachTestTail='''Second Entry Tail'''
|
||||||
|
|
||||||
|
EachTestHead='''Third Entry Head'''
|
||||||
|
EachTestMid='''Third Entry Mid'''
|
||||||
|
EachTestTail='''Third Entry Tail'''
|
||||||
|
|
||||||
|
Each_FILE='''example_config/each_file_zero.html'''
|
||||||
|
Each_FILE='''example_config/each_file_one.html'''
|
||||||
|
Each_FILE='''example_config/each_file_two.html'''
|
||||||
|
|
||||||
PATH=/inner
|
PATH=/inner
|
||||||
HTML_FILE='''example_config/inner.html'''
|
HTML_FILE='''example_config/inner.html'''
|
||||||
|
|
87
src/config.c
87
src/config.c
|
@ -36,6 +36,23 @@ typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
|
||||||
const SDArchiverLinkedList *required;
|
const SDArchiverLinkedList *required;
|
||||||
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
||||||
|
|
||||||
|
void c_simple_http_cleanup_config_value(
|
||||||
|
C_SIMPLE_HTTP_ConfigValue *config_value) {
|
||||||
|
if (config_value) {
|
||||||
|
if (config_value->next) {
|
||||||
|
c_simple_http_cleanup_config_value(config_value->next);
|
||||||
|
}
|
||||||
|
if(config_value->value) {
|
||||||
|
free(config_value->value);
|
||||||
|
}
|
||||||
|
free(config_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_simple_http_cleanup_config_value_void_ptr(void *config_value) {
|
||||||
|
c_simple_http_cleanup_config_value(config_value);
|
||||||
|
}
|
||||||
|
|
||||||
int c_simple_http_required_iter_fn(void *data, void *ud) {
|
int c_simple_http_required_iter_fn(void *data, void *ud) {
|
||||||
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
||||||
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
||||||
|
@ -187,21 +204,26 @@ int internal_check_add_value(uint32_t *state,
|
||||||
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
||||||
unsigned char *key = malloc(separating_key_size);
|
unsigned char *key = malloc(separating_key_size);
|
||||||
strncpy((char*)key, separating_key, separating_key_size);
|
strncpy((char*)key, separating_key, separating_key_size);
|
||||||
unsigned char *value = malloc(*value_idx);
|
C_SIMPLE_HTTP_ConfigValue *config_value =
|
||||||
memcpy(value, *value_buf, (*value_idx));
|
malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
||||||
if (simple_archiver_hash_map_insert(hash_map,
|
config_value->value = malloc(*value_idx);
|
||||||
value,
|
config_value->next = NULL;
|
||||||
key,
|
memcpy(config_value->value, *value_buf, (*value_idx));
|
||||||
separating_key_size,
|
if (simple_archiver_hash_map_insert(
|
||||||
NULL,
|
hash_map,
|
||||||
NULL) != 0) {
|
config_value,
|
||||||
|
key,
|
||||||
|
separating_key_size,
|
||||||
|
c_simple_http_cleanup_config_value_void_ptr,
|
||||||
|
NULL) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: Failed to create hash map for new separating_key "
|
"ERROR: Failed to create hash map for new separating_key "
|
||||||
"block!\n");
|
"block!\n");
|
||||||
c_simple_http_clean_up_parsed_config(config);
|
c_simple_http_clean_up_parsed_config(config);
|
||||||
config->hash_map = NULL;
|
config->hash_map = NULL;
|
||||||
free(key);
|
free(key);
|
||||||
free(value);
|
free(config_value->value);
|
||||||
|
free(config_value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +234,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
if (simple_archiver_hash_map_insert(
|
if (simple_archiver_hash_map_insert(
|
||||||
config->hash_map,
|
config->hash_map,
|
||||||
wrapper,
|
wrapper,
|
||||||
value,
|
config_value->value,
|
||||||
(*value_idx),
|
(*value_idx),
|
||||||
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
||||||
|
@ -223,7 +245,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
simple_archiver_list_add(paths, value,
|
simple_archiver_list_add(paths, config_value->value,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop);
|
simple_archiver_helper_datastructure_cleanup_nop);
|
||||||
} else if (!(*current_separating_key_value)) {
|
} else if (!(*current_separating_key_value)) {
|
||||||
fprintf(
|
fprintf(
|
||||||
|
@ -254,20 +276,37 @@ int internal_check_add_value(uint32_t *state,
|
||||||
unsigned char *value = malloc(*value_idx);
|
unsigned char *value = malloc(*value_idx);
|
||||||
memcpy(value, *value_buf, (*value_idx));
|
memcpy(value, *value_buf, (*value_idx));
|
||||||
|
|
||||||
if (simple_archiver_hash_map_insert(hash_map_wrapper->paths,
|
// Check if key already exists in wrapped hash-map.
|
||||||
value,
|
C_SIMPLE_HTTP_ConfigValue *config_value =
|
||||||
key,
|
simple_archiver_hash_map_get(hash_map_wrapper->paths, key, *key_idx);
|
||||||
*key_idx,
|
if (config_value) {
|
||||||
NULL,
|
while(config_value->next) {
|
||||||
NULL) != 0) {
|
config_value = config_value->next;
|
||||||
fprintf(stderr,
|
}
|
||||||
"ERROR: Internal error failed to insert into hash map with path "
|
config_value->next = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
||||||
"\"%s\"!", (*current_separating_key_value));
|
config_value->next->value = (char*)value;
|
||||||
c_simple_http_clean_up_parsed_config(config);
|
config_value->next->next = NULL;
|
||||||
config->hash_map = NULL;
|
|
||||||
free(key);
|
free(key);
|
||||||
free(value);
|
} else {
|
||||||
return 1;
|
config_value = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
||||||
|
config_value->value = (char*)value;
|
||||||
|
config_value->next = NULL;
|
||||||
|
if (simple_archiver_hash_map_insert(
|
||||||
|
hash_map_wrapper->paths,
|
||||||
|
config_value,
|
||||||
|
key,
|
||||||
|
*key_idx,
|
||||||
|
c_simple_http_cleanup_config_value_void_ptr,
|
||||||
|
NULL) != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: Internal error failed to insert into hash map with path "
|
||||||
|
"\"%s\"!", (*current_separating_key_value));
|
||||||
|
c_simple_http_clean_up_parsed_config(config);
|
||||||
|
config->hash_map = NULL;
|
||||||
|
free(key);
|
||||||
|
free(value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*key_idx) = 0;
|
(*key_idx) = 0;
|
||||||
|
|
12
src/config.h
12
src/config.h
|
@ -30,6 +30,9 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
/// KEY: "/", VALUE: HashMapWrapper struct
|
/// KEY: "/", VALUE: HashMapWrapper struct
|
||||||
/// KEY: "/inner", VALUE: HashMapWrapper struct
|
/// KEY: "/inner", VALUE: HashMapWrapper struct
|
||||||
/// KEY: "/inner/further", VALUE: HashMapWrapper struct
|
/// KEY: "/inner/further", VALUE: HashMapWrapper struct
|
||||||
|
///
|
||||||
|
/// Each HashMapWrapper struct's hash-map has the following:
|
||||||
|
/// KEY: VAR_NAME, VALUE: ConfigValue struct
|
||||||
union {
|
union {
|
||||||
SDArchiverHashMap *paths;
|
SDArchiverHashMap *paths;
|
||||||
SDArchiverHashMap *hash_map;
|
SDArchiverHashMap *hash_map;
|
||||||
|
@ -38,6 +41,15 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
|
|
||||||
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
|
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
|
||||||
|
|
||||||
|
typedef struct C_SIMPLE_HTTP_ConfigValue {
|
||||||
|
char *value;
|
||||||
|
struct C_SIMPLE_HTTP_ConfigValue *next;
|
||||||
|
} C_SIMPLE_HTTP_ConfigValue;
|
||||||
|
|
||||||
|
void c_simple_http_cleanup_config_value(
|
||||||
|
C_SIMPLE_HTTP_ConfigValue *config_value);
|
||||||
|
void c_simple_http_cleanup_config_value_void_ptr(void *config_value);
|
||||||
|
|
||||||
/// Each line in the config should be a key-value pair separated by an equals
|
/// Each line in the config should be a key-value pair separated by an equals
|
||||||
/// sign "=". All whitespace is ignored unless if the value is "quoted". A part
|
/// sign "=". All whitespace is ignored unless if the value is "quoted". A part
|
||||||
/// of a string can be "quoted" if it is surrounded by three single-quotes or
|
/// of a string can be "quoted" if it is surrounded by three single-quotes or
|
||||||
|
|
100
src/helpers.c
100
src/helpers.c
|
@ -17,6 +17,7 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// Standard library includes.
|
// Standard library includes.
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -31,7 +32,9 @@ int c_simple_http_internal_get_string_part_full_size(void *data, void *ud) {
|
||||||
C_SIMPLE_HTTP_String_Part *part = data;
|
C_SIMPLE_HTTP_String_Part *part = data;
|
||||||
size_t *count = ud;
|
size_t *count = ud;
|
||||||
|
|
||||||
*count += part->size - 1;
|
if (part->size > 0) {
|
||||||
|
*count += part->size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -86,9 +89,36 @@ void c_simple_http_add_string_part(
|
||||||
C_SIMPLE_HTTP_String_Part *string_part =
|
C_SIMPLE_HTTP_String_Part *string_part =
|
||||||
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
||||||
|
|
||||||
string_part->size = strlen(c_string) + 1;
|
if (c_string) {
|
||||||
string_part->buf = malloc(string_part->size);
|
string_part->size = strlen(c_string) + 1;
|
||||||
memcpy(string_part->buf, c_string, string_part->size);
|
string_part->buf = malloc(string_part->size);
|
||||||
|
memcpy(string_part->buf, c_string, string_part->size);
|
||||||
|
} else {
|
||||||
|
string_part->size = 0;
|
||||||
|
string_part->buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_part->extra = extra;
|
||||||
|
simple_archiver_list_add(
|
||||||
|
list, string_part, c_simple_http_cleanup_string_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c_simple_http_add_string_part_sized(
|
||||||
|
SDArchiverLinkedList *list,
|
||||||
|
const char *buffer,
|
||||||
|
size_t size,
|
||||||
|
uintptr_t extra) {
|
||||||
|
C_SIMPLE_HTTP_String_Part *string_part =
|
||||||
|
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
||||||
|
|
||||||
|
if (buffer && size > 0) {
|
||||||
|
string_part->size = size;
|
||||||
|
string_part->buf = malloc(string_part->size - 1);
|
||||||
|
memcpy(string_part->buf, buffer, string_part->size - 1);
|
||||||
|
} else {
|
||||||
|
string_part->size = 0;
|
||||||
|
string_part->buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
string_part->extra = extra;
|
string_part->extra = extra;
|
||||||
|
|
||||||
|
@ -264,4 +294,66 @@ void c_simple_http_cleanup_DIR(DIR **fd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *c_simple_http_FILE_to_c_str(const char *filename, uint64_t *size_out) {
|
||||||
|
FILE *fd = fopen(filename, "rb");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "ERROR Failed to open %s!\n", filename);
|
||||||
|
return NULL;
|
||||||
|
} else if (fseek(fd, 0, SEEK_END) != 0) {
|
||||||
|
fprintf(stderr, "ERROR Failed to seek to end of %s!\n", filename);
|
||||||
|
fclose(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long size = ftell(fd);
|
||||||
|
if (size < 0) {
|
||||||
|
fprintf(stderr, "ERROR Failed to get seek pos of end of %s!\n", filename);
|
||||||
|
fclose(fd);
|
||||||
|
return NULL;
|
||||||
|
} else if (size == 0) {
|
||||||
|
fprintf(stderr, "ERROR Size of file \"%s\" is zero!\n", filename);
|
||||||
|
fclose(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (size_out) {
|
||||||
|
*size_out = (uint64_t)size;
|
||||||
|
}
|
||||||
|
char *buf = malloc((uint64_t)size + 1);
|
||||||
|
if (fseek(fd, 0, SEEK_SET) != 0) {
|
||||||
|
fprintf(stderr, "ERROR Failed to seek to beginning of %s!\n", filename);
|
||||||
|
free(buf);
|
||||||
|
fclose(fd);
|
||||||
|
return NULL;
|
||||||
|
} else if (fread(buf, 1, (uint64_t)size, fd) != (uint64_t)size) {
|
||||||
|
fprintf(stderr, "ERROR Failed to read from file %s!\n", filename);
|
||||||
|
free(buf);
|
||||||
|
fclose(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[size] = 0;
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t c_simple_http_trim_end_whitespace(char *c_str) {
|
||||||
|
size_t trimmed = 0;
|
||||||
|
|
||||||
|
uint64_t idx= strlen(c_str);
|
||||||
|
for (; idx-- > 0;) {
|
||||||
|
if (c_str[idx] == ' '
|
||||||
|
|| c_str[idx] == '\n'
|
||||||
|
|| c_str[idx] == '\r'
|
||||||
|
|| c_str[idx] == '\t') {
|
||||||
|
c_str[idx] = 0;
|
||||||
|
++trimmed;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -56,6 +56,16 @@ void c_simple_http_cleanup_string_part(void *data);
|
||||||
void c_simple_http_add_string_part(
|
void c_simple_http_add_string_part(
|
||||||
SDArchiverLinkedList *list, const char *c_string, uintptr_t extra);
|
SDArchiverLinkedList *list, const char *c_string, uintptr_t extra);
|
||||||
|
|
||||||
|
/// Puts a malloced instance of String_Part into the list.
|
||||||
|
/// The given c_string will be copied into a newly malloced buffer.
|
||||||
|
/// "size" must include NULL if "buffer" is a c_string.
|
||||||
|
/// If there is no NULL at the end, "size" must be +1 actual size.
|
||||||
|
void c_simple_http_add_string_part_sized(
|
||||||
|
SDArchiverLinkedList *list,
|
||||||
|
const char *buffer,
|
||||||
|
size_t size,
|
||||||
|
uintptr_t extra);
|
||||||
|
|
||||||
/// Combines all String_Parts in the list and returns it as a single buffer.
|
/// Combines all String_Parts in the list and returns it as a single buffer.
|
||||||
char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list);
|
char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list);
|
||||||
|
|
||||||
|
@ -80,6 +90,13 @@ int c_simple_http_helper_mkdir_tree(const char *dirpath);
|
||||||
|
|
||||||
void c_simple_http_cleanup_DIR(DIR **fd);
|
void c_simple_http_cleanup_DIR(DIR **fd);
|
||||||
|
|
||||||
|
/// Must be free'd if non-NULL.
|
||||||
|
char *c_simple_http_FILE_to_c_str(const char *filename, uint64_t *size_out);
|
||||||
|
|
||||||
|
/// Trims by placing NULL bytes in place of whitespace at the end of c_str.
|
||||||
|
/// Returns number of whitespace trimmed.
|
||||||
|
size_t c_simple_http_trim_end_whitespace(char *c_str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -38,8 +38,12 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "http_template.h"
|
#include "http_template.h"
|
||||||
|
|
||||||
int c_simple_http_internal_write_filenames_to_cache_file(void *data, void *ud) {
|
int c_simple_http_internal_write_filenames_to_cache_file(
|
||||||
char *filename = data;
|
const void *key,
|
||||||
|
__attribute__((unused)) size_t key_size,
|
||||||
|
__attribute__((unused)) const void *value,
|
||||||
|
void *ud) {
|
||||||
|
const char *filename = key;
|
||||||
FILE *cache_fd = ud;
|
FILE *cache_fd = ud;
|
||||||
|
|
||||||
const size_t filename_size = strlen(filename);
|
const size_t filename_size = strlen(filename);
|
||||||
|
@ -436,8 +440,8 @@ CACHE_FILE_WRITE_CHECK:
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
||||||
SDArchiverLinkedList *used_filenames = NULL;
|
SDArchiverHashMap *used_filenames = NULL;
|
||||||
|
|
||||||
size_t generated_html_size = 0;
|
size_t generated_html_size = 0;
|
||||||
|
|
||||||
|
@ -452,10 +456,10 @@ CACHE_FILE_WRITE_CHECK:
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simple_archiver_list_get(
|
if (simple_archiver_hash_map_iter(
|
||||||
used_filenames,
|
used_filenames,
|
||||||
c_simple_http_internal_write_filenames_to_cache_file,
|
c_simple_http_internal_write_filenames_to_cache_file,
|
||||||
cache_fd)) {
|
cache_fd) != 0) {
|
||||||
fprintf(stderr, "ERROR Failed to write filenames to cache file!\n");
|
fprintf(stderr, "ERROR Failed to write filenames to cache file!\n");
|
||||||
return -6;
|
return -6;
|
||||||
} else if (fwrite("--- BEGIN HTML ---\n", 1, 19, cache_fd) != 19) {
|
} else if (fwrite("--- BEGIN HTML ---\n", 1, 19, cache_fd) != 19) {
|
||||||
|
|
1283
src/http_template.c
1283
src/http_template.c
File diff suppressed because it is too large
Load diff
|
@ -17,13 +17,16 @@
|
||||||
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
||||||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
||||||
|
|
||||||
#include "http.h"
|
|
||||||
|
|
||||||
// Standard library includes.
|
// Standard library includes.
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// Third-party includes.
|
// Third-party includes.
|
||||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
||||||
|
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
||||||
|
|
||||||
|
// Local includes.
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
// Returns non-NULL on success, which must be free'd after use. Takes a path
|
// Returns non-NULL on success, which must be free'd after use. Takes a path
|
||||||
// string and templates and returns the generated HTML. If "output_buf_size" is
|
// string and templates and returns the generated HTML. If "output_buf_size" is
|
||||||
|
@ -35,7 +38,7 @@ char *c_simple_http_path_to_generated(
|
||||||
const char *path,
|
const char *path,
|
||||||
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||||
size_t *output_buf_size,
|
size_t *output_buf_size,
|
||||||
SDArchiverLinkedList **files_list_out);
|
SDArchiverHashMap **files_set_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
117
src/test.c
117
src/test.c
|
@ -99,9 +99,13 @@ void test_internal_cleanup_delete_temporary_file(const char **filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_internal_check_matching_string_in_list(void *value, void *ud) {
|
int test_internal_check_matching_string_in_list(
|
||||||
if (value && ud) {
|
const void *key,
|
||||||
if (strcmp(value, ud) == 0) {
|
__attribute__((unused)) size_t key_size,
|
||||||
|
__attribute__((unused)) const void *value,
|
||||||
|
void *ud) {
|
||||||
|
if (key && ud) {
|
||||||
|
if (strcmp(key, ud) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,46 +177,53 @@ int main(int argc, char **argv) {
|
||||||
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
||||||
ASSERT_TRUE(first_path_map_wrapper);
|
ASSERT_TRUE(first_path_map_wrapper);
|
||||||
|
|
||||||
const char *value =
|
C_SIMPLE_HTTP_ConfigValue *value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_STREQ(value, "/");
|
ASSERT_TRUE(value->value);
|
||||||
|
ASSERT_STREQ(value->value, "/");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " one two three ");
|
ASSERT_STREQ(value->value, " one two three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"one two \"three ");
|
ASSERT_STREQ(value->value, " \"one two \"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, "'\"onetwo\"three''");
|
ASSERT_STREQ(value->value, "'\"onetwo\"three''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"one two \"three ''");
|
ASSERT_STREQ(value->value, " \"one two \"three ''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"\"\"one two \"\"\"three ");
|
ASSERT_STREQ(value->value, " \"\"\"one two \"\"\"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " '''one two '''three ");
|
ASSERT_STREQ(value->value, " '''one two '''three ");
|
||||||
|
|
||||||
simple_archiver_list_free(&required_names);
|
simple_archiver_list_free(&required_names);
|
||||||
required_names = simple_archiver_list_init();
|
required_names = simple_archiver_list_init();
|
||||||
|
@ -271,18 +282,18 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
size_t output_buf_size;
|
size_t output_buf_size;
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
||||||
SDArchiverLinkedList *filenames_list = NULL;
|
SDArchiverHashMap *filenames_set = NULL;
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
char *buf = c_simple_http_path_to_generated(
|
char *buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_list);
|
"/", &config, &output_buf_size, &filenames_set);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
ASSERT_TRUE(strcmp(buf, "<h1>Test</h1>") == 0);
|
ASSERT_TRUE(strcmp(buf, "<h1>Test</h1>") == 0);
|
||||||
CHECK_TRUE(output_buf_size == 13);
|
CHECK_TRUE(output_buf_size == 13);
|
||||||
CHECK_TRUE(filenames_list->count == 0);
|
CHECK_TRUE(filenames_set->count == 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_list_free(&filenames_list);
|
simple_archiver_hash_map_free(&filenames_set);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename2 =
|
const char *test_http_template_filename2 =
|
||||||
|
@ -314,7 +325,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_list);
|
"/", &config, &output_buf_size, &filenames_set);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -323,9 +334,9 @@ int main(int argc, char **argv) {
|
||||||
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 46);
|
CHECK_TRUE(output_buf_size == 46);
|
||||||
CHECK_TRUE(filenames_list->count == 0);
|
CHECK_TRUE(filenames_set->count == 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_list_free(&filenames_list);
|
simple_archiver_hash_map_free(&filenames_set);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename3 =
|
const char *test_http_template_filename3 =
|
||||||
|
@ -380,7 +391,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_list);
|
"/", &config, &output_buf_size, &filenames_set);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -389,14 +400,14 @@ int main(int argc, char **argv) {
|
||||||
"<h1> testVar text. </h1><br><h2> testVar2 text. </h2>")
|
"<h1> testVar text. </h1><br><h2> testVar2 text. </h2>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 53);
|
CHECK_TRUE(output_buf_size == 53);
|
||||||
CHECK_TRUE(filenames_list->count == 1);
|
CHECK_TRUE(filenames_set->count == 1);
|
||||||
CHECK_TRUE(simple_archiver_list_get(
|
CHECK_TRUE(simple_archiver_hash_map_iter(
|
||||||
filenames_list,
|
filenames_set,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_filename)
|
(void*)test_http_template_html_filename)
|
||||||
!= NULL);
|
!= 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_list_free(&filenames_list);
|
simple_archiver_hash_map_free(&filenames_set);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename4 =
|
const char *test_http_template_filename4 =
|
||||||
|
@ -471,7 +482,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_list);
|
"/", &config, &output_buf_size, &filenames_set);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -480,17 +491,17 @@ int main(int argc, char **argv) {
|
||||||
"<h1> some test text in test var file. </h1>")
|
"<h1> some test text in test var file. </h1>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 43);
|
CHECK_TRUE(output_buf_size == 43);
|
||||||
CHECK_TRUE(filenames_list->count == 2);
|
CHECK_TRUE(filenames_set->count == 2);
|
||||||
CHECK_TRUE(simple_archiver_list_get(
|
CHECK_TRUE(simple_archiver_hash_map_iter(
|
||||||
filenames_list,
|
filenames_set,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_filename2)
|
(void*)test_http_template_html_filename2)
|
||||||
!= NULL);
|
!= 0);
|
||||||
CHECK_TRUE(simple_archiver_list_get(
|
CHECK_TRUE(simple_archiver_hash_map_iter(
|
||||||
filenames_list,
|
filenames_set,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_var_filename)
|
(void*)test_http_template_html_var_filename)
|
||||||
!= NULL);
|
!= 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,6 +624,46 @@ int main(int argc, char **argv) {
|
||||||
CHECK_TRUE(ret == 0);
|
CHECK_TRUE(ret == 0);
|
||||||
CHECK_TRUE(ret2 == 0);
|
CHECK_TRUE(ret2 == 0);
|
||||||
CHECK_TRUE(ret3 == 0);
|
CHECK_TRUE(ret3 == 0);
|
||||||
|
|
||||||
|
buf = strdup("EndingWithThreeTabs\t\t\t");
|
||||||
|
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
||||||
|
CHECK_TRUE(buf[18] == 's');
|
||||||
|
CHECK_TRUE(buf[19] == 0);
|
||||||
|
CHECK_TRUE(buf[20] == 0);
|
||||||
|
CHECK_TRUE(buf[21] == 0);
|
||||||
|
CHECK_TRUE(buf[22] == 0);
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
|
buf = strdup("EndingWithThreeSpaces ");
|
||||||
|
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
||||||
|
CHECK_TRUE(buf[20] == 's');
|
||||||
|
CHECK_TRUE(buf[21] == 0);
|
||||||
|
CHECK_TRUE(buf[22] == 0);
|
||||||
|
CHECK_TRUE(buf[23] == 0);
|
||||||
|
CHECK_TRUE(buf[24] == 0);
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
|
buf = strdup("EndingWithThreeNewlines\n\n\n");
|
||||||
|
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
||||||
|
CHECK_TRUE(buf[22] == 's');
|
||||||
|
CHECK_TRUE(buf[23] == 0);
|
||||||
|
CHECK_TRUE(buf[24] == 0);
|
||||||
|
CHECK_TRUE(buf[25] == 0);
|
||||||
|
CHECK_TRUE(buf[26] == 0);
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
|
buf = strdup("EndingWithThreeCarraigeReturns\r\r\r");
|
||||||
|
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
||||||
|
CHECK_TRUE(buf[29] == 's');
|
||||||
|
CHECK_TRUE(buf[30] == 0);
|
||||||
|
CHECK_TRUE(buf[31] == 0);
|
||||||
|
CHECK_TRUE(buf[32] == 0);
|
||||||
|
CHECK_TRUE(buf[33] == 0);
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test html_cache.
|
// Test html_cache.
|
||||||
|
|
2
third_party/SimpleArchiver
vendored
2
third_party/SimpleArchiver
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit b256350fbcf170ef3d70e9cf7c6dfa0618e47ef4
|
Subproject commit ce7400a298a95b60d0d482058ed9eae4142f8061
|
Loading…
Reference in a new issue