Serenity Operating System
at hosted 168 lines 5.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <awesomekling@gmail.com> 3 * Copyright (c) 2020, Fei Wu <f.eiwu@yahoo.com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <AK/String.h> 29#include <AK/StringUtils.h> 30#include <AK/StringView.h> 31 32namespace AK { 33 34namespace StringUtils { 35 36bool matches(const StringView& str, const StringView& mask, CaseSensitivity case_sensitivity) 37{ 38 if (str.is_null() || mask.is_null()) 39 return str.is_null() && mask.is_null(); 40 41 if (case_sensitivity == CaseSensitivity::CaseInsensitive) { 42 const String str_lower = String(str).to_lowercase(); 43 const String mask_lower = String(mask).to_lowercase(); 44 return matches(str_lower, mask_lower, CaseSensitivity::CaseSensitive); 45 } 46 47 const char* string_ptr = str.characters_without_null_termination(); 48 const char* string_end = string_ptr + str.length(); 49 const char* mask_ptr = mask.characters_without_null_termination(); 50 const char* mask_end = mask_ptr + mask.length(); 51 52 // Match string against mask directly unless we hit a * 53 while ((string_ptr < string_end) && (mask_ptr < mask_end) && (*mask_ptr != '*')) { 54 if ((*mask_ptr != *string_ptr) && (*mask_ptr != '?')) 55 return false; 56 mask_ptr++; 57 string_ptr++; 58 } 59 60 const char* cp = nullptr; 61 const char* mp = nullptr; 62 63 while (string_ptr < string_end) { 64 if ((mask_ptr < mask_end) && (*mask_ptr == '*')) { 65 // If we have only a * left, there is no way to not match. 66 if (++mask_ptr == mask_end) 67 return true; 68 mp = mask_ptr; 69 cp = string_ptr + 1; 70 } else if ((mask_ptr < mask_end) && ((*mask_ptr == *string_ptr) || (*mask_ptr == '?'))) { 71 mask_ptr++; 72 string_ptr++; 73 } else if ((cp != nullptr) && (mp != nullptr)) { 74 mask_ptr = mp; 75 string_ptr = cp++; 76 } else { 77 break; 78 } 79 } 80 81 // Handle any trailing mask 82 while ((mask_ptr < mask_end) && (*mask_ptr == '*')) 83 mask_ptr++; 84 85 // If we 'ate' all of the mask and the string then we match. 86 return (mask_ptr == mask_end) && string_ptr == string_end; 87} 88 89int convert_to_int(const StringView& str, bool& ok) 90{ 91 if (str.is_empty()) { 92 ok = false; 93 return 0; 94 } 95 96 bool negative = false; 97 size_t i = 0; 98 const auto characters = str.characters_without_null_termination(); 99 100 if (characters[0] == '-' || characters[0] == '+') { 101 if (str.length() == 1) { 102 ok = false; 103 return 0; 104 } 105 i++; 106 negative = (characters[0] == '-'); 107 } 108 109 int value = 0; 110 for (; i < str.length(); i++) { 111 if (characters[i] < '0' || characters[i] > '9') { 112 ok = false; 113 return 0; 114 } 115 value = value * 10; 116 value += characters[i] - '0'; 117 } 118 ok = true; 119 120 return negative ? -value : value; 121} 122 123unsigned convert_to_uint(const StringView& str, bool& ok) 124{ 125 if (str.is_empty()) { 126 ok = false; 127 return 0; 128 } 129 130 unsigned value = 0; 131 const auto characters = str.characters_without_null_termination(); 132 133 for (size_t i = 0; i < str.length(); i++) { 134 if (characters[i] < '0' || characters[i] > '9') { 135 ok = false; 136 return 0; 137 } 138 value = value * 10; 139 value += characters[i] - '0'; 140 } 141 ok = true; 142 143 return value; 144} 145 146static inline char to_lowercase(char c) 147{ 148 if (c >= 'A' && c <= 'Z') 149 return c | 0x20; 150 return c; 151} 152 153bool equals_ignoring_case(const StringView& a, const StringView& b) 154{ 155 if (a.impl() && a.impl() == b.impl()) 156 return true; 157 if (a.length() != b.length()) 158 return false; 159 for (size_t i = 0; i < a.length(); ++i) { 160 if (to_lowercase(a.characters_without_null_termination()[i]) != to_lowercase(b.characters_without_null_termination()[i])) 161 return false; 162 } 163 return true; 164} 165 166} 167 168}