cache refinement
parent
2f4b2a8c98
commit
4baf70ad0c
|
@ -8,8 +8,8 @@
|
|||
#include <unordered_map>
|
||||
#include <blt/std/hashmap.h>
|
||||
|
||||
#define CROW_STATIC_DIRECTORY "/mnt/games/Projects/cpp/crowsite/crow_test/static/"
|
||||
#define SITE_FILES_PATH "/mnt/games/Projects/cpp/crowsite/crow_test"
|
||||
#define CROW_STATIC_DIRECTORY "/home/brett/projects/cpp/crowsite/crow_test/static/"
|
||||
#define SITE_FILES_PATH "/home/brett/projects/cpp/crowsite/crow_test"
|
||||
#define CROW_STATIC_ENDPOINT "/static/<path>"
|
||||
|
||||
#define MILES_SITE
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
|
||||
namespace cs {
|
||||
|
||||
class LexerSyntaxError : public std::runtime_error {
|
||||
public:
|
||||
LexerSyntaxError(): std::runtime_error("Invalid template syntax. EOF occurred before template was fully processed!"){}
|
||||
};
|
||||
|
||||
constexpr uint64_t toMB = 1024 * 1024;
|
||||
|
||||
struct CacheSettings {
|
||||
|
|
|
@ -12,52 +12,6 @@
|
|||
|
||||
namespace cs {
|
||||
|
||||
struct StringLexer
|
||||
{
|
||||
private:
|
||||
std::string str;
|
||||
size_t index = 0;
|
||||
public:
|
||||
explicit StringLexer(std::string str): str(std::move(str))
|
||||
{}
|
||||
|
||||
inline bool hasNext()
|
||||
{
|
||||
if (index >= str.size())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool hasTemplatePrefix(char c)
|
||||
{
|
||||
if (index + 2 >= str.size())
|
||||
return false;
|
||||
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
|
||||
}
|
||||
|
||||
inline bool hasTemplateSuffix()
|
||||
{
|
||||
if (index + 1 >= str.size())
|
||||
return false;
|
||||
return str[index] == '}' && str[index + 1] == '}';
|
||||
}
|
||||
|
||||
inline void consumeTemplatePrefix()
|
||||
{
|
||||
index += 3;
|
||||
}
|
||||
|
||||
inline void consumeTemplateSuffix()
|
||||
{
|
||||
index += 2;
|
||||
}
|
||||
|
||||
inline char consume()
|
||||
{
|
||||
return str[index++];
|
||||
}
|
||||
};
|
||||
|
||||
class StaticContext {
|
||||
private:
|
||||
HASHMAP<std::string, std::string> replacements;
|
||||
|
@ -82,16 +36,6 @@ namespace cs {
|
|||
explicit HTMLPage(std::string siteData);
|
||||
public:
|
||||
static std::unique_ptr<HTMLPage> load(const std::string& path);
|
||||
/**
|
||||
* Attempts to resolve linked resources like CSS and JS in order to speedup page loading.
|
||||
*/
|
||||
void resolveResources();
|
||||
/**
|
||||
* Uses the static context provided to resolve known variables before user requests
|
||||
* @param context context to use
|
||||
* @return string containing resolved static templates
|
||||
*/
|
||||
std::string render(StaticContext& context);
|
||||
|
||||
inline std::string& getRawSite() {
|
||||
return m_SiteData;
|
||||
|
|
|
@ -10,6 +10,72 @@
|
|||
|
||||
namespace cs
|
||||
{
|
||||
struct StringLexer
|
||||
{
|
||||
private:
|
||||
std::string str;
|
||||
size_t index = 0;
|
||||
public:
|
||||
explicit StringLexer(std::string str): str(std::move(str))
|
||||
{}
|
||||
|
||||
inline bool hasNext()
|
||||
{
|
||||
if (index >= str.size())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool hasTemplatePrefix(char c)
|
||||
{
|
||||
if (index + 2 >= str.size())
|
||||
return false;
|
||||
return str[index] == '{' && str[index + 1] == '{' && str[index + 2] == c;
|
||||
}
|
||||
|
||||
inline bool hasTemplateSuffix()
|
||||
{
|
||||
if (index + 1 >= str.size())
|
||||
return false;
|
||||
return str[index] == '}' && str[index + 1] == '}';
|
||||
}
|
||||
|
||||
inline void consumeTemplatePrefix()
|
||||
{
|
||||
// because any custom mustache syntax will have to have a prefix like '$' or '@'
|
||||
// it is fine that we make the assumption of 3 characters consumed.
|
||||
index += 3;
|
||||
}
|
||||
|
||||
inline void consumeTemplateSuffix()
|
||||
{
|
||||
index += 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function assumes hasTemplatePrefix(char) has returned true and will consume both the prefix and suffix
|
||||
* @return the token found between the prefix and suffix
|
||||
* @throws LexerSyntaxError if the parser is unable to process a full token
|
||||
*/
|
||||
inline std::string consumeToken(){
|
||||
consumeTemplatePrefix();
|
||||
std::string token;
|
||||
while (!hasTemplateSuffix()) {
|
||||
if (!hasNext()) {
|
||||
throw LexerSyntaxError();
|
||||
}
|
||||
token += consume();
|
||||
}
|
||||
consumeTemplateSuffix();
|
||||
return token;
|
||||
}
|
||||
|
||||
inline char consume()
|
||||
{
|
||||
return str[index++];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
double toSeconds(uint64_t v)
|
||||
{
|
||||
|
@ -92,7 +158,7 @@ namespace cs
|
|||
auto fullPath = cs::fs::createWebFilePath(path);
|
||||
auto page = HTMLPage::load(fullPath);
|
||||
resolveLinks(path, *page);
|
||||
auto renderedPage = page->render(m_Context);
|
||||
const auto& renderedPage = page->getRawSite();
|
||||
m_Pages[path] = CacheValue{
|
||||
blt::system::getCurrentTimeNanoseconds(),
|
||||
std::filesystem::last_write_time(fullPath),
|
||||
|
@ -152,28 +218,36 @@ namespace cs
|
|||
{
|
||||
if (lexer.hasTemplatePrefix('@'))
|
||||
{
|
||||
lexer.consumeTemplatePrefix();
|
||||
std::string token;
|
||||
while (!lexer.hasTemplateSuffix()) {
|
||||
if (!lexer.hasNext()) {
|
||||
BLT_WARN("Invalid template syntax. EOF occurred before template was fully processed!");
|
||||
break;
|
||||
}
|
||||
token += lexer.consume();
|
||||
}
|
||||
lexer.consumeTemplateSuffix();
|
||||
for (const auto& suffix : valid_file_endings){
|
||||
if (token.ends_with(suffix)) {
|
||||
auto path = cs::fs::createWebFilePath(token);
|
||||
if (path == file){
|
||||
auto token = lexer.consumeToken();
|
||||
for (const auto& suffix : valid_file_endings)
|
||||
{
|
||||
if (token.ends_with(suffix))
|
||||
{
|
||||
if (token == file)
|
||||
{
|
||||
BLT_WARN("Recursive load detected!");
|
||||
BLT_WARN("Caching Engine will ignore this attempt, however, it is recommended that you remove the recursive call.");
|
||||
BLT_WARN("Caching Engine will ignore this, however, it is recommended that you remove the recursive call.");
|
||||
BLT_WARN("Detected in file '%s' offending link '%s'", file.c_str(), token.c_str());
|
||||
break;
|
||||
}
|
||||
resolvedSite += fetch(path);
|
||||
resolvedSite += fetch(token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (lexer.hasTemplatePrefix('$'))
|
||||
{
|
||||
auto token = lexer.consumeToken();
|
||||
if (std::find_if(
|
||||
m_Context.begin(), m_Context.end(),
|
||||
[&token](auto in) -> bool {
|
||||
return token == in.first;
|
||||
}
|
||||
) == m_Context.end())
|
||||
{
|
||||
// unable to find the token, we should throw an error to tell the user! (or admin in this case)
|
||||
BLT_WARN("Unable to find token '%s'!", token.c_str());
|
||||
} else
|
||||
resolvedSite += m_Context[token];
|
||||
} else
|
||||
resolvedSite += lexer.consume();
|
||||
}
|
||||
|
|
|
@ -13,35 +13,6 @@
|
|||
namespace cs
|
||||
{
|
||||
|
||||
class LexerSyntaxException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit LexerSyntaxException(const std::string& token):
|
||||
std::runtime_error(
|
||||
"Extended-mustache syntax error! An opening '{{' must be closed by '}}'! (near: '" +
|
||||
token + "')"
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
class LexerException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit LexerException(const std::string& message):
|
||||
std::runtime_error("Extended-mustache syntax processing error! " + message)
|
||||
{}
|
||||
};
|
||||
|
||||
class SyntaxException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit SyntaxException():
|
||||
std::runtime_error(
|
||||
"Extended-mustache syntax error! Static context keys should not contain $"
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
std::unique_ptr<HTMLPage> HTMLPage::load(const std::string& path)
|
||||
{
|
||||
std::string htmlSource;
|
||||
|
@ -72,51 +43,4 @@ namespace cs
|
|||
|
||||
HTMLPage::HTMLPage(std::string siteData): m_SiteData(std::move(siteData))
|
||||
{}
|
||||
|
||||
std::string HTMLPage::render(StaticContext& context)
|
||||
{
|
||||
std::string processedSiteData = m_SiteData;
|
||||
|
||||
std::string buffer;
|
||||
|
||||
StringLexer lexer(processedSiteData);
|
||||
|
||||
while (lexer.hasNext())
|
||||
{
|
||||
if (lexer.hasTemplatePrefix('$'))
|
||||
{
|
||||
lexer.consumeTemplatePrefix();
|
||||
std::string token;
|
||||
while (!lexer.hasTemplateSuffix())
|
||||
{
|
||||
if (!lexer.hasNext())
|
||||
{
|
||||
BLT_FATAL("Invalid template syntax. EOF occurred before template was fully processed!");
|
||||
throw LexerSyntaxException(token);
|
||||
}
|
||||
token += lexer.consume();
|
||||
}
|
||||
lexer.consumeTemplateSuffix();
|
||||
if (std::find_if(
|
||||
context.begin(), context.end(),
|
||||
[&token](auto in) -> bool {
|
||||
return token == in.first;
|
||||
}
|
||||
) == context.end())
|
||||
{
|
||||
// unable to find the token, we should throw an error to tell the user! (or admin in this case)
|
||||
BLT_WARN("Unable to find token '%s'!", token.c_str());
|
||||
} else
|
||||
buffer += context[token];
|
||||
} else
|
||||
buffer += lexer.consume();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HTMLPage::resolveResources()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,6 +138,8 @@ crow::response handle_root_page(const site_params& params)
|
|||
if (cs::isUserLoggedIn(s_clientID, s_clientToken))
|
||||
{
|
||||
ctx["_logged_in"] = true;
|
||||
} else {
|
||||
ctx["_not_logged_in"] = true;
|
||||
}
|
||||
|
||||
// we don't want to pass all get parameters to the context to prevent leaking information
|
||||
|
|
Loading…
Reference in New Issue