1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package org.jboss.netty.util.internal;
17
18 import java.util.ArrayList;
19 import java.util.Formatter;
20 import java.util.List;
21
22 /**
23 * String utility class.
24 */
25 public final class StringUtil {
26
27 private StringUtil() {
28 // Unused.
29 }
30
31 public static final String NEWLINE;
32
33 static {
34 String newLine;
35
36 try {
37 newLine = new Formatter().format("%n").toString();
38 } catch (Exception e) {
39 newLine = "\n";
40 }
41
42 NEWLINE = newLine;
43 }
44
45 /**
46 * Strip an Object of it's ISO control characters.
47 *
48 * @param value
49 * The Object that should be stripped. This objects toString method will
50 * called and the result passed to {@link #stripControlCharacters(String)}.
51 * @return {@code String}
52 * A new String instance with its hexadecimal control characters replaced
53 * by a space. Or the unmodified String if it does not contain any ISO
54 * control characters.
55 */
56 public static String stripControlCharacters(Object value) {
57 if (value == null) {
58 return null;
59 }
60
61 return stripControlCharacters(value.toString());
62 }
63
64 /**
65 * Strip a String of it's ISO control characters.
66 *
67 * @param value
68 * The String that should be stripped.
69 * @return {@code String}
70 * A new String instance with its hexadecimal control characters replaced
71 * by a space. Or the unmodified String if it does not contain any ISO
72 * control characters.
73 */
74 public static String stripControlCharacters(String value) {
75 if (value == null) {
76 return null;
77 }
78
79 boolean hasControlChars = false;
80 for (int i = value.length() - 1; i >= 0; i --) {
81 if (Character.isISOControl(value.charAt(i))) {
82 hasControlChars = true;
83 break;
84 }
85 }
86
87 if (!hasControlChars) {
88 return value;
89 }
90
91 StringBuilder buf = new StringBuilder(value.length());
92 int i = 0;
93
94 // Skip initial control characters (i.e. left trim)
95 for (; i < value.length(); i ++) {
96 if (!Character.isISOControl(value.charAt(i))) {
97 break;
98 }
99 }
100
101 // Copy non control characters and substitute control characters with
102 // a space. The last control characters are trimmed.
103 boolean suppressingControlChars = false;
104 for (; i < value.length(); i ++) {
105 if (Character.isISOControl(value.charAt(i))) {
106 suppressingControlChars = true;
107 continue;
108 } else {
109 if (suppressingControlChars) {
110 suppressingControlChars = false;
111 buf.append(' ');
112 }
113 buf.append(value.charAt(i));
114 }
115 }
116
117 return buf.toString();
118 }
119
120 private static final String EMPTY_STRING = "";
121
122 /**
123 * Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
124 * version of {@link String#split(String)}.
125 */
126 public static String[] split(String value, char delim) {
127 final int end = value.length();
128 final List<String> res = new ArrayList<String>();
129
130 int start = 0;
131 for (int i = 0; i < end; i ++) {
132 if (value.charAt(i) == delim) {
133 if (start == i) {
134 res.add(EMPTY_STRING);
135 } else {
136 res.add(value.substring(start, i));
137 }
138 start = i + 1;
139 }
140 }
141
142 if (start == 0) { // If no delimiter was found in the value
143 res.add(value);
144 } else {
145 if (start != end) {
146 // Add the last element if it's not empty.
147 res.add(value.substring(start, end));
148 } else {
149 // Truncate trailing empty elements.
150 for (int i = res.size() - 1; i >= 0; i --) {
151 if (res.get(i).length() == 0) {
152 res.remove(i);
153 } else {
154 break;
155 }
156 }
157 }
158 }
159
160 return res.toArray(new String[res.size()]);
161 }
162 }