mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Avoid using std::regex for now
It turned out that on some platforms we still aim to support the stdlib had not yet implemented std::regex. For this reason we want to avoid using it for now. In the particular use cases here it was also not the best solution. It was faster to write using a regular expression instead of a hand coded loop but clearly a simple loop should be more efficient here. See issue #1873.
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
#include "ObjectIdentifier.h"
|
||||
|
||||
#include <regex>
|
||||
static std::string duplicate_char(std::string str, char to_replace)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while((pos = str.find(to_replace, pos)) != std::string::npos)
|
||||
{
|
||||
str.insert(pos, 1, to_replace);
|
||||
pos += 2; // Advance by two characters in order to avoid escaping a character multiple times
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
@@ -15,7 +24,7 @@ std::string escapeIdentifier(const std::string& id)
|
||||
{
|
||||
switch(customQuoting) {
|
||||
case GraveAccents:
|
||||
return '`' + std::regex_replace(id, std::regex("\\`"), std::string("``")) + '`';
|
||||
return '`' + duplicate_char(id, '`') + '`';
|
||||
case SquareBrackets:
|
||||
// There aren't any escaping possibilities for square brackets inside the identifier,
|
||||
// so we rely on the user to not enter these characters when this kind of quoting is
|
||||
@@ -26,7 +35,7 @@ std::string escapeIdentifier(const std::string& id)
|
||||
// This may produce a 'control reaches end of non-void function' warning if the
|
||||
// default branch is removed, even though we have covered all possibilities in the
|
||||
// switch statement.
|
||||
return '"' + std::regex_replace(id, std::regex("\\\""), std::string("\"\"")) + '"';
|
||||
return '"' + duplicate_char(id, '"') + '"';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,18 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <clocale> // This include seems to only be necessary for the Windows build
|
||||
#include <regex>
|
||||
#include <numeric>
|
||||
|
||||
namespace {
|
||||
bool starts_with_ci(const std::string& str, const std::string& with)
|
||||
{
|
||||
if(str.size() < with.size())
|
||||
return false;
|
||||
else
|
||||
return compare_ci(str.substr(0, with.size()), with);
|
||||
}
|
||||
}
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
StringVector escapeIdentifier(StringVector ids)
|
||||
@@ -235,32 +244,55 @@ std::string Field::toString(const std::string& indent, const std::string& sep) c
|
||||
|
||||
bool Field::isText() const
|
||||
{
|
||||
std::regex is_text("(^(character|varchar|varying character|nchar|native character|nvarchar))|(^(text|clob)$)", std::regex::icase);
|
||||
return std::regex_match(m_type, is_text);
|
||||
if(starts_with_ci(m_type, "character")) return true;
|
||||
if(starts_with_ci(m_type, "varchar")) return true;
|
||||
if(starts_with_ci(m_type, "varying character")) return true;
|
||||
if(starts_with_ci(m_type, "nchar")) return true;
|
||||
if(starts_with_ci(m_type, "native character")) return true;
|
||||
if(starts_with_ci(m_type, "nvarchar")) return true;
|
||||
if(compare_ci(m_type, "text")) return true;
|
||||
if(compare_ci(m_type, "clob")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Field::isInteger() const
|
||||
{
|
||||
std::regex is_integer("^(int|integer|tinyint|smallint|mediumint|bigint|unsigned big int|int2|int8)$", std::regex::icase);
|
||||
return std::regex_match(m_type, is_integer);
|
||||
if(compare_ci(m_type, "int")) return true;
|
||||
if(compare_ci(m_type, "integer")) return true;
|
||||
if(compare_ci(m_type, "tinyint")) return true;
|
||||
if(compare_ci(m_type, "smallint")) return true;
|
||||
if(compare_ci(m_type, "mediumint")) return true;
|
||||
if(compare_ci(m_type, "bigint")) return true;
|
||||
if(compare_ci(m_type, "unsigned big int")) return true;
|
||||
if(compare_ci(m_type, "int2")) return true;
|
||||
if(compare_ci(m_type, "int8")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Field::isReal() const
|
||||
{
|
||||
std::regex is_real("^(real|double|double precision|float)$", std::regex::icase);
|
||||
return std::regex_match(m_type, is_real);
|
||||
if(compare_ci(m_type, "real")) return true;
|
||||
if(compare_ci(m_type, "double")) return true;
|
||||
if(compare_ci(m_type, "double precision")) return true;
|
||||
if(compare_ci(m_type, "float")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Field::isNumeric() const
|
||||
{
|
||||
std::regex is_numeric("(^(decimal))|(^(numeric|boolean|date|datetime)$)", std::regex::icase);
|
||||
return std::regex_match(m_type, is_numeric);
|
||||
if(starts_with_ci(m_type, "decimal")) return true;
|
||||
if(compare_ci(m_type, "numeric")) return true;
|
||||
if(compare_ci(m_type, "boolean")) return true;
|
||||
if(compare_ci(m_type, "date")) return true;
|
||||
if(compare_ci(m_type, "datetime")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Field::isBlob() const
|
||||
{
|
||||
std::regex is_blob("(^$)|(^blob$)", std::regex::icase);
|
||||
return std::regex_match(m_type, is_blob);
|
||||
if(m_type.empty()) return true;
|
||||
if(compare_ci(m_type, "blob")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Field::affinity() const
|
||||
@@ -591,6 +623,19 @@ void Table::renameKeyInAllConstraints(const std::string& key, const std::string&
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string unescape_identifier(std::string str, char quote_char)
|
||||
{
|
||||
std::string quote(2, quote_char);
|
||||
|
||||
size_t pos = 0;
|
||||
while((pos = str.find(quote, pos)) != std::string::npos)
|
||||
{
|
||||
str.erase(pos, 1);
|
||||
pos += 1; // Don't remove the other quote char too
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string identifier(antlr::RefAST ident)
|
||||
{
|
||||
std::string sident = ident->getText();
|
||||
@@ -599,7 +644,7 @@ std::string identifier(antlr::RefAST ident)
|
||||
ident->getType() == sqlite3TokenTypes::STRINGLITERAL)
|
||||
{
|
||||
// Remember the way the identifier is quoted
|
||||
std::string quoteChar(1, sident.at(0));
|
||||
char quoteChar = sident.at(0);
|
||||
|
||||
// Remove first and final character, i.e. the quotes
|
||||
sident = sident.substr(1, sident.size() - 2);
|
||||
@@ -608,7 +653,7 @@ std::string identifier(antlr::RefAST ident)
|
||||
// by a single instance. This is done because two quotes can be used as a means of escaping
|
||||
// the quote character, thus only the visual representation has its two quotes, the actual
|
||||
// name contains only one.
|
||||
sident = std::regex_replace(sident, std::regex("\\" + quoteChar + "\\" + quoteChar), quoteChar);
|
||||
sident = unescape_identifier(sident, quoteChar);
|
||||
}
|
||||
|
||||
return sident;
|
||||
|
||||
@@ -24,6 +24,12 @@ bool compare_ci(const T& a, const T& b)
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool compare_ci(const T& a, const char* b)
|
||||
{
|
||||
return compare_ci(a, std::string(b));
|
||||
}
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
using StringVector = std::vector<std::string>;
|
||||
|
||||
Reference in New Issue
Block a user