mirror of
https://github.com/YACReader/yacreader
synced 2025-06-04 01:28:55 -04:00
Apply clang-format
This commit is contained in:
parent
9a660350d2
commit
7ccb338455
@ -5,23 +5,23 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
|
||||||
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
|
const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
|
||||||
{FieldType::numeric, {"numpages", "number", "count", "arcnumber", "arccount"}},
|
{ FieldType::numeric, { "numpages", "number", "count", "arcnumber", "arccount" } },
|
||||||
{FieldType::text, {"title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer",
|
{ FieldType::text, { "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes" } },
|
||||||
"coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes"}},
|
{ FieldType::boolean, { "isbis", "color" } },
|
||||||
{FieldType::boolean, {"isbis", "color"}},
|
{ FieldType::date, { "date" } },
|
||||||
{FieldType::date, {"date"}},
|
{ FieldType::filename, { "filename" } },
|
||||||
{FieldType::filename, {"filename"}},
|
{ FieldType::folder, { "folder" } }
|
||||||
{FieldType::folder, {"folder"}} };
|
};
|
||||||
|
|
||||||
int QueryParser::TreeNode::buildSqlString(std::string& sqlString, int bindPosition) const {
|
int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPosition) const
|
||||||
|
{
|
||||||
if (t == "token") {
|
if (t == "token") {
|
||||||
++bindPosition;
|
++bindPosition;
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
if (toLower(children[0].t) == "all") {
|
if (toLower(children[0].t) == "all") {
|
||||||
oss << "(";
|
oss << "(";
|
||||||
for (const auto& field: fieldNames.at(FieldType::text)) {
|
for (const auto &field : fieldNames.at(FieldType::text)) {
|
||||||
oss << "UPPER(ci." << field << ") LIKE UPPER(:bindPosition" << bindPosition << ") OR ";
|
oss << "UPPER(ci." << field << ") LIKE UPPER(:bindPosition" << bindPosition << ") OR ";
|
||||||
}
|
}
|
||||||
oss << "UPPER(c.filename) LIKE UPPER(:bindPosition" << bindPosition << ") OR ";
|
oss << "UPPER(c.filename) LIKE UPPER(:bindPosition" << bindPosition << ") OR ";
|
||||||
@ -49,16 +49,17 @@ int QueryParser::TreeNode::buildSqlString(std::string& sqlString, int bindPositi
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bindPosition;
|
return bindPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QueryParser::TreeNode::bindValues(QSqlQuery& selectQuery, int bindPosition) const {
|
int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition) const
|
||||||
|
{
|
||||||
if (t == "token") {
|
if (t == "token") {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << ":bindPosition" << ++bindPosition;
|
oss << ":bindPosition" << ++bindPosition;
|
||||||
if (isIn(fieldType(children[0].t), FieldType::numeric, FieldType::boolean)) {
|
if (isIn(fieldType(children[0].t), FieldType::numeric, FieldType::boolean)) {
|
||||||
selectQuery.bindValue(oss.str().c_str(), std::stoi(children[1].t));
|
selectQuery.bindValue(oss.str().c_str(), std::stoi(children[1].t));
|
||||||
} else {
|
} else {
|
||||||
selectQuery.bindValue(oss.str().c_str(), ("%%"+children[1].t+"%%").c_str());
|
selectQuery.bindValue(oss.str().c_str(), ("%%" + children[1].t + "%%").c_str());
|
||||||
}
|
}
|
||||||
} else if (t == "not") {
|
} else if (t == "not") {
|
||||||
bindPosition = children[0].bindValues(selectQuery, bindPosition);
|
bindPosition = children[0].bindValues(selectQuery, bindPosition);
|
||||||
@ -68,10 +69,11 @@ int QueryParser::TreeNode::buildSqlString(std::string& sqlString, int bindPositi
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bindPosition;
|
return bindPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryParser::QueryParser()
|
||||||
QueryParser::QueryParser(): lexScanner(0) {
|
: lexScanner(0)
|
||||||
|
{
|
||||||
|
|
||||||
lexScanner.push("[()]", static_cast<std::underlying_type<TokenType>::type>(TokenType::opcode));
|
lexScanner.push("[()]", static_cast<std::underlying_type<TokenType>::type>(TokenType::opcode));
|
||||||
lexScanner.push("@[^:]+:[^\\\")\\s]+", static_cast<std::underlying_type<TokenType>::type>(TokenType::atWord));
|
lexScanner.push("@[^:]+:[^\\\")\\s]+", static_cast<std::underlying_type<TokenType>::type>(TokenType::atWord));
|
||||||
@ -82,7 +84,8 @@ QueryParser::QueryParser(): lexScanner(0) {
|
|||||||
lexertl::generator::build(lexScanner, sm);
|
lexertl::generator::build(lexScanner, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::parse(const std::string& expr) {
|
QueryParser::TreeNode QueryParser::parse(const std::string &expr)
|
||||||
|
{
|
||||||
tokenize(expr);
|
tokenize(expr);
|
||||||
auto prog = orExpression();
|
auto prog = orExpression();
|
||||||
|
|
||||||
@ -93,52 +96,60 @@ QueryParser::TreeNode QueryParser::parse(const std::string& expr) {
|
|||||||
return prog;
|
return prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QueryParser::toLower(const std::string& string) {
|
std::string QueryParser::toLower(const std::string &string)
|
||||||
|
{
|
||||||
std::string res(string);
|
std::string res(string);
|
||||||
std::transform(res.begin(), res.end(), res.begin(), ::tolower);
|
std::transform(res.begin(), res.end(), res.begin(), ::tolower);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QueryParser::token(bool advance) {
|
std::string QueryParser::token(bool advance)
|
||||||
|
{
|
||||||
if (isEof()) {
|
if (isEof()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto res = (tokenType() == TokenType::quotedWord)?iter->substr(1,1):iter->str();
|
auto res = (tokenType() == TokenType::quotedWord) ? iter->substr(1, 1) : iter->str();
|
||||||
if (advance) {
|
if (advance) {
|
||||||
this->advance();
|
this->advance();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QueryParser::lcaseToken(bool advance) {
|
std::string QueryParser::lcaseToken(bool advance)
|
||||||
|
{
|
||||||
if (isEof()) {
|
if (isEof()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto res = (tokenType() == TokenType::quotedWord)?iter->substr(1,1):iter->str();
|
auto res = (tokenType() == TokenType::quotedWord) ? iter->substr(1, 1) : iter->str();
|
||||||
if (advance) {
|
if (advance) {
|
||||||
this->advance();
|
this->advance();
|
||||||
}
|
}
|
||||||
return toLower(res);
|
return toLower(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TokenType QueryParser::tokenType() {
|
QueryParser::TokenType QueryParser::tokenType()
|
||||||
|
{
|
||||||
if (isEof()) {
|
if (isEof()) {
|
||||||
return TokenType::eof;
|
return TokenType::eof;
|
||||||
}
|
}
|
||||||
return TokenType(iter->id);
|
return TokenType(iter->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueryParser::isEof() const {
|
bool QueryParser::isEof() const
|
||||||
|
{
|
||||||
return iter == end;
|
return iter == end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryParser::advance() {
|
void QueryParser::advance()
|
||||||
|
{
|
||||||
++iter;
|
++iter;
|
||||||
if (tokenType() == TokenType::space) advance();
|
if (tokenType() == TokenType::space)
|
||||||
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::FieldType QueryParser::fieldType(const std::string& str) {
|
QueryParser::FieldType QueryParser::fieldType(const std::string &str)
|
||||||
for (const auto& names : fieldNames) {
|
{
|
||||||
|
for (const auto &names : fieldNames) {
|
||||||
if (std::find(names.second.begin(), names.second.end(), toLower(str)) != names.second.end()) {
|
if (std::find(names.second.begin(), names.second.end(), toLower(str)) != names.second.end()) {
|
||||||
return names.first;
|
return names.first;
|
||||||
}
|
}
|
||||||
@ -147,21 +158,24 @@ QueryParser::FieldType QueryParser::fieldType(const std::string& str) {
|
|||||||
return FieldType::unknown;
|
return FieldType::unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryParser::tokenize (const std::string& expr) {
|
void QueryParser::tokenize(const std::string &expr)
|
||||||
|
{
|
||||||
iter = lexertl::siterator(expr.begin(), expr.end(), sm);
|
iter = lexertl::siterator(expr.begin(), expr.end(), sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QueryParser::join(const std::vector<std::string>& strings, const std::string& delim) {
|
std::string QueryParser::join(const std::vector<std::string> &strings, const std::string &delim)
|
||||||
|
{
|
||||||
return std::accumulate(strings.begin(), strings.end(), std::string(),
|
return std::accumulate(strings.begin(), strings.end(), std::string(),
|
||||||
[&delim](const std::string& a, const std::string& b) -> std::string {
|
[&delim](const std::string &a, const std::string &b) -> std::string {
|
||||||
return a + (a.length() > 0 && b.length() > 0 ? delim : "") + b;
|
return a + (a.length() > 0 && b.length() > 0 ? delim : "") + b;
|
||||||
} );
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> QueryParser::split(const std::string& string, char delim) {
|
std::vector<std::string> QueryParser::split(const std::string &string, char delim)
|
||||||
|
{
|
||||||
std::istringstream iss(string);
|
std::istringstream iss(string);
|
||||||
std::vector<std::string> words;
|
std::vector<std::string> words;
|
||||||
while(iss) {
|
while (iss) {
|
||||||
std::string substr;
|
std::string substr;
|
||||||
std::getline(iss, substr, delim);
|
std::getline(iss, substr, delim);
|
||||||
words.push_back(substr);
|
words.push_back(substr);
|
||||||
@ -169,38 +183,42 @@ std::vector<std::string> QueryParser::split(const std::string& string, char deli
|
|||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::orExpression() {
|
QueryParser::TreeNode QueryParser::orExpression()
|
||||||
|
{
|
||||||
auto lhs = andExpression();
|
auto lhs = andExpression();
|
||||||
if (lcaseToken() == "or") {
|
if (lcaseToken() == "or") {
|
||||||
advance();
|
advance();
|
||||||
return {"or", {lhs, orExpression()}};
|
return { "or", { lhs, orExpression() } };
|
||||||
}
|
}
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::andExpression() {
|
QueryParser::TreeNode QueryParser::andExpression()
|
||||||
|
{
|
||||||
auto lhs = notExpression();
|
auto lhs = notExpression();
|
||||||
if (lcaseToken() == "and") {
|
if (lcaseToken() == "and") {
|
||||||
advance();
|
advance();
|
||||||
return {"and", {lhs, andExpression()}};
|
return { "and", { lhs, andExpression() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isIn(tokenType(), TokenType::atWord, TokenType::word, TokenType::quotedWord) || token() == "(") && lcaseToken() != "or") {
|
if ((isIn(tokenType(), TokenType::atWord, TokenType::word, TokenType::quotedWord) || token() == "(") && lcaseToken() != "or") {
|
||||||
return {"and", {lhs, andExpression()}};
|
return { "and", { lhs, andExpression() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::notExpression() {
|
QueryParser::TreeNode QueryParser::notExpression()
|
||||||
|
{
|
||||||
if (lcaseToken() == "not") {
|
if (lcaseToken() == "not") {
|
||||||
advance();
|
advance();
|
||||||
return {"not", {notExpression()}};
|
return { "not", { notExpression() } };
|
||||||
}
|
}
|
||||||
return locationExpression();
|
return locationExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::locationExpression() {
|
QueryParser::TreeNode QueryParser::locationExpression()
|
||||||
|
{
|
||||||
if (tokenType() == TokenType::opcode && token() == "(") {
|
if (tokenType() == TokenType::opcode && token() == "(") {
|
||||||
advance();
|
advance();
|
||||||
auto res = orExpression();
|
auto res = orExpression();
|
||||||
@ -215,9 +233,10 @@ QueryParser::TreeNode QueryParser::locationExpression() {
|
|||||||
return baseToken();
|
return baseToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParser::TreeNode QueryParser::baseToken() {
|
QueryParser::TreeNode QueryParser::baseToken()
|
||||||
|
{
|
||||||
if (tokenType() == TokenType::quotedWord) {
|
if (tokenType() == TokenType::quotedWord) {
|
||||||
return {"token", {{"all", {}}, {token(true), {}}}};
|
return { "token", { { "all", {} }, { token(true), {} } } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto words(split(token(true), ':'));
|
auto words(split(token(true), ':'));
|
||||||
@ -226,9 +245,9 @@ QueryParser::TreeNode QueryParser::baseToken() {
|
|||||||
auto loc(toLower(words[0]));
|
auto loc(toLower(words[0]));
|
||||||
words.erase(words.begin());
|
words.erase(words.begin());
|
||||||
if (words.size() == 1 && tokenType() == TokenType::quotedWord) {
|
if (words.size() == 1 && tokenType() == TokenType::quotedWord) {
|
||||||
return {"token", {{loc, {}}, {token(true), {}}}};
|
return { "token", { { loc, {} }, { token(true), {} } } };
|
||||||
}
|
}
|
||||||
return {"token", {{loc, {}}, {join(words, ":"), {}}}};
|
return { "token", { { loc, {} }, { join(words, ":"), {} } } };
|
||||||
}
|
}
|
||||||
return {"token", {{"all", {}}, {join(words, ":"), {}}}};
|
return { "token", { { "all", {} }, { join(words, ":"), {} } } };
|
||||||
}
|
}
|
||||||
|
@ -38,24 +38,29 @@
|
|||||||
*
|
*
|
||||||
* selectQuery.exec();
|
* selectQuery.exec();
|
||||||
*/
|
*/
|
||||||
class QueryParser {
|
class QueryParser
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class TokenType { eof,
|
||||||
enum class TokenType {eof, opcode, atWord, word, quotedWord, space};
|
opcode,
|
||||||
|
atWord,
|
||||||
|
word,
|
||||||
|
quotedWord,
|
||||||
|
space };
|
||||||
|
|
||||||
struct TreeNode {
|
struct TreeNode {
|
||||||
std::string t;
|
std::string t;
|
||||||
std::vector<TreeNode> children;
|
std::vector<TreeNode> children;
|
||||||
|
|
||||||
int buildSqlString(std::string& sqlString, int bindPosition = 0) const;
|
int buildSqlString(std::string &sqlString, int bindPosition = 0) const;
|
||||||
int bindValues(QSqlQuery& selectQuery, int bindPosition = 0) const;
|
int bindValues(QSqlQuery &selectQuery, int bindPosition = 0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QueryParser();
|
explicit QueryParser();
|
||||||
TreeNode parse(const std::string& expr);
|
TreeNode parse(const std::string &expr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string toLower(const std::string& string);
|
static std::string toLower(const std::string &string);
|
||||||
|
|
||||||
std::string token(bool advance = false);
|
std::string token(bool advance = false);
|
||||||
std::string lcaseToken(bool advance = false);
|
std::string lcaseToken(bool advance = false);
|
||||||
@ -63,15 +68,24 @@ private:
|
|||||||
bool isEof() const;
|
bool isEof() const;
|
||||||
void advance();
|
void advance();
|
||||||
|
|
||||||
template<typename First, typename ... T>
|
template<typename First, typename... T>
|
||||||
static bool isIn(First &&first, T && ... t) {return ((first == t) || ...);}
|
static bool isIn(First &&first, T &&... t)
|
||||||
|
{
|
||||||
|
return ((first == t) || ...);
|
||||||
|
}
|
||||||
|
|
||||||
enum class FieldType {unknown, numeric, text, boolean, date, folder, filename};
|
enum class FieldType { unknown,
|
||||||
static FieldType fieldType(const std::string& str);
|
numeric,
|
||||||
|
text,
|
||||||
|
boolean,
|
||||||
|
date,
|
||||||
|
folder,
|
||||||
|
filename };
|
||||||
|
static FieldType fieldType(const std::string &str);
|
||||||
|
|
||||||
void tokenize (const std::string& expr);
|
void tokenize(const std::string &expr);
|
||||||
static std::string join(const std::vector<std::string>& strings, const std::string& delim);
|
static std::string join(const std::vector<std::string> &strings, const std::string &delim);
|
||||||
static std::vector<std::string> split(const std::string& string, char delim);
|
static std::vector<std::string> split(const std::string &string, char delim);
|
||||||
|
|
||||||
TreeNode orExpression();
|
TreeNode orExpression();
|
||||||
TreeNode andExpression();
|
TreeNode andExpression();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user