001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.util; 020 021import org.checkerframework.checker.nullness.qual.NonNull; 022 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collection; 026import java.util.Comparator; 027import java.util.List; 028import java.util.Set; 029import java.util.regex.Pattern; 030 031public class StringMan { 032 033 // Stolen from https://stackoverflow.com/a/366532/12620913 | Debug: https://regex101.com/r/DudJLb/1 034 private static final Pattern STRING_SPLIT_PATTERN = Pattern.compile("[^\\s\"]+|\"([^\"]*)\""); 035 036 public static int intersection(Set<String> options, String[] toCheck) { 037 int count = 0; 038 for (String check : toCheck) { 039 if (options.contains(check)) { 040 count++; 041 } 042 } 043 return count; 044 } 045 046 public static boolean isAlphanumericUnd(String str) { 047 for (int i = 0; i < str.length(); i++) { 048 char c = str.charAt(i); 049 if (c < 0x30 || (c >= 0x3a) && (c <= 0x40) || (c > 0x5a) && (c <= 0x60) || (c > 0x7a)) { 050 return false; 051 } 052 } 053 return true; 054 } 055 056 public static String join(Collection<?> collection, String delimiter) { 057 return join(collection.toArray(), delimiter); 058 } 059 060 public static String joinOrdered(Collection<?> collection, String delimiter) { 061 Object[] array = collection.toArray(); 062 Arrays.sort(array, Comparator.comparingInt(Object::hashCode)); 063 return join(array, delimiter); 064 } 065 066 public static int getLevenshteinDistance(String s, String t) { 067 int n = s.length(); 068 int m = t.length(); 069 if (n == 0) { 070 return m; 071 } else if (m == 0) { 072 return n; 073 } 074 if (n > m) { 075 String tmp = s; 076 s = t; 077 t = tmp; 078 n = m; 079 m = t.length(); 080 } 081 int[] p = new int[n + 1]; 082 int[] d = new int[n + 1]; 083 int i; 084 for (i = 0; i <= n; i++) { 085 p[i] = i; 086 } 087 for (int j = 1; j <= m; j++) { 088 char t_j = t.charAt(j - 1); 089 d[0] = j; 090 091 for (i = 1; i <= n; i++) { 092 int cost = s.charAt(i - 1) == t_j ? 0 : 1; 093 d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); 094 } 095 int[] _d = p; 096 p = d; 097 d = _d; 098 } 099 return p[n]; 100 } 101 102 public static String join(Object[] array, String delimiter) { 103 StringBuilder result = new StringBuilder(); 104 for (int i = 0, j = array.length; i < j; i++) { 105 if (i > 0) { 106 result.append(delimiter); 107 } 108 result.append(array[i]); 109 } 110 return result.toString(); 111 } 112 113 public static boolean isEqualIgnoreCaseToAny(@NonNull String a, String... args) { 114 for (String arg : args) { 115 if (a.equalsIgnoreCase(arg)) { 116 return true; 117 } 118 } 119 return false; 120 } 121 122 public static boolean isEqual(String a, String b) { 123 if ((a == null && b != null) || (a != null && b == null)) { 124 return false; 125 } else if (a == null /* implies that b is null */) { 126 return false; 127 } 128 return a.equals(b); 129 } 130 131 public static String repeat(String s, int n) { 132 StringBuilder sb = new StringBuilder(); 133 sb.append(String.valueOf(s).repeat(Math.max(0, n))); 134 return sb.toString(); 135 } 136 137 /** 138 * @param message an input string 139 * @return a list of strings 140 * @since 6.4.0 141 * 142 * <table border="1"> 143 * <caption>Converts multiple quoted and single strings into a list of strings</caption> 144 * <thead> 145 * <tr> 146 * <th>Input</th> 147 * <th>Output</th> 148 * </tr> 149 * </thead> 150 * <tbody> 151 * <tr> 152 * <td>title "sub title"</td> 153 * <td>["title", "sub title"]</td> 154 * </tr> 155 * <tr> 156 * <td>"a title" subtitle</td> 157 * <td>["a title", "subtitle"]</td> 158 * </tr> 159 * <tr> 160 * <td>"title" "subtitle"</td> 161 * <td>["title", "subtitle"]</td> 162 * </tr> 163 * <tr> 164 * <td>"PlotSquared is going well" the authors "and many contributors"</td> 165 * <td>["PlotSquared is going well", "the", "authors", "and many contributors"]</td> 166 * </tr> 167 * </tbody> 168 * </table> 169 */ 170 public static @NonNull List<String> splitMessage(@NonNull String message) { 171 var matcher = StringMan.STRING_SPLIT_PATTERN.matcher(message); 172 List<String> splitMessages = new ArrayList<>(); 173 while (matcher.find()) { 174 splitMessages.add(matcher.group(matcher.groupCount() - 1).replaceAll("\"", "")); 175 } 176 return splitMessages; 177 } 178 179}