From f0f6b09acb2ca9b752cfc0a23387e2566e04deee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lormeau?= Date: Sun, 27 Sep 2020 12:44:03 +0200 Subject: [PATCH] AK: Remove the ctype adapters and use the actual ctype functions instead This finally takes care of the kind-of excessive boilerplate code that were the ctype adapters. On the other hand, I had to link `LibC/ctype.cpp` to the Kernel (for `AK/JsonParser.cpp` and `AK/Format.cpp`). The previous commit actually makes sense now: the `string.h` includes in `ctype.{h,cpp}` would require to link more LibC stuff to the Kernel when it only needs the `_ctype_` array of `ctype.cpp`, and there wasn't any string stuff used in ctype. Instead of all this I could have put static derivatives of `is_any_of()` in the concerned AK files, however that would have meant more boilerplate and workarounds; so I went for the Kernel approach. --- AK/Format.cpp | 3 +- AK/GenericLexer.cpp | 73 +----------------------- AK/GenericLexer.h | 34 +---------- AK/JsonParser.cpp | 25 ++++---- Applications/Spreadsheet/Spreadsheet.cpp | 5 +- Kernel/CMakeLists.txt | 6 +- Userland/lsof.cpp | 5 +- Userland/pro.cpp | 7 ++- 8 files changed, 33 insertions(+), 125 deletions(-) diff --git a/AK/Format.cpp b/AK/Format.cpp index f273e207aa..cae1410a46 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace { @@ -79,7 +80,7 @@ static bool parse_number(GenericLexer& lexer, size_t& value) bool consumed_at_least_one = false; while (!lexer.is_eof()) { - if (lexer.next_is(is_digit)) { + if (lexer.next_is(isdigit)) { value *= 10; value += lexer.consume() - '0'; consumed_at_least_one = true; diff --git a/AK/GenericLexer.cpp b/AK/GenericLexer.cpp index fe47fa6172..ff78aa9f9e 100644 --- a/AK/GenericLexer.cpp +++ b/AK/GenericLexer.cpp @@ -188,7 +188,7 @@ StringView GenericLexer::consume_until(const char* stop) */ StringView GenericLexer::consume_quoted_string(char escape_char) { - if (!is_quote(peek())) + if (!next_is(is_quote)) return {}; char quote_char = consume(); @@ -264,75 +264,4 @@ void GenericLexer::ignore_until(const char* stop) ignore(__builtin_strlen(stop)); } -// CType adapters -bool is_alpha(char c) -{ - return is_lowercase(c) || is_uppercase(c); -} - -bool is_alphanum(char c) -{ - return is_alpha(c) || is_digit(c); -} - -bool is_control(char c) -{ - return (c >= 0 && c <= 31) || c == 127; -} - -bool is_digit(char c) -{ - return c >= '0' && c <= '9'; -} - -bool is_graphic(char c) -{ - return c > ' ' && c <= '~'; -} - -bool is_hex_digit(char c) -{ - return is_digit(c) - || (c >= 'A' && c <= 'F') - || (c >= 'a' && c <= 'f'); -} - -bool is_lowercase(char c) -{ - return c >= 'a' && c <= 'z'; -} - -bool is_path_separator(char c) -{ - return c == '/' || c == '\\'; -} - -bool is_printable(char c) -{ - return c >= ' ' && c <= '~'; -} - -bool is_punctuation(char c) -{ - return (c >= '!' && c <= '/') - || (c >= ':' && c <= '@') - || (c >= '[' && c <= '`') - || (c >= '{' && c <= '~'); -} - -bool is_quote(char c) -{ - return c == '\'' || c == '"'; -} - -bool is_uppercase(char c) -{ - return c >= 'A' && c <= 'Z'; -} - -bool is_whitespace(char c) -{ - return (c >= '\t' && c <= '\r') || c == ' '; -} - } diff --git a/AK/GenericLexer.h b/AK/GenericLexer.h index ab1778c333..bac642b828 100644 --- a/AK/GenericLexer.h +++ b/AK/GenericLexer.h @@ -136,42 +136,12 @@ constexpr auto is_any_of(const StringView& values) return [values](auto c) { return values.contains(c); }; } -/* - * CType adapters: pass them as Conditions to a GenericLexer's methods - * Examples: - * - `if (lexer.next_is(is_digit))` - * - `auto name = lexer.consume_while(is_alphanum); - * - `lexer.ignore_until(is_any_of("<^>"))` - */ -bool is_alpha(char); -bool is_alphanum(char); -bool is_control(char); -bool is_digit(char); -bool is_graphic(char); -bool is_hex_digit(char); -bool is_lowercase(char); -bool is_path_separator(char); -bool is_printable(char); -bool is_punctuation(char); -bool is_quote(char); -bool is_uppercase(char); -bool is_whitespace(char); +constexpr auto is_path_separator = is_any_of("/\\"); +constexpr auto is_quote = is_any_of("'\""); } using AK::GenericLexer; - -using AK::is_alpha; -using AK::is_alphanum; using AK::is_any_of; -using AK::is_control; -using AK::is_digit; -using AK::is_graphic; -using AK::is_hex_digit; -using AK::is_lowercase; using AK::is_path_separator; -using AK::is_printable; -using AK::is_punctuation; using AK::is_quote; -using AK::is_uppercase; -using AK::is_whitespace; diff --git a/AK/JsonParser.cpp b/AK/JsonParser.cpp index 8248b8b85d..2e177ee7f7 100644 --- a/AK/JsonParser.cpp +++ b/AK/JsonParser.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace AK { @@ -104,27 +105,27 @@ Optional JsonParser::parse_object() if (!consume_specific('{')) return {}; for (;;) { - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == '}') break; - ignore_while(is_whitespace); + ignore_while(isspace); auto name = consume_and_unescape_string(); if (name.is_null()) return {}; - ignore_while(is_whitespace); + ignore_while(isspace); if (!consume_specific(':')) return {}; - ignore_while(is_whitespace); + ignore_while(isspace); auto value = parse_helper(); if (!value.has_value()) return {}; object.set(name, move(value.value())); - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == '}') break; if (!consume_specific(',')) return {}; - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == '}') return {}; } @@ -139,23 +140,23 @@ Optional JsonParser::parse_array() if (!consume_specific('[')) return {}; for (;;) { - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == ']') break; auto element = parse_helper(); if (!element.has_value()) return {}; array.append(element.value()); - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == ']') break; if (!consume_specific(',')) return {}; - ignore_while(is_whitespace); + ignore_while(isspace); if (peek() == ']') return {}; } - ignore_while(is_whitespace); + ignore_while(isspace); if (!consume_specific(']')) return {}; return array; @@ -260,7 +261,7 @@ Optional JsonParser::parse_null() Optional JsonParser::parse_helper() { - ignore_while(is_whitespace); + ignore_while(isspace); auto type_hint = peek(); switch (type_hint) { case '{': @@ -297,7 +298,7 @@ Optional JsonParser::parse() auto result = parse_helper(); if (!result.has_value()) return {}; - ignore_while(is_whitespace); + ignore_while(isspace); if (!is_eof()) return {}; return result; diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index e1c79ba606..0519434c1f 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace Spreadsheet { @@ -192,8 +193,8 @@ Cell* Sheet::at(const Position& position) Optional Sheet::parse_cell_name(const StringView& name) { GenericLexer lexer(name); - auto col = lexer.consume_while([](auto c) { return is_alpha(c); }); - auto row = lexer.consume_while([](auto c) { return is_alphanum(c) && !is_alpha(c); }); + auto col = lexer.consume_while(isalpha); + auto row = lexer.consume_while(isdigit); if (!lexer.is_eof() || row.is_empty() || col.is_empty()) return {}; diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 0f3000cda2..c0c43d1384 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -223,7 +223,6 @@ set(VT_SOURCES ../Libraries/LibVT/Line.cpp ) - set(KEYBOARD_SOURCES ../Libraries/LibKeyboard/CharacterMap.cpp ) @@ -233,6 +232,10 @@ set(CRYPTO_SOURCES ../Libraries/LibCrypto/Hash/SHA2.cpp ) +set(C_SOURCES + ../Libraries/LibC/ctype.cpp +) + set(SOURCES ${KERNEL_SOURCES} ${AK_SOURCES} @@ -240,6 +243,7 @@ set(SOURCES ${VT_SOURCES} ${KEYBOARD_SOURCES} ${CRYPTO_SOURCES} + ${C_SOURCES} ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option -DKERNEL") diff --git a/Userland/lsof.cpp b/Userland/lsof.cpp index 94cd4047c9..775955413f 100644 --- a/Userland/lsof.cpp +++ b/Userland/lsof.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include struct OpenFile { @@ -56,8 +57,8 @@ static bool parse_name(StringView name, OpenFile& file) return true; } else { file.type = component1; - auto component2 = lexer.consume_while([](char c) { return is_printable(c) && !is_whitespace(c) && c != '('; }); - lexer.ignore_while(is_whitespace); + auto component2 = lexer.consume_while([](char c) { return isprint(c) && !isspace(c) && c != '('; }); + lexer.ignore_while(isspace); file.name = component2; if (lexer.tell_remaining() == 0) { diff --git a/Userland/pro.cpp b/Userland/pro.cpp index 4fc19dd067..7ce7a39b45 100644 --- a/Userland/pro.cpp +++ b/Userland/pro.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include // FIXME: Move this somewhere else when it's needed (e.g. in the Browser) @@ -43,7 +44,7 @@ public: { GenericLexer lexer(value); - lexer.ignore_while(is_whitespace); + lexer.ignore_while(isspace); if (lexer.consume_specific("inline")) { m_kind = Kind::Inline; @@ -55,7 +56,7 @@ public: if (lexer.consume_specific("attachment")) { m_kind = Kind::Attachment; if (lexer.consume_specific(";")) { - lexer.ignore_while(is_whitespace); + lexer.ignore_while(isspace); if (lexer.consume_specific("filename=")) { // RFC 2183: "A short (length <= 78 characters) // parameter value containing only non-`tspecials' characters SHOULD be @@ -77,7 +78,7 @@ public: if (lexer.consume_specific("form-data")) { m_kind = Kind::FormData; while (lexer.consume_specific(";")) { - lexer.ignore_while(is_whitespace); + lexer.ignore_while(isspace); if (lexer.consume_specific("name=")) { m_name = lexer.consume_quoted_string(); } else if (lexer.consume_specific("filename=")) {