myTinySQL v0.2.0-2-g5000098
A tiny SQL interpreter over fixed-width text files
Loading...
Searching...
No Matches
Util.cpp
Go to the documentation of this file.
1
3
4#include "Util.hpp"
5
6#include <algorithm>
7#include <cctype>
8#include <charconv>
9
10namespace tinysql {
11
12namespace {
13
17bool isSpace(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; }
18
22char upper(unsigned char c) { return static_cast<char>(std::toupper(c)); }
23
24} // namespace
25
26std::string_view trimRight(std::string_view text)
27{
28 while (!text.empty() && isSpace(text.back())) {
29 text.remove_suffix(1);
30 }
31 return text;
32}
33
34std::string_view trim(std::string_view text)
35{
36 while (!text.empty() && isSpace(text.front())) {
37 text.remove_prefix(1);
38 }
39 return trimRight(text);
40}
41
42std::string toUpper(std::string_view text)
43{
44 std::string result(text);
45 std::ranges::transform(result, result.begin(), [](unsigned char c) { return upper(c); });
46 return result;
47}
48
49bool equalsIgnoreCase(std::string_view a, std::string_view b)
50{
51 return std::ranges::equal(a, b, [](unsigned char x, unsigned char y) { return upper(x) == upper(y); });
52}
53
54bool matchesLike(std::string_view text, std::string_view pattern)
55{
56 constexpr std::size_t kNone = std::string_view::npos;
57 std::size_t t = 0, p = 0;
58 // Where the last `%` was, and where in the text it started matching: on a mismatch we come
59 // back there and let that `%` swallow one more character.
60 std::size_t lastPercent = kNone, resumeText = 0;
61
62 while (t < text.size()) {
63 if (p < pattern.size() && pattern[p] == '%') {
64 lastPercent = p++;
65 resumeText = t;
66 } else if (p < pattern.size() && (pattern[p] == '_' || upper(pattern[p]) == upper(text[t]))) {
67 ++p;
68 ++t;
69 } else if (lastPercent != kNone) {
70 p = lastPercent + 1;
71 t = ++resumeText;
72 } else {
73 return false;
74 }
75 }
76 while (p < pattern.size() && pattern[p] == '%') {
77 ++p; // a trailing `%` also matches the empty rest
78 }
79 return p == pattern.size();
80}
81
82std::optional<long long> parseInteger(std::string_view text)
83{
84 text = trim(text);
85 if (text.starts_with('+')) {
86 text.remove_prefix(1);
87 }
88 if (text.empty()) {
89 return std::nullopt;
90 }
91 long long value = 0;
92 const char* end = text.data() + text.size();
93 auto [ptr, ec] = std::from_chars(text.data(), end, value);
94 if (ec != std::errc{} || ptr != end) {
95 return std::nullopt;
96 }
97 return value;
98}
99
100} // namespace tinysql
The SqlError exception and small string helpers used everywhere.
std::optional< long long > parseInteger(std::string_view text)
Parses a whole string as a base-10 integer.
Definition Util.cpp:82
std::string toUpper(std::string_view text)
Converts ASCII letters to upper case.
Definition Util.cpp:42
std::string_view trimRight(std::string_view text)
Removes trailing spaces, tabs and line ends.
Definition Util.cpp:26
bool matchesLike(std::string_view text, std::string_view pattern)
Matches text against an SQL LIKE pattern, ignoring the case of ASCII letters.
Definition Util.cpp:54
bool equalsIgnoreCase(std::string_view a, std::string_view b)
Compares two strings, ignoring the case of ASCII letters.
Definition Util.cpp:49
std::string_view trim(std::string_view text)
Removes leading and trailing spaces, tabs and line ends.
Definition Util.cpp:34
char upper(unsigned char c)
Upper-cases one ASCII character.
Definition Util.cpp:22
bool isSpace(char c)
Tells whether a character is whitespace for trimming.
Definition Util.cpp:17