Jelajahi Sumber

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.
Benoît Lormeau 4 tahun lalu
induk
melakukan
f0f6b09acb

+ 2 - 1
AK/Format.cpp

@@ -29,6 +29,7 @@
 #include <AK/PrintfImplementation.h>
 #include <AK/String.h>
 #include <AK/StringBuilder.h>
+#include <ctype.h>
 
 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;

+ 1 - 72
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 == ' ';
-}
-
 }

+ 2 - 32
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;

+ 13 - 12
AK/JsonParser.cpp

@@ -28,6 +28,7 @@
 #include <AK/JsonObject.h>
 #include <AK/JsonParser.h>
 #include <AK/Memory.h>
+#include <ctype.h>
 
 namespace AK {
 
@@ -104,27 +105,27 @@ Optional<JsonValue> 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<JsonValue> 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<JsonValue> JsonParser::parse_null()
 
 Optional<JsonValue> JsonParser::parse_helper()
 {
-    ignore_while(is_whitespace);
+    ignore_while(isspace);
     auto type_hint = peek();
     switch (type_hint) {
     case '{':
@@ -297,7 +298,7 @@ Optional<JsonValue> JsonParser::parse()
     auto result = parse_helper();
     if (!result.has_value())
         return {};
-    ignore_while(is_whitespace);
+    ignore_while(isspace);
     if (!is_eof())
         return {};
     return result;

+ 3 - 2
Applications/Spreadsheet/Spreadsheet.cpp

@@ -34,6 +34,7 @@
 #include <LibCore/File.h>
 #include <LibJS/Parser.h>
 #include <LibJS/Runtime/Function.h>
+#include <ctype.h>
 
 namespace Spreadsheet {
 
@@ -192,8 +193,8 @@ Cell* Sheet::at(const Position& position)
 Optional<Position> 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 {};

+ 5 - 1
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")

+ 3 - 2
Userland/lsof.cpp

@@ -35,6 +35,7 @@
 #include <LibCore/ArgsParser.h>
 #include <LibCore/File.h>
 #include <LibCore/ProcessStatisticsReader.h>
+#include <ctype.h>
 #include <stdio.h>
 
 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) {

+ 4 - 3
Userland/pro.cpp

@@ -34,6 +34,7 @@
 #include <LibCore/File.h>
 #include <LibProtocol/Client.h>
 #include <LibProtocol/Download.h>
+#include <ctype.h>
 #include <stdio.h>
 
 // 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=")) {