001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import java.util.Arrays; 016 017/** 018 * Stores a set of ASCII characters for quick lookup. 019 */ 020public final class AsciiSet { 021 private final boolean[] store; 022 023 AsciiSet(boolean[] store) { 024 this.store = Arrays.copyOf(store, store.length); 025 } 026 027 /** 028 * Creates an ASCII set with the specified characters. 029 * 030 * @param chars The characters to keep in this store. 031 * @return A new object. 032 */ 033 public static AsciiSet create(String chars) { 034 return new Builder().chars(chars).build(); 035 } 036 037 /** 038 * Creates a builder for an ASCII set. 039 * 040 * @return A new builder. 041 */ 042 public static AsciiSet.Builder create() { 043 return new Builder(); 044 } 045 046 /** 047 * Builder class for {@link AsciiSet} objects. 048 */ 049 public static class Builder { 050 final boolean[] store = new boolean[128]; 051 052 /** 053 * Adds a range of characters to this set. 054 * 055 * @param start The start character. 056 * @param end The end character. 057 * @return This object (for method chaining). 058 */ 059 public AsciiSet.Builder range(char start, char end) { 060 for (char c = start; c <= end; c++) 061 if (c < 128) 062 store[c] = true; 063 return this; 064 } 065 066 /** 067 * Shortcut for calling multiple ranges. 068 * 069 * @param s Strings of the form "A-Z" where A and Z represent the first and last characters in the range. 070 * @return This object (for method chaining). 071 */ 072 public AsciiSet.Builder ranges(String...s) { 073 for (String ss : s) { 074 if (ss.length() != 3 || ss.charAt(1) != '-') 075 throw new RuntimeException("Value passed to ranges() must be 3 characters"); 076 range(ss.charAt(0), ss.charAt(2)); 077 } 078 return this; 079 } 080 081 /** 082 * Adds a set of characters to this set. 083 * 084 * @param chars The characters to keep in this store. 085 * @return This object (for method chaining). 086 */ 087 public AsciiSet.Builder chars(String chars) { 088 for (int i = 0; i < chars.length(); i++) { 089 char c = chars.charAt(i); 090 if (c < 128) 091 store[c] = true; 092 } 093 return this; 094 } 095 096 /** 097 * Create a new {@link AsciiSet} object with the contents of this builder. 098 * 099 * @return A new {link AsciiSet} object. 100 */ 101 public AsciiSet build() { 102 return new AsciiSet(store); 103 } 104 } 105 106 107 /** 108 * Returns <jk>true</jk> if the specified character is in this store. 109 * 110 * @param c The character to check. 111 * @return <jk>true</jk> if the specified character is in this store. 112 */ 113 public boolean contains(char c) { 114 if (c > 127) 115 return false; 116 return store[c]; 117 } 118 119 /** 120 * Returns <jk>true</jk> if the specified character is in this store. 121 * 122 * @param c The character to check. 123 * @return <jk>true</jk> if the specified character is in this store. 124 */ 125 public boolean contains(int c) { 126 if (c < 0 || c > 127) 127 return false; 128 return store[c]; 129 } 130 131 /** 132 * Returns <jk>true</jk> if the specified string contains at least one character in this set. 133 * 134 * @param s The string to test. 135 * @return <jk>true</jk> if the string is not null and contains at least one character in this set. 136 */ 137 public boolean contains(CharSequence s) { 138 if (s == null) 139 return false; 140 for (int i = 0; i < s.length(); i++) 141 if (contains(s.charAt(i))) 142 return true; 143 return false; 144 } 145 146 /** 147 * Returns <jk>true</jk> if the specified string contains only characters in this set. 148 * 149 * @param s The string to test. 150 * @return 151 * <jk>true</jk> if the string contains only characters in this set. 152 * <br>Nulls always return <jk>false</jk>. 153 * <br>Blanks always return <jk>true</jk>. 154 */ 155 public boolean containsOnly(String s) { 156 if (s == null) 157 return false; 158 for (int i = 0; i < s.length(); i++) 159 if (! contains(s.charAt(i))) 160 return false; 161 return true; 162 } 163}