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