1 | /* |
2 | |
3 | Derby - Class com.ihost.cs.StringUtil |
4 | |
5 | Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.iapi.util; |
22 | import java.util.Locale; |
23 | |
24 | /** |
25 | A set of public static methods for dealing with Strings |
26 | */ |
27 | public class StringUtil |
28 | { |
29 | /** |
30 | * Used to print out a string for error messages, |
31 | * chops is off at 60 chars for historical reasons. |
32 | */ |
33 | public final static String formatForPrint(String input) |
34 | { |
35 | if (input.length() > 60) |
36 | { |
37 | StringBuffer tmp = new StringBuffer(input.substring(0, 60)); |
38 | tmp.append("&"); |
39 | input = tmp.toString(); |
40 | } |
41 | return input; |
42 | } |
43 | |
44 | /** |
45 | * A method that receive an array of Objects and return a |
46 | * String array representation of that array. |
47 | */ |
48 | public static String [] toStringArray(Object [] objArray) { |
49 | int idx; |
50 | int len=objArray.length; |
51 | String [] strArray=new String[len]; |
52 | |
53 | for (idx=0 ; idx<len ; idx++) { |
54 | strArray[idx]=objArray[idx].toString(); |
55 | } |
56 | |
57 | return strArray; |
58 | } |
59 | |
60 | /** |
61 | Get 7-bit ASCII character array from input String. |
62 | The lower 7 bits of each character in the input string is assumed to be |
63 | the ASCII character value. |
64 | |
65 | Hexadecimal - Character |
66 | |
67 | | 00 NUL| 01 SOH| 02 STX| 03 ETX| 04 EOT| 05 ENQ| 06 ACK| 07 BEL| |
68 | | 08 BS | 09 HT | 0A NL | 0B VT | 0C NP | 0D CR | 0E SO | 0F SI | |
69 | | 10 DLE| 11 DC1| 12 DC2| 13 DC3| 14 DC4| 15 NAK| 16 SYN| 17 ETB| |
70 | | 18 CAN| 19 EM | 1A SUB| 1B ESC| 1C FS | 1D GS | 1E RS | 1F US | |
71 | | 20 SP | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' | |
72 | | 28 ( | 29 ) | 2A * | 2B + | 2C , | 2D - | 2E . | 2F / | |
73 | | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 | |
74 | | 38 8 | 39 9 | 3A : | 3B ; | 3C < | 3D = | 3E > | 3F ? | |
75 | | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G | |
76 | | 48 H | 49 I | 4A J | 4B K | 4C L | 4D M | 4E N | 4F O | |
77 | | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W | |
78 | | 58 X | 59 Y | 5A Z | 5B [ | 5C \ | 5D ] | 5E ^ | 5F _ | |
79 | | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g | |
80 | | 68 h | 69 i | 6A j | 6B k | 6C l | 6D m | 6E n | 6F o | |
81 | | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w | |
82 | | 78 x | 79 y | 7A z | 7B { | 7C | | 7D } | 7E ~ | 7F DEL| |
83 | |
84 | */ |
85 | public static byte[] getAsciiBytes(String input) |
86 | { |
87 | char[] c = input.toCharArray(); |
88 | byte[] b = new byte[c.length]; |
89 | for (int i = 0; i < c.length; i++) |
90 | b[i] = (byte)(c[i] & 0x007F); |
91 | |
92 | return b; |
93 | } |
94 | |
95 | /** |
96 | * Trim off trailing blanks but not leading blanks |
97 | * |
98 | * @param str |
99 | * |
100 | * @return The input with trailing blanks stipped off |
101 | */ |
102 | public static String trimTrailing( String str) |
103 | { |
104 | if( str == null) |
105 | return null; |
106 | int len = str.length(); |
107 | for( ; len > 0; len--) |
108 | { |
109 | if( ! Character.isWhitespace( str.charAt( len - 1))) |
110 | break; |
111 | } |
112 | return str.substring( 0, len); |
113 | } // end of trimTrailing |
114 | |
115 | |
116 | /** |
117 | Truncate a String to the given length with no warnings |
118 | or error raised if it is bigger. |
119 | |
120 | @param value String to be truncated |
121 | @param length Maximum length of string |
122 | |
123 | @return Returns value if value is null or value.length() is less or equal to than length, otherwise a String representing |
124 | value truncated to length. |
125 | */ |
126 | public static String truncate(String value, int length) |
127 | { |
128 | if (value != null && value.length() > length) |
129 | value = value.substring(0, length); |
130 | return value; |
131 | } |
132 | |
133 | /** |
134 | * Return a slice (substring) of the passed in value, optionally trimmed. |
135 | * WARNING - endOffset is inclusive for historical reasons, unlike |
136 | * String.substring() which has an exclusive ending offset. |
137 | * @param value Value to slice, must be non-null. |
138 | * @param beginOffset Inclusive start character |
139 | * @param endOffset Inclusive end character |
140 | * @param trim To trim or not to trim |
141 | * @return Sliceed value. |
142 | */ |
143 | public static String slice(String value, |
144 | int beginOffset, int endOffset, |
145 | boolean trim) |
146 | { |
147 | String retval = value.substring(beginOffset, endOffset + 1); |
148 | |
149 | if (trim) |
150 | retval = retval.trim(); |
151 | |
152 | return retval; |
153 | } |
154 | |
155 | |
156 | private static char[] hex_table = { |
157 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
158 | 'a', 'b', 'c', 'd', 'e', 'f' |
159 | }; |
160 | |
161 | |
162 | /** |
163 | Convert a byte array to a String with a hexidecimal format. |
164 | The String may be converted back to a byte array using fromHexString. |
165 | <BR> |
166 | For each byte (b) two characaters are generated, the first character |
167 | represents the high nibble (4 bits) in hexidecimal (<code>b & 0xf0</code>), the second character |
168 | represents the low nibble (<code>b & 0x0f</code>). |
169 | <BR> |
170 | The byte at <code>data[offset]</code> is represented by the first two characters in the returned String. |
171 | |
172 | @param data byte array |
173 | @param offset starting byte (zero based) to convert. |
174 | @param length number of bytes to convert. |
175 | |
176 | @return the String (with hexidecimal format) form of the byte array |
177 | */ |
178 | public static String toHexString(byte[] data, int offset, int length) |
179 | { |
180 | StringBuffer s = new StringBuffer(length*2); |
181 | int end = offset+length; |
182 | |
183 | for (int i = offset; i < end; i++) |
184 | { |
185 | int high_nibble = (data[i] & 0xf0) >>> 4; |
186 | int low_nibble = (data[i] & 0x0f); |
187 | s.append(hex_table[high_nibble]); |
188 | s.append(hex_table[low_nibble]); |
189 | } |
190 | |
191 | return s.toString(); |
192 | } |
193 | |
194 | /** |
195 | Convert a hexidecimal string generated by toHexString() back |
196 | into a byte array. |
197 | |
198 | @param s String to convert |
199 | @param offset starting character (zero based) to convert. |
200 | @param length number of characters to convert. |
201 | |
202 | @return the converted byte array. Returns null if the length is |
203 | not a multiple of 2. |
204 | */ |
205 | public static byte[] fromHexString(String s, int offset, int length) |
206 | { |
207 | if ((length%2) != 0) |
208 | return null; |
209 | |
210 | byte[] byteArray = new byte[length/2]; |
211 | |
212 | int j = 0; |
213 | int end = offset+length; |
214 | for (int i = offset; i < end; i += 2) |
215 | { |
216 | int high_nibble = Character.digit(s.charAt(i), 16); |
217 | int low_nibble = Character.digit(s.charAt(i+1), 16); |
218 | |
219 | if (high_nibble == -1 || low_nibble == -1) |
220 | { |
221 | // illegal format |
222 | return null; |
223 | } |
224 | |
225 | byteArray[j++] = (byte)(((high_nibble << 4) & 0xf0) | (low_nibble & 0x0f)); |
226 | } |
227 | return byteArray; |
228 | } |
229 | /** |
230 | Convert a byte array to a human-readable String for debugging purposes. |
231 | */ |
232 | public static String hexDump(byte[] data) |
233 | { |
234 | byte byte_value; |
235 | |
236 | |
237 | StringBuffer str = new StringBuffer(data.length * 3); |
238 | |
239 | str.append("Hex dump:\n"); |
240 | |
241 | for (int i = 0; i < data.length; i += 16) |
242 | { |
243 | // dump the header: 00000000: |
244 | String offset = Integer.toHexString(i); |
245 | |
246 | // "0" left pad offset field so it is always 8 char's long. |
247 | for (int offlen = offset.length(); offlen < 8; offlen++) |
248 | str.append("0"); |
249 | str.append(offset); |
250 | str.append(":"); |
251 | |
252 | // dump hex version of 16 bytes per line. |
253 | for (int j = 0; (j < 16) && ((i + j) < data.length); j++) |
254 | { |
255 | byte_value = data[i + j]; |
256 | |
257 | // add spaces between every 2 bytes. |
258 | if ((j % 2) == 0) |
259 | str.append(" "); |
260 | |
261 | // dump a single byte. |
262 | byte high_nibble = (byte) ((byte_value & 0xf0) >>> 4); |
263 | byte low_nibble = (byte) (byte_value & 0x0f); |
264 | |
265 | str.append(hex_table[high_nibble]); |
266 | str.append(hex_table[low_nibble]); |
267 | } |
268 | |
269 | // dump ascii version of 16 bytes |
270 | str.append(" "); |
271 | |
272 | for (int j = 0; (j < 16) && ((i + j) < data.length); j++) |
273 | { |
274 | char char_value = (char) data[i + j]; |
275 | |
276 | // RESOLVE (really want isAscii() or isPrintable()) |
277 | if (Character.isLetterOrDigit(char_value)) |
278 | str.append(String.valueOf(char_value)); |
279 | else |
280 | str.append("."); |
281 | } |
282 | |
283 | // new line |
284 | str.append("\n"); |
285 | } |
286 | return(str.toString()); |
287 | |
288 | } |
289 | |
290 | // The functions below are used for uppercasing SQL in a consistent manner. |
291 | // Cloudscape will uppercase Turkish to the English locale to avoid i |
292 | // uppercasing to an uppercase dotted i. In future versions, all |
293 | // casing will be done in English. The result will be that we will get |
294 | // only the 1:1 mappings in |
295 | // http://www.unicode.org/Public/3.0-Update1/UnicodeData-3.0.1.txt |
296 | // and avoid the 1:n mappings in |
297 | //http://www.unicode.org/Public/3.0-Update1/SpecialCasing-3.txt |
298 | // |
299 | // Any SQL casing should use these functions |
300 | |
301 | |
302 | /** Convert string to uppercase |
303 | * Always use the java.util.ENGLISH locale |
304 | * @param s string to uppercase |
305 | * @return uppercased string |
306 | */ |
307 | public static String SQLToUpperCase(String s) |
308 | { |
309 | return s.toUpperCase(Locale.ENGLISH); |
310 | } |
311 | |
312 | |
313 | /** Convert string to lowercase |
314 | * Return java.util.Locale.ENGLISH lowercasing |
315 | * @param s string to lowercase |
316 | * @return lowercased string |
317 | */ |
318 | public static String SQLToLowerCase(String s) |
319 | { |
320 | return s.toLowerCase(Locale.ENGLISH); |
321 | |
322 | } |
323 | |
324 | |
325 | /** Compares two strings |
326 | * Strings will be uppercased in english and compared |
327 | * equivalent to s1.equalsIgnoreCase(s2) |
328 | * throws NPE if s1 is null |
329 | * |
330 | * @param s1 first string to compare |
331 | * @param s2 second string to compare |
332 | * |
333 | * @return true if the two upppercased ENGLISH values are equal |
334 | * return false if s2 is null |
335 | */ |
336 | public static boolean SQLEqualsIgnoreCase(String s1, String s2) |
337 | { |
338 | if (s2 == null) |
339 | return false; |
340 | else |
341 | return s1.toUpperCase(Locale.ENGLISH).equals(s2.toUpperCase(Locale.ENGLISH)); |
342 | |
343 | } |
344 | |
345 | } |
346 | |