001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of AutomataLib, http://www.automatalib.net/. 003 * 004 * AutomataLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * AutomataLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with AutomataLib; if not, see 015 * http://www.gnu.de/documents/lgpl.en.html. 016 */ 017package net.automatalib.commons.util.strings; 018 019import java.io.IOException; 020import java.util.regex.Pattern; 021 022/** 023 * Misceallanous utility functions for {@link String}s. 024 * 025 * @author Malte Isberner <malte.isberner@gmail.com> 026 */ 027public abstract class StringUtil { 028 029 private static final String IDENTIFIER_REGEX = "[a-zA-Z_]\\w*"; 030 031 private static Pattern identifierPattern = null; 032 033 private StringUtil() {} 034 035 036 public static Pattern getIdentifierPattern() { 037 if(identifierPattern == null) 038 identifierPattern = Pattern.compile(IDENTIFIER_REGEX); 039 return identifierPattern; 040 } 041 042 public static String enquote(String s) { 043 StringBuilder sb = new StringBuilder(s.length() + 2); 044 try { 045 enquote(s, sb); 046 } 047 catch(IOException e) {} 048 return sb.toString(); 049 } 050 051 public static void enquote(String s, Appendable a) throws IOException { 052 a.append('"'); 053 escapeQuotes(s, a); 054 a.append('"'); 055 } 056 057 public static void enquoteIfNecessary(String s, Appendable a) throws IOException { 058 if(!getIdentifierPattern().matcher(s).matches()) 059 enquote(s, a); 060 else 061 a.append(s); 062 } 063 064 public static void enquoteIfNecessary(String s, Appendable a, Pattern valid) 065 throws IOException { 066 if(!valid.matcher(s).matches()) 067 enquote(s, a); 068 else 069 a.append(s); 070 } 071 072 public static void enquoteIfNecessary(String s, Appendable a, 073 Pattern valid, 074 Pattern exception) throws IOException { 075 if(!valid.matcher(s).matches() || exception.matcher(s).matches()) 076 enquote(s, a); 077 else 078 a.append(s); 079 } 080 081 public static String unquote(String s) { 082 StringBuilder sb = new StringBuilder(s.length() - 2); 083 try { 084 unquote(s, sb); 085 } 086 catch(IOException e) {} 087 return sb.toString(); 088 } 089 090 public static void unquote(String s, Appendable a) throws IOException { 091 if(s.charAt(0) != '"' || s.charAt(s.length()-1) != '"') 092 throw new IllegalArgumentException("Argument to StringUtil.unquote() must begin and end with a double quote ('\"')."); 093 unescapeQuotes(s.substring(1, s.length()-1)); 094 } 095 096 /** 097 * Unescapes escaped double quotes in a string, i.e. 098 * replaces <code>\"</code> by <code>"</code> and 099 * <code>\\</code> by <code>\</code>. 100 * 101 * @param s the string in which to unescape double quotes. 102 * @return the unescaped string. 103 */ 104 public static String unescapeQuotes(String s) { 105 StringBuilder sb = new StringBuilder(s.length()); 106 try { 107 unescapeQuotes(s, sb); 108 } 109 catch(IOException e) {} 110 return sb.toString(); 111 } 112 113 public static void unescapeQuotes(String s, Appendable a) throws IOException { 114 int eos = s.length() - 1; 115 for(int i = 0; i < eos; i++) { 116 char c = s.charAt(i); 117 if(c == '\\') { 118 c = s.charAt(++i); 119 if(c != '"' && c != '\\') 120 a.append('\\'); 121 } 122 a.append(c); 123 } 124 125 a.append(s.charAt(eos)); 126 } 127 128 /** 129 * Escapes double quotes in a string. Effectively, <code>"</code> is 130 * replaced by <code>\"</code> and <code>\</code> is replaced by 131 * <code>\\</code>. 132 * 133 * @param s the string to escape. 134 * @return the escaped string. 135 */ 136 public static String escapeQuotes(String s) { 137 StringBuilder sb = new StringBuilder(s.length()); 138 try { 139 escapeQuotes(s, sb); 140 } 141 catch(IOException e) {} 142 return sb.toString(); 143 } 144 145 public static void escapeQuotes(String s, Appendable a) throws IOException { 146 for(int i = 0; i < s.length(); i++) { 147 char c = s.charAt(i); 148 149 if(c == '\\' || c == '"') 150 a.append('\\'); 151 a.append(c); 152 } 153 } 154 155 156 public static void appendObject(Appendable a, Object obj) throws IOException { 157 if(obj instanceof Printable) 158 ((Printable)obj).print(a); 159 else 160 a.append(String.valueOf(obj)); 161 } 162 163 public static void appendArray(Appendable a, Object[] array, String sepString) throws IOException { 164 boolean first = true; 165 166 for(Object o : array) { 167 if(first) 168 first = false; 169 else 170 a.append(sepString); 171 appendObject(a, o); 172 } 173 } 174 175 public static void appendArrayEnquoted(Appendable a, Object[] array, String sepString) throws IOException { 176 boolean first = true; 177 178 for(Object o : array) { 179 if(first) 180 first = false; 181 else 182 a.append(sepString); 183 enquote(String.valueOf(o), a); 184 } 185 } 186 187 public static void appendIterable(Appendable a, Iterable<?> it, String sepString) throws IOException { 188 boolean first = true; 189 190 for(Object o : it) { 191 if(first) 192 first = false; 193 else 194 a.append(sepString); 195 appendObject(a, o); 196 } 197 } 198 199 public static void appendIterableEnquoted(Appendable a, Iterable<?> it, String sepString) throws IOException { 200 boolean first = true; 201 202 for(Object o : it) { 203 if(first) 204 first = false; 205 else 206 a.append(sepString); 207 if(o == null) 208 a.append("null"); 209 else 210 enquote(o.toString(), a); 211 } 212 } 213}